|| stream == STREAM_WIN32_GZIP_DATA) {
flags |= FO_GZIP;
}
+
+#ifdef USE_WIN32STREAMEXTRACTION
+/* THIS DETERMINES IF WE USE THE WIN32 BACKUPSTREAM DECOMPOSITION */
+ if (is_win32_stream(stream) && !have_win32_api()) {
+ set_portable_backup(&bfd);
+ flags |= FO_WIN32DECOMP;
+ }
+#endif
+
if (extract_data(jcr, &bfd, sd->msg, sd->msglen, &fileAddr, flags) < 0) {
extract = false;
bclose(&bfd);
Dmsg2(30, "Write %u bytes, total before write=%s\n", wsize, edit_uint64(jcr->JobBytes, ec1));
}
+#ifdef USE_WIN32STREAMEXTRACTION
+ 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
+#endif
if (bwrite(bfd, wbuf, wsize) != (ssize_t)wsize) {
berrno be;
Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"),
}
}
+#ifdef USE_WIN32STREAMEXTRACTION
+BOOL processWin32BackupAPIBlock (BFILE *bfd, void *pBuffer, size_t dwSize)
+{
+ /* pByte contains the buffer
+ dwSize the len to be processed. function assumes to be called in successive
+ incremental order over the complete BackupRead stream beginning at pos 0 and
+ ending at the end. */
+
+ PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT* pContext = &(bfd->win32DecompContext);
+ BOOL bContinue = FALSE;
+ LONGLONG dwDataOffset = 0;
+ LONGLONG dwDataLen;
+
+ /* Win32 Stream Header size without name of strem.
+ = sizeof (WIN32_STREAM_ID)- sizeof(WCHAR*); */
+ DWORD dwSizeHeader = 20;
+
+ do {
+ if (pContext->liNextHeader >= dwSize) {
+ dwDataLen = dwSize-dwDataOffset;
+ bContinue = FALSE; /* 1 iteration is enough */
+ }
+ else {
+ dwDataLen = pContext->liNextHeader-dwDataOffset;
+ bContinue = TRUE; /* multiple iterations may be necessary */
+ }
+
+ /* flush */
+ /* copy block of real DATA */
+ if (pContext->bIsInData) {
+ if (bwrite(bfd, ((LPBYTE)pBuffer)+dwDataOffset, dwDataLen) != (ssize_t)dwDataLen)
+ return FALSE;
+ }
+
+ if (pContext->liNextHeader < dwSize) {/* is a header in this block ? */
+ DWORD dwOffsetTarget;
+ DWORD dwOffsetSource;
+
+ if (pContext->liNextHeader < 0) {
+ /* start of header was before this block,
+ so we continue with the part in the current block */
+ dwOffsetTarget = abs (pContext->liNextHeader);
+ dwOffsetSource = 0;
+ }
+ else {
+ /* start of header is inside of this block */
+ dwOffsetTarget = 0;
+ dwOffsetSource = pContext->liNextHeader;
+ }
+
+ DWORD dwHeaderPartLen = dwSizeHeader-dwOffsetTarget;
+ BOOL bHeaderIsComplete;
+
+ if (dwHeaderPartLen <= dwSize-dwOffsetSource)
+ /* header (or rest of header) is completely available in current block */
+ bHeaderIsComplete = TRUE;
+ else {
+ /* header will continue in next block */
+ bHeaderIsComplete = FALSE;
+ dwHeaderPartLen = dwSize-dwOffsetSource;
+ }
+
+ /* copy the available portion of header to persistent copy */
+ memcpy (((LPBYTE) &pContext->header_stream)+dwOffsetTarget, ((LPBYTE) pBuffer)+dwOffsetSource, dwHeaderPartLen);
+
+ /* recalculate position of next header */
+ if (bHeaderIsComplete) {
+ dwDataOffset = pContext->liNextHeader+dwSizeHeader+pContext->header_stream.dwStreamNameSize;
+ pContext->liNextHeader = dwDataOffset+pContext->header_stream.Size.QuadPart;
+ pContext->bIsInData = pContext->header_stream.dwStreamId == BACKUP_DATA;
+ if (dwDataOffset == dwSize)
+ bContinue = FALSE;
+ }
+ else {
+ /* stop and continue with next block */
+ bContinue = FALSE;
+ pContext->bIsInData = FALSE;
+ }
+ }
+ } while (bContinue);
+
+ /* set "NextHeader" relative to the beginning of the next block */
+ pContext->liNextHeader-= dwSize;
+
+ return TRUE;
+}
+#endif
+
/* ===============================================================
#endif
case STREAM_WIN32_DATA:
case STREAM_WIN32_GZIP_DATA:
- return have_win32_api();
+#ifdef USE_WIN32STREAMEXTRACTION
+ return true;
+#else
+ return have_win32_api();
+#endif
+
case STREAM_MACOS_FORK_DATA:
case STREAM_HFSPLUS_ATTRIBUTES:
POOLMEM *win32_fname_wchar;
DWORD dwaccess, dwflags, dwshare;
-
+
/* Convert to Windows path format */
win32_fname = get_pool_memory(PM_FNAME);
win32_fname_wchar = get_pool_memory(PM_FNAME);
}
bfd->errmsg = NULL;
bfd->lpContext = NULL;
+#ifdef USE_WIN32STREAMEXTRACTION
+ bfd->win32DecompContext.bIsInData = FALSE;
+ bfd->win32DecompContext.liNextHeader = 0;
+#endif
free_pool_memory(win32_fname_wchar);
free_pool_memory(win32_fname);
return bfd->mode == BF_CLOSED ? -1 : 1;
case STREAM_GZIP_DATA:
case STREAM_SPARSE_GZIP_DATA:
#endif
+#ifndef USE_WIN32STREAMEXTRACTION
case STREAM_WIN32_DATA:
case STREAM_WIN32_GZIP_DATA:
+#endif
#ifndef HAVE_DARWIN_OS
case STREAM_MACOS_FORK_DATA:
case STREAM_HFSPLUS_ATTRIBUTES:
#ifdef HAVE_LIBZ
case STREAM_GZIP_DATA:
case STREAM_SPARSE_GZIP_DATA:
+#endif
+#ifdef USE_WIN32STREAMEXTRACTION
+ case STREAM_WIN32_DATA:
+#endif
+#if defined(USE_WIN32STREAMEXTRACTION) && defined(HAVE_LIBZ)
+ case STREAM_WIN32_GZIP_DATA:
#endif
case STREAM_UNIX_ATTRIBUTES:
case STREAM_FILE_DATA:
bfd->berrno = errno;
Dmsg1(400, "Open file %d\n", bfd->fid);
errno = bfd->berrno;
+
+#ifdef USE_WIN32STREAMEXTRACTION
+ bfd->win32DecompContext.bIsInData = FALSE;
+ bfd->win32DecompContext.liNextHeader = 0;
+#endif
+
return bfd->fid;
}
};
#endif
+#ifdef USE_WIN32STREAMEXTRACTION
+typedef struct _PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT {
+ LONGLONG liNextHeader;
+ BOOL bIsInData;
+ WIN32_STREAM_ID header_stream;
+} PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT;
+#endif
+
/* =======================================================
*
* W I N D O W S
char *prog; /* reader/writer program if any */
JCR *jcr; /* jcr for editing job codes */
Python_IO pio; /* Python I/O routines */
+#ifdef USE_WIN32STREAMEXTRACTION
+ PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT win32DecompContext; /* context for decomposition of win32 backup streams */
+ int use_backup_decomp; /* set if using BackupRead Stream Decomposition */
+#endif
};
HANDLE bget_handle(BFILE *bfd);
char *prog; /* reader/writer program if any */
JCR *jcr; /* jcr for editing job codes */
Python_IO pio; /* Python I/O routines */
+#ifdef USE_WIN32STREAMEXTRACTION
+ PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT win32DecompContext; /* context for decomposition of win32 backup streams */
+ int use_backup_decomp; /* set if using BackupRead Stream Decomposition */
+#endif
};
#endif
off_t blseek(BFILE *bfd, off_t offset, int whence);
const char *stream_to_ascii(int stream);
+#ifdef USE_WIN32STREAMEXTRACTION
+BOOL processWin32BackupAPIBlock (BFILE *bfd, void *pBuffer, size_t dwSize);
+#endif
+
#endif /* __BFILE_H */