]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/verify_vol.c
======================= Warning ==========================
[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          jcr->lock();
172          jcr->JobFiles++;
173          jcr->num_files_examined++;
174          pm_strcpy(jcr->last_fname, fname); /* last file examined */
175          jcr->unlock();
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_ENCRYPTED_SESSION_DATA:
208       case STREAM_FILE_DATA:
209       case STREAM_SPARSE_DATA:
210       case STREAM_WIN32_DATA:
211       case STREAM_WIN32_GZIP_DATA:
212       case STREAM_GZIP_DATA:
213       case STREAM_SPARSE_GZIP_DATA:
214       case STREAM_SIGNED_DIGEST:
215
216         /* Do nothing */
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       default:
252          Pmsg2(0, "None of above!!! stream=%d data=%s\n", stream,sd->msg);
253          break;
254       } /* end switch */
255    } /* end while bnet_get */
256    set_jcr_job_status(jcr, JS_Terminated);
257    goto ok_out;
258
259 bail_out:
260    set_jcr_job_status(jcr, JS_ErrorTerminated);
261
262 ok_out:
263    if (jcr->compress_buf) {
264       free(jcr->compress_buf);
265       jcr->compress_buf = NULL;
266    }
267    free_pool_memory(fname);
268    free_pool_memory(lname);
269    Dmsg2(050, "End Verify-Vol. Files=%d Bytes=%" lld "\n", jcr->JobFiles,
270       jcr->JobBytes);
271 }