X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;ds=sidebyside;f=bacula%2Fsrc%2Ffindlib%2Fbfile.c;h=6d2d797c6ffd625e9ac41ac0c01aad03993e06e6;hb=2a7fda9473a7ac2669f59e9ff0dec1cba8b12ef1;hp=cab8c54c025b2685a38f5da90d4202552d81c16f;hpb=b0455e438e0314dfd7493d12041f8742f07d160e;p=bacula%2Fbacula diff --git a/bacula/src/findlib/bfile.c b/bacula/src/findlib/bfile.c index cab8c54c02..6d2d797c6f 100644 --- a/bacula/src/findlib/bfile.c +++ b/bacula/src/findlib/bfile.c @@ -1,3 +1,30 @@ +/* + Bacula® - The Network Backup Solution + + Copyright (C) 2003-2010 Free Software Foundation Europe e.V. + + The main author of Bacula is Kern Sibbald, with contributions from + many others, a complete list can be found in the file AUTHORS. + This program is Free Software; you can redistribute it and/or + modify it under the terms of version three of the GNU Affero General Public + License as published by the Free Software Foundation and included + in the file LICENSE. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. + + Bacula® is a registered trademark of Kern Sibbald. + The licensor of Bacula is the Free Software Foundation Europe + (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, + Switzerland, email:ftf@fsfeurope.org. +*/ /* * Bacula low level File I/O routines. This routine simulates * open(), read(), write(), and close(), but using native routines. @@ -5,37 +32,41 @@ * * Kern Sibbald, April MMIII * - * Version $Id$ - * - */ -/* - Copyright (C) 2003-2006 Kern Sibbald - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - version 2 as amended with additional clauses defined in the - file LICENSE in the main source directory. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - the file LICENSE for additional details. - */ #include "bacula.h" #include "find.h" -bool (*python_set_prog)(JCR *jcr, const char *prog) = NULL; -int (*python_open)(BFILE *bfd, const char *fname, int flags, mode_t mode) = NULL; -int (*python_close)(BFILE *bfd) = NULL; -ssize_t (*python_read)(BFILE *bfd, void *buf, size_t count) = NULL; -ssize_t (*python_write)(BFILE *bfd, void *buf, size_t count) = NULL; +const int dbglvl = 200; + +int (*plugin_bopen)(BFILE *bfd, const char *fname, int flags, mode_t mode) = NULL; +int (*plugin_bclose)(BFILE *bfd) = NULL; +ssize_t (*plugin_bread)(BFILE *bfd, void *buf, size_t count) = NULL; +ssize_t (*plugin_bwrite)(BFILE *bfd, void *buf, size_t count) = NULL; +boffset_t (*plugin_blseek)(BFILE *bfd, boffset_t offset, int whence) = NULL; + #ifdef HAVE_DARWIN_OS #include #endif +#if !defined(HAVE_FDATASYNC) +#define fdatasync(fd) +#endif + +#ifdef HAVE_WIN32 +void pause_msg(const char *file, const char *func, int line, const char *msg) +{ + char buf[1000]; + if (msg) { + bsnprintf(buf, sizeof(buf), "%s:%s:%d %s", file, func, line, msg); + } else { + bsnprintf(buf, sizeof(buf), "%s:%s:%d", file, func, line); + } + MessageBox(NULL, buf, "Pause", MB_OK); +} +#endif + /* =============================================================== * * U N I X AND W I N D O W S @@ -60,34 +91,38 @@ const char *stream_to_ascii(int stream) static char buf[20]; switch (stream) { - case STREAM_GZIP_DATA: - return _("GZIP data"); - case STREAM_SPARSE_GZIP_DATA: - return _("GZIP sparse data"); - case STREAM_WIN32_DATA: - return _("Win32 data"); - case STREAM_WIN32_GZIP_DATA: - return _("Win32 GZIP data"); case STREAM_UNIX_ATTRIBUTES: - return _("File attributes"); + return _("Unix attributes"); case STREAM_FILE_DATA: return _("File data"); case STREAM_MD5_DIGEST: return _("MD5 digest"); + case STREAM_GZIP_DATA: + return _("GZIP data"); case STREAM_UNIX_ATTRIBUTES_EX: return _("Extended attributes"); case STREAM_SPARSE_DATA: return _("Sparse data"); + case STREAM_SPARSE_GZIP_DATA: + return _("GZIP sparse data"); case STREAM_PROGRAM_NAMES: return _("Program names"); case STREAM_PROGRAM_DATA: return _("Program data"); case STREAM_SHA1_DIGEST: return _("SHA1 digest"); + case STREAM_WIN32_DATA: + return _("Win32 data"); + case STREAM_WIN32_GZIP_DATA: + return _("Win32 GZIP data"); case STREAM_MACOS_FORK_DATA: - return _("HFS+ resource fork"); + return _("MacOS Fork data"); case STREAM_HFSPLUS_ATTRIBUTES: - return _("HFS+ Finder Info"); + return _("HFS+ attribs"); + case STREAM_UNIX_ACCESS_ACL: + return _("Standard Unix ACL attribs"); + case STREAM_UNIX_DEFAULT_ACL: + return _("Default Unix ACL attribs"); case STREAM_SHA256_DIGEST: return _("SHA256 digest"); case STREAM_SHA512_DIGEST: @@ -96,59 +131,116 @@ const char *stream_to_ascii(int stream) return _("Signed digest"); case STREAM_ENCRYPTED_FILE_DATA: return _("Encrypted File data"); - case STREAM_ENCRYPTED_FILE_GZIP_DATA: - return _("Encrypted GZIP data"); case STREAM_ENCRYPTED_WIN32_DATA: return _("Encrypted Win32 data"); + case STREAM_ENCRYPTED_SESSION_DATA: + return _("Encrypted session data"); + case STREAM_ENCRYPTED_FILE_GZIP_DATA: + return _("Encrypted GZIP data"); case STREAM_ENCRYPTED_WIN32_GZIP_DATA: return _("Encrypted Win32 GZIP data"); case STREAM_ENCRYPTED_MACOS_FORK_DATA: - return _("Encrypted HFS+ resource fork"); + return _("Encrypted MacOS fork data"); + case STREAM_ACL_AIX_TEXT: + return _("AIX Specific ACL attribs"); + case STREAM_ACL_DARWIN_ACCESS_ACL: + return _("Darwin Specific ACL attribs"); + case STREAM_ACL_FREEBSD_DEFAULT_ACL: + return _("FreeBSD Specific Default ACL attribs"); + case STREAM_ACL_FREEBSD_ACCESS_ACL: + return _("FreeBSD Specific Access ACL attribs"); + case STREAM_ACL_HPUX_ACL_ENTRY: + return _("HPUX Specific ACL attribs"); + case STREAM_ACL_IRIX_DEFAULT_ACL: + return _("Irix Specific Default ACL attribs"); + case STREAM_ACL_IRIX_ACCESS_ACL: + return _("Irix Specific Access ACL attribs"); + case STREAM_ACL_LINUX_DEFAULT_ACL: + return _("Linux Specific Default ACL attribs"); + case STREAM_ACL_LINUX_ACCESS_ACL: + return _("Linux Specific Access ACL attribs"); + case STREAM_ACL_TRU64_DEFAULT_ACL: + return _("OSF1 Specific Default ACL attribs"); + case STREAM_ACL_TRU64_ACCESS_ACL: + return _("OSF1 Specific Access ACL attribs"); + case STREAM_ACL_SOLARIS_ACLENT: + return _("Solaris Specific ACL attribs"); + case STREAM_ACL_SOLARIS_ACE: + return _("Solaris Specific ACL attribs"); + case STREAM_ACL_AFS_TEXT: + return _("AFS Specific ACL attribs"); + case STREAM_ACL_AIX_AIXC: + return _("AIX Specific ACL attribs"); + case STREAM_ACL_AIX_NFS4: + return _("AIX Specific ACL attribs"); + case STREAM_XATTR_AIX: + return _("AIX Specific Extended attribs"); + case STREAM_XATTR_OPENBSD: + return _("OpenBSD Specific Extended attribs"); + case STREAM_XATTR_SOLARIS_SYS: + return _("Solaris Specific Extensible attribs or System Extended attribs"); + case STREAM_XATTR_SOLARIS: + return _("Solaris Specific Extended attribs"); + case STREAM_XATTR_DARWIN: + return _("Darwin Specific Extended attribs"); + case STREAM_XATTR_FREEBSD: + return _("FreeBSD Specific Extended attribs"); + case STREAM_XATTR_LINUX: + return _("Linux Specific Extended attribs"); + case STREAM_XATTR_NETBSD: + return _("NetBSD Specific Extended attribs"); default: sprintf(buf, "%d", stream); return (const char *)buf; } } - +/** + * Convert a 64 bit little endian to a big endian + */ void int64_LE2BE(int64_t* pBE, const int64_t v) { /* convert little endian to big endian */ if (htonl(1) != 1L) { /* no work if on little endian machine */ - memcpy(pBE, &v, sizeof(int64_t)); + memcpy(pBE, &v, sizeof(int64_t)); } else { - int i; - uint8_t rv[sizeof(int64_t)]; - uint8_t *pv = (uint8_t *) &v; - - for (i = 0; i < 8; i++) { - rv[i] = pv[7 - i]; - } - memcpy(pBE, &rv, sizeof(int64_t)); + int i; + uint8_t rv[sizeof(int64_t)]; + uint8_t *pv = (uint8_t *) &v; + + for (i = 0; i < 8; i++) { + rv[i] = pv[7 - i]; + } + memcpy(pBE, &rv, sizeof(int64_t)); } } - +/** + * Convert a 32 bit little endian to a big endian + */ void int32_LE2BE(int32_t* pBE, const int32_t v) { /* convert little endian to big endian */ if (htonl(1) != 1L) { /* no work if on little endian machine */ - memcpy(pBE, &v, sizeof(int32_t)); + memcpy(pBE, &v, sizeof(int32_t)); } else { - int i; - uint8_t rv[sizeof(int32_t)]; - uint8_t *pv = (uint8_t *) &v; - - for (i = 0; i < 4; i++) { - rv[i] = pv[3 - i]; - } - memcpy(pBE, &rv, sizeof(int32_t)); + int i; + uint8_t rv[sizeof(int32_t)]; + uint8_t *pv = (uint8_t *) &v; + + for (i = 0; i < 4; i++) { + rv[i] = pv[3 - i]; + } + memcpy(pBE, &rv, sizeof(int32_t)); } } +/** + * Read a BackupRead block and pull out the file data + */ bool processWin32BackupAPIBlock (BFILE *bfd, void *pBuffer, ssize_t dwSize) -{ +{ /* pByte contains the buffer dwSize the len to be processed. function assumes to be called in successive incremental order over the complete @@ -165,12 +257,11 @@ bool processWin32BackupAPIBlock (BFILE *bfd, void *pBuffer, ssize_t dwSize) */ int32_t dwSizeHeader = 20; - do { - if (pContext->liNextHeader >= dwSize) { + do { + if (pContext->liNextHeader >= dwSize) { dwDataLen = dwSize-dwDataOffset; bContinue = false; /* 1 iteration is enough */ - } - else { + } else { dwDataLen = pContext->liNextHeader-dwDataOffset; bContinue = true; /* multiple iterations may be necessary */ } @@ -179,34 +270,34 @@ bool processWin32BackupAPIBlock (BFILE *bfd, void *pBuffer, ssize_t dwSize) /* copy block of real DATA */ if (pContext->bIsInData) { if (bwrite(bfd, ((char *)pBuffer)+dwDataOffset, dwDataLen) != (ssize_t)dwDataLen) - return false; + return false; } if (pContext->liNextHeader < dwSize) {/* is a header in this block ? */ int32_t dwOffsetTarget; int32_t dwOffsetSource; - + if (pContext->liNextHeader < 0) { /* start of header was before this block, so we * continue with the part in the current block */ - dwOffsetTarget = -pContext->liNextHeader; - dwOffsetSource = 0; + dwOffsetTarget = -pContext->liNextHeader; + dwOffsetSource = 0; } else { /* start of header is inside of this block */ dwOffsetTarget = 0; - dwOffsetSource = pContext->liNextHeader; + dwOffsetSource = pContext->liNextHeader; } int32_t dwHeaderPartLen = dwSizeHeader-dwOffsetTarget; bool bHeaderIsComplete; - if (dwHeaderPartLen <= dwSize-dwOffsetSource) + if (dwHeaderPartLen <= dwSize-dwOffsetSource) { /* header (or rest of header) is completely available in current block */ bHeaderIsComplete = true; - else { + } else { /* header will continue in next block */ bHeaderIsComplete = false; dwHeaderPartLen = dwSize-dwOffsetSource; @@ -221,22 +312,21 @@ bool processWin32BackupAPIBlock (BFILE *bfd, void *pBuffer, ssize_t dwSize) int32_t dwNameSize; int32_LE2BE (&dwNameSize, pContext->header_stream.dwStreamNameSize); dwDataOffset = dwNameSize+pContext->liNextHeader+dwSizeHeader; - + /* convert stream size (64 bit little endian) to machine type */ int64_LE2BE (&(pContext->liNextHeader), pContext->header_stream.Size); pContext->liNextHeader += dwDataOffset; pContext->bIsInData = pContext->header_stream.dwStreamId == WIN32_BACKUP_DATA; if (dwDataOffset == dwSize) - bContinue = false; - } - else { + bContinue = false; + } else { /* stop and continue with next block */ bContinue = false; pContext->bIsInData = false; } - } - } while (bContinue); + } + } while (bContinue); /* set "NextHeader" relative to the beginning of the next block */ pContext->liNextHeader-= dwSize; @@ -253,19 +343,19 @@ bool processWin32BackupAPIBlock (BFILE *bfd, void *pBuffer, ssize_t dwSize) * =============================================================== */ -#if defined(HAVE_CYGWIN) || defined(HAVE_WIN32) +#if defined(HAVE_WIN32) void unix_name_to_win32(POOLMEM **win32_name, char *name); extern "C" HANDLE get_osfhandle(int fd); - void binit(BFILE *bfd) { memset(bfd, 0, sizeof(BFILE)); bfd->fid = -1; bfd->mode = BF_CLOSED; bfd->use_backup_api = have_win32_api(); + bfd->cmd_plugin = false; } /* @@ -287,11 +377,11 @@ bool set_portable_backup(BFILE *bfd) return true; } -bool set_prog(BFILE *bfd, char *prog, JCR *jcr) +bool set_cmd_plugin(BFILE *bfd, JCR *jcr) { - bfd->prog = prog; + bfd->cmd_plugin = true; bfd->jcr = jcr; - return false; + return true; } /* @@ -309,7 +399,6 @@ bool have_win32_api() } - /* * Return true if we support the stream * false if we do not support the stream @@ -382,11 +471,37 @@ int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode) unix_name_to_win32(&win32_fname, (char *)fname); - if (!(p_CreateFileA || p_CreateFileW)) + if (bfd->cmd_plugin && plugin_bopen) { + int rtnstat; + Dmsg1(50, "call plugin_bopen fname=%s\n", fname); + rtnstat = plugin_bopen(bfd, fname, flags, mode); + Dmsg1(50, "return from plugin_bopen status=%d\n", rtnstat); + if (rtnstat >= 0) { + if (flags & O_CREAT || flags & O_WRONLY) { /* Open existing for write */ + Dmsg1(50, "plugin_open for write OK file=%s.\n", fname); + bfd->mode = BF_WRITE; + } else { + Dmsg1(50, "plugin_open for read OK file=%s.\n", fname); + bfd->mode = BF_READ; + } + } else { + bfd->mode = BF_CLOSED; + Dmsg1(000, "==== plugin_bopen returned bad status=%d\n", rtnstat); + } + free_pool_memory(win32_fname_wchar); + free_pool_memory(win32_fname); + return bfd->mode == BF_CLOSED ? -1 : 1; + } + Dmsg0(50, "=== NO plugin\n"); + + if (!(p_CreateFileA || p_CreateFileW)) { + Dmsg0(50, "No CreateFileA and no CreateFileW!!!!!\n"); return 0; + } - if (p_CreateFileW && p_MultiByteToWideChar) + if (p_CreateFileW && p_MultiByteToWideChar) { make_win32_path_UTF8_2_wchar(&win32_fname_wchar, fname); + } if (flags & O_CREAT) { /* Create */ if (bfd->use_backup_api) { @@ -397,8 +512,9 @@ int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode) dwflags = 0; } - // unicode or ansii open for create write if (p_CreateFileW && p_MultiByteToWideChar) { + // unicode open for create write + Dmsg1(100, "Create CreateFileW=%s\n", win32_fname); bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar, dwaccess, /* Requested access */ 0, /* Shared mode */ @@ -407,6 +523,8 @@ int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode) dwflags, /* Flags and attributes */ NULL); /* TemplateFile */ } else { + // ascii open + Dmsg1(100, "Create CreateFileA=%s\n", win32_fname); bfd->fh = p_CreateFileA(win32_fname, dwaccess, /* Requested access */ 0, /* Shared mode */ @@ -421,14 +539,15 @@ int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode) } else if (flags & O_WRONLY) { /* Open existing for write */ if (bfd->use_backup_api) { dwaccess = GENERIC_WRITE|WRITE_OWNER|WRITE_DAC; - dwflags = FILE_FLAG_BACKUP_SEMANTICS; + dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT; } else { dwaccess = GENERIC_WRITE; dwflags = 0; } - // unicode or ansii open for open existing write if (p_CreateFileW && p_MultiByteToWideChar) { + // unicode open for open existing write + Dmsg1(100, "Write only CreateFileW=%s\n", win32_fname); bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar, dwaccess, /* Requested access */ 0, /* Shared mode */ @@ -437,6 +556,8 @@ int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode) dwflags, /* Flags and attributes */ NULL); /* TemplateFile */ } else { + // ascii open + Dmsg1(100, "Write only CreateFileA=%s\n", win32_fname); bfd->fh = p_CreateFileA(win32_fname, dwaccess, /* Requested access */ 0, /* Shared mode */ @@ -452,7 +573,8 @@ int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode) } else { /* Read */ if (bfd->use_backup_api) { dwaccess = GENERIC_READ|READ_CONTROL|ACCESS_SYSTEM_SECURITY; - dwflags = FILE_FLAG_BACKUP_SEMANTICS; + dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_SEQUENTIAL_SCAN | + FILE_FLAG_OPEN_REPARSE_POINT; dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE; } else { dwaccess = GENERIC_READ; @@ -460,8 +582,9 @@ int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode) dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE; } - // unicode or ansii open for open existing read if (p_CreateFileW && p_MultiByteToWideChar) { + // unicode open for open existing read + Dmsg1(100, "Read CreateFileW=%s\n", win32_fname); bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar, dwaccess, /* Requested access */ dwshare, /* Share modes */ @@ -470,6 +593,8 @@ int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode) dwflags, /* Flags and attributes */ NULL); /* TemplateFile */ } else { + // ascii open + Dmsg1(100, "Read CreateFileA=%s\n", win32_fname); bfd->fh = p_CreateFileA(win32_fname, dwaccess, /* Requested access */ dwshare, /* Share modes */ @@ -505,16 +630,25 @@ int bclose(BFILE *bfd) { int stat = 0; - if (bfd->errmsg) { - free_pool_memory(bfd->errmsg); - bfd->errmsg = NULL; - } if (bfd->mode == BF_CLOSED) { + Dmsg0(50, "=== BFD already closed.\n"); return 0; } + + if (bfd->cmd_plugin && plugin_bclose) { + stat = plugin_bclose(bfd); + Dmsg0(50, "==== BFD closed!!!\n"); + goto all_done; + } + + /* + * We need to tell the API to release the buffer it + * allocated in lpContext. We do so by calling the + * API one more time, but with the Abort bit set. + */ if (bfd->use_backup_api && bfd->mode == BF_READ) { BYTE buf[10]; - if (!bfd->lpContext && !p_BackupRead(bfd->fh, + if (bfd->lpContext && !p_BackupRead(bfd->fh, buf, /* buffer */ (DWORD)0, /* bytes to read */ &bfd->rw_bytes, /* bytes read */ @@ -526,7 +660,7 @@ int bclose(BFILE *bfd) } } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) { BYTE buf[10]; - if (!bfd->lpContext && !p_BackupWrite(bfd->fh, + if (bfd->lpContext && !p_BackupWrite(bfd->fh, buf, /* buffer */ (DWORD)0, /* bytes to read */ &bfd->rw_bytes, /* bytes written */ @@ -541,8 +675,15 @@ int bclose(BFILE *bfd) stat = -1; errno = b_errno_win32; } + +all_done: + if (bfd->errmsg) { + free_pool_memory(bfd->errmsg); + bfd->errmsg = NULL; + } bfd->mode = BF_CLOSED; bfd->lpContext = NULL; + bfd->cmd_plugin = false; return stat; } @@ -554,6 +695,10 @@ ssize_t bread(BFILE *bfd, void *buf, size_t count) { bfd->rw_bytes = 0; + if (bfd->cmd_plugin && plugin_bread) { + return plugin_bread(bfd, buf, count); + } + if (bfd->use_backup_api) { if (!p_BackupRead(bfd->fh, (BYTE *)buf, @@ -587,6 +732,10 @@ ssize_t bwrite(BFILE *bfd, void *buf, size_t count) { bfd->rw_bytes = 0; + if (bfd->cmd_plugin && plugin_bwrite) { + return plugin_bwrite(bfd, buf, count); + } + if (bfd->use_backup_api) { if (!p_BackupWrite(bfd->fh, (BYTE *)buf, @@ -620,10 +769,23 @@ bool is_bopen(BFILE *bfd) return bfd->mode != BF_CLOSED; } -off_t blseek(BFILE *bfd, off_t offset, int whence) +boffset_t blseek(BFILE *bfd, boffset_t offset, int whence) { - /* ****FIXME**** this must be implemented if we want to read Win32 Archives */ - return -1; + LONG offset_low = (LONG)offset; + LONG offset_high = (LONG)(offset >> 32); + DWORD dwResult; + + if (bfd->cmd_plugin && plugin_blseek) { + return plugin_blseek(bfd, offset, whence); + } + + dwResult = SetFilePointer(bfd->fh, offset_low, &offset_high, whence); + + if (dwResult == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) { + return (boffset_t)-1; + } + + return ((boffset_t)offset_high << 32) | dwResult; } #else /* Unix systems */ @@ -672,22 +834,14 @@ bool is_portable_backup(BFILE *bfd) bool set_prog(BFILE *bfd, char *prog, JCR *jcr) { -#ifdef HAVE_PYTHON - if (bfd->prog && strcmp(prog, bfd->prog) == 0) { - return true; /* already setup */ - } - - if (python_set_prog(jcr, prog)) { - Dmsg1(000, "Set prog=%s\n", prog); - bfd->prog = prog; - bfd->jcr = jcr; - return true; - } -#endif - Dmsg0(000, "No prog set\n"); - bfd->prog = NULL; return false; +} +bool set_cmd_plugin(BFILE *bfd, JCR *jcr) +{ + bfd->cmd_plugin = true; + bfd->jcr = jcr; + return true; } /* @@ -750,22 +904,51 @@ bool is_restore_stream_supported(int stream) int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode) { - /* Open reader/writer program */ - if (bfd->prog) { - Dmsg1(000, "Open file %d\n", bfd->fid); - return python_open(bfd, fname, flags, mode); + if (bfd->cmd_plugin && plugin_bopen) { + Dmsg1(50, "call plugin_bopen fname=%s\n", fname); + bfd->fid = plugin_bopen(bfd, fname, flags, mode); + Dmsg1(50, "Plugin bopen stat=%d\n", bfd->fid); + return bfd->fid; } /* Normal file open */ - Dmsg1(400, "open file %s\n", fname); - bfd->fid = open(fname, flags, mode); + Dmsg1(dbglvl, "open file %s\n", fname); + + /* We use fnctl to set O_NOATIME if requested to avoid open error */ + bfd->fid = open(fname, flags & ~O_NOATIME, mode); + + /* Set O_NOATIME if possible */ + if (bfd->fid != -1 && flags & O_NOATIME) { + int oldflags = fcntl(bfd->fid, F_GETFL, 0); + if (oldflags == -1) { + bfd->berrno = errno; + close(bfd->fid); + bfd->fid = -1; + } else { + int ret = fcntl(bfd->fid, F_SETFL, oldflags | O_NOATIME); + /* EPERM means setting O_NOATIME was not allowed */ + if (ret == -1 && errno != EPERM) { + bfd->berrno = errno; + close(bfd->fid); + bfd->fid = -1; + } + } + } bfd->berrno = errno; + bfd->m_flags = flags; Dmsg1(400, "Open file %d\n", bfd->fid); errno = bfd->berrno; bfd->win32DecompContext.bIsInData = false; bfd->win32DecompContext.liNextHeader = 0; +#if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED) + if (bfd->fid != -1 && flags & O_RDONLY) { + int stat = posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_WILLNEED); + Dmsg2(400, "Did posix_fadvise on %s stat=%d\n", fname, stat); + } +#endif + return bfd->fid; } @@ -782,6 +965,11 @@ int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode) free_pool_memory(rsrc_fname); return bfd->fid; } +#else +int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode) +{ + return -1; +} #endif @@ -791,19 +979,28 @@ int bclose(BFILE *bfd) Dmsg1(400, "Close file %d\n", bfd->fid); - /* Close reader/writer program */ - if (bfd->prog) { - return python_close(bfd); + if (bfd->cmd_plugin && plugin_bclose) { + stat = plugin_bclose(bfd); + bfd->fid = -1; + bfd->cmd_plugin = false; } if (bfd->fid == -1) { return 0; } +#if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED) + if (bfd->m_flags & O_RDONLY) { + fdatasync(bfd->fid); /* sync the file */ + /* Tell OS we don't need it any more */ + posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_DONTNEED); + } +#endif /* Close normal file */ stat = close(bfd->fid); bfd->berrno = errno; bfd->fid = -1; + bfd->cmd_plugin = false; return stat; } @@ -811,9 +1008,10 @@ ssize_t bread(BFILE *bfd, void *buf, size_t count) { ssize_t stat; - if (bfd->prog) { - return python_read(bfd, buf, count); + if (bfd->cmd_plugin && plugin_bread) { + return plugin_bread(bfd, buf, count); } + stat = read(bfd->fid, buf, count); bfd->berrno = errno; return stat; @@ -823,8 +1021,8 @@ ssize_t bwrite(BFILE *bfd, void *buf, size_t count) { ssize_t stat; - if (bfd->prog) { - return python_write(bfd, buf, count); + if (bfd->cmd_plugin && plugin_bwrite) { + return plugin_bwrite(bfd, buf, count); } stat = write(bfd->fid, buf, count); bfd->berrno = errno; @@ -836,12 +1034,16 @@ bool is_bopen(BFILE *bfd) return bfd->fid >= 0; } -off_t blseek(BFILE *bfd, off_t offset, int whence) +boffset_t blseek(BFILE *bfd, boffset_t offset, int whence) { - off_t pos; - pos = lseek(bfd->fid, offset, whence); - bfd->berrno = errno; - return pos; + boffset_t pos; + + if (bfd->cmd_plugin && plugin_bwrite) { + return plugin_blseek(bfd, offset, whence); + } + pos = (boffset_t)lseek(bfd->fid, offset, whence); + bfd->berrno = errno; + return pos; } #endif