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 int32_t extract_data(JCR *jcr, BFILE *bfd, POOLMEM *buf, int32_t buflen,
40 uint64_t *addr, int flags);
42 #define RETRY 10 /* retry wait time */
45 * Close a bfd check that we are at the expected file offset.
46 * Makes some code in set_attributes().
48 int bclose_chksize(JCR *jcr, BFILE *bfd, off_t osize)
50 char ec1[50], ec2[50];
53 fsize = blseek(bfd, 0, SEEK_CUR);
54 bclose(bfd); /* first close file */
55 if (fsize > 0 && fsize != osize) {
56 Jmsg3(jcr, M_ERROR, 0, _("Size of data or stream of %s not correct. Original %s, restored %s.\n"),
57 jcr->last_fname, edit_uint64(osize, ec1),
58 edit_uint64(fsize, ec2));
65 * Restore the requested files.
68 void do_restore(JCR *jcr)
73 uint32_t VolSessionId, VolSessionTime;
76 char ec1[50]; /* Buffer printing huge values */
78 BFILE bfd; /* File content */
79 uint64_t fileAddr = 0; /* file write address */
80 uint32_t size; /* Size of file */
81 BFILE altbfd; /* Alternative data stream */
82 uint64_t alt_addr = 0; /* Write address for alternative stream */
83 intmax_t alt_size = 0; /* Size of alternate stream */
84 int flags; /* Options for extract_data() */
88 /* The following variables keep track of "known unknowns" */
89 int non_support_data = 0;
90 int non_support_attr = 0;
91 int non_support_rsrc = 0;
92 int non_support_finfo = 0;
93 int non_support_acl = 0;
94 int non_support_progname = 0;
96 /* Finally, set up for special configurations */
98 intmax_t rsrc_len = 0; /* Original length of resource fork */
99 struct attrlist attrList;
101 memset(&attrList, 0, sizeof(attrList));
102 attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
103 attrList.commonattr = ATTR_CMN_FNDRINFO;
106 sd = jcr->store_bsock;
107 set_jcr_job_status(jcr, JS_Running);
110 CLIENT *client = (CLIENT *)GetNextRes(R_CLIENT, NULL);
114 buf_size = client->max_network_buffer_size;
116 buf_size = 0; /* use default */
118 if (!bnet_set_buffer_size(sd, buf_size, BNET_SETBUF_WRITE)) {
119 set_jcr_job_status(jcr, JS_ErrorTerminated);
122 jcr->buf_size = sd->msglen;
125 uint32_t compress_buf_size = jcr->buf_size + 12 + ((jcr->buf_size+999) / 1000) + 100;
126 jcr->compress_buf = (char *)bmalloc(compress_buf_size);
127 jcr->compress_buf_size = compress_buf_size;
131 * Get a record from the Storage daemon. We are guaranteed to
132 * receive records in the following order:
133 * 1. Stream record header
135 * a. Attributes (Unix or Win32)
136 * or b. File data for the file
137 * or c. Alternate data stream (e.g. Resource Fork)
140 * or f. Possibly MD5 or SHA1 record
143 * NOTE: We keep track of two bacula file descriptors:
144 * 1. bfd for file data.
145 * This fd is opened for non empty files when an attribute stream is
146 * encountered and closed when we find the next attribute stream.
147 * 2. alt_bfd for alternate data streams
148 * This fd is opened every time we encounter a new alternate data
149 * stream for the current file. When we find any other stream, we
151 * The expected size of the stream, alt_len, should be set when
157 jcr->acl_text = get_pool_memory(PM_MESSAGE);
159 while (bget_msg(sd) >= 0 && !job_canceled(jcr)) {
160 /* Remember previous stream type */
161 prev_stream = stream;
163 /* First we expect a Stream Record Header */
164 if (sscanf(sd->msg, rec_header, &VolSessionId, &VolSessionTime, &file_index,
165 &stream, &size) != 5) {
166 Jmsg1(jcr, M_FATAL, 0, _("Record header scan error: %s\n"), sd->msg);
169 Dmsg2(30, "Got hdr: FilInx=%d Stream=%d.\n", file_index, stream);
171 /* * Now we expect the Stream Data */
172 if (bget_msg(sd) < 0) {
173 Jmsg1(jcr, M_FATAL, 0, _("Data record error. ERR=%s\n"), bnet_strerror(sd));
176 if (size != (uint32_t)sd->msglen) {
177 Jmsg2(jcr, M_FATAL, 0, _("Actual data size %d not same as header %d\n"), sd->msglen, size);
180 Dmsg1(30, "Got stream data, len=%d\n", sd->msglen);
182 /* If we change streams, close and reset alternate data streams */
183 if (prev_stream != stream) {
184 if (is_bopen(&altbfd)) {
185 bclose_chksize(jcr, &altbfd, alt_size);
187 alt_size = -1; /* Use an impossible value and set a proper one below */
191 /* File Attributes stream */
193 case STREAM_UNIX_ATTRIBUTES:
194 case STREAM_UNIX_ATTRIBUTES_EX:
195 Dmsg1(30, "Stream=Unix Attributes. extract=%d\n", extract);
197 * If extracting, it was from previous stream, so
198 * close the output file.
201 if (size > 0 && !is_bopen(&bfd)) {
202 Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should be open\n"));
204 set_attributes(jcr, attr, &bfd);
206 Dmsg0(30, "Stop extracting.\n");
207 } else if (is_bopen(&bfd)) {
208 Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should not be open\n"));
213 * Unpack and do sanity check fo attributes.
215 if (!unpack_attributes_record(jcr, stream, sd->msg, attr)) {
218 if (file_index != attr->file_index) {
219 Jmsg(jcr, M_FATAL, 0, _("Record header file index %ld not equal record index %ld\n"),
220 file_index, attr->file_index);
221 Dmsg0(100, "File index error\n");
225 Dmsg3(200, "File %s\nattrib=%s\nattribsEx=%s\n", attr->fname,
226 attr->attr, attr->attrEx);
228 attr->data_stream = decode_stat(attr->attr, &attr->statp, &attr->LinkFI);
230 if (!is_stream_supported(attr->data_stream)) {
231 if (!non_support_data++) {
232 Jmsg(jcr, M_ERROR, 0, _("%s stream not supported on this Client.\n"),
233 stream_to_ascii(attr->data_stream));
238 build_attr_output_fnames(jcr, attr);
241 * Now determine if we are extracting or not.
243 jcr->num_files_examined++;
244 Dmsg1(30, "Outfile=%s\n", attr->ofname);
246 stat = create_file(jcr, attr, &bfd, jcr->replace);
251 case CF_EXTRACT: /* File created and we expect file data */
254 case CF_CREATED: /* File created, but there is no content */
256 pm_strcpy(jcr->last_fname, attr->ofname);
260 print_ls_output(jcr, attr);
261 #ifdef HAVE_DARWIN_OS
262 /* Only restore the resource fork for regular files */
263 from_base64(&rsrc_len, attr->attrEx);
264 if (attr->type == FT_REG && rsrc_len > 0) {
269 /* set attributes now because file will not be extracted */
270 set_attributes(jcr, attr, &bfd);
277 case STREAM_FILE_DATA:
278 case STREAM_SPARSE_DATA:
279 case STREAM_WIN32_DATA:
280 case STREAM_GZIP_DATA:
281 case STREAM_SPARSE_GZIP_DATA:
282 case STREAM_WIN32_GZIP_DATA:
283 /* Force an expected, consistent stream type here */
284 if (extract && (prev_stream == stream || prev_stream == STREAM_UNIX_ATTRIBUTES
285 || prev_stream == STREAM_UNIX_ATTRIBUTES_EX)) {
287 if (stream == STREAM_SPARSE_DATA || stream == STREAM_SPARSE_GZIP_DATA) {
290 if (stream == STREAM_GZIP_DATA || stream == STREAM_SPARSE_GZIP_DATA
291 || stream == STREAM_WIN32_GZIP_DATA) {
295 if (is_win32_stream(stream) && !have_win32_api()) {
296 set_portable_backup(&bfd);
297 flags |= FO_WIN32DECOMP; /* "decompose" BackupWrite data */
300 if (extract_data(jcr, &bfd, sd->msg, sd->msglen, &fileAddr, flags) < 0) {
308 /* Resource fork stream - only recorded after a file to be restored */
309 /* Silently ignore if we cannot write - we already reported that */
310 case STREAM_MACOS_FORK_DATA:
311 #ifdef HAVE_DARWIN_OS
313 if (prev_stream != stream) {
314 if (bopen_rsrc(&altbfd, jcr->last_fname, O_WRONLY | O_TRUNC | O_BINARY, 0) < 0) {
315 Jmsg(jcr, M_ERROR, 0, _(" Cannot open resource fork for %s.\n"), jcr->last_fname);
320 Dmsg0(30, "Restoring resource fork\n");
323 if (extract_data(jcr, &altbfd, sd->msg, sd->msglen, &alt_addr, flags) < 0) {
334 case STREAM_HFSPLUS_ATTRIBUTES:
335 #ifdef HAVE_DARWIN_OS
336 Dmsg0(30, "Restoring Finder Info\n");
337 if (sd->msglen != 32) {
338 Jmsg(jcr, M_ERROR, 0, _(" Invalid length of Finder Info (got %d, not 32)\n"), sd->msglen);
341 if (setattrlist(jcr->last_fname, &attrList, sd->msg, sd->msglen, 0) != 0) {
342 Jmsg(jcr, M_ERROR, 0, _(" Could not set Finder Info on %s\n"), jcr->last_fname);
349 case STREAM_UNIX_ATTRIBUTES_ACCESS_ACL:
351 pm_strcpy(jcr->acl_text, sd->msg);
352 Dmsg2(400, "Restoring ACL type 0x%2x <%s>\n", BACL_TYPE_ACCESS, jcr->acl_text);
353 if (bacl_set(jcr, BACL_TYPE_ACCESS) != 0) {
354 Jmsg1(jcr, M_WARNING, 0, _("Can't restore ACL of %s\n"), jcr->last_fname);
361 case STREAM_UNIX_ATTRIBUTES_DEFAULT_ACL:
363 pm_strcpy(jcr->acl_text, sd->msg);
364 Dmsg2(400, "Restoring ACL type 0x%2x <%s>\n", BACL_TYPE_DEFAULT, jcr->acl_text);
365 if (bacl_set(jcr, BACL_TYPE_DEFAULT) != 0) {
366 Jmsg1(jcr, M_WARNING, 0, _("Can't restore default ACL of %s\n"), jcr->last_fname);
373 case STREAM_MD5_SIGNATURE:
374 case STREAM_SHA1_SIGNATURE:
377 case STREAM_PROGRAM_NAMES:
378 case STREAM_PROGRAM_DATA:
379 if (!non_support_progname) {
380 Pmsg0(000, "Got Program Name or Data Stream. Ignored.\n");
381 non_support_progname++;
386 /* If extracting, wierd stream (not 1 or 2), close output file anyway */
388 Dmsg1(30, "Found wierd stream %d\n", stream);
389 if (size > 0 && !is_bopen(&bfd)) {
390 Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should be open\n"));
392 set_attributes(jcr, attr, &bfd);
394 } else if (is_bopen(&bfd)) {
395 Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should not be open\n"));
398 Jmsg(jcr, M_ERROR, 0, _("Unknown stream=%d ignored. This shouldn't happen!\n"), stream);
399 Dmsg2(0, "None of above!!! stream=%d data=%s\n", stream,sd->msg);
401 } /* end switch(stream) */
403 } /* end while get_msg() */
405 /* If output file is still open, it was the last one in the
406 * archive since we just hit an end of file, so close the file.
408 if (is_bopen(&altbfd)) {
409 bclose_chksize(jcr, &altbfd, alt_size);
412 set_attributes(jcr, attr, &bfd);
414 if (is_bopen(&bfd)) {
417 set_jcr_job_status(jcr, JS_Terminated);
421 set_jcr_job_status(jcr, JS_ErrorTerminated);
423 if (jcr->compress_buf) {
424 free(jcr->compress_buf);
425 jcr->compress_buf = NULL;
426 jcr->compress_buf_size = 0;
431 free_pool_memory(jcr->acl_text);
432 Dmsg2(10, "End Do Restore. Files=%d Bytes=%s\n", jcr->JobFiles,
433 edit_uint64(jcr->JobBytes, ec1));
434 if (non_support_data > 1 || non_support_attr > 1) {
435 Jmsg(jcr, M_ERROR, 0, _("%d non-supported data streams and %d non-supported attrib streams ignored.\n"),
436 non_support_data, non_support_attr);
438 if (non_support_rsrc) {
439 Jmsg(jcr, M_INFO, 0, _("%d non-supported resource fork streams ignored.\n"), non_support_rsrc);
441 if (non_support_finfo) {
442 Jmsg(jcr, M_INFO, 0, _("%d non-supported Finder Info streams ignored.\n"), non_support_rsrc);
444 if (non_support_acl) {
445 Jmsg(jcr, M_INFO, 0, _("%d non-supported acl streams ignored.\n"), non_support_acl);
452 * Convert ZLIB error code into an ASCII message
454 static const char *zlib_strerror(int stat)
461 return _("Zlib errno");
463 return _("Zlib stream error");
465 return _("Zlib data error");
467 return _("Zlib memory error");
469 return _("Zlib buffer error");
470 case Z_VERSION_ERROR:
471 return _("Zlib version error");
479 * In the context of jcr, write data to bfd.
480 * We write buflen bytes in buf at addr. addr is updated in place.
481 * The flags specify whether to use sparse files or compression.
482 * Return value is the number of bytes written, or -1 on errors.
484 int32_t extract_data(JCR *jcr, BFILE *bfd, POOLMEM *buf, int32_t buflen,
485 uint64_t *addr, int flags)
488 char *wbuf; /* write buffer */
489 uint32_t wsize; /* write size */
490 uint32_t rsize; /* read size */
491 char ec1[50]; /* Buffer printing huge values */
493 if (flags & FO_SPARSE) {
497 wbuf = buf + SPARSE_FADDR_SIZE;
498 rsize = buflen - SPARSE_FADDR_SIZE;
499 ser_begin(buf, SPARSE_FADDR_SIZE);
501 if (*addr != faddr) {
503 if (blseek(bfd, (off_t)*addr, SEEK_SET) < 0) {
505 Jmsg3(jcr, M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"),
506 edit_uint64(*addr, ec1), jcr->last_fname,
507 be.strerror(bfd->berrno));
517 if (flags & FO_GZIP) {
521 * NOTE! We only use uLong and Byte because they are
522 * needed by the zlib routines, they should not otherwise
525 compress_len = jcr->compress_buf_size;
526 Dmsg2(100, "Comp_len=%d msglen=%d\n", compress_len, wsize);
527 if ((stat=uncompress((Byte *)jcr->compress_buf, &compress_len,
528 (const Byte *)wbuf, (uLong)rsize)) != Z_OK) {
529 Jmsg(jcr, M_ERROR, 0, _("Uncompression error on file %s. ERR=%s\n"),
530 jcr->last_fname, zlib_strerror(stat));
533 wbuf = jcr->compress_buf;
534 wsize = compress_len;
535 Dmsg2(100, "Write uncompressed %d bytes, total before write=%s\n", compress_len, edit_uint64(jcr->JobBytes, ec1));
537 Jmsg(jcr, M_ERROR, 0, _("GZIP data stream found, but GZIP not configured!\n"));
541 Dmsg2(30, "Write %u bytes, total before write=%s\n", wsize, edit_uint64(jcr->JobBytes, ec1));
544 #ifdef USE_WIN32STREAMEXTRACTION
545 if (flags & FO_WIN32DECOMP) {
546 if (!processWin32BackupAPIBlock(bfd, wbuf, wsize)) {
548 Jmsg2(jcr, M_ERROR, 0, _("Write error in Win32 Block Decomposition on %s: %s\n"),
549 jcr->last_fname, be.strerror(bfd->berrno));
555 if (bwrite(bfd, wbuf, wsize) != (ssize_t)wsize) {
557 Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"),
558 jcr->last_fname, be.strerror(bfd->berrno));
562 jcr->JobBytes += wsize;
563 jcr->ReadBytes += rsize;