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_EX:
120 Dmsg0(400, "Stream=Unix Attributes.\n");
122 if ((int)sizeof_pool_memory(fname) < sd->msglen) {
123 fname = realloc_pool_memory(fname, sd->msglen + 1);
126 if ((int)sizeof_pool_memory(lname) < sd->msglen) {
127 lname = realloc_pool_memory(lname, sd->msglen + 1);
133 * An Attributes record consists of:
138 * Link name (if file linked i.e. FT_LNK)
139 * Extended Attributes (if Win32)
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");
146 Dmsg2(30, "Got Attr: FilInx=%d type=%d\n", record_file_index, type);
148 while (*ap++ != ' ') /* skip record file index */
150 while (*ap++ != ' ') /* skip type */
152 /* Save filename and position to attributes */
155 *fp++ = *ap++; /* copy filename to fname */
157 *fp = *ap++; /* terminate filename & point to attribs */
159 Dmsg1(200, "Attr=%s\n", ap);
160 /* Skip to Link name */
161 if (type == FT_LNK || type == FT_LNKSAVED) {
166 pm_strcat(lname, lp); /* "save" link name */
172 jcr->num_files_examined++;
173 pm_strcpy(jcr->last_fname, fname); /* last file examined */
177 * Send file attributes to Director
181 * Filename (full path)
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.
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,
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,
199 stat = bnet_fsend(dir,"%d %d %s %s%c%s%c%c", jcr->JobFiles,
200 STREAM_UNIX_ATTRIBUTES, "pinsug5", fname,
203 Dmsg2(200, "bfiled>bdird: attribs len=%d: msg=%s\n", dir->msglen, dir->msg);
205 Jmsg(jcr, M_FATAL, 0, _("Network error in send to Director: ERR=%s\n"), bnet_strerror(dir));
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,
215 Dmsg2(20, "bfiled>bdird: MD5 len=%d: msg=%s\n", dir->msglen, dir->msg);
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);
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);
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);
242 /* Ignore everything else */
247 } /* end while bnet_get */
248 set_jcr_job_status(jcr, JS_Terminated);
252 set_jcr_job_status(jcr, JS_ErrorTerminated);
255 if (jcr->compress_buf) {
256 free(jcr->compress_buf);
257 jcr->compress_buf = NULL;
259 free_pool_memory(fname);
260 free_pool_memory(lname);
261 Dmsg2(050, "End Verify-Vol. Files=%d Bytes=%" lld "\n", jcr->JobFiles,