2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2016 Kern Sibbald
6 The original author of Bacula is Kern Sibbald, with contributions
7 from many others, a complete list can be found in the file AUTHORS.
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
17 Bacula(R) is a registered trademark of Kern Sibbald.
20 * Bacula File Daemon backup.c send file attributes and data
21 * to the Storage daemon.
23 * Kern Sibbald, March MM
32 const bool have_lzo = true;
34 const bool have_lzo = false;
38 const bool have_libz = true;
40 const bool have_libz = false;
43 /* Forward referenced functions */
44 int save_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level);
45 static int send_data(bctx_t &bctx, int stream);
46 static void close_vss_backup_session(JCR *jcr);
48 static bool send_resource_fork(bctx_t &bctx);
50 static bool setup_compression(bctx_t &bctx);
51 static bool do_lzo_compression(bctx_t &bctx);
52 static bool do_libz_compression(bctx_t &bctx);
55 * Find all the requested files and send them
56 * to the Storage daemon.
58 * Note, we normally carry on a one-way
59 * conversation from this point on with the SD, simply blasting
60 * data to him. To properly know what is going on, we
61 * also run a "heartbeat" monitor which reads the socket and
62 * reacts accordingly (at the moment it has nothing to do
63 * except echo the heartbeat to the Director).
66 bool blast_data_to_storage_daemon(JCR *jcr, char *addr)
70 // TODO landonf: Allow user to specify encryption algorithm
72 sd = jcr->store_bsock;
74 jcr->setJobStatus(JS_Running);
76 Dmsg1(300, "bfiled: opened data connection %d to stored\n", sd->m_fd);
79 CLIENT *client = (CLIENT *)GetNextRes(R_CLIENT, NULL);
83 buf_size = client->max_network_buffer_size;
85 buf_size = 0; /* use default */
87 if (!sd->set_buffer_size(buf_size, BNET_SETBUF_WRITE)) {
88 jcr->setJobStatus(JS_ErrorTerminated);
89 Jmsg(jcr, M_FATAL, 0, _("Cannot set buffer size FD->SD.\n"));
93 jcr->buf_size = sd->msglen;
95 * Adjust for compression so that output buffer is
96 * 12 bytes + 0.1% larger than input buffer plus 18 bytes.
97 * This gives a bit extra plus room for the sparse addr if any.
98 * Note, we adjust the read size to be smaller so that the
99 * same output buffer can be used without growing it.
101 * For LZO1X compression the recommended value is :
102 * output_block_size = input_block_size + (input_block_size / 16) + 64 + 3 + sizeof(comp_stream_header)
104 * The zlib compression workset is initialized here to minimize
105 * the "per file" load. The jcr member is only set, if the init
108 * For the same reason, lzo compression is initialized here.
111 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);
112 jcr->compress_buf = get_memory(jcr->compress_buf_size);
114 jcr->compress_buf_size = jcr->buf_size + ((jcr->buf_size+999) / 1000) + 30;
115 jcr->compress_buf = get_memory(jcr->compress_buf_size);
119 z_stream *pZlibStream = (z_stream*)malloc(sizeof(z_stream));
121 pZlibStream->zalloc = Z_NULL;
122 pZlibStream->zfree = Z_NULL;
123 pZlibStream->opaque = Z_NULL;
124 pZlibStream->state = Z_NULL;
126 if (deflateInit(pZlibStream, Z_DEFAULT_COMPRESSION) == Z_OK) {
127 jcr->pZLIB_compress_workset = pZlibStream;
135 lzo_voidp pLzoMem = (lzo_voidp) malloc(LZO1X_1_MEM_COMPRESS);
137 if (lzo_init() == LZO_E_OK) {
138 jcr->LZO_compress_workset = pLzoMem;
145 if (!crypto_session_start(jcr)) {
149 set_find_options(jcr->ff, jcr->incremental, jcr->mtime);
150 set_find_snapshot_function(jcr->ff, snapshot_convert_path);
152 /** in accurate mode, we overload the find_one check function */
154 set_find_changed_function((FF_PKT *)jcr->ff, accurate_check_file);
156 start_heartbeat_monitor(jcr);
158 jcr->xacl = (XACL*)new_xacl();
160 /* Subroutine save_file() is called for each file */
161 if (!find_files(jcr, (FF_PKT *)jcr->ff, save_file, plugin_save)) {
162 ok = false; /* error */
163 jcr->setJobStatus(JS_ErrorTerminated);
166 if (jcr->xacl->get_acl_nr_errors() > 0) {
167 Jmsg(jcr, M_WARNING, 0, _("Had %ld acl errors while doing backup\n"), jcr->xacl->get_acl_nr_errors());
170 if (jcr->xacl->get_xattr_nr_errors() > 0) {
171 Jmsg(jcr, M_WARNING, 0, _("Had %ld xattr errors while doing backup\n"), jcr->xacl->get_xattr_nr_errors());
174 /* Delete or keep snapshots */
175 close_snapshot_backup_session(jcr);
176 close_vss_backup_session(jcr);
178 accurate_finish(jcr); /* send deleted or base file list to SD */
180 stop_heartbeat_monitor(jcr);
182 sd->signal(BNET_EOD); /* end of sending data */
189 bfree_and_null(jcr->big_buf);
191 if (jcr->compress_buf) {
192 free_and_null_pool_memory(jcr->compress_buf);
194 if (jcr->pZLIB_compress_workset) {
195 /* Free the zlib stream */
197 deflateEnd((z_stream *)jcr->pZLIB_compress_workset);
199 bfree_and_null(jcr->pZLIB_compress_workset);
201 if (jcr->LZO_compress_workset) {
202 bfree_and_null(jcr->LZO_compress_workset);
205 crypto_session_end(jcr);
208 Dmsg1(100, "end blast_data ok=%d\n", ok);
214 * Called here by find() for each file included.
215 * This is a callback. The original is find_files() above.
217 * Send the file and its data to the Storage daemon.
221 * -1 to ignore file/directory (not used here)
223 int save_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level)
225 bool do_read = false;
226 bool plugin_started = false;
227 bool do_plugin_set = false;
230 bool has_file_data = false;
231 struct save_pkt sp; /* used by option plugin */
232 BSOCK *sd = jcr->store_bsock;
233 bctx_t bctx; /* backup context */
235 memset(&bctx, 0, sizeof(bctx));
237 bctx.ff_pkt = ff_pkt;
241 time_t now = time(NULL);
242 if (jcr->last_stat_time == 0) {
243 jcr->last_stat_time = now;
244 jcr->stat_interval = 30; /* Default 30 seconds */
245 } else if (now >= jcr->last_stat_time + jcr->stat_interval) {
246 jcr->dir_bsock->fsend("Progress Job=x files=%ld bytes=%lld bps=%ld\n",
247 jcr->JobFiles, jcr->JobBytes, jcr->LastRate);
248 jcr->last_stat_time = now;
251 if (jcr->is_canceled() || jcr->is_incomplete()) {
252 Dmsg0(100, "Job canceled by user or marked incomplete.\n");
256 jcr->num_files_examined++; /* bump total file count */
258 switch (ff_pkt->type) {
259 case FT_LNKSAVED: /* Hard linked, file already saved */
260 Dmsg2(130, "FT_LNKSAVED hard link: %s => %s\n", ff_pkt->fname, ff_pkt->link);
263 Dmsg1(130, "FT_REGE saving: %s\n", ff_pkt->fname);
264 has_file_data = true;
267 Dmsg1(130, "FT_REG saving: %s\n", ff_pkt->fname);
268 has_file_data = true;
271 Dmsg2(130, "FT_LNK saving: %s -> %s\n", ff_pkt->fname, ff_pkt->link);
273 case FT_RESTORE_FIRST:
274 Dmsg1(100, "FT_RESTORE_FIRST saving: %s\n", ff_pkt->fname);
276 case FT_PLUGIN_CONFIG:
277 Dmsg1(100, "FT_PLUGIN_CONFIG saving: %s\n", ff_pkt->fname);
280 jcr->num_files_examined--; /* correct file count */
281 return 1; /* not used */
283 Jmsg(jcr, M_INFO, 1, _(" Recursion turned off. Will not descend from %s into %s\n"),
284 ff_pkt->top_fname, ff_pkt->fname);
285 ff_pkt->type = FT_DIREND; /* Backup only the directory entry */
288 /* Suppress message for /dev filesystems */
289 if (!is_in_fileset(ff_pkt)) {
290 Jmsg(jcr, M_INFO, 1, _(" %s is a different filesystem. Will not descend from %s into it.\n"),
291 ff_pkt->fname, ff_pkt->top_fname);
293 ff_pkt->type = FT_DIREND; /* Backup only the directory entry */
296 Jmsg(jcr, M_INFO, 1, _(" Disallowed filesystem. Will not descend from %s into %s\n"),
297 ff_pkt->top_fname, ff_pkt->fname);
298 ff_pkt->type = FT_DIREND; /* Backup only the directory entry */
301 Jmsg(jcr, M_INFO, 1, _(" Disallowed drive type. Will not descend into %s\n"),
307 Dmsg1(130, "FT_DIREND: %s\n", ff_pkt->link);
310 Dmsg1(130, "FT_SPEC saving: %s\n", ff_pkt->fname);
311 if (S_ISSOCK(ff_pkt->statp.st_mode)) {
312 Jmsg(jcr, M_SKIPPED, 1, _(" Socket file skipped: %s\n"), ff_pkt->fname);
317 Dmsg1(130, "FT_RAW saving: %s\n", ff_pkt->fname);
318 has_file_data = true;
321 Dmsg1(130, "FT_FIFO saving: %s\n", ff_pkt->fname);
325 Jmsg(jcr, M_NOTSAVED, 0, _(" Could not access \"%s\": ERR=%s\n"), ff_pkt->fname,
326 be.bstrerror(ff_pkt->ff_errno));
332 Jmsg(jcr, M_NOTSAVED, 0, _(" Could not follow link \"%s\": ERR=%s\n"),
333 ff_pkt->fname, be.bstrerror(ff_pkt->ff_errno));
339 Jmsg(jcr, M_NOTSAVED, 0, _(" Could not stat \"%s\": ERR=%s\n"), ff_pkt->fname,
340 be.bstrerror(ff_pkt->ff_errno));
346 Jmsg(jcr, M_SKIPPED, 1, _(" Unchanged file skipped: %s\n"), ff_pkt->fname);
349 Jmsg(jcr, M_NOTSAVED, 0, _(" Archive file not saved: %s\n"), ff_pkt->fname);
353 Jmsg(jcr, M_NOTSAVED, 0, _(" Could not open directory \"%s\": ERR=%s\n"),
354 ff_pkt->fname, be.bstrerror(ff_pkt->ff_errno));
359 Dmsg1(130, "FT_DELETED: %s\n", ff_pkt->fname);
362 Jmsg(jcr, M_NOTSAVED, 0, _(" Unknown file type %d; not saved: %s\n"),
363 ff_pkt->type, ff_pkt->fname);
368 Dmsg1(130, "bfiled: sending %s to stored\n", ff_pkt->fname);
370 /** Digests and encryption are only useful if there's file data */
371 if (has_file_data && !crypto_setup_digests(bctx)) {
375 /** Initialize the file descriptor we use for data and other streams. */
377 if (ff_pkt->flags & FO_PORTABLE) {
378 set_portable_backup(&ff_pkt->bfd); /* disable Win32 BackupRead() */
381 if (ff_pkt->cmd_plugin) {
382 do_plugin_set = true;
384 /* option and cmd plugin are not compatible together */
385 } else if (ff_pkt->opt_plugin) {
387 /* ask the option plugin what to do with this file */
388 switch (plugin_option_handle_file(jcr, ff_pkt, &sp)) {
390 Dmsg2(10, "Option plugin %s will be used to backup %s\n",
391 ff_pkt->plugin, ff_pkt->fname);
392 do_plugin_set = true;
395 Dmsg2(10, "Option plugin %s decided to skip %s\n",
396 ff_pkt->plugin, ff_pkt->fname);
399 Dmsg2(10, "Option plugin %s decided to let bacula handle %s\n",
400 ff_pkt->plugin, ff_pkt->fname);
406 /* Tell bfile that it needs to call plugin */
407 if (!set_cmd_plugin(&ff_pkt->bfd, jcr)) {
410 send_plugin_name(jcr, sd, true); /* signal start of plugin data */
411 plugin_started = true;
414 /** Send attributes -- must be done after binit() */
415 if (!encode_and_send_attributes(bctx)) {
418 /** Meta data only for restore object */
419 if (IS_FT_OBJECT(ff_pkt->type)) {
422 /** Meta data only for deleted files */
423 if (ff_pkt->type == FT_DELETED) {
426 /** Set up the encryption context and send the session data to the SD */
427 if (has_file_data && jcr->crypto.pki_encrypt) {
428 if (!crypto_session_send(jcr, sd)) {
434 * Open any file with data that we intend to save, then save it.
436 * Note, if is_win32_backup, we must open the Directory so that
437 * the BackupRead will save its permissions and ownership streams.
439 if (ff_pkt->type != FT_LNKSAVED && S_ISREG(ff_pkt->statp.st_mode)) {
441 do_read = !is_portable_backup(&ff_pkt->bfd) || ff_pkt->statp.st_size > 0;
443 do_read = ff_pkt->statp.st_size > 0;
445 } else if (ff_pkt->type == FT_RAW || ff_pkt->type == FT_FIFO ||
446 ff_pkt->type == FT_REPARSE || ff_pkt->type == FT_JUNCTION ||
447 (!is_portable_backup(&ff_pkt->bfd) && ff_pkt->type == FT_DIREND)) {
451 if (ff_pkt->cmd_plugin && !ff_pkt->no_read) {
455 Dmsg2(150, "type=%d do_read=%d\n", ff_pkt->type, do_read);
459 if (ff_pkt->type == FT_FIFO) {
460 tid = start_thread_timer(jcr, pthread_self(), 60);
464 int noatime = ff_pkt->flags & FO_NOATIME ? O_NOATIME : 0;
465 ff_pkt->bfd.reparse_point = (ff_pkt->type == FT_REPARSE ||
466 ff_pkt->type == FT_JUNCTION);
467 set_fattrs(&ff_pkt->bfd, &ff_pkt->statp);
468 if (bopen(&ff_pkt->bfd, ff_pkt->fname, O_RDONLY | O_BINARY | noatime, 0) < 0) {
469 ff_pkt->ff_errno = errno;
471 Jmsg(jcr, M_NOTSAVED, 0, _(" Cannot open \"%s\": ERR=%s.\n"), ff_pkt->fname,
475 stop_thread_timer(tid);
481 stop_thread_timer(tid);
485 stat = send_data(bctx, bctx.data_stream);
487 if (ff_pkt->flags & FO_CHKCHANGES) {
488 has_file_changed(jcr, ff_pkt);
491 bclose(&ff_pkt->bfd);
498 #ifdef HAVE_DARWIN_OS
499 if (!send_resource_fork(bctx)) {
505 * Save ACLs and Extended Attributes when requested and available
506 * for anything not being a symlink and not being a plugin (why not?).
509 if (jcr->xacl->backup_acl(jcr, ff_pkt) == bRC_XACL_error) {
512 if (jcr->xacl->backup_xattr(jcr, ff_pkt) == bRC_XACL_error) {
517 if (!crypto_terminate_digests(bctx)) {
525 if (jcr->is_incomplete() || jcr->is_canceled()) {
526 Dmsg0(100, "Job canceled by user or marked incomplete.\n");
529 if (plugin_started) {
530 send_plugin_name(jcr, sd, false); /* signal end of plugin data */
532 if (ff_pkt->opt_plugin) {
533 jcr->plugin_sp = NULL; /* sp is local to this function */
534 jcr->plugin_ctx = NULL;
536 jcr->opt_plugin = false;
543 * Send data read from an already open file descriptor.
545 * We return 1 on success and 0 on errors.
548 * We use ff_pkt->statp.st_size when FO_SPARSE to know when to stop
550 * Currently this is not a problem as the only other stream, resource forks,
551 * are not handled as sparse files.
553 static int send_data(bctx_t &bctx, int stream)
556 BSOCK *sd = jcr->store_bsock;
558 #ifdef FD_NO_SEND_TEST
562 bctx.rsize = jcr->buf_size;
564 bctx.cipher_ctx = NULL;
565 bctx.msgsave = sd->msg;
566 bctx.rbuf = sd->msg; /* read buffer */
567 bctx.wbuf = sd->msg; /* write buffer */
568 bctx.cipher_input = (uint8_t *)bctx.rbuf; /* encrypt uncompressed data */
570 Dmsg1(300, "Saving data, type=%d\n", bctx.ff_pkt->type);
572 if (!setup_compression(bctx)) {
576 if (bctx.ff_pkt->flags & FO_ENCRYPT && !crypto_allocate_ctx(bctx)) {
581 * Send Data header to Storage daemon
582 * <file-index> <stream> <expected stream length>
584 if (!sd->fsend("%ld %d %lld", jcr->JobFiles, stream,
585 (int64_t)bctx.ff_pkt->statp.st_size)) {
586 if (!jcr->is_job_canceled()) {
587 Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
592 Dmsg1(300, ">stored: datahdr %s\n", sd->msg);
595 * Make space at beginning of buffer for fileAddr because this
596 * same buffer will be used for writing if compression is off.
598 if ((bctx.ff_pkt->flags & FO_SPARSE) || (bctx.ff_pkt->flags & FO_OFFSETS)) {
599 bctx.rbuf += OFFSET_FADDR_SIZE;
600 bctx.rsize -= OFFSET_FADDR_SIZE;
601 #if defined(HAVE_FREEBSD_OS) || defined(__FreeBSD_kernel__)
603 * To read FreeBSD partitions, the read size must be
606 bctx.rsize = (bctx.rsize/512) * 512;
610 /** a RAW device read on win32 only works if the buffer is a multiple of 512 */
612 if (S_ISBLK(bctx.ff_pkt->statp.st_mode)) {
613 bctx.rsize = (bctx.rsize/512) * 512;
615 Dmsg1(200, "Fattrs=0X%x\n", bctx.ff_pkt->bfd.fattrs);
616 if (bctx.ff_pkt->bfd.fattrs & FILE_ATTRIBUTE_ENCRYPTED) {
617 if (!p_ReadEncryptedFileRaw) {
618 Jmsg0(bctx.jcr, M_FATAL, 0, _("Windows Encrypted data not supported on this OS.\n"));
621 /* This single call reads all EFS data delivers it to a callback */
622 if (p_ReadEncryptedFileRaw((PFE_EXPORT_FUNC)read_efs_data_cb, &bctx,
623 bctx.ff_pkt->bfd.pvContext) != 0) {
626 /* All read, so skip to finish sending */
629 /* Fall through to standard bread() loop */
633 * Normal read the file data in a loop and send it to SD
635 while ((sd->msglen=(uint32_t)bread(&bctx.ff_pkt->bfd, bctx.rbuf, bctx.rsize)) > 0) {
636 if (!process_and_send_data(bctx)) {
639 } /* end while read file data */
643 if (sd->msglen < 0) { /* error */
645 Jmsg(jcr, M_ERROR, 0, _("Read error on file %s. ERR=%s\n"),
646 bctx.ff_pkt->fname, be.bstrerror(bctx.ff_pkt->bfd.berrno));
647 if (jcr->JobErrors++ > 1000) { /* insanity check */
648 Jmsg(jcr, M_FATAL, 0, _("Too many errors. JobErrors=%d.\n"), jcr->JobErrors);
650 } else if (bctx.ff_pkt->flags & FO_ENCRYPT) {
652 * For encryption, we must call finalize to push out any
655 if (!crypto_cipher_finalize(bctx.cipher_ctx, (uint8_t *)jcr->crypto.crypto_buf,
656 &bctx.encrypted_len)) {
657 /* Padding failed. Shouldn't happen. */
658 Jmsg(jcr, M_FATAL, 0, _("Encryption padding error\n"));
662 /** Note, on SSL pre-0.9.7, there is always some output */
663 if (bctx.encrypted_len > 0) {
664 sd->msglen = bctx.encrypted_len; /* set encrypted length */
665 sd->msg = jcr->crypto.crypto_buf; /* set correct write buffer */
667 if (!jcr->is_job_canceled()) {
668 Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
673 Dmsg1(130, "Send data to SD len=%d\n", sd->msglen);
674 jcr->JobBytes += sd->msglen; /* count bytes saved possibly compressed/encrypted */
675 sd->msg = bctx.msgsave; /* restore bnet buffer */
680 if (!sd->signal(BNET_EOD)) { /* indicate end of file data */
681 if (!jcr->is_job_canceled()) {
682 Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
688 /** Free the cipher context */
689 if (bctx.cipher_ctx) {
690 crypto_cipher_free(bctx.cipher_ctx);
695 /** Free the cipher context */
696 if (bctx.cipher_ctx) {
697 crypto_cipher_free(bctx.cipher_ctx);
700 sd->msg = bctx.msgsave; /* restore bnet buffer */
707 * Apply processing (sparse, compression, encryption, and
710 bool process_and_send_data(bctx_t &bctx)
715 /** Check for sparse blocks */
716 if (bctx.ff_pkt->flags & FO_SPARSE) {
718 bool allZeros = false;
719 if ((sd->msglen == bctx.rsize &&
720 bctx.fileAddr+sd->msglen < (uint64_t)bctx.ff_pkt->statp.st_size) ||
721 ((bctx.ff_pkt->type == FT_RAW || bctx.ff_pkt->type == FT_FIFO) &&
722 (uint64_t)bctx.ff_pkt->statp.st_size == 0)) {
723 allZeros = is_buf_zero(bctx.rbuf, bctx.rsize);
726 /** Put file address as first data in buffer */
727 ser_begin(bctx.wbuf, OFFSET_FADDR_SIZE);
728 ser_uint64(bctx.fileAddr); /* store fileAddr in begin of buffer */
730 bctx.fileAddr += sd->msglen; /* update file address */
731 /** Skip block of all zeros */
733 return true; /* skip block of zeros */
735 } else if (bctx.ff_pkt->flags & FO_OFFSETS) {
737 ser_begin(bctx.wbuf, OFFSET_FADDR_SIZE);
738 ser_uint64(bctx.ff_pkt->bfd.offset); /* store offset in begin of buffer */
741 jcr->ReadBytes += sd->msglen; /* count bytes read */
743 /** Uncompressed cipher input length */
744 bctx.cipher_input_len = sd->msglen;
746 /** Update checksum if requested */
748 crypto_digest_update(bctx.digest, (uint8_t *)bctx.rbuf, sd->msglen);
751 /** Update signing digest if requested */
752 if (bctx.signing_digest) {
753 crypto_digest_update(bctx.signing_digest, (uint8_t *)bctx.rbuf, sd->msglen);
756 if (have_libz && !do_libz_compression(bctx)) {
760 if (have_lzo && !do_lzo_compression(bctx)) {
765 * Note, here we prepend the current record length to the beginning
766 * of the encrypted data. This is because both sparse and compression
767 * restore handling want records returned to them with exactly the
768 * same number of bytes that were processed in the backup handling.
769 * That is, both are block filters rather than a stream. When doing
770 * compression, the compression routines may buffer data, so that for
771 * any one record compressed, when it is decompressed the same size
772 * will not be obtained. Of course, the buffered data eventually comes
773 * out in subsequent crypto_cipher_update() calls or at least
774 * when crypto_cipher_finalize() is called. Unfortunately, this
775 * "feature" of encryption enormously complicates the restore code.
777 if (bctx.ff_pkt->flags & FO_ENCRYPT) {
778 uint32_t initial_len = 0;
781 if ((bctx.ff_pkt->flags & FO_SPARSE) || (bctx.ff_pkt->flags & FO_OFFSETS)) {
782 bctx.cipher_input_len += OFFSET_FADDR_SIZE;
785 /** Encrypt the length of the input block */
786 uint8_t packet_len[sizeof(uint32_t)];
788 ser_begin(packet_len, sizeof(uint32_t));
789 ser_uint32(bctx.cipher_input_len); /* store data len in begin of buffer */
790 Dmsg1(20, "Encrypt len=%d\n", bctx.cipher_input_len);
792 if (!crypto_cipher_update(bctx.cipher_ctx, packet_len, sizeof(packet_len),
793 (uint8_t *)jcr->crypto.crypto_buf, &initial_len)) {
794 /** Encryption failed. Shouldn't happen. */
795 Jmsg(jcr, M_FATAL, 0, _("Encryption error\n"));
799 /** Encrypt the input block */
800 if (crypto_cipher_update(bctx.cipher_ctx, bctx.cipher_input, bctx.cipher_input_len,
801 (uint8_t *)&jcr->crypto.crypto_buf[initial_len], &bctx.encrypted_len)) {
802 if ((initial_len + bctx.encrypted_len) == 0) {
803 /** No full block of data available, read more data */
806 Dmsg2(400, "encrypted len=%d unencrypted len=%d\n", bctx.encrypted_len,
808 sd->msglen = initial_len + bctx.encrypted_len; /* set encrypted length */
810 /** Encryption failed. Shouldn't happen. */
811 Jmsg(jcr, M_FATAL, 0, _("Encryption error\n"));
816 /* Send the buffer to the Storage daemon */
817 if ((bctx.ff_pkt->flags & FO_SPARSE) || (bctx.ff_pkt->flags & FO_OFFSETS)) {
818 sd->msglen += OFFSET_FADDR_SIZE; /* include fileAddr in size */
820 sd->msg = bctx.wbuf; /* set correct write buffer */
822 if (!jcr->is_job_canceled()) {
823 Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
828 Dmsg1(130, "Send data to SD len=%d\n", sd->msglen);
830 jcr->JobBytes += sd->msglen; /* count bytes saved possibly compressed/encrypted */
831 sd->msg = bctx.msgsave; /* restore read buffer */
838 bool encode_and_send_attributes(bctx_t &bctx)
840 BSOCK *sd = bctx.jcr->store_bsock;
842 FF_PKT *ff_pkt = bctx.ff_pkt;
843 char attribs[MAXSTRING];
844 char attribsExBuf[MAXSTRING];
845 char *attribsEx = NULL;
849 int hangup = get_hangup();
850 int blowup = get_blowup();
851 #ifdef FD_NO_SEND_TEST
855 Dmsg1(300, "encode_and_send_attrs fname=%s\n", ff_pkt->fname);
856 /** Find what data stream we will use, then encode the attributes */
857 if ((bctx.data_stream = select_data_stream(ff_pkt)) == STREAM_NONE) {
858 /* This should not happen */
859 Jmsg0(jcr, M_FATAL, 0, _("Invalid file flags, no supported data stream type.\n"));
862 encode_stat(attribs, &ff_pkt->statp, sizeof(ff_pkt->statp), ff_pkt->LinkFI, bctx.data_stream);
864 /** Now possibly extend the attributes */
865 if (IS_FT_OBJECT(ff_pkt->type)) {
866 attr_stream = STREAM_RESTORE_OBJECT;
868 attribsEx = attribsExBuf;
869 attr_stream = encode_attribsEx(jcr, attribsEx, ff_pkt);
872 Dmsg3(300, "File %s\nattribs=%s\nattribsEx=%s\n", ff_pkt->fname, attribs, attribsEx);
875 jcr->JobFiles++; /* increment number of files sent */
876 ff_pkt->FileIndex = jcr->JobFiles; /* return FileIndex */
877 pm_strcpy(jcr->last_fname, ff_pkt->fname);
880 /* Debug code: check if we must hangup */
881 if (hangup > 0 && (jcr->JobFiles > (uint32_t)hangup)) {
882 jcr->setJobStatus(JS_Incomplete);
883 Jmsg1(jcr, M_FATAL, 0, "Debug hangup requested after %d files.\n", hangup);
888 if (blowup > 0 && (jcr->JobFiles > (uint32_t)blowup)) {
889 Jmsg1(jcr, M_ABORT, 0, "Debug blowup requested after %d files.\n", blowup);
894 * Send Attributes header to Storage daemon
895 * <file-index> <stream> <info>
897 if (!sd->fsend("%ld %d 0", jcr->JobFiles, attr_stream)) {
898 if (!jcr->is_canceled() && !jcr->is_incomplete()) {
899 Jmsg2(jcr, M_FATAL, 0, _("Network send error to SD. Data=%s ERR=%s\n"),
900 sd->msg, sd->bstrerror());
904 Dmsg1(300, ">stored: attrhdr %s\n", sd->msg);
907 * Send file attributes to Storage daemon
910 * Filename (full path)
912 * Link name (if type==FT_LNK or FT_LNKSAVED)
913 * Encoded extended-attributes (for Win32)
915 * or send Restore Object to Storage daemon
919 * Object_len (possibly compressed)
920 * Object_full_len (not compressed)
926 * For a directory, link is the same as fname, but with trailing
927 * slash. For a linked file, link is the link.
929 if (!IS_FT_OBJECT(ff_pkt->type) && ff_pkt->type != FT_DELETED) { /* already stripped */
932 switch (ff_pkt->type) {
935 Dmsg3(300, "Link %d %s to %s\n", jcr->JobFiles, ff_pkt->fname, ff_pkt->link);
936 stat = sd->fsend("%ld %d %s%c%s%c%s%c%s%c%u%c", jcr->JobFiles,
937 ff_pkt->type, ff_pkt->fname, 0, attribs, 0,
938 ff_pkt->link, 0, attribsEx, 0, ff_pkt->delta_seq, 0);
943 /* Here link is the canonical filename (i.e. with trailing slash) */
944 stat = sd->fsend("%ld %d %s%c%s%c%c%s%c%u%c", jcr->JobFiles,
945 ff_pkt->type, ff_pkt->link, 0, attribs, 0, 0,
946 attribsEx, 0, ff_pkt->delta_seq, 0);
948 case FT_PLUGIN_CONFIG:
949 case FT_RESTORE_FIRST:
950 comp_len = ff_pkt->object_len;
951 ff_pkt->object_compression = 0;
952 if (ff_pkt->object_len > 1000) {
953 /* Big object, compress it */
954 comp_len = ff_pkt->object_len + 1000;
955 POOLMEM *comp_obj = get_memory(comp_len);
956 /* *** FIXME *** check Zdeflate error */
957 Zdeflate(ff_pkt->object, ff_pkt->object_len, comp_obj, comp_len);
958 if (comp_len < ff_pkt->object_len) {
959 ff_pkt->object = comp_obj;
960 ff_pkt->object_compression = 1; /* zlib level 9 compression */
962 /* Uncompressed object smaller, use it */
963 comp_len = ff_pkt->object_len;
965 Dmsg2(100, "Object compressed from %d to %d bytes\n", ff_pkt->object_len, comp_len);
967 sd->msglen = Mmsg(sd->msg, "%d %d %d %d %d %d %s%c%s%c",
968 jcr->JobFiles, ff_pkt->type, ff_pkt->object_index,
969 comp_len, ff_pkt->object_len, ff_pkt->object_compression,
970 ff_pkt->fname, 0, ff_pkt->object_name, 0);
971 sd->msg = check_pool_memory_size(sd->msg, sd->msglen + comp_len + 2);
972 memcpy(sd->msg + sd->msglen, ff_pkt->object, comp_len);
973 /* Note we send one extra byte so Dir can store zero after object */
974 sd->msglen += comp_len + 1;
976 if (ff_pkt->object_compression) {
977 free_and_null_pool_memory(ff_pkt->object);
981 stat = sd->fsend("%ld %d %s%c%s%c%c%s%c%d%c", jcr->JobFiles,
982 ff_pkt->type, ff_pkt->fname, 0, attribs, 0, 0, attribsEx, 0,
983 ff_pkt->delta_seq, 0);
986 stat = sd->fsend("%ld %d %s%c%s%c%c%s%c%u%c", jcr->JobFiles,
987 ff_pkt->type, ff_pkt->fname, 0, attribs, 0, 0,
988 attribsEx, 0, ff_pkt->delta_seq, 0);
992 if (!IS_FT_OBJECT(ff_pkt->type) && ff_pkt->type != FT_DELETED) {
993 unstrip_path(ff_pkt);
996 Dmsg2(300, ">stored: attr len=%d: %s\n", sd->msglen, sd->msg);
997 if (!stat && !jcr->is_job_canceled()) {
998 Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
1001 sd->signal(BNET_EOD); /* indicate end of attributes data */
1006 * Setup bctx for doing compression
1008 static bool setup_compression(bctx_t &bctx)
1010 JCR *jcr = bctx.jcr;
1012 #if defined(HAVE_LIBZ) || defined(HAVE_LZO)
1013 bctx.compress_len = 0;
1014 bctx.max_compress_len = 0;
1019 if ((bctx.ff_pkt->flags & FO_COMPRESS) && bctx.ff_pkt->Compress_algo == COMPRESS_GZIP) {
1020 if ((bctx.ff_pkt->flags & FO_SPARSE) || (bctx.ff_pkt->flags & FO_OFFSETS)) {
1021 bctx.cbuf = (Bytef *)jcr->compress_buf + OFFSET_FADDR_SIZE;
1022 bctx.max_compress_len = jcr->compress_buf_size - OFFSET_FADDR_SIZE;
1024 bctx.cbuf = (Bytef *)jcr->compress_buf;
1025 bctx.max_compress_len = jcr->compress_buf_size; /* set max length */
1027 bctx.wbuf = jcr->compress_buf; /* compressed output here */
1028 bctx.cipher_input = (uint8_t *)jcr->compress_buf; /* encrypt compressed data */
1031 * Only change zlib parameters if there is no pending operation.
1032 * This should never happen as deflatereset is called after each
1036 if (((z_stream*)jcr->pZLIB_compress_workset)->total_in == 0) {
1037 /** set gzip compression level - must be done per file */
1038 if ((zstat=deflateParams((z_stream*)jcr->pZLIB_compress_workset,
1039 bctx.ff_pkt->Compress_level, Z_DEFAULT_STRATEGY)) != Z_OK) {
1040 Jmsg(jcr, M_FATAL, 0, _("Compression deflateParams error: %d\n"), zstat);
1041 jcr->setJobStatus(JS_ErrorTerminated);
1048 memset(&bctx.ch, 0, sizeof(comp_stream_header));
1051 if ((bctx.ff_pkt->flags & FO_COMPRESS) && bctx.ff_pkt->Compress_algo == COMPRESS_LZO1X) {
1052 if ((bctx.ff_pkt->flags & FO_SPARSE) || (bctx.ff_pkt->flags & FO_OFFSETS)) {
1053 bctx.cbuf = (Bytef *)jcr->compress_buf + OFFSET_FADDR_SIZE;
1054 bctx.cbuf2 = (Bytef *)jcr->compress_buf + OFFSET_FADDR_SIZE + sizeof(comp_stream_header);
1055 bctx.max_compress_len = jcr->compress_buf_size - OFFSET_FADDR_SIZE;
1057 bctx.cbuf = (Bytef *)jcr->compress_buf;
1058 bctx.cbuf2 = (Bytef *)jcr->compress_buf + sizeof(comp_stream_header);
1059 bctx.max_compress_len = jcr->compress_buf_size; /* set max length */
1061 bctx.ch.magic = COMPRESS_LZO1X;
1062 bctx.ch.version = COMP_HEAD_VERSION;
1063 bctx.wbuf = jcr->compress_buf; /* compressed output here */
1064 bctx.cipher_input = (uint8_t *)jcr->compress_buf; /* encrypt compressed data */
1068 bctx.max_compress_len = 0;
1074 * Send MacOS resource fork to SD
1076 #ifdef HAVE_DARWIN_OS
1077 static bool send_resource_fork(bctx_t &bctx)
1079 FF_PKT *ff_pkt = bctx.ff_pkt;
1080 JCR *jcr = bctx.jcr;
1081 BSOCK *sd = bctx.sd;
1084 /** Regular files can have resource forks and Finder Info */
1085 if (ff_pkt->type != FT_LNKSAVED && (S_ISREG(ff_pkt->statp.st_mode) &&
1086 ff_pkt->flags & FO_HFSPLUS)) {
1087 if (ff_pkt->hfsinfo.rsrclength > 0) {
1090 if (bopen_rsrc(&ff_pkt->bfd, ff_pkt->fname, O_RDONLY | O_BINARY, 0) < 0) {
1091 ff_pkt->ff_errno = errno;
1093 Jmsg(jcr, M_NOTSAVED, -1, _(" Cannot open resource fork for \"%s\": ERR=%s.\n"),
1094 ff_pkt->fname, be.bstrerror());
1096 if (is_bopen(&ff_pkt->bfd)) {
1097 bclose(&ff_pkt->bfd);
1101 flags = ff_pkt->flags;
1102 ff_pkt->flags &= ~(FO_COMPRESS|FO_SPARSE|FO_OFFSETS);
1103 if (flags & FO_ENCRYPT) {
1104 rsrc_stream = STREAM_ENCRYPTED_MACOS_FORK_DATA;
1106 rsrc_stream = STREAM_MACOS_FORK_DATA;
1108 stat = send_data(bctx, rsrc_stream);
1109 ff_pkt->flags = flags;
1110 bclose(&ff_pkt->bfd);
1116 Dmsg1(300, "Saving Finder Info for \"%s\"\n", ff_pkt->fname);
1117 sd->fsend("%ld %d 0", jcr->JobFiles, STREAM_HFSPLUS_ATTRIBUTES);
1118 Dmsg1(300, "bfiled>stored:header %s\n", sd->msg);
1119 pm_memcpy(sd->msg, ff_pkt->hfsinfo.fndrinfo, 32);
1122 crypto_digest_update(bctx.digest, (uint8_t *)sd->msg, sd->msglen);
1124 if (bctx.signing_digest) {
1125 crypto_digest_update(bctx.signing_digest, (uint8_t *)sd->msg, sd->msglen);
1128 sd->signal(BNET_EOD);
1134 static bool do_libz_compression(bctx_t &bctx)
1137 JCR *jcr = bctx.jcr;
1138 BSOCK *sd = bctx.sd;
1141 /** Do compression if turned on */
1142 if (bctx.ff_pkt->flags & FO_COMPRESS && bctx.ff_pkt->Compress_algo == COMPRESS_GZIP && jcr->pZLIB_compress_workset) {
1143 Dmsg3(400, "cbuf=0x%x rbuf=0x%x len=%u\n", bctx.cbuf, bctx.rbuf, sd->msglen);
1145 ((z_stream*)jcr->pZLIB_compress_workset)->next_in = (Bytef *)bctx.rbuf;
1146 ((z_stream*)jcr->pZLIB_compress_workset)->avail_in = sd->msglen;
1147 ((z_stream*)jcr->pZLIB_compress_workset)->next_out = bctx.cbuf;
1148 ((z_stream*)jcr->pZLIB_compress_workset)->avail_out = bctx.max_compress_len;
1150 if ((zstat=deflate((z_stream*)jcr->pZLIB_compress_workset, Z_FINISH)) != Z_STREAM_END) {
1151 Jmsg(jcr, M_FATAL, 0, _("Compression deflate error: %d\n"), zstat);
1152 jcr->setJobStatus(JS_ErrorTerminated);
1155 bctx.compress_len = ((z_stream*)jcr->pZLIB_compress_workset)->total_out;
1156 /** reset zlib stream to be able to begin from scratch again */
1157 if ((zstat=deflateReset((z_stream*)jcr->pZLIB_compress_workset)) != Z_OK) {
1158 Jmsg(jcr, M_FATAL, 0, _("Compression deflateReset error: %d\n"), zstat);
1159 jcr->setJobStatus(JS_ErrorTerminated);
1163 Dmsg2(400, "GZIP compressed len=%d uncompressed len=%d\n", bctx.compress_len,
1166 sd->msglen = bctx.compress_len; /* set compressed length */
1167 bctx.cipher_input_len = bctx.compress_len;
1173 static bool do_lzo_compression(bctx_t &bctx)
1176 JCR *jcr = bctx.jcr;
1177 BSOCK *sd = bctx.sd;
1180 /** Do compression if turned on */
1181 if (bctx.ff_pkt->flags & FO_COMPRESS && bctx.ff_pkt->Compress_algo == COMPRESS_LZO1X && jcr->LZO_compress_workset) {
1182 lzo_uint len; /* TODO: See with the latest patch how to handle lzo_uint with 64bit */
1185 ser_begin(bctx.cbuf, sizeof(comp_stream_header));
1187 Dmsg3(400, "cbuf=0x%x rbuf=0x%x len=%u\n", bctx.cbuf, bctx.rbuf, sd->msglen);
1189 lzores = lzo1x_1_compress((const unsigned char*)bctx.rbuf, sd->msglen, bctx.cbuf2,
1190 &len, jcr->LZO_compress_workset);
1191 bctx.compress_len = len;
1192 if (lzores == LZO_E_OK && bctx.compress_len <= bctx.max_compress_len) {
1193 /* complete header */
1194 ser_uint32(COMPRESS_LZO1X);
1195 ser_uint32(bctx.compress_len);
1196 ser_uint16(bctx.ch.level);
1197 ser_uint16(bctx.ch.version);
1199 /** this should NEVER happen */
1200 Jmsg(jcr, M_FATAL, 0, _("Compression LZO error: %d\n"), lzores);
1201 jcr->setJobStatus(JS_ErrorTerminated);
1205 Dmsg2(400, "LZO compressed len=%d uncompressed len=%d\n", bctx.compress_len,
1208 bctx.compress_len += sizeof(comp_stream_header); /* add size of header */
1209 sd->msglen = bctx.compress_len; /* set compressed length */
1210 bctx.cipher_input_len = bctx.compress_len;
1217 * Do in place strip of path
1219 static bool do_snap_strip(FF_PKT *ff)
1221 /* if the string starts with the snapshot path name, we can replace
1222 * by the volume name. The volume_path is smaller than the snapshot_path
1223 * snapshot_path = volume_path + /.snapshots/job-xxxx
1225 ASSERT(strlen(ff->snapshot_path) > strlen(ff->volume_path));
1226 int sp_first = strlen(ff->snapshot_path); /* point after snapshot_path in fname */
1227 if (strncmp(ff->fname, ff->snapshot_path, sp_first) == 0) {
1228 int last = pm_strcpy(ff->snap_fname, ff->volume_path);
1229 last = MAX(last - 1, 0);
1231 if (ff->snap_fname[last] == '/') {
1232 if (ff->fname[sp_first] == '/') { /* compare with the first character of the string (sp_first not sp_first-1) */
1233 ff->snap_fname[last] = 0;
1236 if (ff->fname[sp_first] != '/') {
1237 pm_strcat(ff->snap_fname, "/");
1241 pm_strcat(ff->snap_fname, ff->fname + sp_first);
1242 ASSERT(strlen(ff->fname) > strlen(ff->snap_fname));
1243 strcpy(ff->fname, ff->snap_fname);
1244 Dmsg2(DT_SNAPSHOT|20, "%s -> %s\n", ff->fname_save, ff->fname);
1246 if (strncmp(ff->link, ff->snapshot_path, sp_first) == 0) {
1247 int last = pm_strcpy(ff->snap_fname, ff->volume_path);
1248 last = MAX(last - 1, 0);
1250 if (ff->snap_fname[last] == '/') {
1251 if (ff->link[sp_first] == '/') { /* compare with the first character of the string (sp_first not sp_first-1) */
1252 ff->snap_fname[last] = 0;
1255 if (ff->link[sp_first] != '/') {
1256 pm_strcat(ff->snap_fname, "/");
1260 pm_strcat(ff->snap_fname, ff->link + sp_first);
1261 ASSERT(strlen(ff->link) > strlen(ff->snap_fname));
1262 strcpy(ff->link, ff->snap_fname);
1263 Dmsg2(DT_SNAPSHOT|20, "%s -> %s\n", ff->link_save, ff->link);
1270 * Do in place strip of path
1272 static bool do_strip(int count, char *in)
1278 /** Copy to first path separator -- Win32 might have c: ... */
1279 while (*in && !IsPathSeparator(*in)) {
1282 if (*in) { /* Not at the end of the string */
1284 numsep++; /* one separator seen */
1286 for (stripped=0; stripped<count && *in; stripped++) {
1287 while (*in && !IsPathSeparator(*in)) {
1288 in++; /* skip chars */
1291 numsep++; /* count separators seen */
1292 in++; /* skip separator */
1296 while (*in) { /* copy to end */
1297 if (IsPathSeparator(*in)) {
1303 Dmsg4(500, "stripped=%d count=%d numsep=%d sep>count=%d\n",
1304 stripped, count, numsep, numsep>count);
1305 return stripped==count && numsep>count;
1309 * If requested strip leading components of the path so that we can
1310 * save file as if it came from a subdirectory. This is most useful
1311 * for dealing with snapshots, by removing the snapshot directory, or
1312 * in handling vendor migrations where files have been restored with
1313 * a vendor product into a subdirectory.
1315 * When we are using snapshots, we might need to convert the path
1316 * back to the original one using the strip_snap_path option.
1318 void strip_path(FF_PKT *ff_pkt)
1320 if (!ff_pkt->strip_snap_path &&
1321 (!(ff_pkt->flags & FO_STRIPPATH) || ff_pkt->strip_path <= 0))
1323 Dmsg1(200, "No strip for %s\n", ff_pkt->fname);
1326 /* shared part between strip and snapshot */
1327 if (!ff_pkt->fname_save) {
1328 ff_pkt->fname_save = get_pool_memory(PM_FNAME);
1329 ff_pkt->link_save = get_pool_memory(PM_FNAME);
1330 *ff_pkt->link_save = 0;
1332 pm_strcpy(ff_pkt->fname_save, ff_pkt->fname);
1333 if (ff_pkt->type != FT_LNK && ff_pkt->fname != ff_pkt->link) {
1334 pm_strcpy(ff_pkt->link_save, ff_pkt->link);
1335 Dmsg2(500, "strcpy link_save=%d link=%d\n", strlen(ff_pkt->link_save),
1336 strlen(ff_pkt->link));
1340 if (ff_pkt->strip_snap_path) {
1341 if (!do_snap_strip(ff_pkt)) {
1342 Dmsg1(0, "Something wrong with do_snap_strip(%s)\n", ff_pkt->fname);
1343 unstrip_path(ff_pkt);
1348 /* See if we want also to strip the path */
1349 if (!(ff_pkt->flags & FO_STRIPPATH) || ff_pkt->strip_path <= 0) {
1354 * Strip path. If it doesn't succeed put it back. If
1355 * it does, and there is a different link string,
1356 * attempt to strip the link. If it fails, back them
1358 * Do not strip symlinks.
1359 * I.e. if either stripping fails don't strip anything.
1361 if (!do_strip(ff_pkt->strip_path, ff_pkt->fname)) {
1362 unstrip_path(ff_pkt);
1365 /** Strip links but not symlinks */
1366 if (ff_pkt->type != FT_LNK && ff_pkt->fname != ff_pkt->link) {
1367 if (!do_strip(ff_pkt->strip_path, ff_pkt->link)) {
1368 unstrip_path(ff_pkt);
1373 Dmsg3(10, "fname=%s stripped=%s link=%s\n", ff_pkt->fname_save, ff_pkt->fname,
1377 void unstrip_path(FF_PKT *ff_pkt)
1379 if (!ff_pkt->strip_snap_path &&
1380 (!(ff_pkt->flags & FO_STRIPPATH) || ff_pkt->strip_path <= 0))
1385 strcpy(ff_pkt->fname, ff_pkt->fname_save);
1386 if (ff_pkt->type != FT_LNK && ff_pkt->fname != ff_pkt->link) {
1387 Dmsg2(10, "strcpy link=%s link_save=%s\n", ff_pkt->link,
1389 strcpy(ff_pkt->link, ff_pkt->link_save);
1390 Dmsg2(10, "strcpy link=%d link_save=%d\n", strlen(ff_pkt->link),
1391 strlen(ff_pkt->link_save));
1396 static void close_vss_backup_session(JCR *jcr)
1398 #if defined(WIN32_VSS)
1399 /* STOP VSS ON WIN32 */
1400 /* tell vss to close the backup session */
1401 if (jcr->Snapshot) {
1402 if (g_pVSSClient->CloseBackup()) {
1403 /* inform user about writer states */
1404 for (int i=0; i<(int)g_pVSSClient->GetWriterCount(); i++) {
1405 int msg_type = M_INFO;
1406 if (g_pVSSClient->GetWriterState(i) < 1) {
1407 msg_type = M_WARNING;
1410 Jmsg(jcr, msg_type, 0, _("VSS Writer (BackupComplete): %s\n"), g_pVSSClient->GetWriterInfo(i));
1413 /* Generate Job global writer metadata */
1414 WCHAR *metadata = g_pVSSClient->GetMetadata();
1416 FF_PKT *ff_pkt = jcr->ff;
1417 ff_pkt->fname = (char *)"*all*"; /* for all plugins */
1418 ff_pkt->type = FT_RESTORE_FIRST;
1420 ff_pkt->object_name = (char *)"job_metadata.xml";
1421 ff_pkt->object = (char *)metadata;
1422 ff_pkt->object_len = (wcslen(metadata) + 1) * sizeof(WCHAR);
1423 ff_pkt->object_index = (int)time(NULL);
1424 save_file(jcr, ff_pkt, true);