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_OPENBSD:
173 return _("OpenBSD Specific Extended attribs");
174 case STREAM_XATTR_SOLARIS_SYS:
175 return _("Solaris Specific Extensible attribs or System Extended attribs");
176 case STREAM_XATTR_SOLARIS:
177 return _("Solaris Specific Extended attribs");
178 case STREAM_XATTR_DARWIN:
179 return _("Darwin Specific Extended attribs");
180 case STREAM_XATTR_FREEBSD:
181 return _("FreeBSD Specific Extended attribs");
182 case STREAM_XATTR_LINUX:
183 return _("Linux Specific Extended attribs");
184 case STREAM_XATTR_NETBSD:
185 return _("NetBSD Specific Extended attribs");
187 sprintf(buf, "%d", stream);
188 return (const char *)buf;
193 void int64_LE2BE(int64_t* pBE, const int64_t v)
195 /* convert little endian to big endian */
196 if (htonl(1) != 1L) { /* no work if on little endian machine */
197 memcpy(pBE, &v, sizeof(int64_t));
200 uint8_t rv[sizeof(int64_t)];
201 uint8_t *pv = (uint8_t *) &v;
203 for (i = 0; i < 8; i++) {
206 memcpy(pBE, &rv, sizeof(int64_t));
211 void int32_LE2BE(int32_t* pBE, const int32_t v)
213 /* convert little endian to big endian */
214 if (htonl(1) != 1L) { /* no work if on little endian machine */
215 memcpy(pBE, &v, sizeof(int32_t));
218 uint8_t rv[sizeof(int32_t)];
219 uint8_t *pv = (uint8_t *) &v;
221 for (i = 0; i < 4; i++) {
224 memcpy(pBE, &rv, sizeof(int32_t));
229 bool processWin32BackupAPIBlock (BFILE *bfd, void *pBuffer, ssize_t dwSize)
231 /* pByte contains the buffer
232 dwSize the len to be processed. function assumes to be
233 called in successive incremental order over the complete
234 BackupRead stream beginning at pos 0 and ending at the end.
237 PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT* pContext = &(bfd->win32DecompContext);
238 bool bContinue = false;
239 int64_t dwDataOffset = 0;
242 /* Win32 Stream Header size without name of stream.
243 * = sizeof (WIN32_STREAM_ID)- sizeof(WCHAR*);
245 int32_t dwSizeHeader = 20;
248 if (pContext->liNextHeader >= dwSize) {
249 dwDataLen = dwSize-dwDataOffset;
250 bContinue = false; /* 1 iteration is enough */
252 dwDataLen = pContext->liNextHeader-dwDataOffset;
253 bContinue = true; /* multiple iterations may be necessary */
257 /* copy block of real DATA */
258 if (pContext->bIsInData) {
259 if (bwrite(bfd, ((char *)pBuffer)+dwDataOffset, dwDataLen) != (ssize_t)dwDataLen)
263 if (pContext->liNextHeader < dwSize) {/* is a header in this block ? */
264 int32_t dwOffsetTarget;
265 int32_t dwOffsetSource;
267 if (pContext->liNextHeader < 0) {
268 /* start of header was before this block, so we
269 * continue with the part in the current block
271 dwOffsetTarget = -pContext->liNextHeader;
274 /* start of header is inside of this block */
276 dwOffsetSource = pContext->liNextHeader;
279 int32_t dwHeaderPartLen = dwSizeHeader-dwOffsetTarget;
280 bool bHeaderIsComplete;
282 if (dwHeaderPartLen <= dwSize-dwOffsetSource) {
283 /* header (or rest of header) is completely available
286 bHeaderIsComplete = true;
288 /* header will continue in next block */
289 bHeaderIsComplete = false;
290 dwHeaderPartLen = dwSize-dwOffsetSource;
293 /* copy the available portion of header to persistent copy */
294 memcpy(((char *)&pContext->header_stream)+dwOffsetTarget, ((char *)pBuffer)+dwOffsetSource, dwHeaderPartLen);
296 /* recalculate position of next header */
297 if (bHeaderIsComplete) {
298 /* convert stream name size (32 bit little endian) to machine type */
300 int32_LE2BE (&dwNameSize, pContext->header_stream.dwStreamNameSize);
301 dwDataOffset = dwNameSize+pContext->liNextHeader+dwSizeHeader;
303 /* convert stream size (64 bit little endian) to machine type */
304 int64_LE2BE (&(pContext->liNextHeader), pContext->header_stream.Size);
305 pContext->liNextHeader += dwDataOffset;
307 pContext->bIsInData = pContext->header_stream.dwStreamId == WIN32_BACKUP_DATA;
308 if (dwDataOffset == dwSize)
311 /* stop and continue with next block */
313 pContext->bIsInData = false;
318 /* set "NextHeader" relative to the beginning of the next block */
319 pContext->liNextHeader-= dwSize;
326 /* ===============================================================
330 * ===============================================================
333 #if defined(HAVE_WIN32)
335 void unix_name_to_win32(POOLMEM **win32_name, char *name);
336 extern "C" HANDLE get_osfhandle(int fd);
339 void binit(BFILE *bfd)
341 memset(bfd, 0, sizeof(BFILE));
343 bfd->mode = BF_CLOSED;
344 bfd->use_backup_api = have_win32_api();
345 bfd->cmd_plugin = false;
349 * Enables using the Backup API (win32_data).
350 * Returns 1 if function worked
351 * Returns 0 if failed (i.e. do not have Backup API on this machine)
353 bool set_win32_backup(BFILE *bfd)
355 /* We enable if possible here */
356 bfd->use_backup_api = have_win32_api();
357 return bfd->use_backup_api;
361 bool set_portable_backup(BFILE *bfd)
363 bfd->use_backup_api = false;
367 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
369 bfd->cmd_plugin = true;
375 * Return 1 if we are NOT using Win32 BackupWrite()
378 bool is_portable_backup(BFILE *bfd)
380 return !bfd->use_backup_api;
383 bool have_win32_api()
385 return p_BackupRead && p_BackupWrite;
390 * Return true if we support the stream
391 * false if we do not support the stream
393 * This code is running under Win32, so we
394 * do not need #ifdef on MACOS ...
396 bool is_restore_stream_supported(int stream)
400 /* Streams known not to be supported */
402 case STREAM_GZIP_DATA:
403 case STREAM_SPARSE_GZIP_DATA:
404 case STREAM_WIN32_GZIP_DATA:
406 case STREAM_MACOS_FORK_DATA:
407 case STREAM_HFSPLUS_ATTRIBUTES:
408 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
413 case STREAM_GZIP_DATA:
414 case STREAM_SPARSE_GZIP_DATA:
415 case STREAM_WIN32_GZIP_DATA:
417 case STREAM_WIN32_DATA:
418 case STREAM_UNIX_ATTRIBUTES:
419 case STREAM_FILE_DATA:
420 case STREAM_MD5_DIGEST:
421 case STREAM_UNIX_ATTRIBUTES_EX:
422 case STREAM_SPARSE_DATA:
423 case STREAM_PROGRAM_NAMES:
424 case STREAM_PROGRAM_DATA:
425 case STREAM_SHA1_DIGEST:
427 case STREAM_SHA256_DIGEST:
428 case STREAM_SHA512_DIGEST:
431 case STREAM_SIGNED_DIGEST:
432 case STREAM_ENCRYPTED_FILE_DATA:
433 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
434 case STREAM_ENCRYPTED_WIN32_DATA:
435 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
437 case 0: /* compatibility with old tapes */
443 HANDLE bget_handle(BFILE *bfd)
448 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
450 POOLMEM *win32_fname;
451 POOLMEM *win32_fname_wchar;
453 DWORD dwaccess, dwflags, dwshare;
455 /* Convert to Windows path format */
456 win32_fname = get_pool_memory(PM_FNAME);
457 win32_fname_wchar = get_pool_memory(PM_FNAME);
459 unix_name_to_win32(&win32_fname, (char *)fname);
461 if (bfd->cmd_plugin && plugin_bopen) {
463 Dmsg1(50, "call plugin_bopen fname=%s\n", fname);
464 rtnstat = plugin_bopen(bfd, fname, flags, mode);
465 Dmsg1(50, "return from plugin_bopen status=%d\n", rtnstat);
467 if (flags & O_CREAT || flags & O_WRONLY) { /* Open existing for write */
468 Dmsg1(50, "plugin_open for write OK file=%s.\n", fname);
469 bfd->mode = BF_WRITE;
471 Dmsg1(50, "plugin_open for read OK file=%s.\n", fname);
475 bfd->mode = BF_CLOSED;
476 Dmsg1(000, "==== plugin_bopen returned bad status=%d\n", rtnstat);
478 free_pool_memory(win32_fname_wchar);
479 free_pool_memory(win32_fname);
480 return bfd->mode == BF_CLOSED ? -1 : 1;
482 Dmsg0(50, "=== NO plugin\n");
484 if (!(p_CreateFileA || p_CreateFileW)) {
485 Dmsg0(50, "No CreateFileA and no CreateFileW!!!!!\n");
489 if (p_CreateFileW && p_MultiByteToWideChar) {
490 make_win32_path_UTF8_2_wchar(&win32_fname_wchar, fname);
493 if (flags & O_CREAT) { /* Create */
494 if (bfd->use_backup_api) {
495 dwaccess = GENERIC_WRITE|FILE_ALL_ACCESS|WRITE_OWNER|WRITE_DAC|ACCESS_SYSTEM_SECURITY;
496 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
498 dwaccess = GENERIC_WRITE;
502 if (p_CreateFileW && p_MultiByteToWideChar) {
503 // unicode open for create write
504 Dmsg1(100, "Create CreateFileW=%s\n", win32_fname);
505 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
506 dwaccess, /* Requested access */
508 NULL, /* SecurityAttributes */
509 CREATE_ALWAYS, /* CreationDisposition */
510 dwflags, /* Flags and attributes */
511 NULL); /* TemplateFile */
514 Dmsg1(100, "Create CreateFileA=%s\n", win32_fname);
515 bfd->fh = p_CreateFileA(win32_fname,
516 dwaccess, /* Requested access */
518 NULL, /* SecurityAttributes */
519 CREATE_ALWAYS, /* CreationDisposition */
520 dwflags, /* Flags and attributes */
521 NULL); /* TemplateFile */
524 bfd->mode = BF_WRITE;
526 } else if (flags & O_WRONLY) { /* Open existing for write */
527 if (bfd->use_backup_api) {
528 dwaccess = GENERIC_WRITE|WRITE_OWNER|WRITE_DAC;
529 dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT;
531 dwaccess = GENERIC_WRITE;
535 if (p_CreateFileW && p_MultiByteToWideChar) {
536 // unicode open for open existing write
537 Dmsg1(100, "Write only CreateFileW=%s\n", win32_fname);
538 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
539 dwaccess, /* Requested access */
541 NULL, /* SecurityAttributes */
542 OPEN_EXISTING, /* CreationDisposition */
543 dwflags, /* Flags and attributes */
544 NULL); /* TemplateFile */
547 Dmsg1(100, "Write only CreateFileA=%s\n", win32_fname);
548 bfd->fh = p_CreateFileA(win32_fname,
549 dwaccess, /* Requested access */
551 NULL, /* SecurityAttributes */
552 OPEN_EXISTING, /* CreationDisposition */
553 dwflags, /* Flags and attributes */
554 NULL); /* TemplateFile */
558 bfd->mode = BF_WRITE;
561 if (bfd->use_backup_api) {
562 dwaccess = GENERIC_READ|READ_CONTROL|ACCESS_SYSTEM_SECURITY;
563 dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_SEQUENTIAL_SCAN |
564 FILE_FLAG_OPEN_REPARSE_POINT;
565 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
567 dwaccess = GENERIC_READ;
569 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE;
572 if (p_CreateFileW && p_MultiByteToWideChar) {
573 // unicode open for open existing read
574 Dmsg1(100, "Read CreateFileW=%s\n", win32_fname);
575 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
576 dwaccess, /* Requested access */
577 dwshare, /* Share modes */
578 NULL, /* SecurityAttributes */
579 OPEN_EXISTING, /* CreationDisposition */
580 dwflags, /* Flags and attributes */
581 NULL); /* TemplateFile */
584 Dmsg1(100, "Read CreateFileA=%s\n", win32_fname);
585 bfd->fh = p_CreateFileA(win32_fname,
586 dwaccess, /* Requested access */
587 dwshare, /* Share modes */
588 NULL, /* SecurityAttributes */
589 OPEN_EXISTING, /* CreationDisposition */
590 dwflags, /* Flags and attributes */
591 NULL); /* TemplateFile */
597 if (bfd->fh == INVALID_HANDLE_VALUE) {
598 bfd->lerror = GetLastError();
599 bfd->berrno = b_errno_win32;
600 errno = b_errno_win32;
601 bfd->mode = BF_CLOSED;
604 bfd->lpContext = NULL;
605 bfd->win32DecompContext.bIsInData = false;
606 bfd->win32DecompContext.liNextHeader = 0;
607 free_pool_memory(win32_fname_wchar);
608 free_pool_memory(win32_fname);
609 return bfd->mode == BF_CLOSED ? -1 : 1;
613 * Returns 0 on success
616 int bclose(BFILE *bfd)
621 free_pool_memory(bfd->errmsg);
624 if (bfd->mode == BF_CLOSED) {
625 Dmsg0(50, "=== BFD already closed.\n");
629 if (bfd->cmd_plugin && plugin_bclose) {
630 stat = plugin_bclose(bfd);
631 Dmsg0(50, "==== BFD closed!!!\n");
636 * We need to tell the API to release the buffer it
637 * allocated in lpContext. We do so by calling the
638 * API one more time, but with the Abort bit set.
640 if (bfd->use_backup_api && bfd->mode == BF_READ) {
642 if (bfd->lpContext && !p_BackupRead(bfd->fh,
644 (DWORD)0, /* bytes to read */
645 &bfd->rw_bytes, /* bytes read */
647 1, /* ProcessSecurity */
648 &bfd->lpContext)) { /* Read context */
649 errno = b_errno_win32;
652 } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
654 if (bfd->lpContext && !p_BackupWrite(bfd->fh,
656 (DWORD)0, /* bytes to read */
657 &bfd->rw_bytes, /* bytes written */
659 1, /* ProcessSecurity */
660 &bfd->lpContext)) { /* Write context */
661 errno = b_errno_win32;
665 if (!CloseHandle(bfd->fh)) {
667 errno = b_errno_win32;
671 bfd->mode = BF_CLOSED;
672 bfd->lpContext = NULL;
673 bfd->cmd_plugin = false;
677 /* Returns: bytes read on success
681 ssize_t bread(BFILE *bfd, void *buf, size_t count)
685 if (bfd->cmd_plugin && plugin_bread) {
686 return plugin_bread(bfd, buf, count);
689 if (bfd->use_backup_api) {
690 if (!p_BackupRead(bfd->fh,
695 1, /* Process Security */
696 &bfd->lpContext)) { /* Context */
697 bfd->lerror = GetLastError();
698 bfd->berrno = b_errno_win32;
699 errno = b_errno_win32;
703 if (!ReadFile(bfd->fh,
708 bfd->lerror = GetLastError();
709 bfd->berrno = b_errno_win32;
710 errno = b_errno_win32;
715 return (ssize_t)bfd->rw_bytes;
718 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
722 if (bfd->cmd_plugin && plugin_bwrite) {
723 return plugin_bwrite(bfd, buf, count);
726 if (bfd->use_backup_api) {
727 if (!p_BackupWrite(bfd->fh,
732 1, /* Process Security */
733 &bfd->lpContext)) { /* Context */
734 bfd->lerror = GetLastError();
735 bfd->berrno = b_errno_win32;
736 errno = b_errno_win32;
740 if (!WriteFile(bfd->fh,
745 bfd->lerror = GetLastError();
746 bfd->berrno = b_errno_win32;
747 errno = b_errno_win32;
751 return (ssize_t)bfd->rw_bytes;
754 bool is_bopen(BFILE *bfd)
756 return bfd->mode != BF_CLOSED;
759 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
761 LONG offset_low = (LONG)offset;
762 LONG offset_high = (LONG)(offset >> 32);
765 if (bfd->cmd_plugin && plugin_blseek) {
766 return plugin_blseek(bfd, offset, whence);
769 dwResult = SetFilePointer(bfd->fh, offset_low, &offset_high, whence);
771 if (dwResult == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
772 return (boffset_t)-1;
775 return ((boffset_t)offset_high << 32) | dwResult;
778 #else /* Unix systems */
780 /* ===============================================================
784 * ===============================================================
786 void binit(BFILE *bfd)
788 memset(bfd, 0, sizeof(BFILE));
792 bool have_win32_api()
794 return false; /* no can do */
798 * Enables using the Backup API (win32_data).
799 * Returns true if function worked
800 * Returns false if failed (i.e. do not have Backup API on this machine)
802 bool set_win32_backup(BFILE *bfd)
804 return false; /* no can do */
808 bool set_portable_backup(BFILE *bfd)
810 return true; /* no problem */
814 * Return true if we are writing in portable format
815 * return false if not
817 bool is_portable_backup(BFILE *bfd)
819 return true; /* portable by definition */
822 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
827 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
829 bfd->cmd_plugin = true;
835 * This code is running on a non-Win32 machine
837 bool is_restore_stream_supported(int stream)
839 /* No Win32 backup on this machine */
842 case STREAM_GZIP_DATA:
843 case STREAM_SPARSE_GZIP_DATA:
844 case STREAM_WIN32_GZIP_DATA:
846 #ifndef HAVE_DARWIN_OS
847 case STREAM_MACOS_FORK_DATA:
848 case STREAM_HFSPLUS_ATTRIBUTES:
854 case STREAM_GZIP_DATA:
855 case STREAM_SPARSE_GZIP_DATA:
856 case STREAM_WIN32_GZIP_DATA:
858 case STREAM_WIN32_DATA:
859 case STREAM_UNIX_ATTRIBUTES:
860 case STREAM_FILE_DATA:
861 case STREAM_MD5_DIGEST:
862 case STREAM_UNIX_ATTRIBUTES_EX:
863 case STREAM_SPARSE_DATA:
864 case STREAM_PROGRAM_NAMES:
865 case STREAM_PROGRAM_DATA:
866 case STREAM_SHA1_DIGEST:
868 case STREAM_SHA256_DIGEST:
869 case STREAM_SHA512_DIGEST:
872 case STREAM_SIGNED_DIGEST:
873 case STREAM_ENCRYPTED_FILE_DATA:
874 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
875 case STREAM_ENCRYPTED_WIN32_DATA:
876 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
878 #ifdef HAVE_DARWIN_OS
879 case STREAM_MACOS_FORK_DATA:
880 case STREAM_HFSPLUS_ATTRIBUTES:
882 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
883 #endif /* HAVE_CRYPTO */
884 #endif /* HAVE_DARWIN_OS */
885 case 0: /* compatibility with old tapes */
892 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
894 if (bfd->cmd_plugin && plugin_bopen) {
895 Dmsg1(50, "call plugin_bopen fname=%s\n", fname);
896 bfd->fid = plugin_bopen(bfd, fname, flags, mode);
897 Dmsg1(50, "Plugin bopen stat=%d\n", bfd->fid);
901 /* Normal file open */
902 Dmsg1(dbglvl, "open file %s\n", fname);
904 /* We use fnctl to set O_NOATIME if requested to avoid open error */
905 bfd->fid = open(fname, flags & ~O_NOATIME, mode);
907 /* Set O_NOATIME if possible */
908 if (bfd->fid != -1 && flags & O_NOATIME) {
909 int oldflags = fcntl(bfd->fid, F_GETFL, 0);
910 if (oldflags == -1) {
915 int ret = fcntl(bfd->fid, F_SETFL, oldflags | O_NOATIME);
916 /* EPERM means setting O_NOATIME was not allowed */
917 if (ret == -1 && errno != EPERM) {
925 bfd->m_flags = flags;
926 Dmsg1(400, "Open file %d\n", bfd->fid);
929 bfd->win32DecompContext.bIsInData = false;
930 bfd->win32DecompContext.liNextHeader = 0;
932 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
933 if (bfd->fid != -1 && flags & O_RDONLY) {
934 int stat = posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_WILLNEED);
935 Dmsg2(400, "Did posix_fadvise on %s stat=%d\n", fname, stat);
942 #ifdef HAVE_DARWIN_OS
943 /* Open the resource fork of a file. */
944 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
948 rsrc_fname = get_pool_memory(PM_FNAME);
949 pm_strcpy(rsrc_fname, fname);
950 pm_strcat(rsrc_fname, _PATH_RSRCFORKSPEC);
951 bopen(bfd, rsrc_fname, flags, mode);
952 free_pool_memory(rsrc_fname);
956 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
963 int bclose(BFILE *bfd)
967 Dmsg1(400, "Close file %d\n", bfd->fid);
969 if (bfd->cmd_plugin && plugin_bclose) {
970 stat = plugin_bclose(bfd);
972 bfd->cmd_plugin = false;
975 if (bfd->fid == -1) {
978 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
979 if (bfd->m_flags & O_RDONLY) {
980 fdatasync(bfd->fid); /* sync the file */
981 /* Tell OS we don't need it any more */
982 posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_DONTNEED);
986 /* Close normal file */
987 stat = close(bfd->fid);
990 bfd->cmd_plugin = false;
994 ssize_t bread(BFILE *bfd, void *buf, size_t count)
998 if (bfd->cmd_plugin && plugin_bread) {
999 return plugin_bread(bfd, buf, count);
1002 stat = read(bfd->fid, buf, count);
1003 bfd->berrno = errno;
1007 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
1011 if (bfd->cmd_plugin && plugin_bwrite) {
1012 return plugin_bwrite(bfd, buf, count);
1014 stat = write(bfd->fid, buf, count);
1015 bfd->berrno = errno;
1019 bool is_bopen(BFILE *bfd)
1021 return bfd->fid >= 0;
1024 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
1028 if (bfd->cmd_plugin && plugin_bwrite) {
1029 return plugin_blseek(bfd, offset, whence);
1031 pos = (boffset_t)lseek(bfd->fid, offset, whence);
1032 bfd->berrno = errno;