#include "bacula.h"
#include "filed.h"
+#include "ch.h"
#ifdef HAVE_DARWIN_OS
const bool have_darwin_os = true;
* Note, we adjust the read size to be smaller so that the
* same output buffer can be used without growing it.
*
+ * For LZO1X compression the recommended value is :
+ * output_block_size = input_block_size + (input_block_size / 16) + 64 + 3 + sizeof(comp_stream_header)
+ *
* The zlib compression workset is initialized here to minimize
* the "per file" load. The jcr member is only set, if the init
* was successful.
+ *
+ * For the same reason, lzo compression is initialized here.
*/
+#ifdef HAVE_LZO
+ jcr->compress_buf_size = MAX(jcr->buf_size + (jcr->buf_size / 16) + 67 + (int)sizeof(comp_stream_header), jcr->buf_size + ((jcr->buf_size+999) / 1000) + 30);
+ jcr->compress_buf = get_memory(jcr->compress_buf_size);
+#else
jcr->compress_buf_size = jcr->buf_size + ((jcr->buf_size+999) / 1000) + 30;
jcr->compress_buf = get_memory(jcr->compress_buf_size);
+#endif
#ifdef HAVE_LIBZ
z_stream *pZlibStream = (z_stream*)malloc(sizeof(z_stream));
}
#endif
+#ifdef HAVE_LZO
+ lzo_voidp pLzoMem = (lzo_voidp) malloc(LZO1X_1_MEM_COMPRESS);
+ if (pLzoMem) {
+ if (lzo_init() == LZO_E_OK) {
+ jcr->LZO_compress_workset = pLzoMem;
+ } else {
+ free (pLzoMem);
+ }
+ }
+#endif
+
if (!crypto_session_start(jcr)) {
return false;
}
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);
+ memset(jcr->acl_data, 0, sizeof(acl_data_t));
+ jcr->acl_data->u.build = (acl_build_data_t *)malloc(sizeof(acl_build_data_t));
+ memset(jcr->acl_data->u.build, 0, sizeof(acl_build_data_t));
+ jcr->acl_data->u.build->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);
+ memset(jcr->xattr_data, 0, sizeof(xattr_data_t));
+ jcr->xattr_data->u.build = (xattr_build_data_t *)malloc(sizeof(xattr_build_data_t));
+ memset(jcr->xattr_data->u.build, 0, sizeof(xattr_build_data_t));
+ jcr->xattr_data->u.build->content = get_pool_memory(PM_MESSAGE);
}
/** Subroutine save_file() is called for each file */
jcr->setJobStatus(JS_ErrorTerminated);
}
- 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_acl && jcr->acl_data->u.build->nr_errors > 0) {
+ Jmsg(jcr, M_WARNING, 0, _("Encountered %ld acl errors while doing backup\n"),
+ jcr->acl_data->u.build->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);
+ if (have_xattr && jcr->xattr_data->u.build->nr_errors > 0) {
+ Jmsg(jcr, M_WARNING, 0, _("Encountered %ld xattr errors while doing backup\n"),
+ jcr->xattr_data->u.build->nr_errors);
}
close_vss_backup_session(jcr);
sd->signal(BNET_EOD); /* end of sending data */
if (have_acl && jcr->acl_data) {
- free_pool_memory(jcr->acl_data->content);
+ free_pool_memory(jcr->acl_data->u.build->content);
+ free(jcr->acl_data->u.build);
free(jcr->acl_data);
jcr->acl_data = NULL;
}
if (have_xattr && jcr->xattr_data) {
- free_pool_memory(jcr->xattr_data->content);
+ free_pool_memory(jcr->xattr_data->u.build->content);
+ free(jcr->xattr_data->u.build);
free(jcr->xattr_data);
jcr->xattr_data = NULL;
}
free (jcr->pZLIB_compress_workset);
jcr->pZLIB_compress_workset = NULL;
}
+ if (jcr->LZO_compress_workset) {
+ free (jcr->LZO_compress_workset);
+ jcr->LZO_compress_workset = NULL;
+ }
+
crypto_session_end(jcr);
{
bool do_read = false;
bool plugin_started = false;
+ bool do_plugin_set = false;
int stat, data_stream;
int rtnstat = 0;
DIGEST *digest = NULL;
int digest_stream = STREAM_NONE;
SIGNATURE *sig = NULL;
bool has_file_data = false;
+ struct save_pkt sp; /* use by option plugin */
// TODO landonf: Allow the user to specify the digest algorithm
#ifdef HAVE_SHA2
crypto_digest_t signing_algorithm = CRYPTO_DIGEST_SHA256;
case FT_RESTORE_FIRST:
Dmsg1(100, "FT_RESTORE_FIRST saving: %s\n", ff_pkt->fname);
break;
+ case FT_PLUGIN_CONFIG:
+ Dmsg1(100, "FT_PLUGIN_CONFIG saving: %s\n", ff_pkt->fname);
+ break;
case FT_DIRBEGIN:
jcr->num_files_examined--; /* correct file count */
return 1; /* not used */
jcr->JobErrors++;
return 1;
}
+ case FT_DELETED:
+ Dmsg1(130, "FT_DELETED: %s\n", ff_pkt->fname);
+ break;
default:
Jmsg(jcr, M_NOTSAVED, 0, _(" Unknown file type %d; not saved: %s\n"),
ff_pkt->type, ff_pkt->fname);
if (ff_pkt->flags & FO_PORTABLE) {
set_portable_backup(&ff_pkt->bfd); /* disable Win32 BackupRead() */
}
+
if (ff_pkt->cmd_plugin) {
+ do_plugin_set = true;
+
+ /* option and cmd plugin are not compatible together */
+ } else if (ff_pkt->opt_plugin) {
+
+ /* ask the option plugin what to do with this file */
+ switch (plugin_option_handle_file(jcr, ff_pkt, &sp)) {
+ case bRC_OK:
+ Dmsg2(10, "Option plugin %s will be used to backup %s\n",
+ ff_pkt->plugin, ff_pkt->fname);
+ do_plugin_set = true;
+ break;
+ case bRC_Skip:
+ Dmsg2(10, "Option plugin %s decided to skip %s\n",
+ ff_pkt->plugin, ff_pkt->fname);
+ goto good_rtn;
+ default:
+ Dmsg2(10, "Option plugin %s decided to let bacula handle %s\n",
+ ff_pkt->plugin, ff_pkt->fname);
+ break;
+ }
+ }
+
+ if (do_plugin_set) {
/* Tell bfile that it needs to call plugin */
if (!set_cmd_plugin(&ff_pkt->bfd, jcr)) {
goto bail_out;
goto bail_out;
}
/** Meta data only for restore object */
- if (ff_pkt->type == FT_RESTORE_FIRST) {
+ if (IS_FT_OBJECT(ff_pkt->type)) {
+ goto good_rtn;
+ }
+ /** Meta data only for deleted files */
+ if (ff_pkt->type == FT_DELETED) {
goto good_rtn;
}
-
/** Set up the encryption context and send the session data to the SD */
if (has_file_data && jcr->crypto.pki_encrypt) {
if (!crypto_session_send(jcr, sd)) {
do_read = true;
}
- if (ff_pkt->cmd_plugin) {
+ if (ff_pkt->cmd_plugin && !ff_pkt->no_read) {
do_read = true;
}
goto good_rtn;
}
flags = ff_pkt->flags;
- ff_pkt->flags &= ~(FO_GZIP|FO_SPARSE|FO_OFFSETS);
+ ff_pkt->flags &= ~(FO_COMPRESS|FO_SPARSE|FO_OFFSETS);
if (flags & FO_ENCRYPT) {
rsrc_stream = STREAM_ENCRYPTED_MACOS_FORK_DATA;
} else {
}
/**
- * Save ACLs when requested and available for anything not being a symlink and not being a plugin.
+ * Save ACLs when requested and available for anything not being a symlink
+ * and not being a plugin.
*/
if (have_acl) {
if (ff_pkt->flags & FO_ACL && ff_pkt->type != FT_LNK && !ff_pkt->cmd_plugin) {
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.
+ * 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);
+ if (jcr->acl_data->u.build->nr_errors < ACL_REPORT_ERR_MAX_PER_JOB) {
+ Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);
}
- jcr->acl_data->nr_errors++;
+ jcr->acl_data->u.build->nr_errors++;
break;
case bacl_exit_ok:
break;
}
/**
- * Save Extended Attributes when requested and available for all files not being a plugin.
+ * Save Extended Attributes when requested and available for all files not
+ * being a plugin.
*/
if (have_xattr) {
if (ff_pkt->flags & FO_XATTR && !ff_pkt->cmd_plugin) {
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.
+ * 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);
+ if (jcr->xattr_data->u.build->nr_errors < XATTR_REPORT_ERR_MAX_PER_JOB) {
+ Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);
}
- jcr->xattr_data->nr_errors++;
+ jcr->xattr_data->u.build->nr_errors++;
break;
case bxattr_exit_ok:
break;
rtnstat = jcr->is_canceled() ? 0 : 1; /* good return if not canceled */
bail_out:
- if (jcr->is_incomplete()) {
+ if (jcr->is_incomplete() || jcr->is_canceled()) {
rtnstat = 0;
}
- if (ff_pkt->cmd_plugin && plugin_started) {
+ if (plugin_started) {
send_plugin_name(jcr, sd, false); /* signal end of plugin data */
}
+ if (ff_pkt->opt_plugin) {
+ jcr->plugin_sp = NULL; /* sp is local to this function */
+ jcr->plugin_ctx = NULL;
+ jcr->plugin = NULL;
+ jcr->opt_plugin = false;
+ }
if (digest) {
crypto_digest_free(digest);
}
Dmsg1(300, "Saving data, type=%d\n", ff_pkt->type);
-#ifdef HAVE_LIBZ
+#if defined(HAVE_LIBZ) || defined(HAVE_LZO)
uLong compress_len = 0;
uLong max_compress_len = 0;
const Bytef *cbuf = NULL;
+ #ifdef HAVE_LIBZ
int zstat;
- if (ff_pkt->flags & FO_GZIP) {
+ if ((ff_pkt->flags & FO_COMPRESS) && ff_pkt->Compress_algo == COMPRESS_GZIP) {
if ((ff_pkt->flags & FO_SPARSE) || (ff_pkt->flags & FO_OFFSETS)) {
cbuf = (Bytef *)jcr->compress_buf + OFFSET_FADDR_SIZE;
max_compress_len = jcr->compress_buf_size - OFFSET_FADDR_SIZE;
if (((z_stream*)jcr->pZLIB_compress_workset)->total_in == 0) {
/** set gzip compression level - must be done per file */
if ((zstat=deflateParams((z_stream*)jcr->pZLIB_compress_workset,
- ff_pkt->GZIP_level, Z_DEFAULT_STRATEGY)) != Z_OK) {
+ ff_pkt->Compress_level, Z_DEFAULT_STRATEGY)) != Z_OK) {
Jmsg(jcr, M_FATAL, 0, _("Compression deflateParams error: %d\n"), zstat);
jcr->setJobStatus(JS_ErrorTerminated);
goto err;
}
}
}
+ #endif
+ #ifdef HAVE_LZO
+ Bytef *cbuf2;
+ int lzores;
+ comp_stream_header ch;
+
+ memset(&ch, 0, sizeof(comp_stream_header));
+ cbuf2 = NULL;
+
+ if ((ff_pkt->flags & FO_COMPRESS) && ff_pkt->Compress_algo == COMPRESS_LZO1X) {
+ if ((ff_pkt->flags & FO_SPARSE) || (ff_pkt->flags & FO_OFFSETS)) {
+ cbuf = (Bytef *)jcr->compress_buf + OFFSET_FADDR_SIZE;
+ cbuf2 = (Bytef *)jcr->compress_buf + OFFSET_FADDR_SIZE + sizeof(comp_stream_header);
+ max_compress_len = jcr->compress_buf_size - OFFSET_FADDR_SIZE;
+ } else {
+ cbuf = (Bytef *)jcr->compress_buf;
+ cbuf2 = (Bytef *)jcr->compress_buf + sizeof(comp_stream_header);
+ max_compress_len = jcr->compress_buf_size; /* set max length */
+ }
+ ch.magic = COMPRESS_LZO1X;
+ ch.version = COMP_HEAD_VERSION;
+ wbuf = jcr->compress_buf; /* compressed output here */
+ cipher_input = (uint8_t *)jcr->compress_buf; /* encrypt compressed data */
+ }
+ #endif
#else
const uint32_t max_compress_len = 0;
#endif
#ifdef HAVE_LIBZ
/** Do compression if turned on */
- if (ff_pkt->flags & FO_GZIP && jcr->pZLIB_compress_workset) {
+ if (ff_pkt->flags & FO_COMPRESS && ff_pkt->Compress_algo == COMPRESS_GZIP && jcr->pZLIB_compress_workset) {
Dmsg3(400, "cbuf=0x%x rbuf=0x%x len=%u\n", cbuf, rbuf, sd->msglen);
((z_stream*)jcr->pZLIB_compress_workset)->next_in = (Bytef *)rbuf;
goto err;
}
- Dmsg2(400, "compressed len=%d uncompressed len=%d\n", compress_len,
+ Dmsg2(400, "GZIP compressed len=%d uncompressed len=%d\n", compress_len,
+ sd->msglen);
+
+ sd->msglen = compress_len; /* set compressed length */
+ cipher_input_len = compress_len;
+ }
+#endif
+#ifdef HAVE_LZO
+ /** Do compression if turned on */
+ if (ff_pkt->flags & FO_COMPRESS && ff_pkt->Compress_algo == COMPRESS_LZO1X && jcr->LZO_compress_workset) {
+ lzo_uint len; /* TODO: See with the latest patch how to handle lzo_uint with 64bit */
+
+ ser_declare;
+ ser_begin(cbuf, sizeof(comp_stream_header));
+
+ Dmsg3(400, "cbuf=0x%x rbuf=0x%x len=%u\n", cbuf, rbuf, sd->msglen);
+
+ lzores = lzo1x_1_compress((const unsigned char*)rbuf, sd->msglen, cbuf2,
+ &len, jcr->LZO_compress_workset);
+ compress_len = len;
+ if (lzores == LZO_E_OK && compress_len <= max_compress_len)
+ {
+ /* complete header */
+ ser_uint32(COMPRESS_LZO1X);
+ ser_uint32(compress_len);
+ ser_uint16(ch.level);
+ ser_uint16(ch.version);
+ } else {
+ /** this should NEVER happen */
+ Jmsg(jcr, M_FATAL, 0, _("Compression LZO error: %d\n"), lzores);
+ jcr->setJobStatus(JS_ErrorTerminated);
+ goto err;
+ }
+
+ Dmsg2(400, "LZO compressed len=%d uncompressed len=%d\n", compress_len,
sd->msglen);
+ compress_len += sizeof(comp_stream_header); /* add size of header */
sd->msglen = compress_len; /* set compressed length */
cipher_input_len = compress_len;
}
#endif
+
/**
* Note, here we prepend the current record length to the beginning
* of the encrypted data. This is because both sparse and compression
encode_stat(attribs, &ff_pkt->statp, sizeof(ff_pkt->statp), ff_pkt->LinkFI, data_stream);
/** Now possibly extend the attributes */
- if (ff_pkt->type == FT_RESTORE_FIRST) {
+ if (IS_FT_OBJECT(ff_pkt->type)) {
attr_stream = STREAM_RESTORE_OBJECT;
} else {
attribsEx = attribsExBuf;
* For a directory, link is the same as fname, but with trailing
* slash. For a linked file, link is the link.
*/
- if (ff_pkt->type != FT_DELETED) { /* already stripped */
+ if (!IS_FT_OBJECT(ff_pkt->type) && ff_pkt->type != FT_DELETED) { /* already stripped */
strip_path(ff_pkt);
}
switch (ff_pkt->type) {
ff_pkt->type, ff_pkt->link, 0, attribs, 0, 0,
attribsEx, 0, ff_pkt->delta_seq, 0);
break;
+ case FT_PLUGIN_CONFIG:
case FT_RESTORE_FIRST:
comp_len = ff_pkt->object_len;
ff_pkt->object_compression = 0;
if (ff_pkt->object_len > 1000) {
/* Big object, compress it */
- int stat;
comp_len = ff_pkt->object_len + 1000;
POOLMEM *comp_obj = get_memory(comp_len);
- stat = Zdeflate(ff_pkt->object, ff_pkt->object_len, comp_obj, comp_len);
+ /* *** FIXME *** check Zdeflate error */
+ Zdeflate(ff_pkt->object, ff_pkt->object_len, comp_obj, comp_len);
if (comp_len < ff_pkt->object_len) {
ff_pkt->object = comp_obj;
ff_pkt->object_compression = 1; /* zlib level 9 compression */
attribsEx, 0, ff_pkt->delta_seq, 0);
break;
}
- if (ff_pkt->type != FT_DELETED) {
+
+ if (!IS_FT_OBJECT(ff_pkt->type) && ff_pkt->type != FT_DELETED) {
unstrip_path(ff_pkt);
}
while (*in && !IsPathSeparator(*in)) {
out++; in++;
}
- out++; in++;
- numsep++; /* one separator seen */
+ if (*in) { /* Not at the end of the string */
+ out++; in++;
+ numsep++; /* one separator seen */
+ }
for (stripped=0; stripped<count && *in; stripped++) {
while (*in && !IsPathSeparator(*in)) {
in++; /* skip chars */
Jmsg(jcr, msg_type, 0, _("VSS Writer (BackupComplete): %s\n"), g_pVSSClient->GetWriterInfo(i));
}
}
+ /* Generate Job global writer metadata */
WCHAR *metadata = g_pVSSClient->GetMetadata();
if (metadata) {
FF_PKT *ff_pkt = jcr->ff;
- ff_pkt->fname = (char *)"job";
+ ff_pkt->fname = (char *)"*all*"; /* for all plugins */
ff_pkt->type = FT_RESTORE_FIRST;
ff_pkt->LinkFI = 0;
ff_pkt->object_name = (char *)"job_metadata.xml";