]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/verify_vol.c
Convert to pure GPL v2 license.
[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 John Walker.
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          } else {
203             stat = bnet_fsend(dir,"%d %d %s %s%c%s%c%c", jcr->JobFiles,
204                           STREAM_UNIX_ATTRIBUTES, "pinsug5", fname,
205                           0, ap, 0, 0);
206          }
207          Dmsg2(200, "bfiled>bdird: attribs len=%d: msg=%s\n", dir->msglen, dir->msg);
208          if (!stat) {
209             Jmsg(jcr, M_FATAL, 0, _("Network error in send to Director: ERR=%s\n"), bnet_strerror(dir));
210             goto bail_out;
211          }
212          break;
213
214       /* Data streams to ignore */
215       case STREAM_ENCRYPTED_SESSION_DATA:
216       case STREAM_FILE_DATA:
217       case STREAM_SPARSE_DATA:
218       case STREAM_WIN32_DATA:
219       case STREAM_WIN32_GZIP_DATA:
220       case STREAM_GZIP_DATA:
221       case STREAM_SPARSE_GZIP_DATA:
222       case STREAM_SIGNED_DIGEST:
223
224         /* Do nothing */
225         break;
226
227       case STREAM_MD5_DIGEST:
228          bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_MD5_SIZE, true);
229          Dmsg2(400, "send inx=%d MD5=%s\n", jcr->JobFiles, digest);
230          bnet_fsend(dir, "%d %d %s *MD5-%d*", jcr->JobFiles, STREAM_MD5_DIGEST, digest,
231                     jcr->JobFiles);
232          Dmsg2(20, "bfiled>bdird: MD5 len=%d: msg=%s\n", dir->msglen, dir->msg);
233          break;
234
235       case STREAM_SHA1_DIGEST:
236          bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_SHA1_SIZE, true);
237          Dmsg2(400, "send inx=%d SHA1=%s\n", jcr->JobFiles, digest);
238          bnet_fsend(dir, "%d %d %s *SHA1-%d*", jcr->JobFiles, STREAM_SHA1_DIGEST,
239                     digest, jcr->JobFiles);
240          Dmsg2(20, "bfiled>bdird: SHA1 len=%d: msg=%s\n", dir->msglen, dir->msg);
241          break;
242
243       case STREAM_SHA256_DIGEST:
244          bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_SHA256_SIZE, true);
245          Dmsg2(400, "send inx=%d SHA256=%s\n", jcr->JobFiles, digest);
246          bnet_fsend(dir, "%d %d %s *SHA256-%d*", jcr->JobFiles, STREAM_SHA256_DIGEST,
247                     digest, jcr->JobFiles);
248          Dmsg2(20, "bfiled>bdird: SHA256 len=%d: msg=%s\n", dir->msglen, dir->msg);
249          break;
250
251       case STREAM_SHA512_DIGEST:
252          bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_SHA512_SIZE, true);
253          Dmsg2(400, "send inx=%d SHA512=%s\n", jcr->JobFiles, digest);
254          bnet_fsend(dir, "%d %d %s *SHA512-%d*", jcr->JobFiles, STREAM_SHA512_DIGEST,
255                     digest, jcr->JobFiles);
256          Dmsg2(20, "bfiled>bdird: SHA512 len=%d: msg=%s\n", dir->msglen, dir->msg);
257          break;
258
259       default:
260          Pmsg2(0, "None of above!!! stream=%d data=%s\n", stream,sd->msg);
261          break;
262       } /* end switch */
263    } /* end while bnet_get */
264    set_jcr_job_status(jcr, JS_Terminated);
265    goto ok_out;
266
267 bail_out:
268    set_jcr_job_status(jcr, JS_ErrorTerminated);
269
270 ok_out:
271    if (jcr->compress_buf) {
272       free(jcr->compress_buf);
273       jcr->compress_buf = NULL;
274    }
275    free_pool_memory(fname);
276    free_pool_memory(lname);
277    Dmsg2(050, "End Verify-Vol. Files=%d Bytes=%" lld "\n", jcr->JobFiles,
278       jcr->JobBytes);
279 }