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);
38 int32_t extract_data(JCR *jcr, BFILE *bfd, POOLMEM *buf, int32_t buflen,
39 uint64_t *addr, int flags);
41 #define RETRY 10 /* retry wait time */
44 * Close a bfd check that we are at the expected file offset.
45 * Makes some code in set_attributes().
47 int bclose_chksize(JCR *jcr, BFILE *bfd, off_t osize)
49 char ec1[50], ec2[50];
52 fsize = blseek(bfd, 0, SEEK_CUR);
53 bclose(bfd); /* first close file */
54 if (fsize > 0 && fsize != osize) {
55 Jmsg3(jcr, M_ERROR, 0, _("Size of data or stream of %s not correct. Original %s, restored %s.\n"),
56 jcr->last_fname, edit_uint64(osize, ec1),
57 edit_uint64(fsize, ec2));
64 * Restore the requested files.
67 void do_restore(JCR *jcr)
72 uint32_t VolSessionId, VolSessionTime;
75 char ec1[50]; /* Buffer printing huge values */
77 BFILE bfd; /* File content */
78 uint64_t fileAddr = 0; /* file write address */
79 uint32_t size; /* Size of file */
80 BFILE altbfd; /* Alternative data stream */
81 uint64_t alt_addr = 0; /* Write address for alternative stream */
82 intmax_t alt_size = 0; /* Size of alternate stream */
83 int flags; /* Options for extract_data() */
87 /* The following variables keep track of "known unknowns" */
88 int non_support_data = 0;
89 int non_support_attr = 0;
90 int non_support_rsrc = 0;
91 int non_support_finfo = 0;
92 int non_support_acl = 0;
93 int non_support_progname = 0;
95 /* Finally, set up for special configurations */
97 intmax_t rsrc_len = 0; /* Original length of resource fork */
98 struct attrlist attrList;
100 memset(&attrList, 0, sizeof(attrList));
101 attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
102 attrList.commonattr = ATTR_CMN_FNDRINFO;
105 sd = jcr->store_bsock;
106 set_jcr_job_status(jcr, JS_Running);
109 CLIENT *client = (CLIENT *)GetNextRes(R_CLIENT, NULL);
113 buf_size = client->max_network_buffer_size;
115 buf_size = 0; /* use default */
117 if (!bnet_set_buffer_size(sd, buf_size, BNET_SETBUF_WRITE)) {
118 set_jcr_job_status(jcr, JS_ErrorTerminated);
121 jcr->buf_size = sd->msglen;
124 uint32_t compress_buf_size = jcr->buf_size + 12 + ((jcr->buf_size+999) / 1000) + 100;
125 jcr->compress_buf = (char *)bmalloc(compress_buf_size);
126 jcr->compress_buf_size = compress_buf_size;
130 * Get a record from the Storage daemon. We are guaranteed to
131 * receive records in the following order:
132 * 1. Stream record header
134 * a. Attributes (Unix or Win32)
135 * or b. File data for the file
136 * or c. Alternate data stream (e.g. Resource Fork)
139 * or f. Possibly MD5 or SHA1 record
142 * NOTE: We keep track of two bacula file descriptors:
143 * 1. bfd for file data.
144 * This fd is opened for non empty files when an attribute stream is
145 * encountered and closed when we find the next attribute stream.
146 * 2. alt_bfd for alternate data streams
147 * This fd is opened every time we encounter a new alternate data
148 * stream for the current file. When we find any other stream, we
150 * The expected size of the stream, alt_len, should be set when
156 jcr->acl_text = get_pool_memory(PM_MESSAGE);
158 while (bget_msg(sd) >= 0 && !job_canceled(jcr)) {
159 /* Remember previous stream type */
160 prev_stream = stream;
162 /* First we expect a Stream Record Header */
163 if (sscanf(sd->msg, rec_header, &VolSessionId, &VolSessionTime, &file_index,
164 &stream, &size) != 5) {
165 Jmsg1(jcr, M_FATAL, 0, _("Record header scan error: %s\n"), sd->msg);
168 Dmsg2(30, "Got hdr: FilInx=%d Stream=%d.\n", file_index, stream);
170 /* * Now we expect the Stream Data */
171 if (bget_msg(sd) < 0) {
172 Jmsg1(jcr, M_FATAL, 0, _("Data record error. ERR=%s\n"), bnet_strerror(sd));
175 if (size != (uint32_t)sd->msglen) {
176 Jmsg2(jcr, M_FATAL, 0, _("Actual data size %d not same as header %d\n"), sd->msglen, size);
179 Dmsg1(30, "Got stream data, len=%d\n", sd->msglen);
181 /* If we change streams, close and reset alternate data streams */
182 if (prev_stream != stream) {
183 if (is_bopen(&altbfd)) {
184 bclose_chksize(jcr, &altbfd, alt_size);
186 alt_size = -1; /* Use an impossible value and set a proper one below */
190 /* File Attributes stream */
192 case STREAM_UNIX_ATTRIBUTES:
193 case STREAM_UNIX_ATTRIBUTES_EX:
194 Dmsg1(30, "Stream=Unix Attributes. extract=%d\n", extract);
196 * If extracting, it was from previous stream, so
197 * close the output file.
200 if (size > 0 && !is_bopen(&bfd)) {
201 Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should be open\n"));
203 set_attributes(jcr, attr, &bfd);
205 Dmsg0(30, "Stop extracting.\n");
206 } else if (is_bopen(&bfd)) {
207 Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should not be open\n"));
212 * Unpack and do sanity check fo attributes.
214 if (!unpack_attributes_record(jcr, stream, sd->msg, attr)) {
217 if (file_index != attr->file_index) {
218 Jmsg(jcr, M_FATAL, 0, _("Record header file index %ld not equal record index %ld\n"),
219 file_index, attr->file_index);
220 Dmsg0(100, "File index error\n");
224 Dmsg3(200, "File %s\nattrib=%s\nattribsEx=%s\n", attr->fname,
225 attr->attr, attr->attrEx);
227 attr->data_stream = decode_stat(attr->attr, &attr->statp, &attr->LinkFI);
229 if (!is_stream_supported(attr->data_stream)) {
230 if (!non_support_data++) {
231 Jmsg(jcr, M_ERROR, 0, _("%s stream not supported on this Client.\n"),
232 stream_to_ascii(attr->data_stream));
237 build_attr_output_fnames(jcr, attr);
240 * Now determine if we are extracting or not.
242 jcr->num_files_examined++;
243 Dmsg1(30, "Outfile=%s\n", attr->ofname);
245 stat = create_file(jcr, attr, &bfd, jcr->replace);
250 case CF_EXTRACT: /* File created and we expect file data */
253 case CF_CREATED: /* File created, but there is no content */
255 pm_strcpy(jcr->last_fname, attr->ofname);
259 print_ls_output(jcr, attr);
260 #ifdef HAVE_DARWIN_OS
261 /* Only restore the resource fork for regular files */
262 from_base64(&rsrc_len, attr->attrEx);
263 if (attr->type == FT_REG && rsrc_len > 0) {
268 /* set attributes now because file will not be extracted */
269 set_attributes(jcr, attr, &bfd);
276 case STREAM_FILE_DATA:
277 case STREAM_SPARSE_DATA:
278 case STREAM_WIN32_DATA:
279 case STREAM_GZIP_DATA:
280 case STREAM_SPARSE_GZIP_DATA:
281 case STREAM_WIN32_GZIP_DATA:
282 /* Force an expected, consistent stream type here */
283 if (extract && (prev_stream == stream || prev_stream == STREAM_UNIX_ATTRIBUTES
284 || prev_stream == STREAM_UNIX_ATTRIBUTES_EX)) {
286 if (stream == STREAM_SPARSE_DATA || stream == STREAM_SPARSE_GZIP_DATA) {
289 if (stream == STREAM_GZIP_DATA || stream == STREAM_SPARSE_GZIP_DATA
290 || stream == STREAM_WIN32_GZIP_DATA) {
294 #ifdef USE_WIN32STREAMEXTRACTION
295 /* THIS DETERMINES IF WE USE THE WIN32 BACKUPSTREAM DECOMPOSITION */
296 if (is_win32_stream(stream) && !have_win32_api()) {
297 set_portable_backup(&bfd);
298 flags |= FO_WIN32DECOMP;
302 if (extract_data(jcr, &bfd, sd->msg, sd->msglen, &fileAddr, flags) < 0) {
310 /* Resource fork stream - only recorded after a file to be restored */
311 /* Silently ignore if we cannot write - we already reported that */
312 case STREAM_MACOS_FORK_DATA:
313 #ifdef HAVE_DARWIN_OS
315 if (prev_stream != stream) {
316 if (bopen_rsrc(&altbfd, jcr->last_fname, O_WRONLY | O_TRUNC | O_BINARY, 0) < 0) {
317 Jmsg(jcr, M_ERROR, 0, _(" Cannot open resource fork for %s.\n"), jcr->last_fname);
322 Dmsg0(30, "Restoring resource fork\n");
325 if (extract_data(jcr, &altbfd, sd->msg, sd->msglen, &alt_addr, flags) < 0) {
336 case STREAM_HFSPLUS_ATTRIBUTES:
337 #ifdef HAVE_DARWIN_OS
338 Dmsg0(30, "Restoring Finder Info\n");
339 if (sd->msglen != 32) {
340 Jmsg(jcr, M_ERROR, 0, _(" Invalid length of Finder Info (got %d, not 32)\n"), sd->msglen);
343 if (setattrlist(jcr->last_fname, &attrList, sd->msg, sd->msglen, 0) != 0) {
344 Jmsg(jcr, M_ERROR, 0, _(" Could not set Finder Info on %s\n"), jcr->last_fname);
351 case STREAM_UNIX_ATTRIBUTES_ACCESS_ACL:
353 pm_strcpy(jcr->acl_text, sd->msg);
354 Dmsg2(400, "Restoring ACL type 0x%2x <%s>\n", BACL_TYPE_ACCESS, jcr->acl_text);
355 if (bacl_set(jcr, BACL_TYPE_ACCESS) != 0) {
356 Jmsg1(jcr, M_WARNING, 0, _("Can't restore ACL of %s\n"), jcr->last_fname);
363 case STREAM_UNIX_ATTRIBUTES_DEFAULT_ACL:
365 pm_strcpy(jcr->acl_text, sd->msg);
366 Dmsg2(400, "Restoring ACL type 0x%2x <%s>\n", BACL_TYPE_DEFAULT, jcr->acl_text);
367 if (bacl_set(jcr, BACL_TYPE_DEFAULT) != 0) {
368 Jmsg1(jcr, M_WARNING, 0, _("Can't restore default ACL of %s\n"), jcr->last_fname);
375 case STREAM_MD5_SIGNATURE:
376 case STREAM_SHA1_SIGNATURE:
379 case STREAM_PROGRAM_NAMES:
380 case STREAM_PROGRAM_DATA:
381 if (!non_support_progname) {
382 Pmsg0(000, "Got Program Name or Data Stream. Ignored.\n");
383 non_support_progname++;
388 /* If extracting, wierd stream (not 1 or 2), close output file anyway */
390 Dmsg1(30, "Found wierd stream %d\n", stream);
391 if (size > 0 && !is_bopen(&bfd)) {
392 Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should be open\n"));
394 set_attributes(jcr, attr, &bfd);
396 } else if (is_bopen(&bfd)) {
397 Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should not be open\n"));
400 Jmsg(jcr, M_ERROR, 0, _("Unknown stream=%d ignored. This shouldn't happen!\n"), stream);
401 Dmsg2(0, "None of above!!! stream=%d data=%s\n", stream,sd->msg);
403 } /* end switch(stream) */
405 } /* end while get_msg() */
407 /* If output file is still open, it was the last one in the
408 * archive since we just hit an end of file, so close the file.
410 if (is_bopen(&altbfd)) {
411 bclose_chksize(jcr, &altbfd, alt_size);
414 set_attributes(jcr, attr, &bfd);
416 if (is_bopen(&bfd)) {
419 set_jcr_job_status(jcr, JS_Terminated);
423 set_jcr_job_status(jcr, JS_ErrorTerminated);
425 if (jcr->compress_buf) {
426 free(jcr->compress_buf);
427 jcr->compress_buf = NULL;
428 jcr->compress_buf_size = 0;
433 free_pool_memory(jcr->acl_text);
434 Dmsg2(10, "End Do Restore. Files=%d Bytes=%s\n", jcr->JobFiles,
435 edit_uint64(jcr->JobBytes, ec1));
436 if (non_support_data > 1 || non_support_attr > 1) {
437 Jmsg(jcr, M_ERROR, 0, _("%d non-supported data streams and %d non-supported attrib streams ignored.\n"),
438 non_support_data, non_support_attr);
440 if (non_support_rsrc) {
441 Jmsg(jcr, M_INFO, 0, _("%d non-supported resource fork streams ignored.\n"), non_support_rsrc);
443 if (non_support_finfo) {
444 Jmsg(jcr, M_INFO, 0, _("%d non-supported Finder Info streams ignored.\n"), non_support_rsrc);
446 if (non_support_acl) {
447 Jmsg(jcr, M_INFO, 0, _("%d non-supported acl streams ignored.\n"), non_support_acl);
454 * Convert ZLIB error code into an ASCII message
456 static const char *zlib_strerror(int stat)
463 return _("Zlib errno");
465 return _("Zlib stream error");
467 return _("Zlib data error");
469 return _("Zlib memory error");
471 return _("Zlib buffer error");
472 case Z_VERSION_ERROR:
473 return _("Zlib version error");
481 * In the context of jcr, write data to bfd.
482 * We write buflen bytes in buf at addr. addr is updated in place.
483 * The flags specify whether to use sparse files or compression.
484 * Return value is the number of bytes written, or -1 on errors.
486 int32_t extract_data(JCR *jcr, BFILE *bfd, POOLMEM *buf, int32_t buflen,
487 uint64_t *addr, int flags)
490 char *wbuf; /* write buffer */
491 uint32_t wsize; /* write size */
492 uint32_t rsize; /* read size */
493 char ec1[50]; /* Buffer printing huge values */
495 if (flags & FO_SPARSE) {
499 wbuf = buf + SPARSE_FADDR_SIZE;
500 rsize = buflen - SPARSE_FADDR_SIZE;
501 ser_begin(buf, SPARSE_FADDR_SIZE);
503 if (*addr != faddr) {
505 if (blseek(bfd, (off_t)*addr, SEEK_SET) < 0) {
507 Jmsg3(jcr, M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"),
508 edit_uint64(*addr, ec1), jcr->last_fname,
509 be.strerror(bfd->berrno));
519 if (flags & FO_GZIP) {
523 * NOTE! We only use uLong and Byte because they are
524 * needed by the zlib routines, they should not otherwise
527 compress_len = jcr->compress_buf_size;
528 Dmsg2(100, "Comp_len=%d msglen=%d\n", compress_len, wsize);
529 if ((stat=uncompress((Byte *)jcr->compress_buf, &compress_len,
530 (const Byte *)wbuf, (uLong)rsize)) != Z_OK) {
531 Jmsg(jcr, M_ERROR, 0, _("Uncompression error on file %s. ERR=%s\n"),
532 jcr->last_fname, zlib_strerror(stat));
535 wbuf = jcr->compress_buf;
536 wsize = compress_len;
537 Dmsg2(100, "Write uncompressed %d bytes, total before write=%s\n", compress_len, edit_uint64(jcr->JobBytes, ec1));
539 Jmsg(jcr, M_ERROR, 0, _("GZIP data stream found, but GZIP not configured!\n"));
543 Dmsg2(30, "Write %u bytes, total before write=%s\n", wsize, edit_uint64(jcr->JobBytes, ec1));
546 #ifdef USE_WIN32STREAMEXTRACTION
547 if (flags & FO_WIN32DECOMP) {
548 if (!processWin32BackupAPIBlock(bfd, wbuf, wsize)) {
550 Jmsg2(jcr, M_ERROR, 0, _("Write error in Win32 Block Decomposition on %s: %s\n"),
551 jcr->last_fname, be.strerror(bfd->berrno));
557 if (bwrite(bfd, wbuf, wsize) != (ssize_t)wsize) {
559 Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"),
560 jcr->last_fname, be.strerror(bfd->berrno));
564 jcr->JobBytes += wsize;
565 jcr->ReadBytes += rsize;