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 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.
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,
203 stat = bnet_fsend(dir,"%d %d %s %s%c%s%c%c", jcr->JobFiles,
204 STREAM_UNIX_ATTRIBUTES, "pinsug5", fname,
207 Dmsg2(200, "bfiled>bdird: attribs len=%d: msg=%s\n", dir->msglen, dir->msg);
209 Jmsg(jcr, M_FATAL, 0, _("Network error in send to Director: ERR=%s\n"), bnet_strerror(dir));
214 case STREAM_MD5_DIGEST:
215 bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_MD5_SIZE, true);
216 Dmsg2(400, "send inx=%d MD5=%s\n", jcr->JobFiles, digest);
217 bnet_fsend(dir, "%d %d %s *MD5-%d*", jcr->JobFiles, STREAM_MD5_DIGEST, digest,
219 Dmsg2(20, "bfiled>bdird: MD5 len=%d: msg=%s\n", dir->msglen, dir->msg);
222 case STREAM_SHA1_DIGEST:
223 bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_SHA1_SIZE, true);
224 Dmsg2(400, "send inx=%d SHA1=%s\n", jcr->JobFiles, digest);
225 bnet_fsend(dir, "%d %d %s *SHA1-%d*", jcr->JobFiles, STREAM_SHA1_DIGEST,
226 digest, jcr->JobFiles);
227 Dmsg2(20, "bfiled>bdird: SHA1 len=%d: msg=%s\n", dir->msglen, dir->msg);
230 case STREAM_SHA256_DIGEST:
231 bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_SHA256_SIZE, true);
232 Dmsg2(400, "send inx=%d SHA256=%s\n", jcr->JobFiles, digest);
233 bnet_fsend(dir, "%d %d %s *SHA256-%d*", jcr->JobFiles, STREAM_SHA256_DIGEST,
234 digest, jcr->JobFiles);
235 Dmsg2(20, "bfiled>bdird: SHA256 len=%d: msg=%s\n", dir->msglen, dir->msg);
238 case STREAM_SHA512_DIGEST:
239 bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_SHA512_SIZE, true);
240 Dmsg2(400, "send inx=%d SHA512=%s\n", jcr->JobFiles, digest);
241 bnet_fsend(dir, "%d %d %s *SHA512-%d*", jcr->JobFiles, STREAM_SHA512_DIGEST,
242 digest, jcr->JobFiles);
243 Dmsg2(20, "bfiled>bdird: SHA512 len=%d: msg=%s\n", dir->msglen, dir->msg);
246 /* Ignore everything else */
251 } /* end while bnet_get */
252 set_jcr_job_status(jcr, JS_Terminated);
256 set_jcr_job_status(jcr, JS_ErrorTerminated);
259 if (jcr->compress_buf) {
260 free(jcr->compress_buf);
261 jcr->compress_buf = NULL;
263 free_pool_memory(fname);
264 free_pool_memory(lname);
265 Dmsg2(050, "End Verify-Vol. Files=%d Bytes=%" lld "\n", jcr->JobFiles,