From: Thorsten Engel Date: Wed, 2 Nov 2005 15:11:08 +0000 (+0000) Subject: support for WIN32 backup stream restores on platforms without win32 backup api X-Git-Tag: Release-1.38.1~47 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=dc46944f6a36aed8260d095175083c3cb8861e41;p=bacula%2Fbacula support for WIN32 backup stream restores on platforms without win32 backup api PRELIMINARY! must define USE_WIN32STREAMEXTRACTION for enabling git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@2522 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/src/filed/restore.c b/bacula/src/filed/restore.c index e2686298d2..cfda593a2c 100644 --- a/bacula/src/filed/restore.c +++ b/bacula/src/filed/restore.c @@ -290,6 +290,15 @@ void do_restore(JCR *jcr) || 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); @@ -534,6 +543,17 @@ int32_t extract_data(JCR *jcr, BFILE *bfd, POOLMEM *buf, int32_t buflen, 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"), diff --git a/bacula/src/findlib/bfile.c b/bacula/src/findlib/bfile.c index 4dc9df5392..6b740f88b9 100644 --- a/bacula/src/findlib/bfile.c +++ b/bacula/src/findlib/bfile.c @@ -97,6 +97,94 @@ const char *stream_to_ascii(int stream) } } +#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 + /* =============================================================== @@ -178,7 +266,12 @@ bool is_stream_supported(int stream) #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: @@ -214,7 +307,7 @@ int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode) 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); @@ -333,6 +426,10 @@ int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode) } 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; @@ -540,8 +637,10 @@ bool is_stream_supported(int stream) 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: @@ -552,6 +651,12 @@ bool is_stream_supported(int stream) #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: @@ -615,6 +720,12 @@ int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode) 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; } diff --git a/bacula/src/findlib/bfile.h b/bacula/src/findlib/bfile.h index a38e53c1c1..de60b4f23f 100644 --- a/bacula/src/findlib/bfile.h +++ b/bacula/src/findlib/bfile.h @@ -41,6 +41,14 @@ struct Python_IO { }; #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 @@ -74,6 +82,10 @@ struct BFILE { 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); @@ -94,6 +106,10 @@ struct BFILE { 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 @@ -118,4 +134,8 @@ ssize_t bwrite(BFILE *bfd, void *buf, size_t count); 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 */ diff --git a/bacula/src/findlib/find.h b/bacula/src/findlib/find.h index 798fa25940..9e4c0b9bbd 100755 --- a/bacula/src/findlib/find.h +++ b/bacula/src/findlib/find.h @@ -90,6 +90,9 @@ enum { #define FO_NO_HARDLINK (1<<15) /* don't handle hard links */ #define FO_IGNORECASE (1<<16) /* Ignore file name case */ #define FO_HFSPLUS (1<<17) /* Resource forks and Finder Info */ +#ifdef USE_WIN32STREAMEXTRACTION +#define FO_WIN32DECOMP (1<<18) /* Use BackupRead decomposition */ +#endif struct s_included_file { struct s_included_file *next;