]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/verify_vol.c
Merge branch 'master' into basejobv3
[bacula/bacula] / bacula / src / filed / verify_vol.c
1 /*
2  *  Bacula File Daemon  verify-vol.c Verify files on a Volume
3  *    versus attributes in Catalog
4  *
5  *    Kern Sibbald, July MMII
6  *
7  *   Version $Id$
8  *
9  */
10 /*
11    Bacula® - The Network Backup Solution
12
13    Copyright (C) 2002-2006 Free Software Foundation Europe e.V.
14
15    The main author of Bacula is Kern Sibbald, with contributions from
16    many others, a complete list can be found in the file AUTHORS.
17    This program is Free Software; you can redistribute it and/or
18    modify it under the terms of version two of the GNU General Public
19    License as published by the Free Software Foundation and included
20    in the file LICENSE.
21
22    This program is distributed in the hope that it will be useful, but
23    WITHOUT ANY WARRANTY; without even the implied warranty of
24    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25    General Public License for more details.
26
27    You should have received a copy of the GNU General Public License
28    along with this program; if not, write to the Free Software
29    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
30    02110-1301, USA.
31
32    Bacula® is a registered trademark of Kern Sibbald.
33    The licensor of Bacula is the Free Software Foundation Europe
34    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
35    Switzerland, email:ftf@fsfeurope.org.
36 */
37
38 #include "bacula.h"
39 #include "filed.h"
40
41 /* Data received from Storage Daemon */
42 static char rec_header[] = "rechdr %ld %ld %ld %ld %ld";
43
44 /* Forward referenced functions */
45
46
47 /*
48  * Verify attributes of the requested files on the Volume
49  *
50  */
51 void do_verify_volume(JCR *jcr)
52 {
53    BSOCK *sd, *dir;
54    POOLMEM *fname;                    /* original file name */
55    POOLMEM *lname;                    /* link name */
56    int32_t stream;
57    uint32_t size;
58    uint32_t VolSessionId, VolSessionTime, file_index;
59    uint32_t record_file_index;
60    char digest[BASE64_SIZE(CRYPTO_DIGEST_MAX_SIZE)];
61    int type, stat;
62
63    sd = jcr->store_bsock;
64    if (!sd) {
65       Jmsg(jcr, M_FATAL, 0, _("Storage command not issued before Verify.\n"));
66       set_jcr_job_status(jcr, JS_FatalError);
67       return;
68    }
69    dir = jcr->dir_bsock;
70    set_jcr_job_status(jcr, JS_Running);
71
72    LockRes();
73    CLIENT *client = (CLIENT *)GetNextRes(R_CLIENT, NULL);
74    UnlockRes();
75    uint32_t buf_size;
76    if (client) {
77       buf_size = client->max_network_buffer_size;
78    } else {
79       buf_size = 0;                   /* use default */
80    }
81    if (!bnet_set_buffer_size(sd, buf_size, BNET_SETBUF_WRITE)) {
82       set_jcr_job_status(jcr, JS_FatalError);
83       return;
84    }
85    jcr->buf_size = sd->msglen;
86
87    fname = get_pool_memory(PM_FNAME);
88    lname = get_pool_memory(PM_FNAME);
89
90    /*
91     * Get a record from the Storage daemon
92     */
93    while (bget_msg(sd) >= 0 && !job_canceled(jcr)) {
94       /*
95        * First we expect a Stream Record Header
96        */
97       if (sscanf(sd->msg, rec_header, &VolSessionId, &VolSessionTime, &file_index,
98           &stream, &size) != 5) {
99          Jmsg1(jcr, M_FATAL, 0, _("Record header scan error: %s\n"), sd->msg);
100          goto bail_out;
101       }
102       Dmsg2(30, "Got hdr: FilInx=%d Stream=%d.\n", file_index, stream);
103
104       /*
105        * Now we expect the Stream Data
106        */
107       if (bget_msg(sd) < 0) {
108          Jmsg1(jcr, M_FATAL, 0, _("Data record error. ERR=%s\n"), bnet_strerror(sd));
109          goto bail_out;
110       }
111       if (size != ((uint32_t)sd->msglen)) {
112          Jmsg2(jcr, M_FATAL, 0, _("Actual data size %d not same as header %d\n"), sd->msglen, size);
113          goto bail_out;
114       }
115       Dmsg1(30, "Got stream data, len=%d\n", sd->msglen);
116
117       /* File Attributes stream */
118       switch (stream) {
119       case STREAM_UNIX_ATTRIBUTES:
120       case STREAM_UNIX_ATTRIBUTES_EX:
121          char *ap, *lp, *fp;
122
123          Dmsg0(400, "Stream=Unix Attributes.\n");
124
125          if ((int)sizeof_pool_memory(fname) < sd->msglen) {
126             fname = realloc_pool_memory(fname, sd->msglen + 1);
127          }
128
129          if ((int)sizeof_pool_memory(lname) < sd->msglen) {
130             lname = realloc_pool_memory(lname, sd->msglen + 1);
131          }
132          *fname = 0;
133          *lname = 0;
134
135          /*
136           * An Attributes record consists of:
137           *    File_index
138           *    Type   (FT_types)
139           *    Filename
140           *    Attributes
141           *    Link name (if file linked i.e. FT_LNK)
142           *    Extended Attributes (if Win32)
143           */
144          if (sscanf(sd->msg, "%d %d", &record_file_index, &type) != 2) {
145             Jmsg(jcr, M_FATAL, 0, _("Error scanning record header: %s\n"), sd->msg);
146             Dmsg0(0, "\nError scanning header\n");
147             goto bail_out;
148          }
149          Dmsg2(30, "Got Attr: FilInx=%d type=%d\n", record_file_index, type);
150          if (record_file_index != file_index) {
151             Jmsg(jcr, M_FATAL, 0, _("Record header file index %ld not equal record index %ld\n"),
152                file_index, record_file_index);
153             Dmsg0(0, "File index error\n");
154             goto bail_out;
155          }
156          ap = sd->msg;
157          while (*ap++ != ' ')         /* skip record file index */
158             ;
159          while (*ap++ != ' ')         /* skip type */
160             ;
161          /* Save filename and position to attributes */
162          fp = fname;
163          while (*ap != 0) {
164             *fp++  = *ap++;           /* copy filename to fname */
165          }
166          *fp = *ap++;                 /* terminate filename & point to attribs */
167
168          Dmsg1(200, "Attr=%s\n", ap);
169          /* Skip to Link name */
170          if (type == FT_LNK || type == FT_LNKSAVED) {
171             lp = ap;
172             while (*lp++ != 0) {
173                ;
174             }
175             pm_strcat(lname, lp);        /* "save" link name */
176          } else {
177             *lname = 0;
178          }
179          jcr->lock();
180          jcr->JobFiles++;
181          jcr->num_files_examined++;
182          pm_strcpy(jcr->last_fname, fname); /* last file examined */
183          jcr->unlock();
184
185          /*
186           * Send file attributes to Director
187           *   File_index
188           *   Stream
189           *   Verify Options
190           *   Filename (full path)
191           *   Encoded attributes
192           *   Link name (if type==FT_LNK)
193           * For a directory, link is the same as fname, but with trailing
194           * slash. For a linked file, link is the link.
195           */
196          /* Send file attributes to Director */
197          Dmsg2(200, "send ATTR inx=%d fname=%s\n", jcr->JobFiles, fname);
198          if (type == FT_LNK || type == FT_LNKSAVED) {
199             stat = bnet_fsend(dir, "%d %d %s %s%c%s%c%s%c", jcr->JobFiles,
200                           STREAM_UNIX_ATTRIBUTES, "pinsug5", fname,
201                           0, ap, 0, lname, 0);
202          /* for a deleted record, we set fileindex=0 */
203          } else if (type == FT_DELETED)  {
204             stat = bnet_fsend(dir,"%d %d %s %s%c%s%c%c", 0,
205                           STREAM_UNIX_ATTRIBUTES, "pinsug5", fname,
206                           0, ap, 0, 0);
207          } else {
208             stat = bnet_fsend(dir,"%d %d %s %s%c%s%c%c", jcr->JobFiles,
209                           STREAM_UNIX_ATTRIBUTES, "pinsug5", fname,
210                           0, ap, 0, 0);
211          }
212          Dmsg2(200, "bfiled>bdird: attribs len=%d: msg=%s\n", dir->msglen, dir->msg);
213          if (!stat) {
214             Jmsg(jcr, M_FATAL, 0, _("Network error in send to Director: ERR=%s\n"), bnet_strerror(dir));
215             goto bail_out;
216          }
217          break;
218
219       case STREAM_MD5_DIGEST:
220          bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_MD5_SIZE, true);
221          Dmsg2(400, "send inx=%d MD5=%s\n", jcr->JobFiles, digest);
222          bnet_fsend(dir, "%d %d %s *MD5-%d*", jcr->JobFiles, STREAM_MD5_DIGEST, digest,
223                     jcr->JobFiles);
224          Dmsg2(20, "bfiled>bdird: MD5 len=%d: msg=%s\n", dir->msglen, dir->msg);
225          break;
226
227       case STREAM_SHA1_DIGEST:
228          bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_SHA1_SIZE, true);
229          Dmsg2(400, "send inx=%d SHA1=%s\n", jcr->JobFiles, digest);
230          bnet_fsend(dir, "%d %d %s *SHA1-%d*", jcr->JobFiles, STREAM_SHA1_DIGEST,
231                     digest, jcr->JobFiles);
232          Dmsg2(20, "bfiled>bdird: SHA1 len=%d: msg=%s\n", dir->msglen, dir->msg);
233          break;
234
235       case STREAM_SHA256_DIGEST:
236          bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_SHA256_SIZE, true);
237          Dmsg2(400, "send inx=%d SHA256=%s\n", jcr->JobFiles, digest);
238          bnet_fsend(dir, "%d %d %s *SHA256-%d*", jcr->JobFiles, STREAM_SHA256_DIGEST,
239                     digest, jcr->JobFiles);
240          Dmsg2(20, "bfiled>bdird: SHA256 len=%d: msg=%s\n", dir->msglen, dir->msg);
241          break;
242
243       case STREAM_SHA512_DIGEST:
244          bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_SHA512_SIZE, true);
245          Dmsg2(400, "send inx=%d SHA512=%s\n", jcr->JobFiles, digest);
246          bnet_fsend(dir, "%d %d %s *SHA512-%d*", jcr->JobFiles, STREAM_SHA512_DIGEST,
247                     digest, jcr->JobFiles);
248          Dmsg2(20, "bfiled>bdird: SHA512 len=%d: msg=%s\n", dir->msglen, dir->msg);
249          break;
250
251       /* Ignore everything else */
252       default:
253          break;
254
255       } /* end switch */
256    } /* end while bnet_get */
257    set_jcr_job_status(jcr, JS_Terminated);
258    goto ok_out;
259
260 bail_out:
261    set_jcr_job_status(jcr, JS_ErrorTerminated);
262
263 ok_out:
264    if (jcr->compress_buf) {
265       free(jcr->compress_buf);
266       jcr->compress_buf = NULL;
267    }
268    free_pool_memory(fname);
269    free_pool_memory(lname);
270    Dmsg2(050, "End Verify-Vol. Files=%d Bytes=%" lld "\n", jcr->JobFiles,
271       jcr->JobBytes);
272 }