2 * Bacula File Daemon restore.c Restorefiles.
4 * Kern Sibbald, November MM
10 Copyright (C) 2000-2005 Kern Sibbald
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License
14 version 2 as amended with additional clauses defined in the
15 file LICENSE in the main source directory.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 the file LICENSE for additional details.
31 /* Data received from Storage Daemon */
32 static char rec_header[] = "rechdr %ld %ld %ld %ld %ld";
34 /* Forward referenced functions */
36 static const char *zlib_strerror(int stat);
39 int verify_signature(JCR *jcr, SIGNATURE *sig);
40 int32_t extract_data(JCR *jcr, BFILE *bfd, POOLMEM *buf, int32_t buflen,
41 uint64_t *addr, int flags, CIPHER_CONTEXT *cipher, size_t cipher_block_size);
42 bool flush_cipher(JCR *jcr, BFILE *bfd, int flags, CIPHER_CONTEXT *cipher, size_t cipher_block_size);
44 #define RETRY 10 /* retry wait time */
47 * Close a bfd check that we are at the expected file offset.
48 * Makes some code in set_attributes().
50 int bclose_chksize(JCR *jcr, BFILE *bfd, off_t osize)
52 char ec1[50], ec2[50];
55 fsize = blseek(bfd, 0, SEEK_CUR);
56 bclose(bfd); /* first close file */
57 if (fsize > 0 && fsize != osize) {
58 Qmsg3(jcr, M_ERROR, 0, _("Size of data or stream of %s not correct. Original %s, restored %s.\n"),
59 jcr->last_fname, edit_uint64(osize, ec1),
60 edit_uint64(fsize, ec2));
67 * Restore the requested files.
70 void do_restore(JCR *jcr)
75 uint32_t VolSessionId, VolSessionTime;
78 char ec1[50]; /* Buffer printing huge values */
80 BFILE bfd; /* File content */
81 uint64_t fileAddr = 0; /* file write address */
82 uint32_t size; /* Size of file */
83 BFILE altbfd; /* Alternative data stream */
84 uint64_t alt_addr = 0; /* Write address for alternative stream */
85 intmax_t alt_size = 0; /* Size of alternate stream */
86 SIGNATURE *sig = NULL; /* Cryptographic signature (if any) for file */
87 CRYPTO_SESSION *cs = NULL; /* Cryptographic session data (if any) for file */
88 CIPHER_CONTEXT *cipher_ctx = NULL; /* Cryptographic cipher context (if any) for file */
89 size_t cipher_block_size = 0; /* Cryptographic algorithm block size for file */
90 int flags = 0; /* Options for extract_data() */
94 /* The following variables keep track of "known unknowns" */
95 int non_support_data = 0;
96 int non_support_attr = 0;
97 int non_support_rsrc = 0;
98 int non_support_finfo = 0;
99 int non_support_acl = 0;
100 int non_support_progname = 0;
102 /* Finally, set up for special configurations */
103 #ifdef HAVE_DARWIN_OS
104 intmax_t rsrc_len = 0; /* Original length of resource fork */
105 struct attrlist attrList;
107 memset(&attrList, 0, sizeof(attrList));
108 attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
109 attrList.commonattr = ATTR_CMN_FNDRINFO;
112 sd = jcr->store_bsock;
113 set_jcr_job_status(jcr, JS_Running);
116 CLIENT *client = (CLIENT *)GetNextRes(R_CLIENT, NULL);
120 buf_size = client->max_network_buffer_size;
122 buf_size = 0; /* use default */
124 if (!bnet_set_buffer_size(sd, buf_size, BNET_SETBUF_WRITE)) {
125 set_jcr_job_status(jcr, JS_ErrorTerminated);
128 jcr->buf_size = sd->msglen;
130 #ifdef stbernard_implemented
131 / #if defined(HAVE_WIN32)
132 bool bResumeOfmOnExit = FALSE;
133 if (isOpenFileManagerRunning()) {
134 if ( pauseOpenFileManager() ) {
135 Jmsg(jcr, M_INFO, 0, _("Open File Manager paused\n") );
136 bResumeOfmOnExit = TRUE;
139 Jmsg(jcr, M_ERROR, 0, _("FAILED to pause Open File Manager\n") );
143 char username[UNLEN+1];
144 DWORD usize = sizeof(username);
145 int privs = enable_backup_privileges(NULL, 1);
146 if (GetUserName(username, &usize)) {
147 Jmsg2(jcr, M_INFO, 0, _("Running as '%s'. Privmask=%#08x\n"), username,
149 Jmsg(jcr, M_WARNING, 0, _("Failed to retrieve current UserName\n"));
155 uint32_t compress_buf_size = jcr->buf_size + 12 + ((jcr->buf_size+999) / 1000) + 100;
156 jcr->compress_buf = (char *)bmalloc(compress_buf_size);
157 jcr->compress_buf_size = compress_buf_size;
161 jcr->crypto_buf = get_memory(CRYPTO_CIPHER_MAX_BLOCK_SIZE);
165 * Get a record from the Storage daemon. We are guaranteed to
166 * receive records in the following order:
167 * 1. Stream record header
169 * a. Attributes (Unix or Win32)
170 * b. Possibly stream encryption session data (e.g., symmetric session key)
171 * or c. File data for the file
172 * or d. Alternate data stream (e.g. Resource Fork)
175 * or g. Possibly a cryptographic signature
176 * or h. Possibly MD5 or SHA1 record
179 * NOTE: We keep track of two bacula file descriptors:
180 * 1. bfd for file data.
181 * This fd is opened for non empty files when an attribute stream is
182 * encountered and closed when we find the next attribute stream.
183 * 2. alt_bfd for alternate data streams
184 * This fd is opened every time we encounter a new alternate data
185 * stream for the current file. When we find any other stream, we
187 * The expected size of the stream, alt_len, should be set when
193 jcr->acl_text = get_pool_memory(PM_MESSAGE);
195 while (bget_msg(sd) >= 0 && !job_canceled(jcr)) {
196 /* Remember previous stream type */
197 prev_stream = stream;
199 /* First we expect a Stream Record Header */
200 if (sscanf(sd->msg, rec_header, &VolSessionId, &VolSessionTime, &file_index,
201 &stream, &size) != 5) {
202 Jmsg1(jcr, M_FATAL, 0, _("Record header scan error: %s\n"), sd->msg);
205 Dmsg2(30, "Got hdr: FilInx=%d Stream=%d.\n", file_index, stream);
207 /* * Now we expect the Stream Data */
208 if (bget_msg(sd) < 0) {
209 Jmsg1(jcr, M_FATAL, 0, _("Data record error. ERR=%s\n"), bnet_strerror(sd));
212 if (size != (uint32_t)sd->msglen) {
213 Jmsg2(jcr, M_FATAL, 0, _("Actual data size %d not same as header %d\n"), sd->msglen, size);
216 Dmsg1(30, "Got stream data, len=%d\n", sd->msglen);
218 /* If we change streams, close and reset alternate data streams */
219 if (prev_stream != stream) {
220 if (is_bopen(&altbfd)) {
221 bclose_chksize(jcr, &altbfd, alt_size);
223 alt_size = -1; /* Use an impossible value and set a proper one below */
227 /* File Attributes stream */
229 case STREAM_UNIX_ATTRIBUTES:
230 case STREAM_UNIX_ATTRIBUTES_EX:
231 Dmsg1(30, "Stream=Unix Attributes. extract=%d\n", extract);
233 * If extracting, it was from previous stream, so
234 * close the output file and validate the signature.
237 if (size > 0 && !is_bopen(&bfd)) {
238 Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should be open\n"));
240 /* Flush and deallocate previous stream's cipher context */
241 if (cipher_ctx && prev_stream != STREAM_ENCRYPTED_SESSION_DATA) {
242 flush_cipher(jcr, &bfd, flags, cipher_ctx, cipher_block_size);
243 crypto_cipher_free(cipher_ctx);
246 set_attributes(jcr, attr, &bfd);
249 /* Verify the cryptographic signature, if any */
252 // Failure is reported in verify_signature() ...
253 verify_signature(jcr, sig);
255 Jmsg1(jcr, M_ERROR, 0, _("Missing cryptographic signature for %s\n"), jcr->last_fname);
260 crypto_sign_free(sig);
264 crypto_session_free(cs);
267 Dmsg0(30, "Stop extracting.\n");
268 } else if (is_bopen(&bfd)) {
269 Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should not be open\n"));
274 * Unpack and do sanity check fo attributes.
276 if (!unpack_attributes_record(jcr, stream, sd->msg, attr)) {
279 if (file_index != attr->file_index) {
280 Jmsg(jcr, M_FATAL, 0, _("Record header file index %ld not equal record index %ld\n"),
281 file_index, attr->file_index);
282 Dmsg0(100, "File index error\n");
286 Dmsg3(200, "File %s\nattrib=%s\nattribsEx=%s\n", attr->fname,
287 attr->attr, attr->attrEx);
289 attr->data_stream = decode_stat(attr->attr, &attr->statp, &attr->LinkFI);
291 if (!is_restore_stream_supported(attr->data_stream)) {
292 if (!non_support_data++) {
293 Jmsg(jcr, M_ERROR, 0, _("%s stream not supported on this Client.\n"),
294 stream_to_ascii(attr->data_stream));
299 build_attr_output_fnames(jcr, attr);
302 * Now determine if we are extracting or not.
304 jcr->num_files_examined++;
305 Dmsg1(30, "Outfile=%s\n", attr->ofname);
307 stat = create_file(jcr, attr, &bfd, jcr->replace);
312 case CF_EXTRACT: /* File created and we expect file data */
315 case CF_CREATED: /* File created, but there is no content */
317 pm_strcpy(jcr->last_fname, attr->ofname);
321 print_ls_output(jcr, attr);
322 #ifdef HAVE_DARWIN_OS
323 /* Only restore the resource fork for regular files */
324 from_base64(&rsrc_len, attr->attrEx);
325 if (attr->type == FT_REG && rsrc_len > 0) {
330 /* set attributes now because file will not be extracted */
331 set_attributes(jcr, attr, &bfd);
338 case STREAM_ENCRYPTED_SESSION_DATA:
339 crypto_error_t cryptoerr;
341 Dmsg1(30, "Stream=Encrypted Session Data, size: %d\n", sd->msglen);
343 /* Decode and save session keys. */
344 cryptoerr = crypto_session_decode(sd->msg, (size_t) sd->msglen, jcr->pki_recipients, &cs);
346 case CRYPTO_ERROR_NONE:
349 case CRYPTO_ERROR_NORECIPIENT:
350 Jmsg(jcr, M_ERROR, 0, _("Missing private key required to decrypt encrypted backup data."));
352 case CRYPTO_ERROR_DECRYPTION:
353 Jmsg(jcr, M_ERROR, 0, _("Decrypt of the session key failed."));
356 /* Shouldn't happen */
357 Jmsg1(jcr, M_ERROR, 0, _("An error occured while decoding encrypted session data stream: %s"), crypto_strerror(cryptoerr));
361 if (cryptoerr != CRYPTO_ERROR_NONE) {
367 /* Set up a decryption context */
368 if ((cipher_ctx = crypto_cipher_new(cs, false, &cipher_block_size)) == NULL) {
369 Jmsg1(jcr, M_ERROR, 0, _("Failed to initialize decryption context for %s\n"), jcr->last_fname);
370 crypto_session_free(cs);
378 case STREAM_FILE_DATA:
379 case STREAM_SPARSE_DATA:
380 case STREAM_WIN32_DATA:
381 case STREAM_GZIP_DATA:
382 case STREAM_SPARSE_GZIP_DATA:
383 case STREAM_WIN32_GZIP_DATA:
384 case STREAM_ENCRYPTED_FILE_DATA:
385 case STREAM_ENCRYPTED_WIN32_DATA:
386 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
387 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
388 /* Force an expected, consistent stream type here */
389 if (extract && (prev_stream == stream || prev_stream == STREAM_UNIX_ATTRIBUTES
390 || prev_stream == STREAM_UNIX_ATTRIBUTES_EX
391 || prev_stream == STREAM_ENCRYPTED_SESSION_DATA)) {
394 if (stream == STREAM_SPARSE_DATA || stream == STREAM_SPARSE_GZIP_DATA) {
398 if (stream == STREAM_GZIP_DATA || stream == STREAM_SPARSE_GZIP_DATA
399 || stream == STREAM_WIN32_GZIP_DATA || stream == STREAM_ENCRYPTED_FILE_GZIP_DATA
400 || stream == STREAM_ENCRYPTED_WIN32_GZIP_DATA) {
404 if (stream == STREAM_ENCRYPTED_FILE_DATA
405 || stream == STREAM_ENCRYPTED_FILE_GZIP_DATA
406 || stream == STREAM_ENCRYPTED_WIN32_DATA
407 || stream == STREAM_ENCRYPTED_WIN32_GZIP_DATA) {
411 if (is_win32_stream(stream) && !have_win32_api()) {
412 set_portable_backup(&bfd);
413 flags |= FO_WIN32DECOMP; /* "decompose" BackupWrite data */
416 if (extract_data(jcr, &bfd, sd->msg, sd->msglen, &fileAddr, flags, cipher_ctx, cipher_block_size) < 0) {
424 /* Resource fork stream - only recorded after a file to be restored */
425 /* Silently ignore if we cannot write - we already reported that */
426 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
428 case STREAM_MACOS_FORK_DATA:
429 #ifdef HAVE_DARWIN_OS
431 if (prev_stream != stream) {
432 if (bopen_rsrc(&altbfd, jcr->last_fname, O_WRONLY | O_TRUNC | O_BINARY, 0) < 0) {
433 Jmsg(jcr, M_ERROR, 0, _(" Cannot open resource fork for %s.\n"), jcr->last_fname);
438 Dmsg0(30, "Restoring resource fork\n");
441 if (extract_data(jcr, &altbfd, sd->msg, sd->msglen, &alt_addr, flags, cipher_ctx, cipher_block_size) < 0) {
452 case STREAM_HFSPLUS_ATTRIBUTES:
453 #ifdef HAVE_DARWIN_OS
454 Dmsg0(30, "Restoring Finder Info\n");
455 if (sd->msglen != 32) {
456 Jmsg(jcr, M_ERROR, 0, _(" Invalid length of Finder Info (got %d, not 32)\n"), sd->msglen);
459 if (setattrlist(jcr->last_fname, &attrList, sd->msg, sd->msglen, 0) != 0) {
460 Jmsg(jcr, M_ERROR, 0, _(" Could not set Finder Info on %s\n"), jcr->last_fname);
467 case STREAM_UNIX_ATTRIBUTES_ACCESS_ACL:
469 pm_strcpy(jcr->acl_text, sd->msg);
470 Dmsg2(400, "Restoring ACL type 0x%2x <%s>\n", BACL_TYPE_ACCESS, jcr->acl_text);
471 if (bacl_set(jcr, BACL_TYPE_ACCESS) != 0) {
472 Qmsg1(jcr, M_WARNING, 0, _("Can't restore ACL of %s\n"), jcr->last_fname);
479 case STREAM_UNIX_ATTRIBUTES_DEFAULT_ACL:
481 pm_strcpy(jcr->acl_text, sd->msg);
482 Dmsg2(400, "Restoring ACL type 0x%2x <%s>\n", BACL_TYPE_DEFAULT, jcr->acl_text);
483 if (bacl_set(jcr, BACL_TYPE_DEFAULT) != 0) {
484 Qmsg1(jcr, M_WARNING, 0, _("Can't restore default ACL of %s\n"), jcr->last_fname);
491 case STREAM_SIGNED_DIGEST:
492 /* Save signature. */
493 if ((sig = crypto_sign_decode(sd->msg, (size_t) sd->msglen)) == NULL) {
494 Jmsg1(jcr, M_ERROR, 0, _("Failed to decode message signature for %s\n"), jcr->last_fname);
498 case STREAM_MD5_DIGEST:
499 case STREAM_SHA1_DIGEST:
500 case STREAM_SHA256_DIGEST:
501 case STREAM_SHA512_DIGEST:
504 case STREAM_PROGRAM_NAMES:
505 case STREAM_PROGRAM_DATA:
506 if (!non_support_progname) {
507 Pmsg0(000, "Got Program Name or Data Stream. Ignored.\n");
508 non_support_progname++;
513 /* If extracting, wierd stream (not 1 or 2), close output file anyway */
515 Dmsg1(30, "Found wierd stream %d\n", stream);
516 if (size > 0 && !is_bopen(&bfd)) {
517 Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should be open\n"));
519 /* Flush and deallocate cipher context */
521 flush_cipher(jcr, &bfd, flags, cipher_ctx, cipher_block_size);
522 crypto_cipher_free(cipher_ctx);
525 set_attributes(jcr, attr, &bfd);
527 /* Verify the cryptographic signature if any */
530 // Failure is reported in verify_signature() ...
531 verify_signature(jcr, sig);
533 Jmsg1(jcr, M_ERROR, 0, _("Missing cryptographic signature for %s\n"), jcr->last_fname);
538 } else if (is_bopen(&bfd)) {
539 Jmsg0(jcr, M_ERROR, 0, _("Logic error: output file should not be open\n"));
542 Jmsg(jcr, M_ERROR, 0, _("Unknown stream=%d ignored. This shouldn't happen!\n"), stream);
543 Dmsg2(0, "None of above!!! stream=%d data=%s\n", stream,sd->msg);
545 } /* end switch(stream) */
547 } /* end while get_msg() */
549 /* If output file is still open, it was the last one in the
550 * archive since we just hit an end of file, so close the file.
552 if (is_bopen(&altbfd)) {
553 bclose_chksize(jcr, &altbfd, alt_size);
556 /* Flush and deallocate cipher context */
558 flush_cipher(jcr, &bfd, flags, cipher_ctx, cipher_block_size);
559 crypto_cipher_free(cipher_ctx);
562 set_attributes(jcr, attr, &bfd);
564 /* Verify the cryptographic signature on the last file, if any */
567 // Failure is reported in verify_signature() ...
568 verify_signature(jcr, sig);
570 Jmsg1(jcr, M_ERROR, 0, _("Missing cryptographic signature for %s\n"), jcr->last_fname);
575 if (is_bopen(&bfd)) {
579 set_jcr_job_status(jcr, JS_Terminated);
583 set_jcr_job_status(jcr, JS_ErrorTerminated);
586 /* Free Signature & Crypto Data */
588 crypto_sign_free(sig);
592 crypto_session_free(cs);
596 crypto_cipher_free(cipher_ctx);
599 if (jcr->compress_buf) {
600 free(jcr->compress_buf);
601 jcr->compress_buf = NULL;
602 jcr->compress_buf_size = 0;
604 if (jcr->crypto_buf) {
605 free_pool_memory(jcr->crypto_buf);
606 jcr->crypto_buf = NULL;
611 free_pool_memory(jcr->acl_text);
612 Dmsg2(10, "End Do Restore. Files=%d Bytes=%s\n", jcr->JobFiles,
613 edit_uint64(jcr->JobBytes, ec1));
614 if (non_support_data > 1 || non_support_attr > 1) {
615 Jmsg(jcr, M_ERROR, 0, _("%d non-supported data streams and %d non-supported attrib streams ignored.\n"),
616 non_support_data, non_support_attr);
618 if (non_support_rsrc) {
619 Jmsg(jcr, M_INFO, 0, _("%d non-supported resource fork streams ignored.\n"), non_support_rsrc);
621 if (non_support_finfo) {
622 Jmsg(jcr, M_INFO, 0, _("%d non-supported Finder Info streams ignored.\n"), non_support_rsrc);
624 if (non_support_acl) {
625 Jmsg(jcr, M_INFO, 0, _("%d non-supported acl streams ignored.\n"), non_support_acl);
632 * Convert ZLIB error code into an ASCII message
634 static const char *zlib_strerror(int stat)
641 return _("Zlib errno");
643 return _("Zlib stream error");
645 return _("Zlib data error");
647 return _("Zlib memory error");
649 return _("Zlib buffer error");
650 case Z_VERSION_ERROR:
651 return _("Zlib version error");
658 static int do_file_digest(FF_PKT *ff_pkt, void *pkt, bool top_level) {
659 JCR *jcr = (JCR *) pkt;
660 return (digest_file(jcr, ff_pkt, jcr->digest));
664 * Verify the signature for the last restored file
665 * Return value is either true (signature correct)
666 * or false (signature could not be verified).
667 * TODO landonf: Better signature failure handling.
669 int verify_signature(JCR *jcr, SIGNATURE *sig)
671 X509_KEYPAIR *keypair;
672 DIGEST *digest = NULL;
675 /* Iterate through the trusted signers */
676 foreach_alist(keypair, jcr->pki_signers) {
677 err = crypto_sign_get_digest(sig, jcr->pki_keypair, &digest);
680 case CRYPTO_ERROR_NONE:
681 /* Signature found, digest allocated */
682 jcr->digest = digest;
684 /* Checksum the entire file */
685 if (find_one_file(jcr, jcr->ff, do_file_digest, jcr, jcr->last_fname, (dev_t)-1, 1) != 0) {
686 Qmsg(jcr, M_ERROR, 0, _("Signature validation failed for %s: \n"), jcr->last_fname);
690 /* Verify the signature */
691 if ((err = crypto_sign_verify(sig, keypair, digest)) != CRYPTO_ERROR_NONE) {
692 Dmsg1(100, "Bad signature on %s\n", jcr->last_fname);
693 Qmsg2(jcr, M_ERROR, 0, _("Signature validation failed for %s: %s\n"), jcr->last_fname, crypto_strerror(err));
694 crypto_digest_free(digest);
698 /* Valid signature */
699 Dmsg1(100, "Signature good on %s\n", jcr->last_fname);
700 crypto_digest_free(digest);
703 case CRYPTO_ERROR_NOSIGNER:
704 /* Signature not found, try again */
707 /* Something strange happened (that shouldn't happen!)... */
708 Qmsg2(jcr, M_ERROR, 0, _("Signature validation failed for %s: %s\n"), jcr->last_fname, crypto_strerror(err));
710 crypto_digest_free(digest);
717 Dmsg1(100, "Could not find a valid public key for signature on %s\n", jcr->last_fname);
718 crypto_digest_free(digest);
723 * In the context of jcr, write data to bfd.
724 * We write buflen bytes in buf at addr. addr is updated in place.
725 * The flags specify whether to use sparse files or compression.
726 * Return value is the number of bytes written, or -1 on errors.
728 int32_t extract_data(JCR *jcr, BFILE *bfd, POOLMEM *buf, int32_t buflen,
729 uint64_t *addr, int flags, CIPHER_CONTEXT *cipher, size_t cipher_block_size)
732 char *wbuf; /* write buffer */
733 uint32_t wsize; /* write size */
734 uint32_t rsize; /* read size */
735 char ec1[50]; /* Buffer printing huge values */
736 const void *cipher_input; /* Decryption input */
737 size_t cipher_input_len; /* Decryption input length */
738 size_t decrypted_len = 0; /* Decryption output length */
740 if (flags & FO_SPARSE) {
744 wbuf = buf + SPARSE_FADDR_SIZE;
745 rsize = buflen - SPARSE_FADDR_SIZE;
746 ser_begin(buf, SPARSE_FADDR_SIZE);
748 if (*addr != faddr) {
750 if (blseek(bfd, (off_t)*addr, SEEK_SET) < 0) {
752 Jmsg3(jcr, M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"),
753 edit_uint64(*addr, ec1), jcr->last_fname,
754 be.strerror(bfd->berrno));
764 cipher_input_len = wsize;
766 if (flags & FO_GZIP) {
770 * NOTE! We only use uLong and Byte because they are
771 * needed by the zlib routines, they should not otherwise
774 compress_len = jcr->compress_buf_size;
775 Dmsg2(100, "Comp_len=%d msglen=%d\n", compress_len, wsize);
776 if ((stat=uncompress((Byte *)jcr->compress_buf, &compress_len,
777 (const Byte *)wbuf, (uLong)rsize)) != Z_OK) {
778 Qmsg(jcr, M_ERROR, 0, _("Uncompression error on file %s. ERR=%s\n"),
779 jcr->last_fname, zlib_strerror(stat));
782 wbuf = jcr->compress_buf;
783 wsize = compress_len;
784 cipher_input = jcr->compress_buf; /* decrypt decompressed data */
785 cipher_input_len = compress_len;
786 Dmsg2(100, "Write uncompressed %d bytes, total before write=%s\n", compress_len, edit_uint64(jcr->JobBytes, ec1));
788 Qmsg(jcr, M_ERROR, 0, _("GZIP data stream found, but GZIP not configured!\n"));
792 Dmsg2(30, "Write %u bytes, total before write=%s\n", wsize, edit_uint64(jcr->JobBytes, ec1));
795 if (flags & FO_ENCRYPT) {
799 * Grow the crypto buffer, if necessary.
800 * crypto_cipher_update() will process only whole blocks,
801 * buffering the remaining input.
803 jcr->crypto_buf = check_pool_memory_size(jcr->crypto_buf, cipher_input_len + cipher_block_size);
806 /* Encrypt the input block */
807 if (!crypto_cipher_update(cipher, cipher_input, cipher_input_len, jcr->crypto_buf, &decrypted_len)) {
808 /* Decryption failed. Shouldn't happen. */
809 Jmsg(jcr, M_FATAL, 0, _("Decryption error\n"));
813 if (decrypted_len == 0) {
814 /* No full block of data available, write more data */
818 Dmsg2(400, "decrypted len=%d undecrypted len=%d\n",
819 decrypted_len, cipher_input_len);
820 wsize = decrypted_len;
821 wbuf = jcr->crypto_buf; /* Decrypted, possibly decompressed output here. */
825 if (flags & FO_WIN32DECOMP) {
826 if (!processWin32BackupAPIBlock(bfd, wbuf, wsize)) {
828 Jmsg2(jcr, M_ERROR, 0, _("Write error in Win32 Block Decomposition on %s: %s\n"),
829 jcr->last_fname, be.strerror(bfd->berrno));
832 } else if (bwrite(bfd, wbuf, wsize) != (ssize_t)wsize) {
834 Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"),
835 jcr->last_fname, be.strerror(bfd->berrno));
839 if (decrypted_len && decrypted_len > wsize) {
840 /* If more than wsize is output, it was previously buffered
841 * and reported, and should not be reported again */
842 wsize = wsize - decrypted_len;
846 jcr->JobBytes += wsize;
847 jcr->ReadBytes += rsize;
854 * In the context of jcr, flush any remaining data from the cipher context,
856 * Return value is true on success, false on failure.
858 bool flush_cipher(JCR *jcr, BFILE *bfd, int flags, CIPHER_CONTEXT *cipher, size_t cipher_block_size)
860 size_t decrypted_len;
862 /* Write out the remaining block and free the cipher context */
863 jcr->crypto_buf = check_pool_memory_size(jcr->crypto_buf, cipher_block_size);
865 if (!crypto_cipher_finalize(cipher, jcr->crypto_buf, &decrypted_len)) {
866 /* Writing out the final, buffered block failed. Shouldn't happen. */
867 Jmsg1(jcr, M_FATAL, 0, _("Decryption error for %s\n"), jcr->last_fname);
870 if (flags & FO_WIN32DECOMP) {
871 if (!processWin32BackupAPIBlock(bfd, jcr->crypto_buf, decrypted_len)) {
873 Jmsg2(jcr, M_ERROR, 0, _("Write error in Win32 Block Decomposition on %s: %s\n"),
874 jcr->last_fname, be.strerror(bfd->berrno));
877 } else if (bwrite(bfd, jcr->crypto_buf, decrypted_len) != (ssize_t)decrypted_len) {
879 Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"),
880 jcr->last_fname, be.strerror(bfd->berrno));