2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2015 Kern Sibbald
5 Copyright (C) 2002-2014 Free Software Foundation Europe e.V.
7 The original author of Bacula is Kern Sibbald, with contributions
8 from many others, a complete list can be found in the file AUTHORS.
10 You may use this file and others of this release according to the
11 license defined in the LICENSE file, which includes the Affero General
12 Public License, v3.0 ("AGPLv3") and some additional permissions and
13 terms pursuant to its AGPLv3 Section 7.
15 This notice must be preserved when any source code is
16 conveyed and/or propagated.
18 Bacula(R) is a registered trademark of Kern Sibbald.
21 * Bacula File Daemon verify-vol.c Verify files on a Volume
22 * versus attributes in Catalog
24 * Kern Sibbald, July MMII
31 /* Data received from Storage Daemon */
32 static char rec_header[] = "rechdr %ld %ld %ld %ld %ld";
34 /* Forward referenced functions */
38 * Verify attributes of the requested files on the Volume
41 void do_verify_volume(JCR *jcr)
44 POOLMEM *fname; /* original file name */
45 POOLMEM *lname; /* link name */
46 int32_t stream, full_stream;
48 uint32_t VolSessionId, VolSessionTime, file_index;
49 uint32_t record_file_index;
50 char digest[BASE64_SIZE(CRYPTO_DIGEST_MAX_SIZE)];
53 sd = jcr->store_bsock;
55 Jmsg(jcr, M_FATAL, 0, _("Storage command not issued before Verify.\n"));
56 jcr->setJobStatus(JS_FatalError);
60 jcr->setJobStatus(JS_Running);
63 CLIENT *client = (CLIENT *)GetNextRes(R_CLIENT, NULL);
67 buf_size = client->max_network_buffer_size;
69 buf_size = 0; /* use default */
71 if (!sd->set_buffer_size(buf_size, BNET_SETBUF_WRITE)) {
72 jcr->setJobStatus(JS_FatalError);
75 jcr->buf_size = sd->msglen;
77 fname = get_pool_memory(PM_FNAME);
78 lname = get_pool_memory(PM_FNAME);
80 GetMsg *fdmsg = New(GetMsg(jcr, sd, rec_header, GETMSG_MAX_MSG_SIZE));
81 fdmsg->start_read_sock();
82 bmessage *bmsg = New(bmessage(GETMSG_MAX_MSG_SIZE));
85 * Get a record from the Storage daemon
87 while (fdmsg->bget_msg(&bmsg) >= 0 && !job_canceled(jcr)) {
89 * First we expect a Stream Record Header
91 if (sscanf(bmsg->rbuf, rec_header, &VolSessionId, &VolSessionTime, &file_index,
92 &full_stream, &size) != 5) {
93 Jmsg1(jcr, M_FATAL, 0, _("Record header scan error: %s\n"), bmsg->rbuf);
96 stream = full_stream & STREAMMASK_TYPE;
97 Dmsg4(30, "Got hdr: FilInx=%d FullStream=%d Stream=%d size=%d.\n", file_index, full_stream, stream, size);
100 * Now we expect the Stream Data
102 if (fdmsg->bget_msg(&bmsg) < 0) {
103 Jmsg1(jcr, M_FATAL, 0, _("Data record error. ERR=%s\n"), sd->bstrerror());
106 if (size != ((uint32_t)bmsg->origlen)) {
107 Jmsg2(jcr, M_FATAL, 0, _("Actual data size %d not same as header %d\n"), bmsg->origlen, size);
110 Dmsg2(30, "Got stream data %s, len=%d\n", stream_to_ascii(stream), bmsg->rbuflen);
112 /* File Attributes stream */
114 case STREAM_UNIX_ATTRIBUTES:
115 case STREAM_UNIX_ATTRIBUTES_EX:
118 Dmsg0(400, "Stream=Unix Attributes.\n");
120 if ((int)sizeof_pool_memory(fname) < bmsg->rbuflen) {
121 fname = realloc_pool_memory(fname, bmsg->rbuflen + 1);
124 if ((int)sizeof_pool_memory(lname) < bmsg->rbuflen) {
125 lname = realloc_pool_memory(lname, bmsg->rbuflen + 1);
131 * An Attributes record consists of:
136 * Link name (if file linked i.e. FT_LNK)
137 * Extended Attributes (if Win32)
139 if (sscanf(bmsg->rbuf, "%d %d", &record_file_index, &type) != 2) {
140 Jmsg(jcr, M_FATAL, 0, _("Error scanning record header: %s\n"), bmsg->rbuf);
141 Dmsg0(0, "\nError scanning header\n");
144 Dmsg2(30, "Got Attr: FilInx=%d type=%d\n", record_file_index, type);
146 while (*ap++ != ' ') /* skip record file index */
148 while (*ap++ != ' ') /* skip type */
150 /* Save filename and position to attributes */
153 *fp++ = *ap++; /* copy filename to fname */
155 *fp = *ap++; /* terminate filename & point to attribs */
157 Dmsg2(100, "File=%s Attr=%s\n", fname, ap);
158 /* Skip to Link name */
159 if (type == FT_LNK || type == FT_LNKSAVED) {
164 pm_strcat(lname, lp); /* "save" link name */
170 jcr->num_files_examined++;
171 pm_strcpy(jcr->last_fname, fname); /* last file examined */
175 * Send file attributes to Director
179 * Filename (full path)
181 * Link name (if type==FT_LNK)
182 * For a directory, link is the same as fname, but with trailing
183 * slash. For a linked file, link is the link.
185 /* Send file attributes to Director */
186 Dmsg2(200, "send ATTR inx=%d fname=%s\n", jcr->JobFiles, fname);
187 if (type == FT_LNK || type == FT_LNKSAVED) {
188 stat = dir->fsend("%d %d %s %s%c%s%c%s%c", jcr->JobFiles,
189 STREAM_UNIX_ATTRIBUTES, "pinsug5", fname,
191 /* for a deleted record, we set fileindex=0 */
192 } else if (type == FT_DELETED) {
193 stat = dir->fsend("%d %d %s %s%c%s%c%c", 0,
194 STREAM_UNIX_ATTRIBUTES, "pinsug5", fname,
197 stat = dir->fsend("%d %d %s %s%c%s%c%c", jcr->JobFiles,
198 STREAM_UNIX_ATTRIBUTES, "pinsug5", fname,
201 Dmsg2(200, "bfiled>bdird: attribs len=%d: msg=%s\n", dir->msglen, dir->msg);
203 Jmsg(jcr, M_FATAL, 0, _("Network error in send to Director: ERR=%s\n"), dir->bstrerror());
208 case STREAM_MD5_DIGEST:
209 bin_to_base64(digest, sizeof(digest), (char *)bmsg->rbuf, CRYPTO_DIGEST_MD5_SIZE, true);
210 Dmsg2(400, "send inx=%d MD5=%s\n", jcr->JobFiles, digest);
211 dir->fsend("%d %d %s *MD5-%d*", jcr->JobFiles, STREAM_MD5_DIGEST, digest,
213 Dmsg2(20, "bfiled>bdird: MD5 len=%d: msg=%s\n", dir->msglen, dir->msg);
216 case STREAM_SHA1_DIGEST:
217 bin_to_base64(digest, sizeof(digest), (char *)bmsg->rbuf, CRYPTO_DIGEST_SHA1_SIZE, true);
218 Dmsg2(400, "send inx=%d SHA1=%s\n", jcr->JobFiles, digest);
219 dir->fsend("%d %d %s *SHA1-%d*", jcr->JobFiles, STREAM_SHA1_DIGEST,
220 digest, jcr->JobFiles);
221 Dmsg2(20, "bfiled>bdird: SHA1 len=%d: msg=%s\n", dir->msglen, dir->msg);
224 case STREAM_SHA256_DIGEST:
225 bin_to_base64(digest, sizeof(digest), (char *)bmsg->rbuf, CRYPTO_DIGEST_SHA256_SIZE, true);
226 Dmsg2(400, "send inx=%d SHA256=%s\n", jcr->JobFiles, digest);
227 dir->fsend("%d %d %s *SHA256-%d*", jcr->JobFiles, STREAM_SHA256_DIGEST,
228 digest, jcr->JobFiles);
229 Dmsg2(20, "bfiled>bdird: SHA256 len=%d: msg=%s\n", dir->msglen, dir->msg);
232 case STREAM_SHA512_DIGEST:
233 bin_to_base64(digest, sizeof(digest), (char *)bmsg->rbuf, CRYPTO_DIGEST_SHA512_SIZE, true);
234 Dmsg2(400, "send inx=%d SHA512=%s\n", jcr->JobFiles, digest);
235 dir->fsend("%d %d %s *SHA512-%d*", jcr->JobFiles, STREAM_SHA512_DIGEST,
236 digest, jcr->JobFiles);
237 Dmsg2(20, "bfiled>bdird: SHA512 len=%d: msg=%s\n", dir->msglen, dir->msg);
241 * Restore stream object is counted, but not restored here
243 case STREAM_RESTORE_OBJECT:
246 jcr->num_files_examined++;
250 /* Ignore everything else */
255 } /* end while bnet_get */
256 jcr->setJobStatus(JS_Terminated);
260 jcr->setJobStatus(JS_ErrorTerminated);
263 Dmsg0(215, "wait BufferedMsg\n");
264 fdmsg->wait_read_sock();
268 if (jcr->compress_buf) {
269 free(jcr->compress_buf);
270 jcr->compress_buf = NULL;
272 free_pool_memory(fname);
273 free_pool_memory(lname);
274 Dmsg2(050, "End Verify-Vol. Files=%d Bytes=%" lld "\n", jcr->JobFiles,