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_SYS:
173 return _("Solaris Specific Extensible attribs or System Extended attribs");
174 case STREAM_XATTR_SOLARIS:
175 return _("Solaris Specific Extended attribs");
176 case STREAM_XATTR_DARWIN:
177 return _("Darwin Specific Extended attribs");
178 case STREAM_XATTR_FREEBSD:
179 return _("FreeBSD Specific Extended attribs");
180 case STREAM_XATTR_LINUX:
181 return _("Linux Specific Extended attribs");
182 case STREAM_XATTR_NETBSD:
183 return _("NetBSD Specific Extended attribs");
185 sprintf(buf, "%d", stream);
186 return (const char *)buf;
191 void int64_LE2BE(int64_t* pBE, const int64_t v)
193 /* convert little endian to big endian */
194 if (htonl(1) != 1L) { /* no work if on little endian machine */
195 memcpy(pBE, &v, sizeof(int64_t));
198 uint8_t rv[sizeof(int64_t)];
199 uint8_t *pv = (uint8_t *) &v;
201 for (i = 0; i < 8; i++) {
204 memcpy(pBE, &rv, sizeof(int64_t));
209 void int32_LE2BE(int32_t* pBE, const int32_t v)
211 /* convert little endian to big endian */
212 if (htonl(1) != 1L) { /* no work if on little endian machine */
213 memcpy(pBE, &v, sizeof(int32_t));
216 uint8_t rv[sizeof(int32_t)];
217 uint8_t *pv = (uint8_t *) &v;
219 for (i = 0; i < 4; i++) {
222 memcpy(pBE, &rv, sizeof(int32_t));
227 bool processWin32BackupAPIBlock (BFILE *bfd, void *pBuffer, ssize_t dwSize)
229 /* pByte contains the buffer
230 dwSize the len to be processed. function assumes to be
231 called in successive incremental order over the complete
232 BackupRead stream beginning at pos 0 and ending at the end.
235 PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT* pContext = &(bfd->win32DecompContext);
236 bool bContinue = false;
237 int64_t dwDataOffset = 0;
240 /* Win32 Stream Header size without name of stream.
241 * = sizeof (WIN32_STREAM_ID)- sizeof(WCHAR*);
243 int32_t dwSizeHeader = 20;
246 if (pContext->liNextHeader >= dwSize) {
247 dwDataLen = dwSize-dwDataOffset;
248 bContinue = false; /* 1 iteration is enough */
250 dwDataLen = pContext->liNextHeader-dwDataOffset;
251 bContinue = true; /* multiple iterations may be necessary */
255 /* copy block of real DATA */
256 if (pContext->bIsInData) {
257 if (bwrite(bfd, ((char *)pBuffer)+dwDataOffset, dwDataLen) != (ssize_t)dwDataLen)
261 if (pContext->liNextHeader < dwSize) {/* is a header in this block ? */
262 int32_t dwOffsetTarget;
263 int32_t dwOffsetSource;
265 if (pContext->liNextHeader < 0) {
266 /* start of header was before this block, so we
267 * continue with the part in the current block
269 dwOffsetTarget = -pContext->liNextHeader;
272 /* start of header is inside of this block */
274 dwOffsetSource = pContext->liNextHeader;
277 int32_t dwHeaderPartLen = dwSizeHeader-dwOffsetTarget;
278 bool bHeaderIsComplete;
280 if (dwHeaderPartLen <= dwSize-dwOffsetSource) {
281 /* header (or rest of header) is completely available
284 bHeaderIsComplete = true;
286 /* header will continue in next block */
287 bHeaderIsComplete = false;
288 dwHeaderPartLen = dwSize-dwOffsetSource;
291 /* copy the available portion of header to persistent copy */
292 memcpy(((char *)&pContext->header_stream)+dwOffsetTarget, ((char *)pBuffer)+dwOffsetSource, dwHeaderPartLen);
294 /* recalculate position of next header */
295 if (bHeaderIsComplete) {
296 /* convert stream name size (32 bit little endian) to machine type */
298 int32_LE2BE (&dwNameSize, pContext->header_stream.dwStreamNameSize);
299 dwDataOffset = dwNameSize+pContext->liNextHeader+dwSizeHeader;
301 /* convert stream size (64 bit little endian) to machine type */
302 int64_LE2BE (&(pContext->liNextHeader), pContext->header_stream.Size);
303 pContext->liNextHeader += dwDataOffset;
305 pContext->bIsInData = pContext->header_stream.dwStreamId == WIN32_BACKUP_DATA;
306 if (dwDataOffset == dwSize)
309 /* stop and continue with next block */
311 pContext->bIsInData = false;
316 /* set "NextHeader" relative to the beginning of the next block */
317 pContext->liNextHeader-= dwSize;
324 /* ===============================================================
328 * ===============================================================
331 #if defined(HAVE_WIN32)
333 void unix_name_to_win32(POOLMEM **win32_name, char *name);
334 extern "C" HANDLE get_osfhandle(int fd);
337 void binit(BFILE *bfd)
339 memset(bfd, 0, sizeof(BFILE));
341 bfd->mode = BF_CLOSED;
342 bfd->use_backup_api = have_win32_api();
343 bfd->cmd_plugin = false;
347 * Enables using the Backup API (win32_data).
348 * Returns 1 if function worked
349 * Returns 0 if failed (i.e. do not have Backup API on this machine)
351 bool set_win32_backup(BFILE *bfd)
353 /* We enable if possible here */
354 bfd->use_backup_api = have_win32_api();
355 return bfd->use_backup_api;
359 bool set_portable_backup(BFILE *bfd)
361 bfd->use_backup_api = false;
365 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
367 bfd->cmd_plugin = true;
373 * Return 1 if we are NOT using Win32 BackupWrite()
376 bool is_portable_backup(BFILE *bfd)
378 return !bfd->use_backup_api;
381 bool have_win32_api()
383 return p_BackupRead && p_BackupWrite;
388 * Return true if we support the stream
389 * false if we do not support the stream
391 * This code is running under Win32, so we
392 * do not need #ifdef on MACOS ...
394 bool is_restore_stream_supported(int stream)
398 /* Streams known not to be supported */
400 case STREAM_GZIP_DATA:
401 case STREAM_SPARSE_GZIP_DATA:
402 case STREAM_WIN32_GZIP_DATA:
404 case STREAM_MACOS_FORK_DATA:
405 case STREAM_HFSPLUS_ATTRIBUTES:
406 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
411 case STREAM_GZIP_DATA:
412 case STREAM_SPARSE_GZIP_DATA:
413 case STREAM_WIN32_GZIP_DATA:
415 case STREAM_WIN32_DATA:
416 case STREAM_UNIX_ATTRIBUTES:
417 case STREAM_FILE_DATA:
418 case STREAM_MD5_DIGEST:
419 case STREAM_UNIX_ATTRIBUTES_EX:
420 case STREAM_SPARSE_DATA:
421 case STREAM_PROGRAM_NAMES:
422 case STREAM_PROGRAM_DATA:
423 case STREAM_SHA1_DIGEST:
425 case STREAM_SHA256_DIGEST:
426 case STREAM_SHA512_DIGEST:
429 case STREAM_SIGNED_DIGEST:
430 case STREAM_ENCRYPTED_FILE_DATA:
431 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
432 case STREAM_ENCRYPTED_WIN32_DATA:
433 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
435 case 0: /* compatibility with old tapes */
441 HANDLE bget_handle(BFILE *bfd)
446 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
448 POOLMEM *win32_fname;
449 POOLMEM *win32_fname_wchar;
451 DWORD dwaccess, dwflags, dwshare;
453 /* Convert to Windows path format */
454 win32_fname = get_pool_memory(PM_FNAME);
455 win32_fname_wchar = get_pool_memory(PM_FNAME);
457 unix_name_to_win32(&win32_fname, (char *)fname);
459 if (bfd->cmd_plugin && plugin_bopen) {
461 Dmsg1(50, "call plugin_bopen fname=%s\n", fname);
462 rtnstat = plugin_bopen(bfd, fname, flags, mode);
463 Dmsg1(50, "return from plugin_bopen status=%d\n", rtnstat);
465 if (flags & O_CREAT || flags & O_WRONLY) { /* Open existing for write */
466 Dmsg1(50, "plugin_open for write OK file=%s.\n", fname);
467 bfd->mode = BF_WRITE;
469 Dmsg1(50, "plugin_open for read OK file=%s.\n", fname);
473 bfd->mode = BF_CLOSED;
474 Dmsg1(000, "==== plugin_bopen returned bad status=%d\n", rtnstat);
476 free_pool_memory(win32_fname_wchar);
477 free_pool_memory(win32_fname);
478 return bfd->mode == BF_CLOSED ? -1 : 1;
480 Dmsg0(50, "=== NO plugin\n");
482 if (!(p_CreateFileA || p_CreateFileW)) {
483 Dmsg0(50, "No CreateFileA and no CreateFileW!!!!!\n");
487 if (p_CreateFileW && p_MultiByteToWideChar) {
488 make_win32_path_UTF8_2_wchar(&win32_fname_wchar, fname);
491 if (flags & O_CREAT) { /* Create */
492 if (bfd->use_backup_api) {
493 dwaccess = GENERIC_WRITE|FILE_ALL_ACCESS|WRITE_OWNER|WRITE_DAC|ACCESS_SYSTEM_SECURITY;
494 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
496 dwaccess = GENERIC_WRITE;
500 if (p_CreateFileW && p_MultiByteToWideChar) {
501 // unicode open for create write
502 Dmsg1(100, "Create CreateFileW=%s\n", win32_fname);
503 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
504 dwaccess, /* Requested access */
506 NULL, /* SecurityAttributes */
507 CREATE_ALWAYS, /* CreationDisposition */
508 dwflags, /* Flags and attributes */
509 NULL); /* TemplateFile */
512 Dmsg1(100, "Create CreateFileA=%s\n", win32_fname);
513 bfd->fh = p_CreateFileA(win32_fname,
514 dwaccess, /* Requested access */
516 NULL, /* SecurityAttributes */
517 CREATE_ALWAYS, /* CreationDisposition */
518 dwflags, /* Flags and attributes */
519 NULL); /* TemplateFile */
522 bfd->mode = BF_WRITE;
524 } else if (flags & O_WRONLY) { /* Open existing for write */
525 if (bfd->use_backup_api) {
526 dwaccess = GENERIC_WRITE|WRITE_OWNER|WRITE_DAC;
527 dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT;
529 dwaccess = GENERIC_WRITE;
533 if (p_CreateFileW && p_MultiByteToWideChar) {
534 // unicode open for open existing write
535 Dmsg1(100, "Write only CreateFileW=%s\n", win32_fname);
536 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
537 dwaccess, /* Requested access */
539 NULL, /* SecurityAttributes */
540 OPEN_EXISTING, /* CreationDisposition */
541 dwflags, /* Flags and attributes */
542 NULL); /* TemplateFile */
545 Dmsg1(100, "Write only CreateFileA=%s\n", win32_fname);
546 bfd->fh = p_CreateFileA(win32_fname,
547 dwaccess, /* Requested access */
549 NULL, /* SecurityAttributes */
550 OPEN_EXISTING, /* CreationDisposition */
551 dwflags, /* Flags and attributes */
552 NULL); /* TemplateFile */
556 bfd->mode = BF_WRITE;
559 if (bfd->use_backup_api) {
560 dwaccess = GENERIC_READ|READ_CONTROL|ACCESS_SYSTEM_SECURITY;
561 dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_SEQUENTIAL_SCAN |
562 FILE_FLAG_OPEN_REPARSE_POINT;
563 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
565 dwaccess = GENERIC_READ;
567 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE;
570 if (p_CreateFileW && p_MultiByteToWideChar) {
571 // unicode open for open existing read
572 Dmsg1(100, "Read CreateFileW=%s\n", win32_fname);
573 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
574 dwaccess, /* Requested access */
575 dwshare, /* Share modes */
576 NULL, /* SecurityAttributes */
577 OPEN_EXISTING, /* CreationDisposition */
578 dwflags, /* Flags and attributes */
579 NULL); /* TemplateFile */
582 Dmsg1(100, "Read CreateFileA=%s\n", win32_fname);
583 bfd->fh = p_CreateFileA(win32_fname,
584 dwaccess, /* Requested access */
585 dwshare, /* Share modes */
586 NULL, /* SecurityAttributes */
587 OPEN_EXISTING, /* CreationDisposition */
588 dwflags, /* Flags and attributes */
589 NULL); /* TemplateFile */
595 if (bfd->fh == INVALID_HANDLE_VALUE) {
596 bfd->lerror = GetLastError();
597 bfd->berrno = b_errno_win32;
598 errno = b_errno_win32;
599 bfd->mode = BF_CLOSED;
602 bfd->lpContext = NULL;
603 bfd->win32DecompContext.bIsInData = false;
604 bfd->win32DecompContext.liNextHeader = 0;
605 free_pool_memory(win32_fname_wchar);
606 free_pool_memory(win32_fname);
607 return bfd->mode == BF_CLOSED ? -1 : 1;
611 * Returns 0 on success
614 int bclose(BFILE *bfd)
619 free_pool_memory(bfd->errmsg);
622 if (bfd->mode == BF_CLOSED) {
623 Dmsg0(50, "=== BFD already closed.\n");
627 if (bfd->cmd_plugin && plugin_bclose) {
628 stat = plugin_bclose(bfd);
629 Dmsg0(50, "==== BFD closed!!!\n");
634 * We need to tell the API to release the buffer it
635 * allocated in lpContext. We do so by calling the
636 * API one more time, but with the Abort bit set.
638 if (bfd->use_backup_api && bfd->mode == BF_READ) {
640 if (bfd->lpContext && !p_BackupRead(bfd->fh,
642 (DWORD)0, /* bytes to read */
643 &bfd->rw_bytes, /* bytes read */
645 1, /* ProcessSecurity */
646 &bfd->lpContext)) { /* Read context */
647 errno = b_errno_win32;
650 } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
652 if (bfd->lpContext && !p_BackupWrite(bfd->fh,
654 (DWORD)0, /* bytes to read */
655 &bfd->rw_bytes, /* bytes written */
657 1, /* ProcessSecurity */
658 &bfd->lpContext)) { /* Write context */
659 errno = b_errno_win32;
663 if (!CloseHandle(bfd->fh)) {
665 errno = b_errno_win32;
669 bfd->mode = BF_CLOSED;
670 bfd->lpContext = NULL;
671 bfd->cmd_plugin = false;
675 /* Returns: bytes read on success
679 ssize_t bread(BFILE *bfd, void *buf, size_t count)
683 if (bfd->cmd_plugin && plugin_bread) {
684 return plugin_bread(bfd, buf, count);
687 if (bfd->use_backup_api) {
688 if (!p_BackupRead(bfd->fh,
693 1, /* Process Security */
694 &bfd->lpContext)) { /* Context */
695 bfd->lerror = GetLastError();
696 bfd->berrno = b_errno_win32;
697 errno = b_errno_win32;
701 if (!ReadFile(bfd->fh,
706 bfd->lerror = GetLastError();
707 bfd->berrno = b_errno_win32;
708 errno = b_errno_win32;
713 return (ssize_t)bfd->rw_bytes;
716 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
720 if (bfd->cmd_plugin && plugin_bwrite) {
721 return plugin_bwrite(bfd, buf, count);
724 if (bfd->use_backup_api) {
725 if (!p_BackupWrite(bfd->fh,
730 1, /* Process Security */
731 &bfd->lpContext)) { /* Context */
732 bfd->lerror = GetLastError();
733 bfd->berrno = b_errno_win32;
734 errno = b_errno_win32;
738 if (!WriteFile(bfd->fh,
743 bfd->lerror = GetLastError();
744 bfd->berrno = b_errno_win32;
745 errno = b_errno_win32;
749 return (ssize_t)bfd->rw_bytes;
752 bool is_bopen(BFILE *bfd)
754 return bfd->mode != BF_CLOSED;
757 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
759 LONG offset_low = (LONG)offset;
760 LONG offset_high = (LONG)(offset >> 32);
763 if (bfd->cmd_plugin && plugin_blseek) {
764 return plugin_blseek(bfd, offset, whence);
767 dwResult = SetFilePointer(bfd->fh, offset_low, &offset_high, whence);
769 if (dwResult == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
770 return (boffset_t)-1;
773 return ((boffset_t)offset_high << 32) | dwResult;
776 #else /* Unix systems */
778 /* ===============================================================
782 * ===============================================================
784 void binit(BFILE *bfd)
786 memset(bfd, 0, sizeof(BFILE));
790 bool have_win32_api()
792 return false; /* no can do */
796 * Enables using the Backup API (win32_data).
797 * Returns true if function worked
798 * Returns false if failed (i.e. do not have Backup API on this machine)
800 bool set_win32_backup(BFILE *bfd)
802 return false; /* no can do */
806 bool set_portable_backup(BFILE *bfd)
808 return true; /* no problem */
812 * Return true if we are writing in portable format
813 * return false if not
815 bool is_portable_backup(BFILE *bfd)
817 return true; /* portable by definition */
820 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
825 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
827 bfd->cmd_plugin = true;
833 * This code is running on a non-Win32 machine
835 bool is_restore_stream_supported(int stream)
837 /* No Win32 backup on this machine */
840 case STREAM_GZIP_DATA:
841 case STREAM_SPARSE_GZIP_DATA:
842 case STREAM_WIN32_GZIP_DATA:
844 #ifndef HAVE_DARWIN_OS
845 case STREAM_MACOS_FORK_DATA:
846 case STREAM_HFSPLUS_ATTRIBUTES:
852 case STREAM_GZIP_DATA:
853 case STREAM_SPARSE_GZIP_DATA:
854 case STREAM_WIN32_GZIP_DATA:
856 case STREAM_WIN32_DATA:
857 case STREAM_UNIX_ATTRIBUTES:
858 case STREAM_FILE_DATA:
859 case STREAM_MD5_DIGEST:
860 case STREAM_UNIX_ATTRIBUTES_EX:
861 case STREAM_SPARSE_DATA:
862 case STREAM_PROGRAM_NAMES:
863 case STREAM_PROGRAM_DATA:
864 case STREAM_SHA1_DIGEST:
866 case STREAM_SHA256_DIGEST:
867 case STREAM_SHA512_DIGEST:
870 case STREAM_SIGNED_DIGEST:
871 case STREAM_ENCRYPTED_FILE_DATA:
872 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
873 case STREAM_ENCRYPTED_WIN32_DATA:
874 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
876 #ifdef HAVE_DARWIN_OS
877 case STREAM_MACOS_FORK_DATA:
878 case STREAM_HFSPLUS_ATTRIBUTES:
880 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
881 #endif /* HAVE_CRYPTO */
882 #endif /* HAVE_DARWIN_OS */
883 case 0: /* compatibility with old tapes */
890 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
892 if (bfd->cmd_plugin && plugin_bopen) {
893 Dmsg1(50, "call plugin_bopen fname=%s\n", fname);
894 bfd->fid = plugin_bopen(bfd, fname, flags, mode);
895 Dmsg1(50, "Plugin bopen stat=%d\n", bfd->fid);
899 /* Normal file open */
900 Dmsg1(dbglvl, "open file %s\n", fname);
902 /* We use fnctl to set O_NOATIME if requested to avoid open error */
903 bfd->fid = open(fname, flags & ~O_NOATIME, mode);
905 /* Set O_NOATIME if possible */
906 if (bfd->fid != -1 && flags & O_NOATIME) {
907 int oldflags = fcntl(bfd->fid, F_GETFL, 0);
908 if (oldflags == -1) {
913 int ret = fcntl(bfd->fid, F_SETFL, oldflags | O_NOATIME);
914 /* EPERM means setting O_NOATIME was not allowed */
915 if (ret == -1 && errno != EPERM) {
923 bfd->m_flags = flags;
924 Dmsg1(400, "Open file %d\n", bfd->fid);
927 bfd->win32DecompContext.bIsInData = false;
928 bfd->win32DecompContext.liNextHeader = 0;
930 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
931 if (bfd->fid != -1 && flags & O_RDONLY) {
932 int stat = posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_WILLNEED);
933 Dmsg2(400, "Did posix_fadvise on %s stat=%d\n", fname, stat);
940 #ifdef HAVE_DARWIN_OS
941 /* Open the resource fork of a file. */
942 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
946 rsrc_fname = get_pool_memory(PM_FNAME);
947 pm_strcpy(rsrc_fname, fname);
948 pm_strcat(rsrc_fname, _PATH_RSRCFORKSPEC);
949 bopen(bfd, rsrc_fname, flags, mode);
950 free_pool_memory(rsrc_fname);
954 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
961 int bclose(BFILE *bfd)
965 Dmsg1(400, "Close file %d\n", bfd->fid);
967 if (bfd->cmd_plugin && plugin_bclose) {
968 stat = plugin_bclose(bfd);
970 bfd->cmd_plugin = false;
973 if (bfd->fid == -1) {
976 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
977 if (bfd->m_flags & O_RDONLY) {
978 fdatasync(bfd->fid); /* sync the file */
979 /* Tell OS we don't need it any more */
980 posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_DONTNEED);
984 /* Close normal file */
985 stat = close(bfd->fid);
988 bfd->cmd_plugin = false;
992 ssize_t bread(BFILE *bfd, void *buf, size_t count)
996 if (bfd->cmd_plugin && plugin_bread) {
997 return plugin_bread(bfd, buf, count);
1000 stat = read(bfd->fid, buf, count);
1001 bfd->berrno = errno;
1005 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
1009 if (bfd->cmd_plugin && plugin_bwrite) {
1010 return plugin_bwrite(bfd, buf, count);
1012 stat = write(bfd->fid, buf, count);
1013 bfd->berrno = errno;
1017 bool is_bopen(BFILE *bfd)
1019 return bfd->fid >= 0;
1022 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
1026 if (bfd->cmd_plugin && plugin_bwrite) {
1027 return plugin_blseek(bfd, offset, whence);
1029 pos = (boffset_t)lseek(bfd->fid, offset, whence);
1030 bfd->berrno = errno;