2 Bacula® - The Network Backup Solution
4 Copyright (C) 2002-2010 Free Software Foundation Europe e.V.
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
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.
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
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.
29 * Bacula File Daemon verify-vol.c Verify files on a Volume
30 * versus attributes in Catalog
32 * Kern Sibbald, July MMII
39 /* Data received from Storage Daemon */
40 static char rec_header[] = "rechdr %ld %ld %ld %ld %ld";
42 /* Forward referenced functions */
46 * Verify attributes of the requested files on the Volume
49 void do_verify_volume(JCR *jcr)
52 POOLMEM *fname; /* original file name */
53 POOLMEM *lname; /* link name */
56 uint32_t VolSessionId, VolSessionTime, file_index;
57 uint32_t record_file_index;
58 char digest[BASE64_SIZE(CRYPTO_DIGEST_MAX_SIZE)];
61 sd = jcr->store_bsock;
63 Jmsg(jcr, M_FATAL, 0, _("Storage command not issued before Verify.\n"));
64 set_jcr_job_status(jcr, JS_FatalError);
68 set_jcr_job_status(jcr, JS_Running);
71 CLIENT *client = (CLIENT *)GetNextRes(R_CLIENT, NULL);
75 buf_size = client->max_network_buffer_size;
77 buf_size = 0; /* use default */
79 if (!bnet_set_buffer_size(sd, buf_size, BNET_SETBUF_WRITE)) {
80 set_jcr_job_status(jcr, JS_FatalError);
83 jcr->buf_size = sd->msglen;
85 fname = get_pool_memory(PM_FNAME);
86 lname = get_pool_memory(PM_FNAME);
89 * Get a record from the Storage daemon
91 while (bget_msg(sd) >= 0 && !job_canceled(jcr)) {
93 * First we expect a Stream Record Header
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);
100 Dmsg2(30, "Got hdr: FilInx=%d Stream=%d.\n", file_index, stream);
103 * Now we expect the Stream Data
105 if (bget_msg(sd) < 0) {
106 Jmsg1(jcr, M_FATAL, 0, _("Data record error. ERR=%s\n"), bnet_strerror(sd));
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);
113 Dmsg1(30, "Got stream data, len=%d\n", sd->msglen);
115 /* File Attributes stream */
117 case STREAM_UNIX_ATTRIBUTES:
118 case STREAM_UNIX_ATTRIBUTES_EX:
121 Dmsg0(400, "Stream=Unix Attributes.\n");
123 if ((int)sizeof_pool_memory(fname) < sd->msglen) {
124 fname = realloc_pool_memory(fname, sd->msglen + 1);
127 if ((int)sizeof_pool_memory(lname) < sd->msglen) {
128 lname = realloc_pool_memory(lname, sd->msglen + 1);
134 * An Attributes record consists of:
139 * Link name (if file linked i.e. FT_LNK)
140 * Extended Attributes (if Win32)
142 if (sscanf(sd->msg, "%d %d", &record_file_index, &type) != 2) {
143 Jmsg(jcr, M_FATAL, 0, _("Error scanning record header: %s\n"), sd->msg);
144 Dmsg0(0, "\nError scanning header\n");
147 Dmsg2(30, "Got Attr: FilInx=%d type=%d\n", record_file_index, type);
149 while (*ap++ != ' ') /* skip record file index */
151 while (*ap++ != ' ') /* skip type */
153 /* Save filename and position to attributes */
156 *fp++ = *ap++; /* copy filename to fname */
158 *fp = *ap++; /* terminate filename & point to attribs */
160 Dmsg1(200, "Attr=%s\n", ap);
161 /* Skip to Link name */
162 if (type == FT_LNK || type == FT_LNKSAVED) {
167 pm_strcat(lname, lp); /* "save" link name */
173 jcr->num_files_examined++;
174 pm_strcpy(jcr->last_fname, fname); /* last file examined */
178 * Send file attributes to Director
182 * Filename (full path)
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.
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,
194 /* for a deleted record, we set fileindex=0 */
195 } else if (type == FT_DELETED) {
196 stat = bnet_fsend(dir,"%d %d %s %s%c%s%c%c", 0,
197 STREAM_UNIX_ATTRIBUTES, "pinsug5", fname,
200 stat = bnet_fsend(dir,"%d %d %s %s%c%s%c%c", jcr->JobFiles,
201 STREAM_UNIX_ATTRIBUTES, "pinsug5", fname,
204 Dmsg2(200, "bfiled>bdird: attribs len=%d: msg=%s\n", dir->msglen, dir->msg);
206 Jmsg(jcr, M_FATAL, 0, _("Network error in send to Director: ERR=%s\n"), bnet_strerror(dir));
211 case STREAM_MD5_DIGEST:
212 bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_MD5_SIZE, true);
213 Dmsg2(400, "send inx=%d MD5=%s\n", jcr->JobFiles, digest);
214 bnet_fsend(dir, "%d %d %s *MD5-%d*", jcr->JobFiles, STREAM_MD5_DIGEST, digest,
216 Dmsg2(20, "bfiled>bdird: MD5 len=%d: msg=%s\n", dir->msglen, dir->msg);
219 case STREAM_SHA1_DIGEST:
220 bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_SHA1_SIZE, true);
221 Dmsg2(400, "send inx=%d SHA1=%s\n", jcr->JobFiles, digest);
222 bnet_fsend(dir, "%d %d %s *SHA1-%d*", jcr->JobFiles, STREAM_SHA1_DIGEST,
223 digest, jcr->JobFiles);
224 Dmsg2(20, "bfiled>bdird: SHA1 len=%d: msg=%s\n", dir->msglen, dir->msg);
227 case STREAM_SHA256_DIGEST:
228 bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_SHA256_SIZE, true);
229 Dmsg2(400, "send inx=%d SHA256=%s\n", jcr->JobFiles, digest);
230 bnet_fsend(dir, "%d %d %s *SHA256-%d*", jcr->JobFiles, STREAM_SHA256_DIGEST,
231 digest, jcr->JobFiles);
232 Dmsg2(20, "bfiled>bdird: SHA256 len=%d: msg=%s\n", dir->msglen, dir->msg);
235 case STREAM_SHA512_DIGEST:
236 bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_SHA512_SIZE, true);
237 Dmsg2(400, "send inx=%d SHA512=%s\n", jcr->JobFiles, digest);
238 bnet_fsend(dir, "%d %d %s *SHA512-%d*", jcr->JobFiles, STREAM_SHA512_DIGEST,
239 digest, jcr->JobFiles);
240 Dmsg2(20, "bfiled>bdird: SHA512 len=%d: msg=%s\n", dir->msglen, dir->msg);
243 /* Ignore everything else */
248 } /* end while bnet_get */
249 set_jcr_job_status(jcr, JS_Terminated);
253 set_jcr_job_status(jcr, JS_ErrorTerminated);
256 if (jcr->compress_buf) {
257 free(jcr->compress_buf);
258 jcr->compress_buf = NULL;
260 free_pool_memory(fname);
261 free_pool_memory(lname);
262 Dmsg2(050, "End Verify-Vol. Files=%d Bytes=%" lld "\n", jcr->JobFiles,