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 Qmsg3(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 * b. Possibly stream encryption session data (e.g., symmetric session key)
139 * or c. File data for the file
140 * or d. Alternate data stream (e.g. Resource Fork)
143 * or g. Possibly a cryptographic signature
144 * or h. Possibly MD5 or SHA1 record
147 * NOTE: We keep track of two bacula file descriptors:
148 * 1. bfd for file data.
149 * This fd is opened for non empty files when an attribute stream is
150 * encountered and closed when we find the next attribute stream.
151 * 2. alt_bfd for alternate data streams
152 * This fd is opened every time we encounter a new alternate data
153 * stream for the current file. When we find any other stream, we
155 * The expected size of the stream, alt_len, should be set when
161 jcr->acl_text = get_pool_memory(PM_MESSAGE);
163 while (bget_msg(sd) >= 0 && !job_canceled(jcr)) {
164 /* Remember previous stream type */
165 prev_stream = stream;
167 /* First we expect a Stream Record Header */
168 if (sscanf(sd->msg, rec_header, &VolSessionId, &VolSessionTime, &file_index,
169 &stream, &size) != 5) {
170 Jmsg1(jcr, M_FATAL, 0, _("Record header scan error: %s\n"), sd->msg);
173 Dmsg2(30, "Got hdr: FilInx=%d Stream=%d.\n", file_index, stream);
175 /* * Now we expect the Stream Data */
176 if (bget_msg(sd) < 0) {
177 Jmsg1(jcr, M_FATAL, 0, _("Data record error. ERR=%s\n"), bnet_strerror(sd));
180 if (size != (uint32_t)sd->msglen) {
181 Jmsg2(jcr, M_FATAL, 0, _("Actual data size %d not same as header %d\n"), sd->msglen, size);
184 Dmsg1(30, "Got stream data, len=%d\n", sd->msglen);
186 /* If we change streams, close and reset alternate data streams */
187 if (prev_stream != stream) {
188 if (is_bopen(&altbfd)) {
189 bclose_chksize(jcr, &altbfd, alt_size);
191 alt_size = -1; /* Use an impossible value and set a proper one below */
195 /* File Attributes stream */
197 case STREAM_UNIX_ATTRIBUTES:
198 case STREAM_UNIX_ATTRIBUTES_EX:
199 Dmsg1(30, "Stream=Unix Attributes. extract=%d\n", extract);
201 * If extracting, it was from previous stream, so
202 * close the output file and validate the signature.
205 if (size > 0 && !is_bopen(&bfd)) {
206 Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should be open\n"));
208 set_attributes(jcr, attr, &bfd);
211 /* Verify the cryptographic signature, if any */
214 if (!verify_signature(jcr, sig)) {
215 // TODO landonf: Better signature failure handling.
216 // The failure is reported to the director in verify_signature() ...
217 Dmsg1(100, "Bad signature on %s\n", jcr->last_fname);
219 Dmsg1(100, "Signature good on %s\n", jcr->last_fname);
221 crypto_sign_free(sig);
224 Jmsg1(jcr, M_ERROR, 0, _("Missing cryptographic signature for %s\n"), jcr->last_fname);
227 Dmsg0(30, "Stop extracting.\n");
228 } else if (is_bopen(&bfd)) {
229 Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should not be open\n"));
234 * Unpack and do sanity check fo attributes.
236 if (!unpack_attributes_record(jcr, stream, sd->msg, attr)) {
239 if (file_index != attr->file_index) {
240 Jmsg(jcr, M_FATAL, 0, _("Record header file index %ld not equal record index %ld\n"),
241 file_index, attr->file_index);
242 Dmsg0(100, "File index error\n");
246 Dmsg3(200, "File %s\nattrib=%s\nattribsEx=%s\n", attr->fname,
247 attr->attr, attr->attrEx);
249 attr->data_stream = decode_stat(attr->attr, &attr->statp, &attr->LinkFI);
251 if (!is_restore_stream_supported(attr->data_stream)) {
252 if (!non_support_data++) {
253 Jmsg(jcr, M_ERROR, 0, _("%s stream not supported on this Client.\n"),
254 stream_to_ascii(attr->data_stream));
259 build_attr_output_fnames(jcr, attr);
262 * Now determine if we are extracting or not.
264 jcr->num_files_examined++;
265 Dmsg1(30, "Outfile=%s\n", attr->ofname);
267 stat = create_file(jcr, attr, &bfd, jcr->replace);
272 case CF_EXTRACT: /* File created and we expect file data */
275 case CF_CREATED: /* File created, but there is no content */
277 pm_strcpy(jcr->last_fname, attr->ofname);
281 print_ls_output(jcr, attr);
282 #ifdef HAVE_DARWIN_OS
283 /* Only restore the resource fork for regular files */
284 from_base64(&rsrc_len, attr->attrEx);
285 if (attr->type == FT_REG && rsrc_len > 0) {
290 /* set attributes now because file will not be extracted */
291 set_attributes(jcr, attr, &bfd);
298 case STREAM_ENCRYPTED_SESSION_DATA:
299 // TODO landonf: Implement
300 // sig = crypto_sign_decode(sd->msg, (size_t) sd->msglen);
301 Dmsg1(30, "Stream=Encrypted Session Data, size: %d\n", sd->msglen);
304 case STREAM_FILE_DATA:
305 case STREAM_SPARSE_DATA:
306 case STREAM_WIN32_DATA:
307 case STREAM_GZIP_DATA:
308 case STREAM_SPARSE_GZIP_DATA:
309 case STREAM_WIN32_GZIP_DATA:
310 /* Force an expected, consistent stream type here */
311 if (extract && (prev_stream == stream || prev_stream == STREAM_UNIX_ATTRIBUTES
312 || prev_stream == STREAM_UNIX_ATTRIBUTES_EX
313 || prev_stream == STREAM_ENCRYPTED_SESSION_DATA)) {
315 if (stream == STREAM_SPARSE_DATA || stream == STREAM_SPARSE_GZIP_DATA) {
318 if (stream == STREAM_GZIP_DATA || stream == STREAM_SPARSE_GZIP_DATA
319 || stream == STREAM_WIN32_GZIP_DATA) {
323 if (is_win32_stream(stream) && !have_win32_api()) {
324 set_portable_backup(&bfd);
325 flags |= FO_WIN32DECOMP; /* "decompose" BackupWrite data */
328 if (extract_data(jcr, &bfd, sd->msg, sd->msglen, &fileAddr, flags) < 0) {
336 /* Resource fork stream - only recorded after a file to be restored */
337 /* Silently ignore if we cannot write - we already reported that */
338 case STREAM_MACOS_FORK_DATA:
339 #ifdef HAVE_DARWIN_OS
341 if (prev_stream != stream) {
342 if (bopen_rsrc(&altbfd, jcr->last_fname, O_WRONLY | O_TRUNC | O_BINARY, 0) < 0) {
343 Jmsg(jcr, M_ERROR, 0, _(" Cannot open resource fork for %s.\n"), jcr->last_fname);
348 Dmsg0(30, "Restoring resource fork\n");
351 if (extract_data(jcr, &altbfd, sd->msg, sd->msglen, &alt_addr, flags) < 0) {
362 case STREAM_HFSPLUS_ATTRIBUTES:
363 #ifdef HAVE_DARWIN_OS
364 Dmsg0(30, "Restoring Finder Info\n");
365 if (sd->msglen != 32) {
366 Jmsg(jcr, M_ERROR, 0, _(" Invalid length of Finder Info (got %d, not 32)\n"), sd->msglen);
369 if (setattrlist(jcr->last_fname, &attrList, sd->msg, sd->msglen, 0) != 0) {
370 Jmsg(jcr, M_ERROR, 0, _(" Could not set Finder Info on %s\n"), jcr->last_fname);
377 case STREAM_UNIX_ATTRIBUTES_ACCESS_ACL:
379 pm_strcpy(jcr->acl_text, sd->msg);
380 Dmsg2(400, "Restoring ACL type 0x%2x <%s>\n", BACL_TYPE_ACCESS, jcr->acl_text);
381 if (bacl_set(jcr, BACL_TYPE_ACCESS) != 0) {
382 Qmsg1(jcr, M_WARNING, 0, _("Can't restore ACL of %s\n"), jcr->last_fname);
389 case STREAM_UNIX_ATTRIBUTES_DEFAULT_ACL:
391 pm_strcpy(jcr->acl_text, sd->msg);
392 Dmsg2(400, "Restoring ACL type 0x%2x <%s>\n", BACL_TYPE_DEFAULT, jcr->acl_text);
393 if (bacl_set(jcr, BACL_TYPE_DEFAULT) != 0) {
394 Qmsg1(jcr, M_WARNING, 0, _("Can't restore default ACL of %s\n"), jcr->last_fname);
401 case STREAM_SIGNED_DIGEST:
402 /* Save signature. */
403 sig = crypto_sign_decode(sd->msg, (size_t) sd->msglen);
406 case STREAM_MD5_DIGEST:
407 case STREAM_SHA1_DIGEST:
408 case STREAM_SHA256_DIGEST:
409 case STREAM_SHA512_DIGEST:
412 case STREAM_PROGRAM_NAMES:
413 case STREAM_PROGRAM_DATA:
414 if (!non_support_progname) {
415 Pmsg0(000, "Got Program Name or Data Stream. Ignored.\n");
416 non_support_progname++;
421 /* If extracting, wierd stream (not 1 or 2), close output file anyway */
423 Dmsg1(30, "Found wierd stream %d\n", stream);
424 if (size > 0 && !is_bopen(&bfd)) {
425 Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should be open\n"));
427 set_attributes(jcr, attr, &bfd);
429 } else if (is_bopen(&bfd)) {
430 Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should not be open\n"));
433 Jmsg(jcr, M_ERROR, 0, _("Unknown stream=%d ignored. This shouldn't happen!\n"), stream);
434 Dmsg2(0, "None of above!!! stream=%d data=%s\n", stream,sd->msg);
436 } /* end switch(stream) */
438 } /* end while get_msg() */
440 /* If output file is still open, it was the last one in the
441 * archive since we just hit an end of file, so close the file.
443 if (is_bopen(&altbfd)) {
444 bclose_chksize(jcr, &altbfd, alt_size);
447 set_attributes(jcr, attr, &bfd);
449 if (is_bopen(&bfd)) {
452 set_jcr_job_status(jcr, JS_Terminated);
456 set_jcr_job_status(jcr, JS_ErrorTerminated);
458 if (jcr->compress_buf) {
459 free(jcr->compress_buf);
460 jcr->compress_buf = NULL;
461 jcr->compress_buf_size = 0;
466 free_pool_memory(jcr->acl_text);
467 Dmsg2(10, "End Do Restore. Files=%d Bytes=%s\n", jcr->JobFiles,
468 edit_uint64(jcr->JobBytes, ec1));
469 if (non_support_data > 1 || non_support_attr > 1) {
470 Jmsg(jcr, M_ERROR, 0, _("%d non-supported data streams and %d non-supported attrib streams ignored.\n"),
471 non_support_data, non_support_attr);
473 if (non_support_rsrc) {
474 Jmsg(jcr, M_INFO, 0, _("%d non-supported resource fork streams ignored.\n"), non_support_rsrc);
476 if (non_support_finfo) {
477 Jmsg(jcr, M_INFO, 0, _("%d non-supported Finder Info streams ignored.\n"), non_support_rsrc);
479 if (non_support_acl) {
480 Jmsg(jcr, M_INFO, 0, _("%d non-supported acl streams ignored.\n"), non_support_acl);
487 * Convert ZLIB error code into an ASCII message
489 static const char *zlib_strerror(int stat)
496 return _("Zlib errno");
498 return _("Zlib stream error");
500 return _("Zlib data error");
502 return _("Zlib memory error");
504 return _("Zlib buffer error");
505 case Z_VERSION_ERROR:
506 return _("Zlib version error");
513 static int do_file_digest(FF_PKT *ff_pkt, void *pkt, bool top_level) {
514 JCR *jcr = (JCR *) pkt;
515 return (digest_file(jcr, ff_pkt, jcr->digest));
519 * Verify the signature for the last restored file
520 * Return value is either true (signature correct)
521 * or false (signature could not be verified).
523 int verify_signature(JCR *jcr, SIGNATURE *sig)
525 X509_KEYPAIR *keypair;
526 DIGEST *digest = NULL;
530 /* Iterate through the trusted signers */
531 foreach_alist(keypair, jcr->pki_signers) {
532 err = crypto_sign_get_digest(sig, jcr->pki_keypair, &digest);
535 case CRYPTO_ERROR_NONE:
536 /* Signature found, digest allocated */
537 jcr->digest = digest;
539 /* Checksum the entire file */
540 if (find_one_file(jcr, jcr->ff, do_file_digest, jcr, jcr->last_fname, (dev_t)-1, 1) != 0) {
541 Qmsg(jcr, M_ERROR, 0, _("Signature validation failed for %s: \n"), jcr->last_fname);
545 /* Verify the signature */
546 if ((err = crypto_sign_verify(sig, keypair, digest)) != CRYPTO_ERROR_NONE) {
547 Qmsg2(jcr, M_ERROR, 0, _("Signature validation failed for %s: %s\n"), jcr->last_fname, crypto_strerror(err));
548 crypto_digest_free(digest);
552 /* Valid signature */
553 crypto_digest_free(digest);
556 case CRYPTO_ERROR_NOSIGNER:
557 /* Signature not found, try again */
560 /* Something strange happened (that shouldn't happen!)... */
561 Qmsg2(jcr, M_ERROR, 0, _("Signature validation failed for %s: %s\n"), jcr->last_fname, crypto_strerror(err));
563 crypto_digest_free(digest);
574 * In the context of jcr, write data to bfd.
575 * We write buflen bytes in buf at addr. addr is updated in place.
576 * The flags specify whether to use sparse files or compression.
577 * Return value is the number of bytes written, or -1 on errors.
579 int32_t extract_data(JCR *jcr, BFILE *bfd, POOLMEM *buf, int32_t buflen,
580 uint64_t *addr, int flags)
583 char *wbuf; /* write buffer */
584 uint32_t wsize; /* write size */
585 uint32_t rsize; /* read size */
586 char ec1[50]; /* Buffer printing huge values */
588 if (flags & FO_SPARSE) {
592 wbuf = buf + SPARSE_FADDR_SIZE;
593 rsize = buflen - SPARSE_FADDR_SIZE;
594 ser_begin(buf, SPARSE_FADDR_SIZE);
596 if (*addr != faddr) {
598 if (blseek(bfd, (off_t)*addr, SEEK_SET) < 0) {
600 Jmsg3(jcr, M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"),
601 edit_uint64(*addr, ec1), jcr->last_fname,
602 be.strerror(bfd->berrno));
612 if (flags & FO_GZIP) {
616 * NOTE! We only use uLong and Byte because they are
617 * needed by the zlib routines, they should not otherwise
620 compress_len = jcr->compress_buf_size;
621 Dmsg2(100, "Comp_len=%d msglen=%d\n", compress_len, wsize);
622 if ((stat=uncompress((Byte *)jcr->compress_buf, &compress_len,
623 (const Byte *)wbuf, (uLong)rsize)) != Z_OK) {
624 Qmsg(jcr, M_ERROR, 0, _("Uncompression error on file %s. ERR=%s\n"),
625 jcr->last_fname, zlib_strerror(stat));
628 wbuf = jcr->compress_buf;
629 wsize = compress_len;
630 Dmsg2(100, "Write uncompressed %d bytes, total before write=%s\n", compress_len, edit_uint64(jcr->JobBytes, ec1));
632 Qmsg(jcr, M_ERROR, 0, _("GZIP data stream found, but GZIP not configured!\n"));
636 Dmsg2(30, "Write %u bytes, total before write=%s\n", wsize, edit_uint64(jcr->JobBytes, ec1));
639 if (flags & FO_WIN32DECOMP) {
640 if (!processWin32BackupAPIBlock(bfd, wbuf, wsize)) {
642 Jmsg2(jcr, M_ERROR, 0, _("Write error in Win32 Block Decomposition on %s: %s\n"),
643 jcr->last_fname, be.strerror(bfd->berrno));
646 } else if (bwrite(bfd, wbuf, wsize) != (ssize_t)wsize) {
648 Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"),
649 jcr->last_fname, be.strerror(bfd->berrno));
653 jcr->JobBytes += wsize;
654 jcr->ReadBytes += rsize;