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