/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-2009 Free Software Foundation Europe e.V.
The main author of Bacula is Kern Sibbald, with contributions from
many others, a complete list can be found in the file AUTHORS.
#include "bacula.h"
#include "filed.h"
+#ifdef HAVE_DARWIN_OS
+const bool have_darwin_os = true;
+#else
+const bool have_darwin_os = false;
+#endif
+
+#if defined(HAVE_ACL)
+const bool have_acl = true;
+#else
+const bool have_acl = false;
+#endif
+
+#if defined(HAVE_XATTR)
+const bool have_xattr = true;
+#else
+const bool have_xattr = false;
+#endif
+
/* Forward referenced functions */
int save_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level);
static int send_data(JCR *jcr, int stream, FF_PKT *ff_pkt, DIGEST *digest, DIGEST *signature_digest);
static void crypto_session_end(JCR *jcr);
static bool crypto_session_send(JCR *jcr, BSOCK *sd);
-/*
- * check for BSD nodump flag
- */
-static bool no_dump(JCR *jcr, FF_PKT *ff_pkt)
-{
-#if defined(HAVE_CHFLAGS) && defined(UF_NODUMP)
- if ( (ff_pkt->flags & FO_HONOR_NODUMP) &&
- (ff_pkt->statp.st_flags & UF_NODUMP) ) {
- Jmsg(jcr, M_INFO, 1, _(" NODUMP flag set - will not process %s\n"),
- ff_pkt->fname);
- return true; /* do not backup this file */
- }
-#endif
- return false; /* do backup */
-}
-
/*
* Find all the requested files and send them
* to the Storage daemon.
start_heartbeat_monitor(jcr);
- jcr->acl_data = get_pool_memory(PM_MESSAGE);
- jcr->xattr_data = get_pool_memory(PM_MESSAGE);
+ if (have_acl) {
+ jcr->acl_data = (acl_data_t *)malloc(sizeof(acl_data_t));
+ memset((caddr_t)jcr->acl_data, 0, sizeof(acl_data_t));
+ jcr->acl_data->content = get_pool_memory(PM_MESSAGE);
+ }
+
+ if (have_xattr) {
+ jcr->xattr_data = (xattr_data_t *)malloc(sizeof(xattr_data_t));
+ memset((caddr_t)jcr->xattr_data, 0, sizeof(xattr_data_t));
+ jcr->xattr_data->content = get_pool_memory(PM_MESSAGE);
+ }
/* Subroutine save_file() is called for each file */
if (!find_files(jcr, (FF_PKT *)jcr->ff, save_file, plugin_save)) {
set_jcr_job_status(jcr, JS_ErrorTerminated);
}
- accurate_send_deleted_list(jcr); /* send deleted list to SD */
+ if (have_acl && jcr->acl_data->nr_errors > 0) {
+ Jmsg(jcr, M_ERROR, 0, _("Encountered %ld acl errors while doing backup\n"),
+ jcr->acl_data->nr_errors);
+ }
+ if (have_xattr && jcr->xattr_data->nr_errors > 0) {
+ Jmsg(jcr, M_ERROR, 0, _("Encountered %ld xattr errors while doing backup\n"),
+ jcr->xattr_data->nr_errors);
+ }
- free_pool_memory(jcr->acl_data);
- free_pool_memory(jcr->xattr_data);
+ accurate_send_deleted_list(jcr); /* send deleted list to SD */
stop_heartbeat_monitor(jcr);
sd->signal(BNET_EOD); /* end of sending data */
+ if (have_acl && jcr->acl_data) {
+ free_pool_memory(jcr->acl_data->content);
+ free(jcr->acl_data);
+ jcr->acl_data = NULL;
+ }
+ if (have_xattr && jcr->xattr_data) {
+ free_pool_memory(jcr->xattr_data->content);
+ free(jcr->xattr_data);
+ jcr->xattr_data = NULL;
+ }
if (jcr->big_buf) {
free(jcr->big_buf);
jcr->big_buf = NULL;
break;
case FT_REGE:
Dmsg1(130, "FT_REGE saving: %s\n", ff_pkt->fname);
- if (no_dump(jcr, ff_pkt))
- return 1;
has_file_data = true;
break;
case FT_REG:
Dmsg1(130, "FT_REG saving: %s\n", ff_pkt->fname);
- if (no_dump(jcr, ff_pkt))
- return 1;
has_file_data = true;
break;
case FT_LNK:
break;
case FT_DIRBEGIN:
jcr->num_files_examined--; /* correct file count */
- if (no_dump(jcr, ff_pkt)) /* disable recursion on nodump directories */
- ff_pkt->flags |= FO_NO_RECURSION;
return 1; /* not used */
case FT_NORECURSE:
Jmsg(jcr, M_INFO, 1, _(" Recursion turned off. Will not descend from %s into %s\n"),
berrno be;
Jmsg(jcr, M_NOTSAVED, 0, _(" Could not access \"%s\": ERR=%s\n"), ff_pkt->fname,
be.bstrerror(ff_pkt->ff_errno));
- jcr->Errors++;
+ jcr->JobErrors++;
return 1;
}
case FT_NOFOLLOW: {
berrno be;
Jmsg(jcr, M_NOTSAVED, 0, _(" Could not follow link \"%s\": ERR=%s\n"),
ff_pkt->fname, be.bstrerror(ff_pkt->ff_errno));
- jcr->Errors++;
+ jcr->JobErrors++;
return 1;
}
case FT_NOSTAT: {
berrno be;
Jmsg(jcr, M_NOTSAVED, 0, _(" Could not stat \"%s\": ERR=%s\n"), ff_pkt->fname,
be.bstrerror(ff_pkt->ff_errno));
- jcr->Errors++;
+ jcr->JobErrors++;
return 1;
}
case FT_DIRNOCHG:
berrno be;
Jmsg(jcr, M_NOTSAVED, 0, _(" Could not open directory \"%s\": ERR=%s\n"),
ff_pkt->fname, be.bstrerror(ff_pkt->ff_errno));
- jcr->Errors++;
+ jcr->JobErrors++;
return 1;
}
default:
Jmsg(jcr, M_NOTSAVED, 0, _(" Unknown file type %d; not saved: %s\n"),
ff_pkt->type, ff_pkt->fname);
- jcr->Errors++;
+ jcr->JobErrors++;
return 1;
}
if (signing_digest == NULL) {
Jmsg(jcr, M_NOTSAVED, 0, _("%s signature digest initialization failed\n"),
stream_to_ascii(signing_algorithm));
- jcr->Errors++;
+ jcr->JobErrors++;
goto good_rtn;
}
}
berrno be;
Jmsg(jcr, M_NOTSAVED, 0, _(" Cannot open \"%s\": ERR=%s.\n"), ff_pkt->fname,
be.bstrerror());
- jcr->Errors++;
+ jcr->JobErrors++;
if (tid) {
stop_thread_timer(tid);
tid = NULL;
}
}
-#ifdef HAVE_DARWIN_OS
- /* Regular files can have resource forks and Finder Info */
- if (ff_pkt->type != FT_LNKSAVED && (S_ISREG(ff_pkt->statp.st_mode) &&
- ff_pkt->flags & FO_HFSPLUS)) {
- if (ff_pkt->hfsinfo.rsrclength > 0) {
- int flags;
- int rsrc_stream;
- if (!bopen_rsrc(&ff_pkt->bfd, ff_pkt->fname, O_RDONLY | O_BINARY, 0) < 0) {
- ff_pkt->ff_errno = errno;
- berrno be;
- Jmsg(jcr, M_NOTSAVED, -1, _(" Cannot open resource fork for \"%s\": ERR=%s.\n"),
- ff_pkt->fname, be.bstrerror());
- jcr->Errors++;
- if (is_bopen(&ff_pkt->bfd)) {
- bclose(&ff_pkt->bfd);
+ if (have_darwin_os) {
+ /* Regular files can have resource forks and Finder Info */
+ if (ff_pkt->type != FT_LNKSAVED && (S_ISREG(ff_pkt->statp.st_mode) &&
+ ff_pkt->flags & FO_HFSPLUS)) {
+ if (ff_pkt->hfsinfo.rsrclength > 0) {
+ int flags;
+ int rsrc_stream;
+ if (!bopen_rsrc(&ff_pkt->bfd, ff_pkt->fname, O_RDONLY | O_BINARY, 0) < 0) {
+ ff_pkt->ff_errno = errno;
+ berrno be;
+ Jmsg(jcr, M_NOTSAVED, -1, _(" Cannot open resource fork for \"%s\": ERR=%s.\n"),
+ ff_pkt->fname, be.bstrerror());
+ jcr->JobErrors++;
+ if (is_bopen(&ff_pkt->bfd)) {
+ bclose(&ff_pkt->bfd);
+ }
+ goto good_rtn;
+ }
+ flags = ff_pkt->flags;
+ ff_pkt->flags &= ~(FO_GZIP|FO_SPARSE);
+ if (flags & FO_ENCRYPT) {
+ rsrc_stream = STREAM_ENCRYPTED_MACOS_FORK_DATA;
+ } else {
+ rsrc_stream = STREAM_MACOS_FORK_DATA;
+ }
+ stat = send_data(jcr, rsrc_stream, ff_pkt, digest, signing_digest);
+ ff_pkt->flags = flags;
+ bclose(&ff_pkt->bfd);
+ if (!stat) {
+ goto bail_out;
}
- goto good_rtn;
}
- flags = ff_pkt->flags;
- ff_pkt->flags &= ~(FO_GZIP|FO_SPARSE);
- if (flags & FO_ENCRYPT) {
- rsrc_stream = STREAM_ENCRYPTED_MACOS_FORK_DATA;
- } else {
- rsrc_stream = STREAM_MACOS_FORK_DATA;
+
+ Dmsg1(300, "Saving Finder Info for \"%s\"\n", ff_pkt->fname);
+ sd->fsend("%ld %d 0", jcr->JobFiles, STREAM_HFSPLUS_ATTRIBUTES);
+ Dmsg1(300, "bfiled>stored:header %s\n", sd->msg);
+ pm_memcpy(sd->msg, ff_pkt->hfsinfo.fndrinfo, 32);
+ sd->msglen = 32;
+ if (digest) {
+ crypto_digest_update(digest, (uint8_t *)sd->msg, sd->msglen);
}
- stat = send_data(jcr, rsrc_stream, ff_pkt, digest, signing_digest);
- ff_pkt->flags = flags;
- bclose(&ff_pkt->bfd);
- if (!stat) {
- goto bail_out;
+ if (signing_digest) {
+ crypto_digest_update(signing_digest, (uint8_t *)sd->msg, sd->msglen);
}
+ sd->send();
+ sd->signal(BNET_EOD);
}
-
- Dmsg1(300, "Saving Finder Info for \"%s\"\n", ff_pkt->fname);
- sd->fsend("%ld %d 0", jcr->JobFiles, STREAM_HFSPLUS_ATTRIBUTES);
- Dmsg1(300, "bfiled>stored:header %s\n", sd->msg);
- pm_memcpy(sd->msg, ff_pkt->hfsinfo.fndrinfo, 32);
- sd->msglen = 32;
- if (digest) {
- crypto_digest_update(digest, (uint8_t *)sd->msg, sd->msglen);
- }
- if (signing_digest) {
- crypto_digest_update(signing_digest, (uint8_t *)sd->msg, sd->msglen);
- }
- sd->send();
- sd->signal(BNET_EOD);
}
-#endif
/*
- * Save ACLs for anything not being a symlink.
+ * Save ACLs when requested and available for anything not being a symlink and not being a plugin.
*/
- if (ff_pkt->flags & FO_ACL && ff_pkt->type != FT_LNK) {
- if (!build_acl_streams(jcr, ff_pkt))
- goto bail_out;
+ if (have_acl) {
+ if (ff_pkt->flags & FO_ACL && ff_pkt->type != FT_LNK && !ff_pkt->cmd_plugin) {
+ switch (build_acl_streams(jcr, ff_pkt)) {
+ case bacl_exit_fatal:
+ goto bail_out;
+ case bacl_exit_error:
+ /*
+ * Non-fatal errors, count them and when the number is under ACL_REPORT_ERR_MAX_PER_JOB
+ * print the error message set by the lower level routine in jcr->errmsg.
+ */
+ if (jcr->acl_data->nr_errors < ACL_REPORT_ERR_MAX_PER_JOB) {
+ Jmsg(jcr, M_ERROR, 0, "%s", jcr->errmsg);
+ }
+ jcr->acl_data->nr_errors++;
+ break;
+ case bacl_exit_ok:
+ break;
+ }
+ }
}
/*
- * Save Extended Attributes for all files.
+ * Save Extended Attributes when requested and available for all files not being a plugin.
*/
- if (ff_pkt->flags & FO_XATTR) {
- if (!build_xattr_streams(jcr, ff_pkt))
- goto bail_out;
+ if (have_xattr) {
+ if (ff_pkt->flags & FO_XATTR && !ff_pkt->cmd_plugin) {
+ switch (build_xattr_streams(jcr, ff_pkt)) {
+ case bxattr_exit_fatal:
+ goto bail_out;
+ case bxattr_exit_error:
+ /*
+ * Non-fatal errors, count them and when the number is under XATTR_REPORT_ERR_MAX_PER_JOB
+ * print the error message set by the lower level routine in jcr->errmsg.
+ */
+ if (jcr->xattr_data->nr_errors < XATTR_REPORT_ERR_MAX_PER_JOB) {
+ Jmsg(jcr, M_ERROR, 0, "%s", jcr->errmsg);
+ }
+ jcr->xattr_data->nr_errors++;
+ break;
+ case bxattr_exit_ok:
+ break;
+ }
+ }
}
/* Terminate the signing digest and send it to the Storage daemon */
* Currently this is not a problem as the only other stream, resource forks,
* are not handled as sparse files.
*/
-int send_data(JCR *jcr, int stream, FF_PKT *ff_pkt, DIGEST *digest,
- DIGEST *signing_digest)
+static int send_data(JCR *jcr, int stream, FF_PKT *ff_pkt, DIGEST *digest,
+ DIGEST *signing_digest)
{
BSOCK *sd = jcr->store_bsock;
uint64_t fileAddr = 0; /* file address */
* <file-index> <stream> <info>
*/
if (!sd->fsend("%ld %d 0", jcr->JobFiles, stream)) {
- Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
- sd->bstrerror());
+ if (!job_canceled(jcr)) {
+ Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
+ sd->bstrerror());
+ }
goto err;
}
Dmsg1(300, ">stored: datahdr %s\n", sd->msg);
}
sd->msg = wbuf; /* set correct write buffer */
if (!sd->send()) {
- Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
- sd->bstrerror());
+ if (!job_canceled(jcr)) {
+ Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
+ sd->bstrerror());
+ }
goto err;
}
Dmsg1(130, "Send data to SD len=%d\n", sd->msglen);
berrno be;
Jmsg(jcr, M_ERROR, 0, _("Read error on file %s. ERR=%s\n"),
ff_pkt->fname, be.bstrerror(ff_pkt->bfd.berrno));
- if (jcr->Errors++ > 1000) { /* insanity check */
+ if (jcr->JobErrors++ > 1000) { /* insanity check */
Jmsg(jcr, M_FATAL, 0, _("Too many errors.\n"));
}
} else if (ff_pkt->flags & FO_ENCRYPT) {
sd->msglen = encrypted_len; /* set encrypted length */
sd->msg = jcr->crypto.crypto_buf; /* set correct write buffer */
if (!sd->send()) {
- Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
- sd->bstrerror());
+ if (!job_canceled(jcr)) {
+ Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
+ sd->bstrerror());
+ }
goto err;
}
Dmsg1(130, "Send data to SD len=%d\n", sd->msglen);
}
if (!sd->signal(BNET_EOD)) { /* indicate end of file data */
- Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
- sd->bstrerror());
+ if (!job_canceled(jcr)) {
+ Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
+ sd->bstrerror());
+ }
goto err;
}
Jmsg0(jcr, M_FATAL, 0, _("Invalid file flags, no supported data stream type.\n"));
return false;
}
- encode_stat(attribs, ff_pkt, data_stream);
+ encode_stat(attribs, &ff_pkt->statp, ff_pkt->LinkFI, data_stream);
/* Now possibly extend the attributes */
attr_stream = encode_attribsEx(jcr, attribsEx, ff_pkt);
* <file-index> <stream> <info>
*/
if (!sd->fsend("%ld %d 0", jcr->JobFiles, attr_stream)) {
- Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
- sd->bstrerror());
+ if (!job_canceled(jcr)) {
+ Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
+ sd->bstrerror());
+ }
return false;
}
Dmsg1(300, ">stored: attrhdr %s\n", sd->msg);
Dmsg2(300, ">stored: attr len=%d: %s\n", sd->msglen, sd->msg);
if (!stat) {
- Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
- sd->bstrerror());
+ if (!job_canceled(jcr)) {
+ Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
+ sd->bstrerror());
+ }
return false;
}
sd->signal(BNET_EOD); /* indicate end of attributes data */