2 * Bacula File Daemon restore.c Restorefiles.
4 * Kern Sibbald, November MM
10 Copyright (C) 2000-2005 Kern Sibbald
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License
14 version 2 as amended with additional clauses defined in the
15 file LICENSE in the main source directory.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 the file LICENSE for additional details.
31 /* Data received from Storage Daemon */
32 static char rec_header[] = "rechdr %ld %ld %ld %ld %ld";
34 /* Forward referenced functions */
36 static const char *zlib_strerror(int stat);
39 int verify_signature(JCR *jcr, SIGNATURE *sig);
40 int32_t extract_data(JCR *jcr, BFILE *bfd, POOLMEM *buf, int32_t buflen,
41 uint64_t *addr, int flags);
43 #define RETRY 10 /* retry wait time */
46 * Close a bfd check that we are at the expected file offset.
47 * Makes some code in set_attributes().
49 int bclose_chksize(JCR *jcr, BFILE *bfd, off_t osize)
51 char ec1[50], ec2[50];
54 fsize = blseek(bfd, 0, SEEK_CUR);
55 bclose(bfd); /* first close file */
56 if (fsize > 0 && fsize != osize) {
57 Jmsg3(jcr, M_ERROR, 0, _("Size of data or stream of %s not correct. Original %s, restored %s.\n"),
58 jcr->last_fname, edit_uint64(osize, ec1),
59 edit_uint64(fsize, ec2));
66 * Restore the requested files.
69 void do_restore(JCR *jcr)
74 uint32_t VolSessionId, VolSessionTime;
77 char ec1[50]; /* Buffer printing huge values */
79 BFILE bfd; /* File content */
80 uint64_t fileAddr = 0; /* file write address */
81 uint32_t size; /* Size of file */
82 BFILE altbfd; /* Alternative data stream */
83 uint64_t alt_addr = 0; /* Write address for alternative stream */
84 intmax_t alt_size = 0; /* Size of alternate stream */
85 SIGNATURE *sig = NULL; /* Cryptographic signature (if any) for file */
86 int flags; /* Options for extract_data() */
90 /* The following variables keep track of "known unknowns" */
91 int non_support_data = 0;
92 int non_support_attr = 0;
93 int non_support_rsrc = 0;
94 int non_support_finfo = 0;
95 int non_support_acl = 0;
96 int non_support_progname = 0;
98 /* Finally, set up for special configurations */
100 intmax_t rsrc_len = 0; /* Original length of resource fork */
101 struct attrlist attrList;
103 memset(&attrList, 0, sizeof(attrList));
104 attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
105 attrList.commonattr = ATTR_CMN_FNDRINFO;
108 sd = jcr->store_bsock;
109 set_jcr_job_status(jcr, JS_Running);
112 CLIENT *client = (CLIENT *)GetNextRes(R_CLIENT, NULL);
116 buf_size = client->max_network_buffer_size;
118 buf_size = 0; /* use default */
120 if (!bnet_set_buffer_size(sd, buf_size, BNET_SETBUF_WRITE)) {
121 set_jcr_job_status(jcr, JS_ErrorTerminated);
124 jcr->buf_size = sd->msglen;
127 uint32_t compress_buf_size = jcr->buf_size + 12 + ((jcr->buf_size+999) / 1000) + 100;
128 jcr->compress_buf = (char *)bmalloc(compress_buf_size);
129 jcr->compress_buf_size = compress_buf_size;
133 * Get a record from the Storage daemon. We are guaranteed to
134 * receive records in the following order:
135 * 1. Stream record header
137 * a. Attributes (Unix or Win32)
138 * or b. File data for the file
139 * or c. Alternate data stream (e.g. Resource Fork)
142 * or f. Possibly a cryptographic signature
143 * or g. Possibly MD5 or SHA1 record
146 * NOTE: We keep track of two bacula file descriptors:
147 * 1. bfd for file data.
148 * This fd is opened for non empty files when an attribute stream is
149 * encountered and closed when we find the next attribute stream.
150 * 2. alt_bfd for alternate data streams
151 * This fd is opened every time we encounter a new alternate data
152 * stream for the current file. When we find any other stream, we
154 * The expected size of the stream, alt_len, should be set when
160 jcr->acl_text = get_pool_memory(PM_MESSAGE);
162 while (bget_msg(sd) >= 0 && !job_canceled(jcr)) {
163 /* Remember previous stream type */
164 prev_stream = stream;
166 /* First we expect a Stream Record Header */
167 if (sscanf(sd->msg, rec_header, &VolSessionId, &VolSessionTime, &file_index,
168 &stream, &size) != 5) {
169 Jmsg1(jcr, M_FATAL, 0, _("Record header scan error: %s\n"), sd->msg);
172 Dmsg2(30, "Got hdr: FilInx=%d Stream=%d.\n", file_index, stream);
174 /* * Now we expect the Stream Data */
175 if (bget_msg(sd) < 0) {
176 Jmsg1(jcr, M_FATAL, 0, _("Data record error. ERR=%s\n"), bnet_strerror(sd));
179 if (size != (uint32_t)sd->msglen) {
180 Jmsg2(jcr, M_FATAL, 0, _("Actual data size %d not same as header %d\n"), sd->msglen, size);
183 Dmsg1(30, "Got stream data, len=%d\n", sd->msglen);
185 /* If we change streams, close and reset alternate data streams */
186 if (prev_stream != stream) {
187 if (is_bopen(&altbfd)) {
188 bclose_chksize(jcr, &altbfd, alt_size);
190 alt_size = -1; /* Use an impossible value and set a proper one below */
194 /* File Attributes stream */
196 case STREAM_UNIX_ATTRIBUTES:
197 case STREAM_UNIX_ATTRIBUTES_EX:
198 Dmsg1(30, "Stream=Unix Attributes. extract=%d\n", extract);
200 * If extracting, it was from previous stream, so
201 * close the output file and validate the signature.
204 if (size > 0 && !is_bopen(&bfd)) {
205 Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should be open\n"));
207 set_attributes(jcr, attr, &bfd);
210 /* Verify the cryptographic signature, if any */
213 if (!verify_signature(jcr, sig)) {
214 // TODO landonf: Better signature failure handling.
215 // The failure is reported to the director in verify_signature() ...
216 Dmsg1(100, "Bad signature on %s\n", jcr->last_fname);
218 Dmsg1(100, "Signature good on %s\n", jcr->last_fname);
220 crypto_sign_free(sig);
223 Jmsg1(jcr, M_ERROR, 0, _("Missing cryptographic signature for %s\n"), jcr->last_fname);
226 Dmsg0(30, "Stop extracting.\n");
227 } else if (is_bopen(&bfd)) {
228 Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should not be open\n"));
233 * Unpack and do sanity check fo attributes.
235 if (!unpack_attributes_record(jcr, stream, sd->msg, attr)) {
238 if (file_index != attr->file_index) {
239 Jmsg(jcr, M_FATAL, 0, _("Record header file index %ld not equal record index %ld\n"),
240 file_index, attr->file_index);
241 Dmsg0(100, "File index error\n");
245 Dmsg3(200, "File %s\nattrib=%s\nattribsEx=%s\n", attr->fname,
246 attr->attr, attr->attrEx);
248 attr->data_stream = decode_stat(attr->attr, &attr->statp, &attr->LinkFI);
250 if (!is_restore_stream_supported(attr->data_stream)) {
251 if (!non_support_data++) {
252 Jmsg(jcr, M_ERROR, 0, _("%s stream not supported on this Client.\n"),
253 stream_to_ascii(attr->data_stream));
258 build_attr_output_fnames(jcr, attr);
261 * Now determine if we are extracting or not.
263 jcr->num_files_examined++;
264 Dmsg1(30, "Outfile=%s\n", attr->ofname);
266 stat = create_file(jcr, attr, &bfd, jcr->replace);
271 case CF_EXTRACT: /* File created and we expect file data */
274 case CF_CREATED: /* File created, but there is no content */
276 pm_strcpy(jcr->last_fname, attr->ofname);
280 print_ls_output(jcr, attr);
281 #ifdef HAVE_DARWIN_OS
282 /* Only restore the resource fork for regular files */
283 from_base64(&rsrc_len, attr->attrEx);
284 if (attr->type == FT_REG && rsrc_len > 0) {
289 /* set attributes now because file will not be extracted */
290 set_attributes(jcr, attr, &bfd);
297 case STREAM_FILE_DATA:
298 case STREAM_SPARSE_DATA:
299 case STREAM_WIN32_DATA:
300 case STREAM_GZIP_DATA:
301 case STREAM_SPARSE_GZIP_DATA:
302 case STREAM_WIN32_GZIP_DATA:
303 /* Force an expected, consistent stream type here */
304 if (extract && (prev_stream == stream || prev_stream == STREAM_UNIX_ATTRIBUTES
305 || prev_stream == STREAM_UNIX_ATTRIBUTES_EX)) {
307 if (stream == STREAM_SPARSE_DATA || stream == STREAM_SPARSE_GZIP_DATA) {
310 if (stream == STREAM_GZIP_DATA || stream == STREAM_SPARSE_GZIP_DATA
311 || stream == STREAM_WIN32_GZIP_DATA) {
315 if (is_win32_stream(stream) && !have_win32_api()) {
316 set_portable_backup(&bfd);
317 flags |= FO_WIN32DECOMP; /* "decompose" BackupWrite data */
320 if (extract_data(jcr, &bfd, sd->msg, sd->msglen, &fileAddr, flags) < 0) {
328 /* Resource fork stream - only recorded after a file to be restored */
329 /* Silently ignore if we cannot write - we already reported that */
330 case STREAM_MACOS_FORK_DATA:
331 #ifdef HAVE_DARWIN_OS
333 if (prev_stream != stream) {
334 if (bopen_rsrc(&altbfd, jcr->last_fname, O_WRONLY | O_TRUNC | O_BINARY, 0) < 0) {
335 Jmsg(jcr, M_ERROR, 0, _(" Cannot open resource fork for %s.\n"), jcr->last_fname);
340 Dmsg0(30, "Restoring resource fork\n");
343 if (extract_data(jcr, &altbfd, sd->msg, sd->msglen, &alt_addr, flags) < 0) {
354 case STREAM_HFSPLUS_ATTRIBUTES:
355 #ifdef HAVE_DARWIN_OS
356 Dmsg0(30, "Restoring Finder Info\n");
357 if (sd->msglen != 32) {
358 Jmsg(jcr, M_ERROR, 0, _(" Invalid length of Finder Info (got %d, not 32)\n"), sd->msglen);
361 if (setattrlist(jcr->last_fname, &attrList, sd->msg, sd->msglen, 0) != 0) {
362 Jmsg(jcr, M_ERROR, 0, _(" Could not set Finder Info on %s\n"), jcr->last_fname);
369 case STREAM_UNIX_ATTRIBUTES_ACCESS_ACL:
371 pm_strcpy(jcr->acl_text, sd->msg);
372 Dmsg2(400, "Restoring ACL type 0x%2x <%s>\n", BACL_TYPE_ACCESS, jcr->acl_text);
373 if (bacl_set(jcr, BACL_TYPE_ACCESS) != 0) {
374 Jmsg1(jcr, M_WARNING, 0, _("Can't restore ACL of %s\n"), jcr->last_fname);
381 case STREAM_UNIX_ATTRIBUTES_DEFAULT_ACL:
383 pm_strcpy(jcr->acl_text, sd->msg);
384 Dmsg2(400, "Restoring ACL type 0x%2x <%s>\n", BACL_TYPE_DEFAULT, jcr->acl_text);
385 if (bacl_set(jcr, BACL_TYPE_DEFAULT) != 0) {
386 Jmsg1(jcr, M_WARNING, 0, _("Can't restore default ACL of %s\n"), jcr->last_fname);
393 case STREAM_SIGNED_DIGEST:
394 /* Save signature. */
395 sig = crypto_sign_decode(sd->msg, (size_t) sd->msglen);
398 case STREAM_MD5_DIGEST:
399 case STREAM_SHA1_DIGEST:
400 case STREAM_SHA256_DIGEST:
401 case STREAM_SHA512_DIGEST:
404 case STREAM_PROGRAM_NAMES:
405 case STREAM_PROGRAM_DATA:
406 if (!non_support_progname) {
407 Pmsg0(000, "Got Program Name or Data Stream. Ignored.\n");
408 non_support_progname++;
413 /* If extracting, wierd stream (not 1 or 2), close output file anyway */
415 Dmsg1(30, "Found wierd stream %d\n", stream);
416 if (size > 0 && !is_bopen(&bfd)) {
417 Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should be open\n"));
419 set_attributes(jcr, attr, &bfd);
421 } else if (is_bopen(&bfd)) {
422 Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should not be open\n"));
425 Jmsg(jcr, M_ERROR, 0, _("Unknown stream=%d ignored. This shouldn't happen!\n"), stream);
426 Dmsg2(0, "None of above!!! stream=%d data=%s\n", stream,sd->msg);
428 } /* end switch(stream) */
430 } /* end while get_msg() */
432 /* If output file is still open, it was the last one in the
433 * archive since we just hit an end of file, so close the file.
435 if (is_bopen(&altbfd)) {
436 bclose_chksize(jcr, &altbfd, alt_size);
439 set_attributes(jcr, attr, &bfd);
441 if (is_bopen(&bfd)) {
444 set_jcr_job_status(jcr, JS_Terminated);
448 set_jcr_job_status(jcr, JS_ErrorTerminated);
450 if (jcr->compress_buf) {
451 free(jcr->compress_buf);
452 jcr->compress_buf = NULL;
453 jcr->compress_buf_size = 0;
458 free_pool_memory(jcr->acl_text);
459 Dmsg2(10, "End Do Restore. Files=%d Bytes=%s\n", jcr->JobFiles,
460 edit_uint64(jcr->JobBytes, ec1));
461 if (non_support_data > 1 || non_support_attr > 1) {
462 Jmsg(jcr, M_ERROR, 0, _("%d non-supported data streams and %d non-supported attrib streams ignored.\n"),
463 non_support_data, non_support_attr);
465 if (non_support_rsrc) {
466 Jmsg(jcr, M_INFO, 0, _("%d non-supported resource fork streams ignored.\n"), non_support_rsrc);
468 if (non_support_finfo) {
469 Jmsg(jcr, M_INFO, 0, _("%d non-supported Finder Info streams ignored.\n"), non_support_rsrc);
471 if (non_support_acl) {
472 Jmsg(jcr, M_INFO, 0, _("%d non-supported acl streams ignored.\n"), non_support_acl);
479 * Convert ZLIB error code into an ASCII message
481 static const char *zlib_strerror(int stat)
488 return _("Zlib errno");
490 return _("Zlib stream error");
492 return _("Zlib data error");
494 return _("Zlib memory error");
496 return _("Zlib buffer error");
497 case Z_VERSION_ERROR:
498 return _("Zlib version error");
505 static int do_file_digest(FF_PKT *ff_pkt, void *pkt, bool top_level) {
506 JCR *jcr = (JCR *) pkt;
507 return (digest_file(jcr, ff_pkt, jcr->digest));
511 * Verify the signature for the last restored file
512 * Return value is either true (signature correct)
513 * or false (signature could not be verified).
515 int verify_signature(JCR *jcr, SIGNATURE *sig)
517 X509_KEYPAIR *keypair;
518 DIGEST *digest = NULL;
522 /* Iterate through the trusted signers */
523 foreach_alist(keypair, jcr->pki_signers) {
524 err = crypto_sign_get_digest(sig, jcr->pki_keypair, &digest);
527 case CRYPTO_ERROR_NONE:
528 /* Signature found, digest allocated */
529 jcr->digest = digest;
531 /* Checksum the entire file */
532 if (find_one_file(jcr, jcr->ff, do_file_digest, jcr, jcr->last_fname, (dev_t)-1, 1) != 0) {
533 Jmsg(jcr, M_ERROR, 0, _("Signature validation failed for %s: \n"), jcr->last_fname);
537 /* Verify the signature */
538 if ((err = crypto_sign_verify(sig, keypair, digest)) != CRYPTO_ERROR_NONE) {
539 Jmsg2(jcr, M_ERROR, 0, _("Signature validation failed for %s: %s\n"), jcr->last_fname, crypto_strerror(err));
540 crypto_digest_free(digest);
544 /* Valid signature */
545 crypto_digest_free(digest);
548 case CRYPTO_ERROR_NOSIGNER:
549 /* Signature not found, try again */
552 /* Something strange happened (that shouldn't happen!)... */
553 Jmsg2(jcr, M_ERROR, 0, _("Signature validation failed for %s: %s\n"), jcr->last_fname, crypto_strerror(err));
555 crypto_digest_free(digest);
566 * In the context of jcr, write data to bfd.
567 * We write buflen bytes in buf at addr. addr is updated in place.
568 * The flags specify whether to use sparse files or compression.
569 * Return value is the number of bytes written, or -1 on errors.
571 int32_t extract_data(JCR *jcr, BFILE *bfd, POOLMEM *buf, int32_t buflen,
572 uint64_t *addr, int flags)
575 char *wbuf; /* write buffer */
576 uint32_t wsize; /* write size */
577 uint32_t rsize; /* read size */
578 char ec1[50]; /* Buffer printing huge values */
580 if (flags & FO_SPARSE) {
584 wbuf = buf + SPARSE_FADDR_SIZE;
585 rsize = buflen - SPARSE_FADDR_SIZE;
586 ser_begin(buf, SPARSE_FADDR_SIZE);
588 if (*addr != faddr) {
590 if (blseek(bfd, (off_t)*addr, SEEK_SET) < 0) {
592 Jmsg3(jcr, M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"),
593 edit_uint64(*addr, ec1), jcr->last_fname,
594 be.strerror(bfd->berrno));
604 if (flags & FO_GZIP) {
608 * NOTE! We only use uLong and Byte because they are
609 * needed by the zlib routines, they should not otherwise
612 compress_len = jcr->compress_buf_size;
613 Dmsg2(100, "Comp_len=%d msglen=%d\n", compress_len, wsize);
614 if ((stat=uncompress((Byte *)jcr->compress_buf, &compress_len,
615 (const Byte *)wbuf, (uLong)rsize)) != Z_OK) {
616 Jmsg(jcr, M_ERROR, 0, _("Uncompression error on file %s. ERR=%s\n"),
617 jcr->last_fname, zlib_strerror(stat));
620 wbuf = jcr->compress_buf;
621 wsize = compress_len;
622 Dmsg2(100, "Write uncompressed %d bytes, total before write=%s\n", compress_len, edit_uint64(jcr->JobBytes, ec1));
624 Jmsg(jcr, M_ERROR, 0, _("GZIP data stream found, but GZIP not configured!\n"));
628 Dmsg2(30, "Write %u bytes, total before write=%s\n", wsize, edit_uint64(jcr->JobBytes, ec1));
631 if (flags & FO_WIN32DECOMP) {
632 if (!processWin32BackupAPIBlock(bfd, wbuf, wsize)) {
634 Jmsg2(jcr, M_ERROR, 0, _("Write error in Win32 Block Decomposition on %s: %s\n"),
635 jcr->last_fname, be.strerror(bfd->berrno));
638 } else if (bwrite(bfd, wbuf, wsize) != (ssize_t)wsize) {
640 Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"),
641 jcr->last_fname, be.strerror(bfd->berrno));
645 jcr->JobBytes += wsize;
646 jcr->ReadBytes += rsize;