]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/verify_vol.c
c3bdd2463b0c5355dfb04ea2d13f0e938fcefdd0
[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          ap = sd->msg;
151          while (*ap++ != ' ')         /* skip record file index */
152             ;
153          while (*ap++ != ' ')         /* skip type */
154             ;
155          /* Save filename and position to attributes */
156          fp = fname;
157          while (*ap != 0) {
158             *fp++  = *ap++;           /* copy filename to fname */
159          }
160          *fp = *ap++;                 /* terminate filename & point to attribs */
161
162          Dmsg1(200, "Attr=%s\n", ap);
163          /* Skip to Link name */
164          if (type == FT_LNK || type == FT_LNKSAVED) {
165             lp = ap;
166             while (*lp++ != 0) {
167                ;
168             }
169             pm_strcat(lname, lp);        /* "save" link name */
170          } else {
171             *lname = 0;
172          }
173          jcr->lock();
174          jcr->JobFiles++;
175          jcr->num_files_examined++;
176          pm_strcpy(jcr->last_fname, fname); /* last file examined */
177          jcr->unlock();
178
179          /*
180           * Send file attributes to Director
181           *   File_index
182           *   Stream
183           *   Verify Options
184           *   Filename (full path)
185           *   Encoded attributes
186           *   Link name (if type==FT_LNK)
187           * For a directory, link is the same as fname, but with trailing
188           * slash. For a linked file, link is the link.
189           */
190          /* Send file attributes to Director */
191          Dmsg2(200, "send ATTR inx=%d fname=%s\n", jcr->JobFiles, fname);
192          if (type == FT_LNK || type == FT_LNKSAVED) {
193             stat = bnet_fsend(dir, "%d %d %s %s%c%s%c%s%c", jcr->JobFiles,
194                           STREAM_UNIX_ATTRIBUTES, "pinsug5", fname,
195                           0, ap, 0, lname, 0);
196          /* for a deleted record, we set fileindex=0 */
197          } else if (type == FT_DELETED)  {
198             stat = bnet_fsend(dir,"%d %d %s %s%c%s%c%c", 0,
199                           STREAM_UNIX_ATTRIBUTES, "pinsug5", fname,
200                           0, ap, 0, 0);
201          } else {
202             stat = bnet_fsend(dir,"%d %d %s %s%c%s%c%c", jcr->JobFiles,
203                           STREAM_UNIX_ATTRIBUTES, "pinsug5", fname,
204                           0, ap, 0, 0);
205          }
206          Dmsg2(200, "bfiled>bdird: attribs len=%d: msg=%s\n", dir->msglen, dir->msg);
207          if (!stat) {
208             Jmsg(jcr, M_FATAL, 0, _("Network error in send to Director: ERR=%s\n"), bnet_strerror(dir));
209             goto bail_out;
210          }
211          break;
212
213       case STREAM_MD5_DIGEST:
214          bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_MD5_SIZE, true);
215          Dmsg2(400, "send inx=%d MD5=%s\n", jcr->JobFiles, digest);
216          bnet_fsend(dir, "%d %d %s *MD5-%d*", jcr->JobFiles, STREAM_MD5_DIGEST, digest,
217                     jcr->JobFiles);
218          Dmsg2(20, "bfiled>bdird: MD5 len=%d: msg=%s\n", dir->msglen, dir->msg);
219          break;
220
221       case STREAM_SHA1_DIGEST:
222          bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_SHA1_SIZE, true);
223          Dmsg2(400, "send inx=%d SHA1=%s\n", jcr->JobFiles, digest);
224          bnet_fsend(dir, "%d %d %s *SHA1-%d*", jcr->JobFiles, STREAM_SHA1_DIGEST,
225                     digest, jcr->JobFiles);
226          Dmsg2(20, "bfiled>bdird: SHA1 len=%d: msg=%s\n", dir->msglen, dir->msg);
227          break;
228
229       case STREAM_SHA256_DIGEST:
230          bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_SHA256_SIZE, true);
231          Dmsg2(400, "send inx=%d SHA256=%s\n", jcr->JobFiles, digest);
232          bnet_fsend(dir, "%d %d %s *SHA256-%d*", jcr->JobFiles, STREAM_SHA256_DIGEST,
233                     digest, jcr->JobFiles);
234          Dmsg2(20, "bfiled>bdird: SHA256 len=%d: msg=%s\n", dir->msglen, dir->msg);
235          break;
236
237       case STREAM_SHA512_DIGEST:
238          bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_SHA512_SIZE, true);
239          Dmsg2(400, "send inx=%d SHA512=%s\n", jcr->JobFiles, digest);
240          bnet_fsend(dir, "%d %d %s *SHA512-%d*", jcr->JobFiles, STREAM_SHA512_DIGEST,
241                     digest, jcr->JobFiles);
242          Dmsg2(20, "bfiled>bdird: SHA512 len=%d: msg=%s\n", dir->msglen, dir->msg);
243          break;
244
245       /* Ignore everything else */
246       default:
247          break;
248
249       } /* end switch */
250    } /* end while bnet_get */
251    set_jcr_job_status(jcr, JS_Terminated);
252    goto ok_out;
253
254 bail_out:
255    set_jcr_job_status(jcr, JS_ErrorTerminated);
256
257 ok_out:
258    if (jcr->compress_buf) {
259       free(jcr->compress_buf);
260       jcr->compress_buf = NULL;
261    }
262    free_pool_memory(fname);
263    free_pool_memory(lname);
264    Dmsg2(050, "End Verify-Vol. Files=%d Bytes=%" lld "\n", jcr->JobFiles,
265       jcr->JobBytes);
266 }