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_DARWIN:
173 return _("Darwin Specific Extended attribs");
174 case STREAM_XATTR_FREEBSD:
175 return _("FreeBSD Specific Extended attribs");
176 case STREAM_XATTR_LINUX:
177 return _("Linux Specific Extended attribs");
178 case STREAM_XATTR_NETBSD:
179 return _("NetBSD Specific Extended attribs");
181 sprintf(buf, "%d", stream);
182 return (const char *)buf;
187 void int64_LE2BE(int64_t* pBE, const int64_t v)
189 /* convert little endian to big endian */
190 if (htonl(1) != 1L) { /* no work if on little endian machine */
191 memcpy(pBE, &v, sizeof(int64_t));
194 uint8_t rv[sizeof(int64_t)];
195 uint8_t *pv = (uint8_t *) &v;
197 for (i = 0; i < 8; i++) {
200 memcpy(pBE, &rv, sizeof(int64_t));
205 void int32_LE2BE(int32_t* pBE, const int32_t v)
207 /* convert little endian to big endian */
208 if (htonl(1) != 1L) { /* no work if on little endian machine */
209 memcpy(pBE, &v, sizeof(int32_t));
212 uint8_t rv[sizeof(int32_t)];
213 uint8_t *pv = (uint8_t *) &v;
215 for (i = 0; i < 4; i++) {
218 memcpy(pBE, &rv, sizeof(int32_t));
223 bool processWin32BackupAPIBlock (BFILE *bfd, void *pBuffer, ssize_t dwSize)
225 /* pByte contains the buffer
226 dwSize the len to be processed. function assumes to be
227 called in successive incremental order over the complete
228 BackupRead stream beginning at pos 0 and ending at the end.
231 PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT* pContext = &(bfd->win32DecompContext);
232 bool bContinue = false;
233 int64_t dwDataOffset = 0;
236 /* Win32 Stream Header size without name of stream.
237 * = sizeof (WIN32_STREAM_ID)- sizeof(WCHAR*);
239 int32_t dwSizeHeader = 20;
242 if (pContext->liNextHeader >= dwSize) {
243 dwDataLen = dwSize-dwDataOffset;
244 bContinue = false; /* 1 iteration is enough */
246 dwDataLen = pContext->liNextHeader-dwDataOffset;
247 bContinue = true; /* multiple iterations may be necessary */
251 /* copy block of real DATA */
252 if (pContext->bIsInData) {
253 if (bwrite(bfd, ((char *)pBuffer)+dwDataOffset, dwDataLen) != (ssize_t)dwDataLen)
257 if (pContext->liNextHeader < dwSize) {/* is a header in this block ? */
258 int32_t dwOffsetTarget;
259 int32_t dwOffsetSource;
261 if (pContext->liNextHeader < 0) {
262 /* start of header was before this block, so we
263 * continue with the part in the current block
265 dwOffsetTarget = -pContext->liNextHeader;
268 /* start of header is inside of this block */
270 dwOffsetSource = pContext->liNextHeader;
273 int32_t dwHeaderPartLen = dwSizeHeader-dwOffsetTarget;
274 bool bHeaderIsComplete;
276 if (dwHeaderPartLen <= dwSize-dwOffsetSource) {
277 /* header (or rest of header) is completely available
280 bHeaderIsComplete = true;
282 /* header will continue in next block */
283 bHeaderIsComplete = false;
284 dwHeaderPartLen = dwSize-dwOffsetSource;
287 /* copy the available portion of header to persistent copy */
288 memcpy(((char *)&pContext->header_stream)+dwOffsetTarget, ((char *)pBuffer)+dwOffsetSource, dwHeaderPartLen);
290 /* recalculate position of next header */
291 if (bHeaderIsComplete) {
292 /* convert stream name size (32 bit little endian) to machine type */
294 int32_LE2BE (&dwNameSize, pContext->header_stream.dwStreamNameSize);
295 dwDataOffset = dwNameSize+pContext->liNextHeader+dwSizeHeader;
297 /* convert stream size (64 bit little endian) to machine type */
298 int64_LE2BE (&(pContext->liNextHeader), pContext->header_stream.Size);
299 pContext->liNextHeader += dwDataOffset;
301 pContext->bIsInData = pContext->header_stream.dwStreamId == WIN32_BACKUP_DATA;
302 if (dwDataOffset == dwSize)
305 /* stop and continue with next block */
307 pContext->bIsInData = false;
312 /* set "NextHeader" relative to the beginning of the next block */
313 pContext->liNextHeader-= dwSize;
320 /* ===============================================================
324 * ===============================================================
327 #if defined(HAVE_WIN32)
329 void unix_name_to_win32(POOLMEM **win32_name, char *name);
330 extern "C" HANDLE get_osfhandle(int fd);
333 void binit(BFILE *bfd)
335 memset(bfd, 0, sizeof(BFILE));
337 bfd->mode = BF_CLOSED;
338 bfd->use_backup_api = have_win32_api();
339 bfd->cmd_plugin = false;
343 * Enables using the Backup API (win32_data).
344 * Returns 1 if function worked
345 * Returns 0 if failed (i.e. do not have Backup API on this machine)
347 bool set_win32_backup(BFILE *bfd)
349 /* We enable if possible here */
350 bfd->use_backup_api = have_win32_api();
351 return bfd->use_backup_api;
355 bool set_portable_backup(BFILE *bfd)
357 bfd->use_backup_api = false;
361 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
363 bfd->cmd_plugin = true;
369 * Return 1 if we are NOT using Win32 BackupWrite()
372 bool is_portable_backup(BFILE *bfd)
374 return !bfd->use_backup_api;
377 bool have_win32_api()
379 return p_BackupRead && p_BackupWrite;
384 * Return true if we support the stream
385 * false if we do not support the stream
387 * This code is running under Win32, so we
388 * do not need #ifdef on MACOS ...
390 bool is_restore_stream_supported(int stream)
394 /* Streams known not to be supported */
396 case STREAM_GZIP_DATA:
397 case STREAM_SPARSE_GZIP_DATA:
398 case STREAM_WIN32_GZIP_DATA:
400 case STREAM_MACOS_FORK_DATA:
401 case STREAM_HFSPLUS_ATTRIBUTES:
402 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
407 case STREAM_GZIP_DATA:
408 case STREAM_SPARSE_GZIP_DATA:
409 case STREAM_WIN32_GZIP_DATA:
411 case STREAM_WIN32_DATA:
412 case STREAM_UNIX_ATTRIBUTES:
413 case STREAM_FILE_DATA:
414 case STREAM_MD5_DIGEST:
415 case STREAM_UNIX_ATTRIBUTES_EX:
416 case STREAM_SPARSE_DATA:
417 case STREAM_PROGRAM_NAMES:
418 case STREAM_PROGRAM_DATA:
419 case STREAM_SHA1_DIGEST:
421 case STREAM_SHA256_DIGEST:
422 case STREAM_SHA512_DIGEST:
425 case STREAM_SIGNED_DIGEST:
426 case STREAM_ENCRYPTED_FILE_DATA:
427 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
428 case STREAM_ENCRYPTED_WIN32_DATA:
429 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
431 case 0: /* compatibility with old tapes */
437 HANDLE bget_handle(BFILE *bfd)
442 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
444 POOLMEM *win32_fname;
445 POOLMEM *win32_fname_wchar;
447 DWORD dwaccess, dwflags, dwshare;
449 /* Convert to Windows path format */
450 win32_fname = get_pool_memory(PM_FNAME);
451 win32_fname_wchar = get_pool_memory(PM_FNAME);
453 unix_name_to_win32(&win32_fname, (char *)fname);
455 if (bfd->cmd_plugin && plugin_bopen) {
457 Dmsg1(50, "call plugin_bopen fname=%s\n", fname);
458 rtnstat = plugin_bopen(bfd, fname, flags, mode);
459 Dmsg1(50, "return from plugin_bopen status=%d\n", rtnstat);
461 if (flags & O_CREAT || flags & O_WRONLY) { /* Open existing for write */
462 Dmsg1(50, "plugin_open for write OK file=%s.\n", fname);
463 bfd->mode = BF_WRITE;
465 Dmsg1(50, "plugin_open for read OK file=%s.\n", fname);
469 bfd->mode = BF_CLOSED;
470 Dmsg1(000, "==== plugin_bopen returned bad status=%d\n", rtnstat);
472 free_pool_memory(win32_fname_wchar);
473 free_pool_memory(win32_fname);
474 return bfd->mode == BF_CLOSED ? -1 : 1;
476 Dmsg0(50, "=== NO plugin\n");
478 if (!(p_CreateFileA || p_CreateFileW)) {
479 Dmsg0(50, "No CreateFileA and no CreateFileW!!!!!\n");
483 if (p_CreateFileW && p_MultiByteToWideChar) {
484 make_win32_path_UTF8_2_wchar(&win32_fname_wchar, fname);
487 if (flags & O_CREAT) { /* Create */
488 if (bfd->use_backup_api) {
489 dwaccess = GENERIC_WRITE|FILE_ALL_ACCESS|WRITE_OWNER|WRITE_DAC|ACCESS_SYSTEM_SECURITY;
490 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
492 dwaccess = GENERIC_WRITE;
496 if (p_CreateFileW && p_MultiByteToWideChar) {
497 // unicode open for create write
498 Dmsg1(100, "Create CreateFileW=%s\n", win32_fname);
499 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
500 dwaccess, /* Requested access */
502 NULL, /* SecurityAttributes */
503 CREATE_ALWAYS, /* CreationDisposition */
504 dwflags, /* Flags and attributes */
505 NULL); /* TemplateFile */
508 Dmsg1(100, "Create CreateFileA=%s\n", win32_fname);
509 bfd->fh = p_CreateFileA(win32_fname,
510 dwaccess, /* Requested access */
512 NULL, /* SecurityAttributes */
513 CREATE_ALWAYS, /* CreationDisposition */
514 dwflags, /* Flags and attributes */
515 NULL); /* TemplateFile */
518 bfd->mode = BF_WRITE;
520 } else if (flags & O_WRONLY) { /* Open existing for write */
521 if (bfd->use_backup_api) {
522 dwaccess = GENERIC_WRITE|WRITE_OWNER|WRITE_DAC;
523 dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT;
525 dwaccess = GENERIC_WRITE;
529 if (p_CreateFileW && p_MultiByteToWideChar) {
530 // unicode open for open existing write
531 Dmsg1(100, "Write only CreateFileW=%s\n", win32_fname);
532 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
533 dwaccess, /* Requested access */
535 NULL, /* SecurityAttributes */
536 OPEN_EXISTING, /* CreationDisposition */
537 dwflags, /* Flags and attributes */
538 NULL); /* TemplateFile */
541 Dmsg1(100, "Write only CreateFileA=%s\n", win32_fname);
542 bfd->fh = p_CreateFileA(win32_fname,
543 dwaccess, /* Requested access */
545 NULL, /* SecurityAttributes */
546 OPEN_EXISTING, /* CreationDisposition */
547 dwflags, /* Flags and attributes */
548 NULL); /* TemplateFile */
552 bfd->mode = BF_WRITE;
555 if (bfd->use_backup_api) {
556 dwaccess = GENERIC_READ|READ_CONTROL|ACCESS_SYSTEM_SECURITY;
557 dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_SEQUENTIAL_SCAN |
558 FILE_FLAG_OPEN_REPARSE_POINT;
559 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
561 dwaccess = GENERIC_READ;
563 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE;
566 if (p_CreateFileW && p_MultiByteToWideChar) {
567 // unicode open for open existing read
568 Dmsg1(100, "Read CreateFileW=%s\n", win32_fname);
569 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
570 dwaccess, /* Requested access */
571 dwshare, /* Share modes */
572 NULL, /* SecurityAttributes */
573 OPEN_EXISTING, /* CreationDisposition */
574 dwflags, /* Flags and attributes */
575 NULL); /* TemplateFile */
578 Dmsg1(100, "Read CreateFileA=%s\n", win32_fname);
579 bfd->fh = p_CreateFileA(win32_fname,
580 dwaccess, /* Requested access */
581 dwshare, /* Share modes */
582 NULL, /* SecurityAttributes */
583 OPEN_EXISTING, /* CreationDisposition */
584 dwflags, /* Flags and attributes */
585 NULL); /* TemplateFile */
591 if (bfd->fh == INVALID_HANDLE_VALUE) {
592 bfd->lerror = GetLastError();
593 bfd->berrno = b_errno_win32;
594 errno = b_errno_win32;
595 bfd->mode = BF_CLOSED;
598 bfd->lpContext = NULL;
599 bfd->win32DecompContext.bIsInData = false;
600 bfd->win32DecompContext.liNextHeader = 0;
601 free_pool_memory(win32_fname_wchar);
602 free_pool_memory(win32_fname);
603 return bfd->mode == BF_CLOSED ? -1 : 1;
607 * Returns 0 on success
610 int bclose(BFILE *bfd)
615 free_pool_memory(bfd->errmsg);
618 if (bfd->mode == BF_CLOSED) {
619 Dmsg0(50, "=== BFD already closed.\n");
623 if (bfd->cmd_plugin && plugin_bclose) {
624 stat = plugin_bclose(bfd);
625 Dmsg0(50, "==== BFD closed!!!\n");
630 * We need to tell the API to release the buffer it
631 * allocated in lpContext. We do so by calling the
632 * API one more time, but with the Abort bit set.
634 if (bfd->use_backup_api && bfd->mode == BF_READ) {
636 if (bfd->lpContext && !p_BackupRead(bfd->fh,
638 (DWORD)0, /* bytes to read */
639 &bfd->rw_bytes, /* bytes read */
641 1, /* ProcessSecurity */
642 &bfd->lpContext)) { /* Read context */
643 errno = b_errno_win32;
646 } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
648 if (bfd->lpContext && !p_BackupWrite(bfd->fh,
650 (DWORD)0, /* bytes to read */
651 &bfd->rw_bytes, /* bytes written */
653 1, /* ProcessSecurity */
654 &bfd->lpContext)) { /* Write context */
655 errno = b_errno_win32;
659 if (!CloseHandle(bfd->fh)) {
661 errno = b_errno_win32;
665 bfd->mode = BF_CLOSED;
666 bfd->lpContext = NULL;
667 bfd->cmd_plugin = false;
671 /* Returns: bytes read on success
675 ssize_t bread(BFILE *bfd, void *buf, size_t count)
679 if (bfd->cmd_plugin && plugin_bread) {
680 return plugin_bread(bfd, buf, count);
683 if (bfd->use_backup_api) {
684 if (!p_BackupRead(bfd->fh,
689 1, /* Process Security */
690 &bfd->lpContext)) { /* Context */
691 bfd->lerror = GetLastError();
692 bfd->berrno = b_errno_win32;
693 errno = b_errno_win32;
697 if (!ReadFile(bfd->fh,
702 bfd->lerror = GetLastError();
703 bfd->berrno = b_errno_win32;
704 errno = b_errno_win32;
709 return (ssize_t)bfd->rw_bytes;
712 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
716 if (bfd->cmd_plugin && plugin_bwrite) {
717 return plugin_bwrite(bfd, buf, count);
720 if (bfd->use_backup_api) {
721 if (!p_BackupWrite(bfd->fh,
726 1, /* Process Security */
727 &bfd->lpContext)) { /* Context */
728 bfd->lerror = GetLastError();
729 bfd->berrno = b_errno_win32;
730 errno = b_errno_win32;
734 if (!WriteFile(bfd->fh,
739 bfd->lerror = GetLastError();
740 bfd->berrno = b_errno_win32;
741 errno = b_errno_win32;
745 return (ssize_t)bfd->rw_bytes;
748 bool is_bopen(BFILE *bfd)
750 return bfd->mode != BF_CLOSED;
753 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
755 LONG offset_low = (LONG)offset;
756 LONG offset_high = (LONG)(offset >> 32);
759 if (bfd->cmd_plugin && plugin_blseek) {
760 return plugin_blseek(bfd, offset, whence);
763 dwResult = SetFilePointer(bfd->fh, offset_low, &offset_high, whence);
765 if (dwResult == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
766 return (boffset_t)-1;
769 return ((boffset_t)offset_high << 32) | dwResult;
772 #else /* Unix systems */
774 /* ===============================================================
778 * ===============================================================
780 void binit(BFILE *bfd)
782 memset(bfd, 0, sizeof(BFILE));
786 bool have_win32_api()
788 return false; /* no can do */
792 * Enables using the Backup API (win32_data).
793 * Returns true if function worked
794 * Returns false if failed (i.e. do not have Backup API on this machine)
796 bool set_win32_backup(BFILE *bfd)
798 return false; /* no can do */
802 bool set_portable_backup(BFILE *bfd)
804 return true; /* no problem */
808 * Return true if we are writing in portable format
809 * return false if not
811 bool is_portable_backup(BFILE *bfd)
813 return true; /* portable by definition */
816 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
821 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
823 bfd->cmd_plugin = true;
829 * This code is running on a non-Win32 machine
831 bool is_restore_stream_supported(int stream)
833 /* No Win32 backup on this machine */
836 case STREAM_GZIP_DATA:
837 case STREAM_SPARSE_GZIP_DATA:
838 case STREAM_WIN32_GZIP_DATA:
840 #ifndef HAVE_DARWIN_OS
841 case STREAM_MACOS_FORK_DATA:
842 case STREAM_HFSPLUS_ATTRIBUTES:
848 case STREAM_GZIP_DATA:
849 case STREAM_SPARSE_GZIP_DATA:
850 case STREAM_WIN32_GZIP_DATA:
852 case STREAM_WIN32_DATA:
853 case STREAM_UNIX_ATTRIBUTES:
854 case STREAM_FILE_DATA:
855 case STREAM_MD5_DIGEST:
856 case STREAM_UNIX_ATTRIBUTES_EX:
857 case STREAM_SPARSE_DATA:
858 case STREAM_PROGRAM_NAMES:
859 case STREAM_PROGRAM_DATA:
860 case STREAM_SHA1_DIGEST:
862 case STREAM_SHA256_DIGEST:
863 case STREAM_SHA512_DIGEST:
866 case STREAM_SIGNED_DIGEST:
867 case STREAM_ENCRYPTED_FILE_DATA:
868 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
869 case STREAM_ENCRYPTED_WIN32_DATA:
870 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
872 #ifdef HAVE_DARWIN_OS
873 case STREAM_MACOS_FORK_DATA:
874 case STREAM_HFSPLUS_ATTRIBUTES:
876 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
877 #endif /* HAVE_CRYPTO */
878 #endif /* HAVE_DARWIN_OS */
879 case 0: /* compatibility with old tapes */
886 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
888 if (bfd->cmd_plugin && plugin_bopen) {
889 Dmsg1(50, "call plugin_bopen fname=%s\n", fname);
890 bfd->fid = plugin_bopen(bfd, fname, flags, mode);
891 Dmsg1(50, "Plugin bopen stat=%d\n", bfd->fid);
895 /* Normal file open */
896 Dmsg1(dbglvl, "open file %s\n", fname);
898 /* We use fnctl to set O_NOATIME if requested to avoid open error */
899 bfd->fid = open(fname, flags & ~O_NOATIME, mode);
901 /* Set O_NOATIME if possible */
902 if (bfd->fid != -1 && flags & O_NOATIME) {
903 int oldflags = fcntl(bfd->fid, F_GETFL, 0);
904 if (oldflags == -1) {
909 int ret = fcntl(bfd->fid, F_SETFL, oldflags | O_NOATIME);
910 /* EPERM means setting O_NOATIME was not allowed */
911 if (ret == -1 && errno != EPERM) {
919 bfd->m_flags = flags;
920 Dmsg1(400, "Open file %d\n", bfd->fid);
923 bfd->win32DecompContext.bIsInData = false;
924 bfd->win32DecompContext.liNextHeader = 0;
926 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
927 if (bfd->fid != -1 && flags & O_RDONLY) {
928 int stat = posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_WILLNEED);
929 Dmsg2(400, "Did posix_fadvise on %s stat=%d\n", fname, stat);
936 #ifdef HAVE_DARWIN_OS
937 /* Open the resource fork of a file. */
938 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
942 rsrc_fname = get_pool_memory(PM_FNAME);
943 pm_strcpy(rsrc_fname, fname);
944 pm_strcat(rsrc_fname, _PATH_RSRCFORKSPEC);
945 bopen(bfd, rsrc_fname, flags, mode);
946 free_pool_memory(rsrc_fname);
952 int bclose(BFILE *bfd)
956 Dmsg1(400, "Close file %d\n", bfd->fid);
958 if (bfd->cmd_plugin && plugin_bclose) {
959 stat = plugin_bclose(bfd);
961 bfd->cmd_plugin = false;
964 if (bfd->fid == -1) {
967 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
968 if (bfd->m_flags & O_RDONLY) {
969 fdatasync(bfd->fid); /* sync the file */
970 /* Tell OS we don't need it any more */
971 posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_DONTNEED);
975 /* Close normal file */
976 stat = close(bfd->fid);
979 bfd->cmd_plugin = false;
983 ssize_t bread(BFILE *bfd, void *buf, size_t count)
987 if (bfd->cmd_plugin && plugin_bread) {
988 return plugin_bread(bfd, buf, count);
991 stat = read(bfd->fid, buf, count);
996 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
1000 if (bfd->cmd_plugin && plugin_bwrite) {
1001 return plugin_bwrite(bfd, buf, count);
1003 stat = write(bfd->fid, buf, count);
1004 bfd->berrno = errno;
1008 bool is_bopen(BFILE *bfd)
1010 return bfd->fid >= 0;
1013 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
1017 if (bfd->cmd_plugin && plugin_bwrite) {
1018 return plugin_blseek(bfd, offset, whence);
1020 pos = (boffset_t)lseek(bfd->fid, offset, whence);
1021 bfd->berrno = errno;