2 Bacula® - The Network Backup Solution
4 Copyright (C) 2003-2010 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 three of the GNU Affero 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 Affero 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
40 const int dbglvl = 200;
42 int (*plugin_bopen)(BFILE *bfd, const char *fname, int flags, mode_t mode) = NULL;
43 int (*plugin_bclose)(BFILE *bfd) = NULL;
44 ssize_t (*plugin_bread)(BFILE *bfd, void *buf, size_t count) = NULL;
45 ssize_t (*plugin_bwrite)(BFILE *bfd, void *buf, size_t count) = NULL;
46 boffset_t (*plugin_blseek)(BFILE *bfd, boffset_t offset, int whence) = NULL;
50 #include <sys/paths.h>
53 #if !defined(HAVE_FDATASYNC)
58 void pause_msg(const char *file, const char *func, int line, const char *msg)
62 bsnprintf(buf, sizeof(buf), "%s:%s:%d %s", file, func, line, msg);
64 bsnprintf(buf, sizeof(buf), "%s:%s:%d", file, func, line);
66 MessageBox(NULL, buf, "Pause", MB_OK);
70 /* ===============================================================
72 * U N I X AND W I N D O W S
74 * ===============================================================
77 bool is_win32_stream(int stream)
80 case STREAM_WIN32_DATA:
81 case STREAM_WIN32_GZIP_DATA:
82 case STREAM_ENCRYPTED_WIN32_DATA:
83 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
89 const char *stream_to_ascii(int stream)
94 case STREAM_UNIX_ATTRIBUTES:
95 return _("Unix attributes");
96 case STREAM_FILE_DATA:
97 return _("File data");
98 case STREAM_MD5_DIGEST:
99 return _("MD5 digest");
100 case STREAM_GZIP_DATA:
101 return _("GZIP data");
102 case STREAM_UNIX_ATTRIBUTES_EX:
103 return _("Extended attributes");
104 case STREAM_SPARSE_DATA:
105 return _("Sparse data");
106 case STREAM_SPARSE_GZIP_DATA:
107 return _("GZIP sparse data");
108 case STREAM_PROGRAM_NAMES:
109 return _("Program names");
110 case STREAM_PROGRAM_DATA:
111 return _("Program data");
112 case STREAM_SHA1_DIGEST:
113 return _("SHA1 digest");
114 case STREAM_WIN32_DATA:
115 return _("Win32 data");
116 case STREAM_WIN32_GZIP_DATA:
117 return _("Win32 GZIP data");
118 case STREAM_MACOS_FORK_DATA:
119 return _("MacOS Fork data");
120 case STREAM_HFSPLUS_ATTRIBUTES:
121 return _("HFS+ attribs");
122 case STREAM_UNIX_ACCESS_ACL:
123 return _("Standard Unix ACL attribs");
124 case STREAM_UNIX_DEFAULT_ACL:
125 return _("Default Unix ACL attribs");
126 case STREAM_SHA256_DIGEST:
127 return _("SHA256 digest");
128 case STREAM_SHA512_DIGEST:
129 return _("SHA512 digest");
130 case STREAM_SIGNED_DIGEST:
131 return _("Signed digest");
132 case STREAM_ENCRYPTED_FILE_DATA:
133 return _("Encrypted File data");
134 case STREAM_ENCRYPTED_WIN32_DATA:
135 return _("Encrypted Win32 data");
136 case STREAM_ENCRYPTED_SESSION_DATA:
137 return _("Encrypted session data");
138 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
139 return _("Encrypted GZIP data");
140 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
141 return _("Encrypted Win32 GZIP data");
142 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
143 return _("Encrypted MacOS fork data");
144 case STREAM_ACL_AIX_TEXT:
145 return _("AIX Specific ACL attribs");
146 case STREAM_ACL_DARWIN_ACCESS_ACL:
147 return _("Darwin Specific ACL attribs");
148 case STREAM_ACL_FREEBSD_DEFAULT_ACL:
149 return _("FreeBSD Specific Default ACL attribs");
150 case STREAM_ACL_FREEBSD_ACCESS_ACL:
151 return _("FreeBSD Specific Access ACL attribs");
152 case STREAM_ACL_HPUX_ACL_ENTRY:
153 return _("HPUX Specific ACL attribs");
154 case STREAM_ACL_IRIX_DEFAULT_ACL:
155 return _("Irix Specific Default ACL attribs");
156 case STREAM_ACL_IRIX_ACCESS_ACL:
157 return _("Irix Specific Access ACL attribs");
158 case STREAM_ACL_LINUX_DEFAULT_ACL:
159 return _("Linux Specific Default ACL attribs");
160 case STREAM_ACL_LINUX_ACCESS_ACL:
161 return _("Linux Specific Access ACL attribs");
162 case STREAM_ACL_TRU64_DEFAULT_ACL:
163 return _("TRU64 Specific Default ACL attribs");
164 case STREAM_ACL_TRU64_ACCESS_ACL:
165 return _("TRU64 Specific Access ACL attribs");
166 case STREAM_ACL_SOLARIS_ACLENT:
167 return _("Solaris Specific ACL attribs");
168 case STREAM_ACL_SOLARIS_ACE:
169 return _("Solaris Specific ACL attribs");
170 case STREAM_ACL_AFS_TEXT:
171 return _("AFS Specific ACL attribs");
172 case STREAM_ACL_AIX_AIXC:
173 return _("AIX Specific ACL attribs");
174 case STREAM_ACL_AIX_NFS4:
175 return _("AIX Specific ACL attribs");
176 case STREAM_XATTR_IRIX:
177 return _("IRIX Specific Extended attribs");
178 case STREAM_XATTR_TRU64:
179 return _("TRU64 Specific Extended attribs");
180 case STREAM_XATTR_AIX:
181 return _("AIX Specific Extended attribs");
182 case STREAM_XATTR_OPENBSD:
183 return _("OpenBSD Specific Extended attribs");
184 case STREAM_XATTR_SOLARIS_SYS:
185 return _("Solaris Specific Extensible attribs or System Extended attribs");
186 case STREAM_XATTR_SOLARIS:
187 return _("Solaris Specific Extended attribs");
188 case STREAM_XATTR_DARWIN:
189 return _("Darwin Specific Extended attribs");
190 case STREAM_XATTR_FREEBSD:
191 return _("FreeBSD Specific Extended attribs");
192 case STREAM_XATTR_LINUX:
193 return _("Linux Specific Extended attribs");
194 case STREAM_XATTR_NETBSD:
195 return _("NetBSD Specific Extended attribs");
197 sprintf(buf, "%d", stream);
198 return (const char *)buf;
203 * Convert a 64 bit little endian to a big endian
205 void int64_LE2BE(int64_t* pBE, const int64_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(int64_t));
212 uint8_t rv[sizeof(int64_t)];
213 uint8_t *pv = (uint8_t *) &v;
215 for (i = 0; i < 8; i++) {
218 memcpy(pBE, &rv, sizeof(int64_t));
223 * Convert a 32 bit little endian to a big endian
225 void int32_LE2BE(int32_t* pBE, const int32_t v)
227 /* convert little endian to big endian */
228 if (htonl(1) != 1L) { /* no work if on little endian machine */
229 memcpy(pBE, &v, sizeof(int32_t));
232 uint8_t rv[sizeof(int32_t)];
233 uint8_t *pv = (uint8_t *) &v;
235 for (i = 0; i < 4; i++) {
238 memcpy(pBE, &rv, sizeof(int32_t));
244 * Read a BackupRead block and pull out the file data
246 bool processWin32BackupAPIBlock (BFILE *bfd, void *pBuffer, ssize_t dwSize)
248 /* pByte contains the buffer
249 dwSize the len to be processed. function assumes to be
250 called in successive incremental order over the complete
251 BackupRead stream beginning at pos 0 and ending at the end.
254 PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT* pContext = &(bfd->win32DecompContext);
255 bool bContinue = false;
256 int64_t dwDataOffset = 0;
259 /* Win32 Stream Header size without name of stream.
260 * = sizeof (WIN32_STREAM_ID)- sizeof(WCHAR*);
262 int32_t dwSizeHeader = 20;
265 if (pContext->liNextHeader >= dwSize) {
266 dwDataLen = dwSize-dwDataOffset;
267 bContinue = false; /* 1 iteration is enough */
269 dwDataLen = pContext->liNextHeader-dwDataOffset;
270 bContinue = true; /* multiple iterations may be necessary */
274 /* copy block of real DATA */
275 if (pContext->bIsInData) {
276 if (bwrite(bfd, ((char *)pBuffer)+dwDataOffset, dwDataLen) != (ssize_t)dwDataLen)
280 if (pContext->liNextHeader < dwSize) {/* is a header in this block ? */
281 int32_t dwOffsetTarget;
282 int32_t dwOffsetSource;
284 if (pContext->liNextHeader < 0) {
285 /* start of header was before this block, so we
286 * continue with the part in the current block
288 dwOffsetTarget = -pContext->liNextHeader;
291 /* start of header is inside of this block */
293 dwOffsetSource = pContext->liNextHeader;
296 int32_t dwHeaderPartLen = dwSizeHeader-dwOffsetTarget;
297 bool bHeaderIsComplete;
299 if (dwHeaderPartLen <= dwSize-dwOffsetSource) {
300 /* header (or rest of header) is completely available
303 bHeaderIsComplete = true;
305 /* header will continue in next block */
306 bHeaderIsComplete = false;
307 dwHeaderPartLen = dwSize-dwOffsetSource;
310 /* copy the available portion of header to persistent copy */
311 memcpy(((char *)&pContext->header_stream)+dwOffsetTarget, ((char *)pBuffer)+dwOffsetSource, dwHeaderPartLen);
313 /* recalculate position of next header */
314 if (bHeaderIsComplete) {
315 /* convert stream name size (32 bit little endian) to machine type */
317 int32_LE2BE (&dwNameSize, pContext->header_stream.dwStreamNameSize);
318 dwDataOffset = dwNameSize+pContext->liNextHeader+dwSizeHeader;
320 /* convert stream size (64 bit little endian) to machine type */
321 int64_LE2BE (&(pContext->liNextHeader), pContext->header_stream.Size);
322 pContext->liNextHeader += dwDataOffset;
324 pContext->bIsInData = pContext->header_stream.dwStreamId == WIN32_BACKUP_DATA;
325 if (dwDataOffset == dwSize)
328 /* stop and continue with next block */
330 pContext->bIsInData = false;
335 /* set "NextHeader" relative to the beginning of the next block */
336 pContext->liNextHeader-= dwSize;
343 /* ===============================================================
347 * ===============================================================
350 #if defined(HAVE_WIN32)
352 void unix_name_to_win32(POOLMEM **win32_name, char *name);
353 extern "C" HANDLE get_osfhandle(int fd);
356 void binit(BFILE *bfd)
358 memset(bfd, 0, sizeof(BFILE));
360 bfd->mode = BF_CLOSED;
361 bfd->use_backup_api = have_win32_api();
362 bfd->cmd_plugin = false;
366 * Enables using the Backup API (win32_data).
367 * Returns 1 if function worked
368 * Returns 0 if failed (i.e. do not have Backup API on this machine)
370 bool set_win32_backup(BFILE *bfd)
372 /* We enable if possible here */
373 bfd->use_backup_api = have_win32_api();
374 return bfd->use_backup_api;
378 bool set_portable_backup(BFILE *bfd)
380 bfd->use_backup_api = false;
384 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
386 bfd->cmd_plugin = true;
392 * Return 1 if we are NOT using Win32 BackupWrite()
395 bool is_portable_backup(BFILE *bfd)
397 return !bfd->use_backup_api;
400 bool have_win32_api()
402 return p_BackupRead && p_BackupWrite;
407 * Return true if we support the stream
408 * false if we do not support the stream
410 * This code is running under Win32, so we
411 * do not need #ifdef on MACOS ...
413 bool is_restore_stream_supported(int stream)
417 /* Streams known not to be supported */
419 case STREAM_GZIP_DATA:
420 case STREAM_SPARSE_GZIP_DATA:
421 case STREAM_WIN32_GZIP_DATA:
423 case STREAM_MACOS_FORK_DATA:
424 case STREAM_HFSPLUS_ATTRIBUTES:
425 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
430 case STREAM_GZIP_DATA:
431 case STREAM_SPARSE_GZIP_DATA:
432 case STREAM_WIN32_GZIP_DATA:
434 case STREAM_WIN32_DATA:
435 case STREAM_UNIX_ATTRIBUTES:
436 case STREAM_FILE_DATA:
437 case STREAM_MD5_DIGEST:
438 case STREAM_UNIX_ATTRIBUTES_EX:
439 case STREAM_SPARSE_DATA:
440 case STREAM_PROGRAM_NAMES:
441 case STREAM_PROGRAM_DATA:
442 case STREAM_SHA1_DIGEST:
444 case STREAM_SHA256_DIGEST:
445 case STREAM_SHA512_DIGEST:
448 case STREAM_SIGNED_DIGEST:
449 case STREAM_ENCRYPTED_FILE_DATA:
450 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
451 case STREAM_ENCRYPTED_WIN32_DATA:
452 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
454 case 0: /* compatibility with old tapes */
460 HANDLE bget_handle(BFILE *bfd)
465 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
467 POOLMEM *win32_fname;
468 POOLMEM *win32_fname_wchar;
470 DWORD dwaccess, dwflags, dwshare;
472 /* Convert to Windows path format */
473 win32_fname = get_pool_memory(PM_FNAME);
474 win32_fname_wchar = get_pool_memory(PM_FNAME);
476 unix_name_to_win32(&win32_fname, (char *)fname);
478 if (bfd->cmd_plugin && plugin_bopen) {
480 Dmsg1(50, "call plugin_bopen fname=%s\n", fname);
481 rtnstat = plugin_bopen(bfd, fname, flags, mode);
482 Dmsg1(50, "return from plugin_bopen status=%d\n", rtnstat);
484 if (flags & O_CREAT || flags & O_WRONLY) { /* Open existing for write */
485 Dmsg1(50, "plugin_open for write OK file=%s.\n", fname);
486 bfd->mode = BF_WRITE;
488 Dmsg1(50, "plugin_open for read OK file=%s.\n", fname);
492 bfd->mode = BF_CLOSED;
493 Dmsg1(000, "==== plugin_bopen returned bad status=%d\n", rtnstat);
495 free_pool_memory(win32_fname_wchar);
496 free_pool_memory(win32_fname);
497 return bfd->mode == BF_CLOSED ? -1 : 1;
499 Dmsg0(50, "=== NO plugin\n");
501 if (!(p_CreateFileA || p_CreateFileW)) {
502 Dmsg0(50, "No CreateFileA and no CreateFileW!!!!!\n");
506 if (p_CreateFileW && p_MultiByteToWideChar) {
507 make_win32_path_UTF8_2_wchar(&win32_fname_wchar, fname);
510 if (flags & O_CREAT) { /* Create */
511 if (bfd->use_backup_api) {
512 dwaccess = GENERIC_WRITE|FILE_ALL_ACCESS|WRITE_OWNER|WRITE_DAC|ACCESS_SYSTEM_SECURITY;
513 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
515 dwaccess = GENERIC_WRITE;
519 if (p_CreateFileW && p_MultiByteToWideChar) {
520 // unicode open for create write
521 Dmsg1(100, "Create CreateFileW=%s\n", win32_fname);
522 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
523 dwaccess, /* Requested access */
525 NULL, /* SecurityAttributes */
526 CREATE_ALWAYS, /* CreationDisposition */
527 dwflags, /* Flags and attributes */
528 NULL); /* TemplateFile */
531 Dmsg1(100, "Create CreateFileA=%s\n", win32_fname);
532 bfd->fh = p_CreateFileA(win32_fname,
533 dwaccess, /* Requested access */
535 NULL, /* SecurityAttributes */
536 CREATE_ALWAYS, /* CreationDisposition */
537 dwflags, /* Flags and attributes */
538 NULL); /* TemplateFile */
541 bfd->mode = BF_WRITE;
543 } else if (flags & O_WRONLY) { /* Open existing for write */
544 if (bfd->use_backup_api) {
545 dwaccess = GENERIC_WRITE|WRITE_OWNER|WRITE_DAC;
546 dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT;
548 dwaccess = GENERIC_WRITE;
552 if (p_CreateFileW && p_MultiByteToWideChar) {
553 // unicode open for open existing write
554 Dmsg1(100, "Write only CreateFileW=%s\n", win32_fname);
555 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
556 dwaccess, /* Requested access */
558 NULL, /* SecurityAttributes */
559 OPEN_EXISTING, /* CreationDisposition */
560 dwflags, /* Flags and attributes */
561 NULL); /* TemplateFile */
564 Dmsg1(100, "Write only CreateFileA=%s\n", win32_fname);
565 bfd->fh = p_CreateFileA(win32_fname,
566 dwaccess, /* Requested access */
568 NULL, /* SecurityAttributes */
569 OPEN_EXISTING, /* CreationDisposition */
570 dwflags, /* Flags and attributes */
571 NULL); /* TemplateFile */
575 bfd->mode = BF_WRITE;
578 if (bfd->use_backup_api) {
579 dwaccess = GENERIC_READ|READ_CONTROL|ACCESS_SYSTEM_SECURITY;
580 dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_SEQUENTIAL_SCAN |
581 FILE_FLAG_OPEN_REPARSE_POINT;
582 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
584 dwaccess = GENERIC_READ;
586 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE;
589 if (p_CreateFileW && p_MultiByteToWideChar) {
590 // unicode open for open existing read
591 Dmsg1(100, "Read CreateFileW=%s\n", win32_fname);
592 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
593 dwaccess, /* Requested access */
594 dwshare, /* Share modes */
595 NULL, /* SecurityAttributes */
596 OPEN_EXISTING, /* CreationDisposition */
597 dwflags, /* Flags and attributes */
598 NULL); /* TemplateFile */
601 Dmsg1(100, "Read CreateFileA=%s\n", win32_fname);
602 bfd->fh = p_CreateFileA(win32_fname,
603 dwaccess, /* Requested access */
604 dwshare, /* Share modes */
605 NULL, /* SecurityAttributes */
606 OPEN_EXISTING, /* CreationDisposition */
607 dwflags, /* Flags and attributes */
608 NULL); /* TemplateFile */
614 if (bfd->fh == INVALID_HANDLE_VALUE) {
615 bfd->lerror = GetLastError();
616 bfd->berrno = b_errno_win32;
617 errno = b_errno_win32;
618 bfd->mode = BF_CLOSED;
621 bfd->lpContext = NULL;
622 bfd->win32DecompContext.bIsInData = false;
623 bfd->win32DecompContext.liNextHeader = 0;
624 free_pool_memory(win32_fname_wchar);
625 free_pool_memory(win32_fname);
626 return bfd->mode == BF_CLOSED ? -1 : 1;
630 * Returns 0 on success
633 int bclose(BFILE *bfd)
637 if (bfd->mode == BF_CLOSED) {
638 Dmsg0(50, "=== BFD already closed.\n");
642 if (bfd->cmd_plugin && plugin_bclose) {
643 stat = plugin_bclose(bfd);
644 Dmsg0(50, "==== BFD closed!!!\n");
649 * We need to tell the API to release the buffer it
650 * allocated in lpContext. We do so by calling the
651 * API one more time, but with the Abort bit set.
653 if (bfd->use_backup_api && bfd->mode == BF_READ) {
655 if (bfd->lpContext && !p_BackupRead(bfd->fh,
657 (DWORD)0, /* bytes to read */
658 &bfd->rw_bytes, /* bytes read */
660 1, /* ProcessSecurity */
661 &bfd->lpContext)) { /* Read context */
662 errno = b_errno_win32;
665 } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
667 if (bfd->lpContext && !p_BackupWrite(bfd->fh,
669 (DWORD)0, /* bytes to read */
670 &bfd->rw_bytes, /* bytes written */
672 1, /* ProcessSecurity */
673 &bfd->lpContext)) { /* Write context */
674 errno = b_errno_win32;
678 if (!CloseHandle(bfd->fh)) {
680 errno = b_errno_win32;
685 free_pool_memory(bfd->errmsg);
688 bfd->mode = BF_CLOSED;
689 bfd->lpContext = NULL;
690 bfd->cmd_plugin = false;
694 /* Returns: bytes read on success
698 ssize_t bread(BFILE *bfd, void *buf, size_t count)
702 if (bfd->cmd_plugin && plugin_bread) {
703 return plugin_bread(bfd, buf, count);
706 if (bfd->use_backup_api) {
707 if (!p_BackupRead(bfd->fh,
712 1, /* Process Security */
713 &bfd->lpContext)) { /* Context */
714 bfd->lerror = GetLastError();
715 bfd->berrno = b_errno_win32;
716 errno = b_errno_win32;
720 if (!ReadFile(bfd->fh,
725 bfd->lerror = GetLastError();
726 bfd->berrno = b_errno_win32;
727 errno = b_errno_win32;
732 return (ssize_t)bfd->rw_bytes;
735 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
739 if (bfd->cmd_plugin && plugin_bwrite) {
740 return plugin_bwrite(bfd, buf, count);
743 if (bfd->use_backup_api) {
744 if (!p_BackupWrite(bfd->fh,
749 1, /* Process Security */
750 &bfd->lpContext)) { /* Context */
751 bfd->lerror = GetLastError();
752 bfd->berrno = b_errno_win32;
753 errno = b_errno_win32;
757 if (!WriteFile(bfd->fh,
762 bfd->lerror = GetLastError();
763 bfd->berrno = b_errno_win32;
764 errno = b_errno_win32;
768 return (ssize_t)bfd->rw_bytes;
771 bool is_bopen(BFILE *bfd)
773 return bfd->mode != BF_CLOSED;
776 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
778 LONG offset_low = (LONG)offset;
779 LONG offset_high = (LONG)(offset >> 32);
782 if (bfd->cmd_plugin && plugin_blseek) {
783 return plugin_blseek(bfd, offset, whence);
786 dwResult = SetFilePointer(bfd->fh, offset_low, &offset_high, whence);
788 if (dwResult == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
789 return (boffset_t)-1;
792 return ((boffset_t)offset_high << 32) | dwResult;
795 #else /* Unix systems */
797 /* ===============================================================
801 * ===============================================================
803 void binit(BFILE *bfd)
805 memset(bfd, 0, sizeof(BFILE));
809 bool have_win32_api()
811 return false; /* no can do */
815 * Enables using the Backup API (win32_data).
816 * Returns true if function worked
817 * Returns false if failed (i.e. do not have Backup API on this machine)
819 bool set_win32_backup(BFILE *bfd)
821 return false; /* no can do */
825 bool set_portable_backup(BFILE *bfd)
827 return true; /* no problem */
831 * Return true if we are writing in portable format
832 * return false if not
834 bool is_portable_backup(BFILE *bfd)
836 return true; /* portable by definition */
839 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
844 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
846 bfd->cmd_plugin = true;
852 * This code is running on a non-Win32 machine
854 bool is_restore_stream_supported(int stream)
856 /* No Win32 backup on this machine */
859 case STREAM_GZIP_DATA:
860 case STREAM_SPARSE_GZIP_DATA:
861 case STREAM_WIN32_GZIP_DATA:
863 #ifndef HAVE_DARWIN_OS
864 case STREAM_MACOS_FORK_DATA:
865 case STREAM_HFSPLUS_ATTRIBUTES:
871 case STREAM_GZIP_DATA:
872 case STREAM_SPARSE_GZIP_DATA:
873 case STREAM_WIN32_GZIP_DATA:
875 case STREAM_WIN32_DATA:
876 case STREAM_UNIX_ATTRIBUTES:
877 case STREAM_FILE_DATA:
878 case STREAM_MD5_DIGEST:
879 case STREAM_UNIX_ATTRIBUTES_EX:
880 case STREAM_SPARSE_DATA:
881 case STREAM_PROGRAM_NAMES:
882 case STREAM_PROGRAM_DATA:
883 case STREAM_SHA1_DIGEST:
885 case STREAM_SHA256_DIGEST:
886 case STREAM_SHA512_DIGEST:
889 case STREAM_SIGNED_DIGEST:
890 case STREAM_ENCRYPTED_FILE_DATA:
891 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
892 case STREAM_ENCRYPTED_WIN32_DATA:
893 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
895 #ifdef HAVE_DARWIN_OS
896 case STREAM_MACOS_FORK_DATA:
897 case STREAM_HFSPLUS_ATTRIBUTES:
899 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
900 #endif /* HAVE_CRYPTO */
901 #endif /* HAVE_DARWIN_OS */
902 case 0: /* compatibility with old tapes */
909 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
911 if (bfd->cmd_plugin && plugin_bopen) {
912 Dmsg1(50, "call plugin_bopen fname=%s\n", fname);
913 bfd->fid = plugin_bopen(bfd, fname, flags, mode);
914 Dmsg1(50, "Plugin bopen stat=%d\n", bfd->fid);
918 /* Normal file open */
919 Dmsg1(dbglvl, "open file %s\n", fname);
921 /* We use fnctl to set O_NOATIME if requested to avoid open error */
922 bfd->fid = open(fname, flags & ~O_NOATIME, mode);
924 /* Set O_NOATIME if possible */
925 if (bfd->fid != -1 && flags & O_NOATIME) {
926 int oldflags = fcntl(bfd->fid, F_GETFL, 0);
927 if (oldflags == -1) {
932 int ret = fcntl(bfd->fid, F_SETFL, oldflags | O_NOATIME);
933 /* EPERM means setting O_NOATIME was not allowed */
934 if (ret == -1 && errno != EPERM) {
942 bfd->m_flags = flags;
943 Dmsg1(400, "Open file %d\n", bfd->fid);
946 bfd->win32DecompContext.bIsInData = false;
947 bfd->win32DecompContext.liNextHeader = 0;
949 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
950 if (bfd->fid != -1 && flags & O_RDONLY) {
951 int stat = posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_WILLNEED);
952 Dmsg2(400, "Did posix_fadvise on %s stat=%d\n", fname, stat);
959 #ifdef HAVE_DARWIN_OS
960 /* Open the resource fork of a file. */
961 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
965 rsrc_fname = get_pool_memory(PM_FNAME);
966 pm_strcpy(rsrc_fname, fname);
967 pm_strcat(rsrc_fname, _PATH_RSRCFORKSPEC);
968 bopen(bfd, rsrc_fname, flags, mode);
969 free_pool_memory(rsrc_fname);
973 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
980 int bclose(BFILE *bfd)
984 Dmsg1(400, "Close file %d\n", bfd->fid);
986 if (bfd->cmd_plugin && plugin_bclose) {
987 stat = plugin_bclose(bfd);
989 bfd->cmd_plugin = false;
992 if (bfd->fid == -1) {
995 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
996 if (bfd->m_flags & O_RDONLY) {
997 fdatasync(bfd->fid); /* sync the file */
998 /* Tell OS we don't need it any more */
999 posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_DONTNEED);
1003 /* Close normal file */
1004 stat = close(bfd->fid);
1005 bfd->berrno = errno;
1007 bfd->cmd_plugin = false;
1011 ssize_t bread(BFILE *bfd, void *buf, size_t count)
1015 if (bfd->cmd_plugin && plugin_bread) {
1016 return plugin_bread(bfd, buf, count);
1019 stat = read(bfd->fid, buf, count);
1020 bfd->berrno = errno;
1024 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
1028 if (bfd->cmd_plugin && plugin_bwrite) {
1029 return plugin_bwrite(bfd, buf, count);
1031 stat = write(bfd->fid, buf, count);
1032 bfd->berrno = errno;
1036 bool is_bopen(BFILE *bfd)
1038 return bfd->fid >= 0;
1041 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
1045 if (bfd->cmd_plugin && plugin_bwrite) {
1046 return plugin_blseek(bfd, offset, whence);
1048 pos = (boffset_t)lseek(bfd->fid, offset, whence);
1049 bfd->berrno = errno;