+ return stat;
+}
+
+/*
+ * Setup bctx for doing compression
+ */
+static bool setup_compression(bctx_t &bctx)
+{
+ JCR *jcr = bctx.jcr;
+
+#if defined(HAVE_LIBZ) || defined(HAVE_LZO)
+ bctx.compress_len = 0;
+ bctx.max_compress_len = 0;
+ bctx.cbuf = NULL;
+ #ifdef HAVE_LIBZ
+ int zstat;
+
+ if ((bctx.ff_pkt->flags & FO_COMPRESS) && bctx.ff_pkt->Compress_algo == COMPRESS_GZIP) {
+ if ((bctx.ff_pkt->flags & FO_SPARSE) || (bctx.ff_pkt->flags & FO_OFFSETS)) {
+ bctx.cbuf = (unsigned char *)jcr->compress_buf + OFFSET_FADDR_SIZE;
+ bctx.max_compress_len = jcr->compress_buf_size - OFFSET_FADDR_SIZE;
+ } else {
+ bctx.cbuf = (unsigned char *)jcr->compress_buf;
+ bctx.max_compress_len = jcr->compress_buf_size; /* set max length */
+ }
+ bctx.wbuf = jcr->compress_buf; /* compressed output here */
+ bctx.cipher_input = (uint8_t *)jcr->compress_buf; /* encrypt compressed data */
+
+ /**
+ * Only change zlib parameters if there is no pending operation.
+ * This should never happen as deflatereset is called after each
+ * deflate.
+ */
+
+ 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,
+ bctx.ff_pkt->Compress_level, Z_DEFAULT_STRATEGY)) != Z_OK) {
+ Jmsg(jcr, M_FATAL, 0, _("Compression deflateParams error: %d\n"), zstat);
+ jcr->setJobStatus(JS_ErrorTerminated);
+ return false;
+ }
+ }
+ }
+ #endif
+ #ifdef HAVE_LZO
+ memset(&bctx.ch, 0, sizeof(comp_stream_header));
+ bctx.cbuf2 = NULL;
+
+ if ((bctx.ff_pkt->flags & FO_COMPRESS) && bctx.ff_pkt->Compress_algo == COMPRESS_LZO1X) {
+ if ((bctx.ff_pkt->flags & FO_SPARSE) || (bctx.ff_pkt->flags & FO_OFFSETS)) {
+ bctx.cbuf = (unsigned char *)jcr->compress_buf + OFFSET_FADDR_SIZE;
+ bctx.cbuf2 = (unsigned char *)jcr->compress_buf + OFFSET_FADDR_SIZE + sizeof(comp_stream_header);
+ bctx.max_compress_len = jcr->compress_buf_size - OFFSET_FADDR_SIZE;
+ } else {
+ bctx.cbuf = (unsigned char *)jcr->compress_buf;
+ bctx.cbuf2 = (unsigned char *)jcr->compress_buf + sizeof(comp_stream_header);
+ bctx.max_compress_len = jcr->compress_buf_size; /* set max length */
+ }
+ bctx.ch.magic = COMPRESS_LZO1X;
+ bctx.ch.version = COMP_HEAD_VERSION;
+ bctx.wbuf = jcr->compress_buf; /* compressed output here */
+ bctx.cipher_input = (uint8_t *)jcr->compress_buf; /* encrypt compressed data */
+ }
+ #endif
+#endif
+ return true;
+}
+
+/*
+ * Send MacOS resource fork to SD
+ */
+#ifdef HAVE_DARWIN_OS
+static bool send_resource_fork(bctx_t &bctx)
+{
+ FF_PKT *ff_pkt = bctx.ff_pkt;
+ JCR *jcr = bctx.jcr;
+ BSOCK *sd = bctx.sd;
+ int stat;
+
+ /** 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);
+ }
+ return true;
+ }
+ flags = ff_pkt->flags;
+ ff_pkt->flags &= ~(FO_COMPRESS|FO_SPARSE|FO_OFFSETS);
+ if (flags & FO_ENCRYPT) {
+ rsrc_stream = STREAM_ENCRYPTED_MACOS_FORK_DATA;
+ } else {
+ rsrc_stream = STREAM_MACOS_FORK_DATA;
+ }
+ stat = send_data(bctx, rsrc_stream);
+ ff_pkt->flags = flags;
+ bclose(&ff_pkt->bfd);
+ if (!stat) {
+ return false;
+ }
+ }
+
+ 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 (bctx.digest) {
+ crypto_digest_update(bctx.digest, (uint8_t *)sd->msg, sd->msglen);
+ }
+ if (bctx.signing_digest) {
+ crypto_digest_update(bctx.signing_digest, (uint8_t *)sd->msg, sd->msglen);
+ }
+ sd->send();
+ sd->signal(BNET_EOD);
+ }
+ return true;
+}
+#endif
+
+static bool do_libz_compression(bctx_t &bctx)
+{
+#ifdef HAVE_LIBZ
+ JCR *jcr = bctx.jcr;
+ BSOCK *sd = bctx.sd;
+ int zstat;
+
+ /** Do compression if turned on */
+ if (bctx.ff_pkt->flags & FO_COMPRESS && bctx.ff_pkt->Compress_algo == COMPRESS_GZIP && jcr->pZLIB_compress_workset) {
+ Dmsg3(400, "cbuf=0x%x rbuf=0x%x len=%u\n", bctx.cbuf, bctx.rbuf, sd->msglen);
+
+ ((z_stream*)jcr->pZLIB_compress_workset)->next_in = (unsigned char *)bctx.rbuf;
+ ((z_stream*)jcr->pZLIB_compress_workset)->avail_in = sd->msglen;
+ ((z_stream*)jcr->pZLIB_compress_workset)->next_out = bctx.cbuf;
+ ((z_stream*)jcr->pZLIB_compress_workset)->avail_out = bctx.max_compress_len;
+
+ if ((zstat=deflate((z_stream*)jcr->pZLIB_compress_workset, Z_FINISH)) != Z_STREAM_END) {
+ Jmsg(jcr, M_FATAL, 0, _("Compression deflate error: %d\n"), zstat);
+ jcr->setJobStatus(JS_ErrorTerminated);
+ return false;
+ }
+ bctx.compress_len = ((z_stream*)jcr->pZLIB_compress_workset)->total_out;
+ /** reset zlib stream to be able to begin from scratch again */
+ if ((zstat=deflateReset((z_stream*)jcr->pZLIB_compress_workset)) != Z_OK) {
+ Jmsg(jcr, M_FATAL, 0, _("Compression deflateReset error: %d\n"), zstat);
+ jcr->setJobStatus(JS_ErrorTerminated);
+ return false;
+ }
+
+ Dmsg2(400, "GZIP compressed len=%d uncompressed len=%d\n", bctx.compress_len,
+ sd->msglen);
+
+ sd->msglen = bctx.compress_len; /* set compressed length */
+ bctx.cipher_input_len = bctx.compress_len;
+ }
+#endif
+ return true;
+}
+
+static bool do_lzo_compression(bctx_t &bctx)
+{
+#ifdef HAVE_LZO
+ JCR *jcr = bctx.jcr;
+ BSOCK *sd = bctx.sd;
+ int lzores;
+
+ /** Do compression if turned on */
+ if (bctx.ff_pkt->flags & FO_COMPRESS && bctx.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(bctx.cbuf, sizeof(comp_stream_header));
+
+ Dmsg3(400, "cbuf=0x%x rbuf=0x%x len=%u\n", bctx.cbuf, bctx.rbuf, sd->msglen);
+
+ lzores = lzo1x_1_compress((const unsigned char*)bctx.rbuf, sd->msglen, bctx.cbuf2,
+ &len, jcr->LZO_compress_workset);
+ bctx.compress_len = len;
+ if (lzores == LZO_E_OK && bctx.compress_len <= bctx.max_compress_len) {
+ /* complete header */
+ ser_uint32(COMPRESS_LZO1X);
+ ser_uint32(bctx.compress_len);
+ ser_uint16(bctx.ch.level);
+ ser_uint16(bctx.ch.version);
+ } else {
+ /** this should NEVER happen */
+ Jmsg(jcr, M_FATAL, 0, _("Compression LZO error: %d\n"), lzores);
+ jcr->setJobStatus(JS_ErrorTerminated);
+ return false;
+ }
+
+ Dmsg2(400, "LZO compressed len=%d uncompressed len=%d\n", bctx.compress_len,
+ sd->msglen);
+
+ bctx.compress_len += sizeof(comp_stream_header); /* add size of header */
+ sd->msglen = bctx.compress_len; /* set compressed length */
+ bctx.cipher_input_len = bctx.compress_len;
+ }
+#endif