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