*
*/
/*
- Copyright (C) 2000-2003 Kern Sibbald and John Walker
+ Copyright (C) 2000-2004 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
#include "bacula.h"
#include "filed.h"
+#ifdef HAVE_ACL
+#include <sys/acl.h>
+#include <acl/libacl.h>
+#endif
+
/* Data received from Storage Daemon */
static char rec_header[] = "rechdr %ld %ld %ld %ld %ld";
/* Forward referenced functions */
+#ifdef HAVE_LIBZ
+static const char *zlib_strerror(int stat);
+#endif
#define RETRY 10 /* retry wait time */
*/
void do_restore(JCR *jcr)
{
- int wherelen;
BSOCK *sd;
int32_t stream;
uint32_t size;
uint32_t VolSessionId, VolSessionTime;
int32_t file_index;
- int extract = FALSE;
+ bool extract = false;
BFILE bfd;
int stat;
uint32_t total = 0; /* Job total but only 32 bits for debug */
uint64_t fileAddr = 0; /* file write address */
int non_support_data = 0;
int non_support_attr = 0;
+ int non_support_acl = 0;
int prog_name_msg = 0;
ATTR *attr;
-
- wherelen = strlen(jcr->where);
+#ifdef HAVE_ACL
+ acl_t acl;
+#endif
binit(&bfd);
sd = jcr->store_bsock;
set_jcr_job_status(jcr, JS_Running);
- if (!bnet_set_buffer_size(sd, MAX_NETWORK_BUFFER_SIZE, BNET_SETBUF_READ)) {
+ LockRes();
+ CLIENT *client = (CLIENT *)GetNextRes(R_CLIENT, NULL);
+ UnlockRes();
+ uint32_t buf_size;
+ if (client) {
+ buf_size = client->max_network_buffer_size;
+ } else {
+ buf_size = 0; /* use default */
+ }
+ if (!bnet_set_buffer_size(sd, buf_size, BNET_SETBUF_WRITE)) {
set_jcr_job_status(jcr, JS_ErrorTerminated);
return;
}
switch (stream) {
case STREAM_UNIX_ATTRIBUTES:
case STREAM_UNIX_ATTRIBUTES_EX:
-
Dmsg1(30, "Stream=Unix Attributes. extract=%d\n", extract);
/* If extracting, it was from previous stream, so
* close the output file.
Jmsg0(jcr, M_ERROR, 0, _("Logic error output file should be open\n"));
}
set_attributes(jcr, attr, &bfd);
- extract = FALSE;
+ extract = false;
Dmsg0(30, "Stop extracting.\n");
}
jcr->num_files_examined++;
Dmsg1(30, "Outfile=%s\n", attr->ofname);
- extract = FALSE;
+ extract = false;
stat = create_file(jcr, attr, &bfd, jcr->replace);
switch (stat) {
case CF_ERROR:
case CF_SKIP:
break;
case CF_EXTRACT:
- extract = TRUE;
+ extract = true;
P(jcr->mutex);
- pm_strcpy(&jcr->last_fname, attr->ofname);
+ pm_strcpy(jcr->last_fname, attr->ofname);
V(jcr->mutex);
jcr->JobFiles++;
fileAddr = 0;
break;
case CF_CREATED:
P(jcr->mutex);
- pm_strcpy(&jcr->last_fname, attr->ofname);
+ pm_strcpy(jcr->last_fname, attr->ofname);
V(jcr->mutex);
jcr->JobFiles++;
fileAddr = 0;
}
break;
- /* Windows Backup data stream */
- case STREAM_WIN32_DATA:
- if (!is_win32_backup()) {
- if (!non_support_data) {
- Jmsg(jcr, M_ERROR, 0, _("%s stream not supported on this Client.\n"),
- stream_to_ascii(stream));
- }
- extract = FALSE;
- non_support_data++;
- continue;
- }
- goto extract_data;
-
/* Data stream */
case STREAM_FILE_DATA:
case STREAM_SPARSE_DATA:
-
-extract_data:
+ case STREAM_WIN32_DATA:
if (extract) {
if (stream == STREAM_SPARSE_DATA) {
ser_declare;
if (fileAddr != faddr) {
fileAddr = faddr;
if (blseek(&bfd, (off_t)fileAddr, SEEK_SET) < 0) {
+ berrno be;
+ be.set_errno(bfd.berrno);
Jmsg3(jcr, M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"),
- edit_uint64(fileAddr, ec1), attr->ofname, berror(&bfd));
- extract = FALSE;
+ edit_uint64(fileAddr, ec1), attr->ofname, be.strerror());
+ extract = false;
+ bclose(&bfd);
continue;
}
}
Dmsg2(30, "Write %u bytes, total before write=%u\n", wsize, total);
if ((uint32_t)bwrite(&bfd, wbuf, wsize) != wsize) {
Dmsg0(0, "===Write error===\n");
- Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: ERR=%s\n"), attr->ofname, berror(&bfd));
- extract = FALSE;
+ berrno be;
+ be.set_errno(bfd.berrno);
+ Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: ERR=%s\n"), attr->ofname,
+ be.strerror());
+ extract = false;
+ bclose(&bfd);
continue;
}
total += wsize;
}
break;
- /* Windows Backup GZIP data stream */
- case STREAM_WIN32_GZIP_DATA:
- if (!is_win32_backup()) {
- if (!non_support_attr) {
- Jmsg(jcr, M_ERROR, 0, _("%s stream not supported on this Client.\n"),
- stream_to_ascii(stream));
- }
- extract = FALSE;
- non_support_attr++;
- continue;
- }
- /* Fall through desired */
-
/* GZIP data stream */
case STREAM_GZIP_DATA:
case STREAM_SPARSE_GZIP_DATA:
+ case STREAM_WIN32_GZIP_DATA:
#ifdef HAVE_LIBZ
if (extract) {
- ser_declare;
uLong compress_len;
- uint64_t faddr;
- char ec1[50];
int stat;
if (stream == STREAM_SPARSE_GZIP_DATA) {
+ ser_declare;
+ uint64_t faddr;
+ char ec1[50];
wbuf = sd->msg + SPARSE_FADDR_SIZE;
wsize = sd->msglen - SPARSE_FADDR_SIZE;
ser_begin(sd->msg, SPARSE_FADDR_SIZE);
if (fileAddr != faddr) {
fileAddr = faddr;
if (blseek(&bfd, (off_t)fileAddr, SEEK_SET) < 0) {
+ berrno be;
+ be.set_errno(bfd.berrno);
Jmsg3(jcr, M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"),
- edit_uint64(fileAddr, ec1), attr->ofname, berror(&bfd));
- extract = FALSE;
+ edit_uint64(fileAddr, ec1), attr->ofname, be.strerror());
+ extract = false;
+ bclose(&bfd);
continue;
}
}
Dmsg2(100, "Comp_len=%d msglen=%d\n", compress_len, wsize);
if ((stat=uncompress((Byte *)jcr->compress_buf, &compress_len,
(const Byte *)wbuf, (uLong)wsize)) != Z_OK) {
- Jmsg(jcr, M_ERROR, 0, _("Uncompression error. ERR=%d\n"), stat);
- extract = FALSE;
+ Jmsg(jcr, M_ERROR, 0, _("Uncompression error on file %s. ERR=%s\n"),
+ attr->ofname, zlib_strerror(stat));
+ extract = false;
+ bclose(&bfd);
continue;
}
Dmsg2(100, "Write uncompressed %d bytes, total before write=%d\n", compress_len, total);
if ((uLong)bwrite(&bfd, jcr->compress_buf, compress_len) != compress_len) {
Dmsg0(0, "===Write error===\n");
- Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"), attr->ofname, berror(&bfd));
- extract = FALSE;
+ berrno be;
+ be.set_errno(bfd.berrno);
+ Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"), attr->ofname, be.strerror());
+ extract = false;
+ bclose(&bfd);
continue;
}
total += compress_len;
#else
if (extract) {
Jmsg(jcr, M_ERROR, 0, _("GZIP data stream found, but GZIP not configured!\n"));
- extract = FALSE;
+ extract = false;
+ bclose(&bfd);
continue;
}
#endif
break;
+ case STREAM_UNIX_ATTRIBUTES_ACL:
+#ifdef HAVE_ACL
+ /* Recover ACL from stream and check it */
+ acl = acl_from_text(sd->msg);
+ if (acl_valid(acl) != 0) {
+ Jmsg1(jcr, M_WARNING, 0, "Failure in the ACL of %s! FD is not able to restore it!\n", jcr->last_fname);
+ acl_free(acl);
+ }
+
+ /* Try to restore ACL */
+ if (attr->type == FT_DIREND) {
+ /* Directory */
+ if (acl_set_file(jcr->last_fname, ACL_TYPE_DEFAULT, acl) != 0 &&
+ acl_set_file(jcr->last_fname, ACL_TYPE_ACCESS, acl) != 0) {
+ Jmsg1(jcr, M_WARNING, 0, "Error! Can't restore ACL of directory: %s! Maybe system does not support ACLs!\n", jcr->last_fname);
+ }
+ /* File or Link */
+ } else if (acl_set_file(jcr->last_fname, ACL_TYPE_ACCESS, acl) != 0) {
+ Jmsg1(jcr, M_WARNING, 0, "Error! Can't restore ACL of file: %s! Maybe system does not support ACLs!\n", jcr->last_fname);
+ }
+ acl_free(acl);
+ Dmsg1(200, "ACL of file: %s successfully restored!", jcr->last_fname);
+ break;
+#else
+ non_support_acl++;
+ break; /* unconfigured, ignore */
+#endif
+
case STREAM_MD5_SIGNATURE:
case STREAM_SHA1_SIGNATURE:
break;
Jmsg0(jcr, M_ERROR, 0, _("Logic error output file should be open but is not.\n"));
}
set_attributes(jcr, attr, &bfd);
- extract = FALSE;
+ extract = false;
}
Jmsg(jcr, M_ERROR, 0, _("Unknown stream=%d ignored. This shouldn't happen!\n"), stream);
Dmsg2(0, "None of above!!! stream=%d data=%s\n", stream,sd->msg);
free(jcr->compress_buf);
jcr->compress_buf = NULL;
}
+ bclose(&bfd);
free_attr(attr);
Dmsg2(10, "End Do Restore. Files=%d Bytes=%" lld "\n", jcr->JobFiles,
jcr->JobBytes);
Jmsg(jcr, M_ERROR, 0, _("%d non-supported data streams and %d non-supported attrib streams ignored.\n"),
non_support_data, non_support_attr);
}
+ if (non_support_acl) {
+ Jmsg(jcr, M_INFO, 0, _("%d non-supported acl streams ignored.\n"), non_support_acl);
+ }
+
}
+
+#ifdef HAVE_LIBZ
+/*
+ * Convert ZLIB error code into an ASCII message
+ */
+static const char *zlib_strerror(int stat)
+{
+ if (stat >= 0) {
+ return "None";
+ }
+ switch (stat) {
+ case Z_ERRNO:
+ return "Zlib errno";
+ case Z_STREAM_ERROR:
+ return "Zlib stream error";
+ case Z_DATA_ERROR:
+ return "Zlib data error";
+ case Z_MEM_ERROR:
+ return "Zlib memory error";
+ case Z_BUF_ERROR:
+ return "Zlib buffer error";
+ case Z_VERSION_ERROR:
+ return "Zlib version error";
+ default:
+ return "*none*";
+ }
+}
+#endif