2 Bacula® - The Network Backup Solution
4 Copyright (C) 2003-2008 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation and included
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of Kern Sibbald.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
29 * Bacula low level File I/O routines. This routine simulates
30 * open(), read(), write(), and close(), but using native routines.
31 * I.e. on Windows, we use Windows APIs.
33 * Kern Sibbald, April MMIII
42 const int dbglvl = 200;
44 int (*plugin_bopen)(BFILE *bfd, const char *fname, int flags, mode_t mode) = NULL;
45 int (*plugin_bclose)(BFILE *bfd) = NULL;
46 ssize_t (*plugin_bread)(BFILE *bfd, void *buf, size_t count) = NULL;
47 ssize_t (*plugin_bwrite)(BFILE *bfd, void *buf, size_t count) = NULL;
48 boffset_t (*plugin_blseek)(BFILE *bfd, boffset_t offset, int whence) = NULL;
52 #include <sys/paths.h>
55 #if !defined(HAVE_FDATASYNC)
60 void pause_msg(const char *file, const char *func, int line, const char *msg)
64 bsnprintf(buf, sizeof(buf), "%s:%s:%d %s", file, func, line, msg);
66 bsnprintf(buf, sizeof(buf), "%s:%s:%d", file, func, line);
68 MessageBox(NULL, buf, "Pause", MB_OK);
72 /* ===============================================================
74 * U N I X AND W I N D O W S
76 * ===============================================================
79 bool is_win32_stream(int stream)
82 case STREAM_WIN32_DATA:
83 case STREAM_WIN32_GZIP_DATA:
84 case STREAM_ENCRYPTED_WIN32_DATA:
85 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
91 const char *stream_to_ascii(int stream)
96 case STREAM_UNIX_ATTRIBUTES:
97 return _("Unix attributes");
98 case STREAM_FILE_DATA:
99 return _("File data");
100 case STREAM_MD5_DIGEST:
101 return _("MD5 digest");
102 case STREAM_GZIP_DATA:
103 return _("GZIP data");
104 case STREAM_UNIX_ATTRIBUTES_EX:
105 return _("Extended attributes");
106 case STREAM_SPARSE_DATA:
107 return _("Sparse data");
108 case STREAM_SPARSE_GZIP_DATA:
109 return _("GZIP sparse data");
110 case STREAM_PROGRAM_NAMES:
111 return _("Program names");
112 case STREAM_PROGRAM_DATA:
113 return _("Program data");
114 case STREAM_SHA1_DIGEST:
115 return _("SHA1 digest");
116 case STREAM_WIN32_DATA:
117 return _("Win32 data");
118 case STREAM_WIN32_GZIP_DATA:
119 return _("Win32 GZIP data");
120 case STREAM_MACOS_FORK_DATA:
121 return _("MacOS Fork data");
122 case STREAM_HFSPLUS_ATTRIBUTES:
123 return _("HFS+ attribs");
124 case STREAM_UNIX_ACCESS_ACL:
125 return _("Standard Unix ACL attribs");
126 case STREAM_UNIX_DEFAULT_ACL:
127 return _("Default Unix ACL attribs");
128 case STREAM_SHA256_DIGEST:
129 return _("SHA256 digest");
130 case STREAM_SHA512_DIGEST:
131 return _("SHA512 digest");
132 case STREAM_SIGNED_DIGEST:
133 return _("Signed digest");
134 case STREAM_ENCRYPTED_FILE_DATA:
135 return _("Encrypted File data");
136 case STREAM_ENCRYPTED_WIN32_DATA:
137 return _("Encrypted Win32 data");
138 case STREAM_ENCRYPTED_SESSION_DATA:
139 return _("Encrypted session data");
140 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
141 return _("Encrypted GZIP data");
142 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
143 return _("Encrypted Win32 GZIP data");
144 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
145 return _("Encrypted MacOS fork data");
146 case STREAM_ACL_AIX_TEXT:
147 return _("AIX Specific ACL attribs");
148 case STREAM_ACL_DARWIN_ACCESS_ACL:
149 return _("Darwin Specific ACL attribs");
150 case STREAM_ACL_FREEBSD_DEFAULT_ACL:
151 return _("FreeBSD Specific Default ACL attribs");
152 case STREAM_ACL_FREEBSD_ACCESS_ACL:
153 return _("FreeBSD Specific Access ACL attribs");
154 case STREAM_ACL_HPUX_ACL_ENTRY:
155 return _("HPUX Specific ACL attribs");
156 case STREAM_ACL_IRIX_DEFAULT_ACL:
157 return _("Irix Specific Default ACL attribs");
158 case STREAM_ACL_IRIX_ACCESS_ACL:
159 return _("Irix Specific Access ACL attribs");
160 case STREAM_ACL_LINUX_DEFAULT_ACL:
161 return _("Linux Specific Default ACL attribs");
162 case STREAM_ACL_LINUX_ACCESS_ACL:
163 return _("Linux Specific Access ACL attribs");
164 case STREAM_ACL_TRU64_DEFAULT_ACL:
165 return _("OSF1 Specific Default ACL attribs");
166 case STREAM_ACL_TRU64_ACCESS_ACL:
167 return _("OSF1 Specific Access ACL attribs");
168 case STREAM_ACL_SOLARIS_ACLENT:
169 return _("Solaris Specific ACL attribs");
170 case STREAM_ACL_SOLARIS_ACE:
171 return _("Solaris Specific ACL attribs");
172 case STREAM_XATTR_SOLARIS:
173 return _("Solaris Specific Extended attribs and Extensible attribs");
174 case STREAM_XATTR_DARWIN:
175 return _("Darwin Specific Extended attribs");
176 case STREAM_XATTR_FREEBSD:
177 return _("FreeBSD Specific Extended attribs");
178 case STREAM_XATTR_LINUX:
179 return _("Linux Specific Extended attribs");
180 case STREAM_XATTR_NETBSD:
181 return _("NetBSD Specific Extended attribs");
183 sprintf(buf, "%d", stream);
184 return (const char *)buf;
189 void int64_LE2BE(int64_t* pBE, const int64_t v)
191 /* convert little endian to big endian */
192 if (htonl(1) != 1L) { /* no work if on little endian machine */
193 memcpy(pBE, &v, sizeof(int64_t));
196 uint8_t rv[sizeof(int64_t)];
197 uint8_t *pv = (uint8_t *) &v;
199 for (i = 0; i < 8; i++) {
202 memcpy(pBE, &rv, sizeof(int64_t));
207 void int32_LE2BE(int32_t* pBE, const int32_t v)
209 /* convert little endian to big endian */
210 if (htonl(1) != 1L) { /* no work if on little endian machine */
211 memcpy(pBE, &v, sizeof(int32_t));
214 uint8_t rv[sizeof(int32_t)];
215 uint8_t *pv = (uint8_t *) &v;
217 for (i = 0; i < 4; i++) {
220 memcpy(pBE, &rv, sizeof(int32_t));
225 bool processWin32BackupAPIBlock (BFILE *bfd, void *pBuffer, ssize_t dwSize)
227 /* pByte contains the buffer
228 dwSize the len to be processed. function assumes to be
229 called in successive incremental order over the complete
230 BackupRead stream beginning at pos 0 and ending at the end.
233 PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT* pContext = &(bfd->win32DecompContext);
234 bool bContinue = false;
235 int64_t dwDataOffset = 0;
238 /* Win32 Stream Header size without name of stream.
239 * = sizeof (WIN32_STREAM_ID)- sizeof(WCHAR*);
241 int32_t dwSizeHeader = 20;
244 if (pContext->liNextHeader >= dwSize) {
245 dwDataLen = dwSize-dwDataOffset;
246 bContinue = false; /* 1 iteration is enough */
248 dwDataLen = pContext->liNextHeader-dwDataOffset;
249 bContinue = true; /* multiple iterations may be necessary */
253 /* copy block of real DATA */
254 if (pContext->bIsInData) {
255 if (bwrite(bfd, ((char *)pBuffer)+dwDataOffset, dwDataLen) != (ssize_t)dwDataLen)
259 if (pContext->liNextHeader < dwSize) {/* is a header in this block ? */
260 int32_t dwOffsetTarget;
261 int32_t dwOffsetSource;
263 if (pContext->liNextHeader < 0) {
264 /* start of header was before this block, so we
265 * continue with the part in the current block
267 dwOffsetTarget = -pContext->liNextHeader;
270 /* start of header is inside of this block */
272 dwOffsetSource = pContext->liNextHeader;
275 int32_t dwHeaderPartLen = dwSizeHeader-dwOffsetTarget;
276 bool bHeaderIsComplete;
278 if (dwHeaderPartLen <= dwSize-dwOffsetSource) {
279 /* header (or rest of header) is completely available
282 bHeaderIsComplete = true;
284 /* header will continue in next block */
285 bHeaderIsComplete = false;
286 dwHeaderPartLen = dwSize-dwOffsetSource;
289 /* copy the available portion of header to persistent copy */
290 memcpy(((char *)&pContext->header_stream)+dwOffsetTarget, ((char *)pBuffer)+dwOffsetSource, dwHeaderPartLen);
292 /* recalculate position of next header */
293 if (bHeaderIsComplete) {
294 /* convert stream name size (32 bit little endian) to machine type */
296 int32_LE2BE (&dwNameSize, pContext->header_stream.dwStreamNameSize);
297 dwDataOffset = dwNameSize+pContext->liNextHeader+dwSizeHeader;
299 /* convert stream size (64 bit little endian) to machine type */
300 int64_LE2BE (&(pContext->liNextHeader), pContext->header_stream.Size);
301 pContext->liNextHeader += dwDataOffset;
303 pContext->bIsInData = pContext->header_stream.dwStreamId == WIN32_BACKUP_DATA;
304 if (dwDataOffset == dwSize)
307 /* stop and continue with next block */
309 pContext->bIsInData = false;
314 /* set "NextHeader" relative to the beginning of the next block */
315 pContext->liNextHeader-= dwSize;
322 /* ===============================================================
326 * ===============================================================
329 #if defined(HAVE_WIN32)
331 void unix_name_to_win32(POOLMEM **win32_name, char *name);
332 extern "C" HANDLE get_osfhandle(int fd);
335 void binit(BFILE *bfd)
337 memset(bfd, 0, sizeof(BFILE));
339 bfd->mode = BF_CLOSED;
340 bfd->use_backup_api = have_win32_api();
341 bfd->cmd_plugin = false;
345 * Enables using the Backup API (win32_data).
346 * Returns 1 if function worked
347 * Returns 0 if failed (i.e. do not have Backup API on this machine)
349 bool set_win32_backup(BFILE *bfd)
351 /* We enable if possible here */
352 bfd->use_backup_api = have_win32_api();
353 return bfd->use_backup_api;
357 bool set_portable_backup(BFILE *bfd)
359 bfd->use_backup_api = false;
363 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
365 bfd->cmd_plugin = true;
371 * Return 1 if we are NOT using Win32 BackupWrite()
374 bool is_portable_backup(BFILE *bfd)
376 return !bfd->use_backup_api;
379 bool have_win32_api()
381 return p_BackupRead && p_BackupWrite;
386 * Return true if we support the stream
387 * false if we do not support the stream
389 * This code is running under Win32, so we
390 * do not need #ifdef on MACOS ...
392 bool is_restore_stream_supported(int stream)
396 /* Streams known not to be supported */
398 case STREAM_GZIP_DATA:
399 case STREAM_SPARSE_GZIP_DATA:
400 case STREAM_WIN32_GZIP_DATA:
402 case STREAM_MACOS_FORK_DATA:
403 case STREAM_HFSPLUS_ATTRIBUTES:
404 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
409 case STREAM_GZIP_DATA:
410 case STREAM_SPARSE_GZIP_DATA:
411 case STREAM_WIN32_GZIP_DATA:
413 case STREAM_WIN32_DATA:
414 case STREAM_UNIX_ATTRIBUTES:
415 case STREAM_FILE_DATA:
416 case STREAM_MD5_DIGEST:
417 case STREAM_UNIX_ATTRIBUTES_EX:
418 case STREAM_SPARSE_DATA:
419 case STREAM_PROGRAM_NAMES:
420 case STREAM_PROGRAM_DATA:
421 case STREAM_SHA1_DIGEST:
423 case STREAM_SHA256_DIGEST:
424 case STREAM_SHA512_DIGEST:
427 case STREAM_SIGNED_DIGEST:
428 case STREAM_ENCRYPTED_FILE_DATA:
429 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
430 case STREAM_ENCRYPTED_WIN32_DATA:
431 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
433 case 0: /* compatibility with old tapes */
439 HANDLE bget_handle(BFILE *bfd)
444 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
446 POOLMEM *win32_fname;
447 POOLMEM *win32_fname_wchar;
449 DWORD dwaccess, dwflags, dwshare;
451 /* Convert to Windows path format */
452 win32_fname = get_pool_memory(PM_FNAME);
453 win32_fname_wchar = get_pool_memory(PM_FNAME);
455 unix_name_to_win32(&win32_fname, (char *)fname);
457 if (bfd->cmd_plugin && plugin_bopen) {
459 Dmsg1(50, "call plugin_bopen fname=%s\n", fname);
460 rtnstat = plugin_bopen(bfd, fname, flags, mode);
461 Dmsg1(50, "return from plugin_bopen status=%d\n", rtnstat);
463 if (flags & O_CREAT || flags & O_WRONLY) { /* Open existing for write */
464 Dmsg1(50, "plugin_open for write OK file=%s.\n", fname);
465 bfd->mode = BF_WRITE;
467 Dmsg1(50, "plugin_open for read OK file=%s.\n", fname);
471 bfd->mode = BF_CLOSED;
472 Dmsg1(000, "==== plugin_bopen returned bad status=%d\n", rtnstat);
474 free_pool_memory(win32_fname_wchar);
475 free_pool_memory(win32_fname);
476 return bfd->mode == BF_CLOSED ? -1 : 1;
478 Dmsg0(50, "=== NO plugin\n");
480 if (!(p_CreateFileA || p_CreateFileW)) {
481 Dmsg0(50, "No CreateFileA and no CreateFileW!!!!!\n");
485 if (p_CreateFileW && p_MultiByteToWideChar) {
486 make_win32_path_UTF8_2_wchar(&win32_fname_wchar, fname);
489 if (flags & O_CREAT) { /* Create */
490 if (bfd->use_backup_api) {
491 dwaccess = GENERIC_WRITE|FILE_ALL_ACCESS|WRITE_OWNER|WRITE_DAC|ACCESS_SYSTEM_SECURITY;
492 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
494 dwaccess = GENERIC_WRITE;
498 if (p_CreateFileW && p_MultiByteToWideChar) {
499 // unicode open for create write
500 Dmsg1(100, "Create CreateFileW=%s\n", win32_fname);
501 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
502 dwaccess, /* Requested access */
504 NULL, /* SecurityAttributes */
505 CREATE_ALWAYS, /* CreationDisposition */
506 dwflags, /* Flags and attributes */
507 NULL); /* TemplateFile */
510 Dmsg1(100, "Create CreateFileA=%s\n", win32_fname);
511 bfd->fh = p_CreateFileA(win32_fname,
512 dwaccess, /* Requested access */
514 NULL, /* SecurityAttributes */
515 CREATE_ALWAYS, /* CreationDisposition */
516 dwflags, /* Flags and attributes */
517 NULL); /* TemplateFile */
520 bfd->mode = BF_WRITE;
522 } else if (flags & O_WRONLY) { /* Open existing for write */
523 if (bfd->use_backup_api) {
524 dwaccess = GENERIC_WRITE|WRITE_OWNER|WRITE_DAC;
525 dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT;
527 dwaccess = GENERIC_WRITE;
531 if (p_CreateFileW && p_MultiByteToWideChar) {
532 // unicode open for open existing write
533 Dmsg1(100, "Write only CreateFileW=%s\n", win32_fname);
534 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
535 dwaccess, /* Requested access */
537 NULL, /* SecurityAttributes */
538 OPEN_EXISTING, /* CreationDisposition */
539 dwflags, /* Flags and attributes */
540 NULL); /* TemplateFile */
543 Dmsg1(100, "Write only CreateFileA=%s\n", win32_fname);
544 bfd->fh = p_CreateFileA(win32_fname,
545 dwaccess, /* Requested access */
547 NULL, /* SecurityAttributes */
548 OPEN_EXISTING, /* CreationDisposition */
549 dwflags, /* Flags and attributes */
550 NULL); /* TemplateFile */
554 bfd->mode = BF_WRITE;
557 if (bfd->use_backup_api) {
558 dwaccess = GENERIC_READ|READ_CONTROL|ACCESS_SYSTEM_SECURITY;
559 dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_SEQUENTIAL_SCAN |
560 FILE_FLAG_OPEN_REPARSE_POINT;
561 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
563 dwaccess = GENERIC_READ;
565 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE;
568 if (p_CreateFileW && p_MultiByteToWideChar) {
569 // unicode open for open existing read
570 Dmsg1(100, "Read CreateFileW=%s\n", win32_fname);
571 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
572 dwaccess, /* Requested access */
573 dwshare, /* Share modes */
574 NULL, /* SecurityAttributes */
575 OPEN_EXISTING, /* CreationDisposition */
576 dwflags, /* Flags and attributes */
577 NULL); /* TemplateFile */
580 Dmsg1(100, "Read CreateFileA=%s\n", win32_fname);
581 bfd->fh = p_CreateFileA(win32_fname,
582 dwaccess, /* Requested access */
583 dwshare, /* Share modes */
584 NULL, /* SecurityAttributes */
585 OPEN_EXISTING, /* CreationDisposition */
586 dwflags, /* Flags and attributes */
587 NULL); /* TemplateFile */
593 if (bfd->fh == INVALID_HANDLE_VALUE) {
594 bfd->lerror = GetLastError();
595 bfd->berrno = b_errno_win32;
596 errno = b_errno_win32;
597 bfd->mode = BF_CLOSED;
600 bfd->lpContext = NULL;
601 bfd->win32DecompContext.bIsInData = false;
602 bfd->win32DecompContext.liNextHeader = 0;
603 free_pool_memory(win32_fname_wchar);
604 free_pool_memory(win32_fname);
605 return bfd->mode == BF_CLOSED ? -1 : 1;
609 * Returns 0 on success
612 int bclose(BFILE *bfd)
617 free_pool_memory(bfd->errmsg);
620 if (bfd->mode == BF_CLOSED) {
621 Dmsg0(50, "=== BFD already closed.\n");
625 if (bfd->cmd_plugin && plugin_bclose) {
626 stat = plugin_bclose(bfd);
627 Dmsg0(50, "==== BFD closed!!!\n");
632 * We need to tell the API to release the buffer it
633 * allocated in lpContext. We do so by calling the
634 * API one more time, but with the Abort bit set.
636 if (bfd->use_backup_api && bfd->mode == BF_READ) {
638 if (bfd->lpContext && !p_BackupRead(bfd->fh,
640 (DWORD)0, /* bytes to read */
641 &bfd->rw_bytes, /* bytes read */
643 1, /* ProcessSecurity */
644 &bfd->lpContext)) { /* Read context */
645 errno = b_errno_win32;
648 } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
650 if (bfd->lpContext && !p_BackupWrite(bfd->fh,
652 (DWORD)0, /* bytes to read */
653 &bfd->rw_bytes, /* bytes written */
655 1, /* ProcessSecurity */
656 &bfd->lpContext)) { /* Write context */
657 errno = b_errno_win32;
661 if (!CloseHandle(bfd->fh)) {
663 errno = b_errno_win32;
667 bfd->mode = BF_CLOSED;
668 bfd->lpContext = NULL;
669 bfd->cmd_plugin = false;
673 /* Returns: bytes read on success
677 ssize_t bread(BFILE *bfd, void *buf, size_t count)
681 if (bfd->cmd_plugin && plugin_bread) {
682 return plugin_bread(bfd, buf, count);
685 if (bfd->use_backup_api) {
686 if (!p_BackupRead(bfd->fh,
691 1, /* Process Security */
692 &bfd->lpContext)) { /* Context */
693 bfd->lerror = GetLastError();
694 bfd->berrno = b_errno_win32;
695 errno = b_errno_win32;
699 if (!ReadFile(bfd->fh,
704 bfd->lerror = GetLastError();
705 bfd->berrno = b_errno_win32;
706 errno = b_errno_win32;
711 return (ssize_t)bfd->rw_bytes;
714 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
718 if (bfd->cmd_plugin && plugin_bwrite) {
719 return plugin_bwrite(bfd, buf, count);
722 if (bfd->use_backup_api) {
723 if (!p_BackupWrite(bfd->fh,
728 1, /* Process Security */
729 &bfd->lpContext)) { /* Context */
730 bfd->lerror = GetLastError();
731 bfd->berrno = b_errno_win32;
732 errno = b_errno_win32;
736 if (!WriteFile(bfd->fh,
741 bfd->lerror = GetLastError();
742 bfd->berrno = b_errno_win32;
743 errno = b_errno_win32;
747 return (ssize_t)bfd->rw_bytes;
750 bool is_bopen(BFILE *bfd)
752 return bfd->mode != BF_CLOSED;
755 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
757 LONG offset_low = (LONG)offset;
758 LONG offset_high = (LONG)(offset >> 32);
761 if (bfd->cmd_plugin && plugin_blseek) {
762 return plugin_blseek(bfd, offset, whence);
765 dwResult = SetFilePointer(bfd->fh, offset_low, &offset_high, whence);
767 if (dwResult == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
768 return (boffset_t)-1;
771 return ((boffset_t)offset_high << 32) | dwResult;
774 #else /* Unix systems */
776 /* ===============================================================
780 * ===============================================================
782 void binit(BFILE *bfd)
784 memset(bfd, 0, sizeof(BFILE));
788 bool have_win32_api()
790 return false; /* no can do */
794 * Enables using the Backup API (win32_data).
795 * Returns true if function worked
796 * Returns false if failed (i.e. do not have Backup API on this machine)
798 bool set_win32_backup(BFILE *bfd)
800 return false; /* no can do */
804 bool set_portable_backup(BFILE *bfd)
806 return true; /* no problem */
810 * Return true if we are writing in portable format
811 * return false if not
813 bool is_portable_backup(BFILE *bfd)
815 return true; /* portable by definition */
818 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
823 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
825 bfd->cmd_plugin = true;
831 * This code is running on a non-Win32 machine
833 bool is_restore_stream_supported(int stream)
835 /* No Win32 backup on this machine */
838 case STREAM_GZIP_DATA:
839 case STREAM_SPARSE_GZIP_DATA:
840 case STREAM_WIN32_GZIP_DATA:
842 #ifndef HAVE_DARWIN_OS
843 case STREAM_MACOS_FORK_DATA:
844 case STREAM_HFSPLUS_ATTRIBUTES:
850 case STREAM_GZIP_DATA:
851 case STREAM_SPARSE_GZIP_DATA:
852 case STREAM_WIN32_GZIP_DATA:
854 case STREAM_WIN32_DATA:
855 case STREAM_UNIX_ATTRIBUTES:
856 case STREAM_FILE_DATA:
857 case STREAM_MD5_DIGEST:
858 case STREAM_UNIX_ATTRIBUTES_EX:
859 case STREAM_SPARSE_DATA:
860 case STREAM_PROGRAM_NAMES:
861 case STREAM_PROGRAM_DATA:
862 case STREAM_SHA1_DIGEST:
864 case STREAM_SHA256_DIGEST:
865 case STREAM_SHA512_DIGEST:
868 case STREAM_SIGNED_DIGEST:
869 case STREAM_ENCRYPTED_FILE_DATA:
870 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
871 case STREAM_ENCRYPTED_WIN32_DATA:
872 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
874 #ifdef HAVE_DARWIN_OS
875 case STREAM_MACOS_FORK_DATA:
876 case STREAM_HFSPLUS_ATTRIBUTES:
878 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
879 #endif /* HAVE_CRYPTO */
880 #endif /* HAVE_DARWIN_OS */
881 case 0: /* compatibility with old tapes */
888 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
890 if (bfd->cmd_plugin && plugin_bopen) {
891 Dmsg1(50, "call plugin_bopen fname=%s\n", fname);
892 bfd->fid = plugin_bopen(bfd, fname, flags, mode);
893 Dmsg1(50, "Plugin bopen stat=%d\n", bfd->fid);
897 /* Normal file open */
898 Dmsg1(dbglvl, "open file %s\n", fname);
900 /* We use fnctl to set O_NOATIME if requested to avoid open error */
901 bfd->fid = open(fname, flags & ~O_NOATIME, mode);
903 /* Set O_NOATIME if possible */
904 if (bfd->fid != -1 && flags & O_NOATIME) {
905 int oldflags = fcntl(bfd->fid, F_GETFL, 0);
906 if (oldflags == -1) {
911 int ret = fcntl(bfd->fid, F_SETFL, oldflags | O_NOATIME);
912 /* EPERM means setting O_NOATIME was not allowed */
913 if (ret == -1 && errno != EPERM) {
921 bfd->m_flags = flags;
922 Dmsg1(400, "Open file %d\n", bfd->fid);
925 bfd->win32DecompContext.bIsInData = false;
926 bfd->win32DecompContext.liNextHeader = 0;
928 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
929 if (bfd->fid != -1 && flags & O_RDONLY) {
930 int stat = posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_WILLNEED);
931 Dmsg2(400, "Did posix_fadvise on %s stat=%d\n", fname, stat);
938 #ifdef HAVE_DARWIN_OS
939 /* Open the resource fork of a file. */
940 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
944 rsrc_fname = get_pool_memory(PM_FNAME);
945 pm_strcpy(rsrc_fname, fname);
946 pm_strcat(rsrc_fname, _PATH_RSRCFORKSPEC);
947 bopen(bfd, rsrc_fname, flags, mode);
948 free_pool_memory(rsrc_fname);
954 int bclose(BFILE *bfd)
958 Dmsg1(400, "Close file %d\n", bfd->fid);
960 if (bfd->cmd_plugin && plugin_bclose) {
961 stat = plugin_bclose(bfd);
963 bfd->cmd_plugin = false;
966 if (bfd->fid == -1) {
969 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
970 if (bfd->m_flags & O_RDONLY) {
971 fdatasync(bfd->fid); /* sync the file */
972 /* Tell OS we don't need it any more */
973 posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_DONTNEED);
977 /* Close normal file */
978 stat = close(bfd->fid);
981 bfd->cmd_plugin = false;
985 ssize_t bread(BFILE *bfd, void *buf, size_t count)
989 if (bfd->cmd_plugin && plugin_bread) {
990 return plugin_bread(bfd, buf, count);
993 stat = read(bfd->fid, buf, count);
998 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
1002 if (bfd->cmd_plugin && plugin_bwrite) {
1003 return plugin_bwrite(bfd, buf, count);
1005 stat = write(bfd->fid, buf, count);
1006 bfd->berrno = errno;
1010 bool is_bopen(BFILE *bfd)
1012 return bfd->fid >= 0;
1015 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
1019 if (bfd->cmd_plugin && plugin_bwrite) {
1020 return plugin_blseek(bfd, offset, whence);
1022 pos = (boffset_t)lseek(bfd->fid, offset, whence);
1023 bfd->berrno = errno;