2 * Bacula File Daemon verify-vol.c Verify files on a Volume
3 * versus attributes in Catalog
5 * Kern Sibbald, July MMII
11 Bacula® - The Network Backup Solution
13 Copyright (C) 2002-2006 Free Software Foundation Europe e.V.
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
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.
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
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.
41 /* Data received from Storage Daemon */
42 static char rec_header[] = "rechdr %ld %ld %ld %ld %ld";
44 /* Forward referenced functions */
48 * Verify attributes of the requested files on the Volume
51 void do_verify_volume(JCR *jcr)
54 POOLMEM *fname; /* original file name */
55 POOLMEM *lname; /* link name */
58 uint32_t VolSessionId, VolSessionTime, file_index;
59 uint32_t record_file_index;
60 char digest[BASE64_SIZE(CRYPTO_DIGEST_MAX_SIZE)];
63 sd = jcr->store_bsock;
65 Jmsg(jcr, M_FATAL, 0, _("Storage command not issued before Verify.\n"));
66 set_jcr_job_status(jcr, JS_FatalError);
70 set_jcr_job_status(jcr, JS_Running);
73 CLIENT *client = (CLIENT *)GetNextRes(R_CLIENT, NULL);
77 buf_size = client->max_network_buffer_size;
79 buf_size = 0; /* use default */
81 if (!bnet_set_buffer_size(sd, buf_size, BNET_SETBUF_WRITE)) {
82 set_jcr_job_status(jcr, JS_FatalError);
85 jcr->buf_size = sd->msglen;
87 fname = get_pool_memory(PM_FNAME);
88 lname = get_pool_memory(PM_FNAME);
91 * Get a record from the Storage daemon
93 while (bget_msg(sd) >= 0 && !job_canceled(jcr)) {
95 * First we expect a Stream Record Header
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);
102 Dmsg2(30, "Got hdr: FilInx=%d Stream=%d.\n", file_index, stream);
105 * Now we expect the Stream Data
107 if (bget_msg(sd) < 0) {
108 Jmsg1(jcr, M_FATAL, 0, _("Data record error. ERR=%s\n"), bnet_strerror(sd));
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);
115 Dmsg1(30, "Got stream data, len=%d\n", sd->msglen);
117 /* File Attributes stream */
119 case STREAM_UNIX_ATTRIBUTES:
120 case STREAM_UNIX_ATTRIBUTES_EX:
123 Dmsg0(400, "Stream=Unix Attributes.\n");
125 if ((int)sizeof_pool_memory(fname) < sd->msglen) {
126 fname = realloc_pool_memory(fname, sd->msglen + 1);
129 if ((int)sizeof_pool_memory(lname) < sd->msglen) {
130 lname = realloc_pool_memory(lname, sd->msglen + 1);
136 * An Attributes record consists of:
141 * Link name (if file linked i.e. FT_LNK)
142 * Extended Attributes (if Win32)
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");
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");
157 while (*ap++ != ' ') /* skip record file index */
159 while (*ap++ != ' ') /* skip type */
161 /* Save filename and position to attributes */
164 *fp++ = *ap++; /* copy filename to fname */
166 *fp = *ap++; /* terminate filename & point to attribs */
168 Dmsg1(200, "Attr=%s\n", ap);
169 /* Skip to Link name */
170 if (type == FT_LNK || type == FT_LNKSAVED) {
175 pm_strcat(lname, lp); /* "save" link name */
181 jcr->num_files_examined++;
182 pm_strcpy(jcr->last_fname, fname); /* last file examined */
186 * Send file attributes to Director
190 * Filename (full path)
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.
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,
202 /* for a deleted record, we set fileindex=0 */
203 } else if (type == FT_DELETED) {
204 stat = bnet_fsend(dir,"%d %d %s %s%c%s%c%c", 0,
205 STREAM_UNIX_ATTRIBUTES, "pinsug5", fname,
208 stat = bnet_fsend(dir,"%d %d %s %s%c%s%c%c", jcr->JobFiles,
209 STREAM_UNIX_ATTRIBUTES, "pinsug5", fname,
212 Dmsg2(200, "bfiled>bdird: attribs len=%d: msg=%s\n", dir->msglen, dir->msg);
214 Jmsg(jcr, M_FATAL, 0, _("Network error in send to Director: ERR=%s\n"), bnet_strerror(dir));
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,
224 Dmsg2(20, "bfiled>bdird: MD5 len=%d: msg=%s\n", dir->msglen, dir->msg);
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);
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);
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);
251 /* Ignore everything else */
256 } /* end while bnet_get */
257 set_jcr_job_status(jcr, JS_Terminated);
261 set_jcr_job_status(jcr, JS_ErrorTerminated);
264 if (jcr->compress_buf) {
265 free(jcr->compress_buf);
266 jcr->compress_buf = NULL;
268 free_pool_memory(fname);
269 free_pool_memory(lname);
270 Dmsg2(050, "End Verify-Vol. Files=%d Bytes=%" lld "\n", jcr->JobFiles,