+ } else {
+ Dmsg2(30, "Write %u bytes, total before write=%s\n", wsize, edit_uint64(jcr->JobBytes, ec1));
+ }
+
+ if (flags & FO_ENCRYPT) {
+ ASSERT(cipher);
+
+ /*
+ * Grow the crypto buffer, if necessary.
+ * crypto_cipher_update() will process only whole blocks,
+ * buffering the remaining input.
+ */
+ jcr->crypto_buf = check_pool_memory_size(jcr->crypto_buf, cipher_input_len + cipher_block_size);
+
+
+ /* Encrypt the input block */
+ if (!crypto_cipher_update(cipher, cipher_input, cipher_input_len, (uint8_t *)jcr->crypto_buf, &decrypted_len)) {
+ /* Decryption failed. Shouldn't happen. */
+ Jmsg(jcr, M_FATAL, 0, _("Decryption error\n"));
+ return -1;
+ }
+
+ if (decrypted_len == 0) {
+ /* No full block of data available, write more data */
+ goto ok;
+ }
+
+ Dmsg2(400, "decrypted len=%d undecrypted len=%d\n",
+ decrypted_len, cipher_input_len);
+ wsize = decrypted_len;
+ wbuf = jcr->crypto_buf; /* Decrypted, possibly decompressed output here. */
+ }
+
+
+ if (flags & FO_WIN32DECOMP) {
+ if (!processWin32BackupAPIBlock(bfd, wbuf, wsize)) {
+ berrno be;
+ Jmsg2(jcr, M_ERROR, 0, _("Write error in Win32 Block Decomposition on %s: %s\n"),
+ jcr->last_fname, be.strerror(bfd->berrno));
+ return -1;
+ }
+ } else if (bwrite(bfd, wbuf, wsize) != (ssize_t)wsize) {
+ berrno be;
+ Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"),
+ jcr->last_fname, be.strerror(bfd->berrno));
+ return -1;
+ }
+
+ if (decrypted_len && decrypted_len > wsize) {
+ /* If more than wsize is output, it was previously buffered
+ * and reported, and should not be reported again */
+ wsize = wsize - decrypted_len;
+ }
+
+ok:
+ jcr->JobBytes += wsize;
+ jcr->ReadBytes += rsize;
+ *addr += wsize;
+
+ return wsize;
+}
+
+/*
+ * In the context of jcr, flush any remaining data from the cipher context,
+ * writing it to bfd.
+ * Return value is true on success, false on failure.
+ */
+bool flush_cipher(JCR *jcr, BFILE *bfd, int flags, CIPHER_CONTEXT *cipher, uint32_t cipher_block_size)
+{
+ uint32_t decrypted_len;
+
+ /* Write out the remaining block and free the cipher context */
+ jcr->crypto_buf = check_pool_memory_size(jcr->crypto_buf, cipher_block_size);
+
+ if (!crypto_cipher_finalize(cipher, (uint8_t *)jcr->crypto_buf, &decrypted_len)) {
+ /* Writing out the final, buffered block failed. Shouldn't happen. */
+ Jmsg1(jcr, M_FATAL, 0, _("Decryption error for %s\n"), jcr->last_fname);
+ }
+
+ if (flags & FO_WIN32DECOMP) {
+ if (!processWin32BackupAPIBlock(bfd, jcr->crypto_buf, decrypted_len)) {
+ berrno be;
+ Jmsg2(jcr, M_ERROR, 0, _("Write error in Win32 Block Decomposition on %s: %s\n"),
+ jcr->last_fname, be.strerror(bfd->berrno));
+ return false;
+ }
+ } else if (bwrite(bfd, jcr->crypto_buf, decrypted_len) != (ssize_t)decrypted_len) {
+ berrno be;
+ Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"),
+ jcr->last_fname, be.strerror(bfd->berrno));
+ return false;
+ }
+
+ return true;
+}