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)
93 switch (stream & STREAMMASK_TYPE) {
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 POSIX ACL attribs");
168 case STREAM_ACL_SOLARIS_ACE:
169 return _("Solaris Specific NFSv4/ZFS ACL attribs");
170 case STREAM_ACL_AFS_TEXT:
171 return _("AFS Specific ACL attribs");
172 case STREAM_ACL_AIX_AIXC:
173 return _("AIX Specific POSIX ACL attribs");
174 case STREAM_ACL_AIX_NFS4:
175 return _("AIX Specific NFSv4 ACL attribs");
176 case STREAM_ACL_FREEBSD_NFS4_ACL:
177 return _("FreeBSD Specific NFSv4/ZFS ACL attribs");
178 case STREAM_XATTR_IRIX:
179 return _("IRIX Specific Extended attribs");
180 case STREAM_XATTR_TRU64:
181 return _("TRU64 Specific Extended attribs");
182 case STREAM_XATTR_AIX:
183 return _("AIX Specific Extended attribs");
184 case STREAM_XATTR_OPENBSD:
185 return _("OpenBSD Specific Extended attribs");
186 case STREAM_XATTR_SOLARIS_SYS:
187 return _("Solaris Specific Extensible attribs or System Extended attribs");
188 case STREAM_XATTR_SOLARIS:
189 return _("Solaris Specific Extended attribs");
190 case STREAM_XATTR_DARWIN:
191 return _("Darwin Specific Extended attribs");
192 case STREAM_XATTR_FREEBSD:
193 return _("FreeBSD Specific Extended attribs");
194 case STREAM_XATTR_LINUX:
195 return _("Linux Specific Extended attribs");
196 case STREAM_XATTR_NETBSD:
197 return _("NetBSD Specific Extended attribs");
199 sprintf(buf, "%d", stream);
200 return (const char *)buf;
205 * Convert a 64 bit little endian to a big endian
207 void int64_LE2BE(int64_t* pBE, const int64_t v)
209 /* convert little endian to big endian */
210 if (htonl(1) != 1L) { /* no work if on little endian machine */
211 memcpy(pBE, &v, sizeof(int64_t));
214 uint8_t rv[sizeof(int64_t)];
215 uint8_t *pv = (uint8_t *) &v;
217 for (i = 0; i < 8; i++) {
220 memcpy(pBE, &rv, sizeof(int64_t));
225 * Convert a 32 bit little endian to a big endian
227 void int32_LE2BE(int32_t* pBE, const int32_t v)
229 /* convert little endian to big endian */
230 if (htonl(1) != 1L) { /* no work if on little endian machine */
231 memcpy(pBE, &v, sizeof(int32_t));
234 uint8_t rv[sizeof(int32_t)];
235 uint8_t *pv = (uint8_t *) &v;
237 for (i = 0; i < 4; i++) {
240 memcpy(pBE, &rv, sizeof(int32_t));
246 * Read a BackupRead block and pull out the file data
248 bool processWin32BackupAPIBlock (BFILE *bfd, void *pBuffer, ssize_t dwSize)
250 /* pByte contains the buffer
251 dwSize the len to be processed. function assumes to be
252 called in successive incremental order over the complete
253 BackupRead stream beginning at pos 0 and ending at the end.
256 PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT* pContext = &(bfd->win32DecompContext);
257 bool bContinue = false;
258 int64_t dwDataOffset = 0;
261 /* Win32 Stream Header size without name of stream.
262 * = sizeof (WIN32_STREAM_ID)- sizeof(WCHAR*);
264 int32_t dwSizeHeader = 20;
267 if (pContext->liNextHeader >= dwSize) {
268 dwDataLen = dwSize-dwDataOffset;
269 bContinue = false; /* 1 iteration is enough */
271 dwDataLen = pContext->liNextHeader-dwDataOffset;
272 bContinue = true; /* multiple iterations may be necessary */
276 /* copy block of real DATA */
277 if (pContext->bIsInData) {
278 if (bwrite(bfd, ((char *)pBuffer)+dwDataOffset, dwDataLen) != (ssize_t)dwDataLen)
282 if (pContext->liNextHeader < dwSize) {/* is a header in this block ? */
283 int32_t dwOffsetTarget;
284 int32_t dwOffsetSource;
286 if (pContext->liNextHeader < 0) {
287 /* start of header was before this block, so we
288 * continue with the part in the current block
290 dwOffsetTarget = -pContext->liNextHeader;
293 /* start of header is inside of this block */
295 dwOffsetSource = pContext->liNextHeader;
298 int32_t dwHeaderPartLen = dwSizeHeader-dwOffsetTarget;
299 bool bHeaderIsComplete;
301 if (dwHeaderPartLen <= dwSize-dwOffsetSource) {
302 /* header (or rest of header) is completely available
305 bHeaderIsComplete = true;
307 /* header will continue in next block */
308 bHeaderIsComplete = false;
309 dwHeaderPartLen = dwSize-dwOffsetSource;
312 /* copy the available portion of header to persistent copy */
313 memcpy(((char *)&pContext->header_stream)+dwOffsetTarget, ((char *)pBuffer)+dwOffsetSource, dwHeaderPartLen);
315 /* recalculate position of next header */
316 if (bHeaderIsComplete) {
317 /* convert stream name size (32 bit little endian) to machine type */
319 int32_LE2BE (&dwNameSize, pContext->header_stream.dwStreamNameSize);
320 dwDataOffset = dwNameSize+pContext->liNextHeader+dwSizeHeader;
322 /* convert stream size (64 bit little endian) to machine type */
323 int64_LE2BE (&(pContext->liNextHeader), pContext->header_stream.Size);
324 pContext->liNextHeader += dwDataOffset;
326 pContext->bIsInData = pContext->header_stream.dwStreamId == WIN32_BACKUP_DATA;
327 if (dwDataOffset == dwSize)
330 /* stop and continue with next block */
332 pContext->bIsInData = false;
337 /* set "NextHeader" relative to the beginning of the next block */
338 pContext->liNextHeader-= dwSize;
345 /* ===============================================================
349 * ===============================================================
352 #if defined(HAVE_WIN32)
354 void unix_name_to_win32(POOLMEM **win32_name, char *name);
355 extern "C" HANDLE get_osfhandle(int fd);
358 void binit(BFILE *bfd)
360 memset(bfd, 0, sizeof(BFILE));
362 bfd->mode = BF_CLOSED;
363 bfd->use_backup_api = have_win32_api();
364 bfd->cmd_plugin = false;
368 * Enables using the Backup API (win32_data).
369 * Returns 1 if function worked
370 * Returns 0 if failed (i.e. do not have Backup API on this machine)
372 bool set_win32_backup(BFILE *bfd)
374 /* We enable if possible here */
375 bfd->use_backup_api = have_win32_api();
376 return bfd->use_backup_api;
380 bool set_portable_backup(BFILE *bfd)
382 bfd->use_backup_api = false;
386 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
388 bfd->cmd_plugin = true;
394 * Return 1 if we are NOT using Win32 BackupWrite()
397 bool is_portable_backup(BFILE *bfd)
399 return !bfd->use_backup_api;
402 bool have_win32_api()
404 return p_BackupRead && p_BackupWrite;
409 * Return true if we support the stream
410 * false if we do not support the stream
412 * This code is running under Win32, so we
413 * do not need #ifdef on MACOS ...
415 bool is_restore_stream_supported(int stream)
419 /* Streams known not to be supported */
421 case STREAM_GZIP_DATA:
422 case STREAM_SPARSE_GZIP_DATA:
423 case STREAM_WIN32_GZIP_DATA:
425 case STREAM_MACOS_FORK_DATA:
426 case STREAM_HFSPLUS_ATTRIBUTES:
427 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
432 case STREAM_GZIP_DATA:
433 case STREAM_SPARSE_GZIP_DATA:
434 case STREAM_WIN32_GZIP_DATA:
436 case STREAM_WIN32_DATA:
437 case STREAM_UNIX_ATTRIBUTES:
438 case STREAM_FILE_DATA:
439 case STREAM_MD5_DIGEST:
440 case STREAM_UNIX_ATTRIBUTES_EX:
441 case STREAM_SPARSE_DATA:
442 case STREAM_PROGRAM_NAMES:
443 case STREAM_PROGRAM_DATA:
444 case STREAM_SHA1_DIGEST:
446 case STREAM_SHA256_DIGEST:
447 case STREAM_SHA512_DIGEST:
450 case STREAM_SIGNED_DIGEST:
451 case STREAM_ENCRYPTED_FILE_DATA:
452 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
453 case STREAM_ENCRYPTED_WIN32_DATA:
454 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
456 case 0: /* compatibility with old tapes */
462 HANDLE bget_handle(BFILE *bfd)
467 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
469 POOLMEM *win32_fname;
470 POOLMEM *win32_fname_wchar;
472 DWORD dwaccess, dwflags, dwshare;
474 /* Convert to Windows path format */
475 win32_fname = get_pool_memory(PM_FNAME);
476 win32_fname_wchar = get_pool_memory(PM_FNAME);
478 unix_name_to_win32(&win32_fname, (char *)fname);
480 if (bfd->cmd_plugin && plugin_bopen) {
482 Dmsg1(50, "call plugin_bopen fname=%s\n", fname);
483 rtnstat = plugin_bopen(bfd, fname, flags, mode);
484 Dmsg1(50, "return from plugin_bopen status=%d\n", rtnstat);
486 if (flags & O_CREAT || flags & O_WRONLY) { /* Open existing for write */
487 Dmsg1(50, "plugin_open for write OK file=%s.\n", fname);
488 bfd->mode = BF_WRITE;
490 Dmsg1(50, "plugin_open for read OK file=%s.\n", fname);
494 bfd->mode = BF_CLOSED;
495 Dmsg1(000, "==== plugin_bopen returned bad status=%d\n", rtnstat);
497 free_pool_memory(win32_fname_wchar);
498 free_pool_memory(win32_fname);
499 return bfd->mode == BF_CLOSED ? -1 : 1;
501 Dmsg0(50, "=== NO plugin\n");
503 if (!(p_CreateFileA || p_CreateFileW)) {
504 Dmsg0(50, "No CreateFileA and no CreateFileW!!!!!\n");
508 if (p_CreateFileW && p_MultiByteToWideChar) {
509 make_win32_path_UTF8_2_wchar(&win32_fname_wchar, fname);
512 if (flags & O_CREAT) { /* Create */
513 if (bfd->use_backup_api) {
514 dwaccess = GENERIC_WRITE|FILE_ALL_ACCESS|WRITE_OWNER|WRITE_DAC|ACCESS_SYSTEM_SECURITY;
515 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
517 dwaccess = GENERIC_WRITE;
521 if (p_CreateFileW && p_MultiByteToWideChar) {
522 // unicode open for create write
523 Dmsg1(100, "Create CreateFileW=%s\n", win32_fname);
524 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
525 dwaccess, /* Requested access */
527 NULL, /* SecurityAttributes */
528 CREATE_ALWAYS, /* CreationDisposition */
529 dwflags, /* Flags and attributes */
530 NULL); /* TemplateFile */
533 Dmsg1(100, "Create CreateFileA=%s\n", win32_fname);
534 bfd->fh = p_CreateFileA(win32_fname,
535 dwaccess, /* Requested access */
537 NULL, /* SecurityAttributes */
538 CREATE_ALWAYS, /* CreationDisposition */
539 dwflags, /* Flags and attributes */
540 NULL); /* TemplateFile */
543 bfd->mode = BF_WRITE;
545 } else if (flags & O_WRONLY) { /* Open existing for write */
546 if (bfd->use_backup_api) {
547 dwaccess = GENERIC_WRITE|WRITE_OWNER|WRITE_DAC;
548 dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT;
550 dwaccess = GENERIC_WRITE;
554 if (p_CreateFileW && p_MultiByteToWideChar) {
555 // unicode open for open existing write
556 Dmsg1(100, "Write only CreateFileW=%s\n", win32_fname);
557 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
558 dwaccess, /* Requested access */
560 NULL, /* SecurityAttributes */
561 OPEN_EXISTING, /* CreationDisposition */
562 dwflags, /* Flags and attributes */
563 NULL); /* TemplateFile */
566 Dmsg1(100, "Write only CreateFileA=%s\n", win32_fname);
567 bfd->fh = p_CreateFileA(win32_fname,
568 dwaccess, /* Requested access */
570 NULL, /* SecurityAttributes */
571 OPEN_EXISTING, /* CreationDisposition */
572 dwflags, /* Flags and attributes */
573 NULL); /* TemplateFile */
577 bfd->mode = BF_WRITE;
580 if (bfd->use_backup_api) {
581 dwaccess = GENERIC_READ|READ_CONTROL|ACCESS_SYSTEM_SECURITY;
582 dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_SEQUENTIAL_SCAN |
583 FILE_FLAG_OPEN_REPARSE_POINT;
584 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
586 dwaccess = GENERIC_READ;
588 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE;
591 if (p_CreateFileW && p_MultiByteToWideChar) {
592 // unicode open for open existing read
593 Dmsg1(100, "Read CreateFileW=%s\n", win32_fname);
594 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
595 dwaccess, /* Requested access */
596 dwshare, /* Share modes */
597 NULL, /* SecurityAttributes */
598 OPEN_EXISTING, /* CreationDisposition */
599 dwflags, /* Flags and attributes */
600 NULL); /* TemplateFile */
603 Dmsg1(100, "Read CreateFileA=%s\n", win32_fname);
604 bfd->fh = p_CreateFileA(win32_fname,
605 dwaccess, /* Requested access */
606 dwshare, /* Share modes */
607 NULL, /* SecurityAttributes */
608 OPEN_EXISTING, /* CreationDisposition */
609 dwflags, /* Flags and attributes */
610 NULL); /* TemplateFile */
616 if (bfd->fh == INVALID_HANDLE_VALUE) {
617 bfd->lerror = GetLastError();
618 bfd->berrno = b_errno_win32;
619 errno = b_errno_win32;
620 bfd->mode = BF_CLOSED;
623 bfd->lpContext = NULL;
624 bfd->win32DecompContext.bIsInData = false;
625 bfd->win32DecompContext.liNextHeader = 0;
626 free_pool_memory(win32_fname_wchar);
627 free_pool_memory(win32_fname);
628 return bfd->mode == BF_CLOSED ? -1 : 1;
632 * Returns 0 on success
635 int bclose(BFILE *bfd)
639 if (bfd->mode == BF_CLOSED) {
640 Dmsg0(50, "=== BFD already closed.\n");
644 if (bfd->cmd_plugin && plugin_bclose) {
645 stat = plugin_bclose(bfd);
646 Dmsg0(50, "==== BFD closed!!!\n");
651 * We need to tell the API to release the buffer it
652 * allocated in lpContext. We do so by calling the
653 * API one more time, but with the Abort bit set.
655 if (bfd->use_backup_api && bfd->mode == BF_READ) {
657 if (bfd->lpContext && !p_BackupRead(bfd->fh,
659 (DWORD)0, /* bytes to read */
660 &bfd->rw_bytes, /* bytes read */
662 1, /* ProcessSecurity */
663 &bfd->lpContext)) { /* Read context */
664 errno = b_errno_win32;
667 } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
669 if (bfd->lpContext && !p_BackupWrite(bfd->fh,
671 (DWORD)0, /* bytes to read */
672 &bfd->rw_bytes, /* bytes written */
674 1, /* ProcessSecurity */
675 &bfd->lpContext)) { /* Write context */
676 errno = b_errno_win32;
680 if (!CloseHandle(bfd->fh)) {
682 errno = b_errno_win32;
687 free_pool_memory(bfd->errmsg);
690 bfd->mode = BF_CLOSED;
691 bfd->lpContext = NULL;
692 bfd->cmd_plugin = false;
696 /* Returns: bytes read on success
700 ssize_t bread(BFILE *bfd, void *buf, size_t count)
704 if (bfd->cmd_plugin && plugin_bread) {
705 return plugin_bread(bfd, buf, count);
708 if (bfd->use_backup_api) {
709 if (!p_BackupRead(bfd->fh,
714 1, /* Process Security */
715 &bfd->lpContext)) { /* Context */
716 bfd->lerror = GetLastError();
717 bfd->berrno = b_errno_win32;
718 errno = b_errno_win32;
722 if (!ReadFile(bfd->fh,
727 bfd->lerror = GetLastError();
728 bfd->berrno = b_errno_win32;
729 errno = b_errno_win32;
734 return (ssize_t)bfd->rw_bytes;
737 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
741 if (bfd->cmd_plugin && plugin_bwrite) {
742 return plugin_bwrite(bfd, buf, count);
745 if (bfd->use_backup_api) {
746 if (!p_BackupWrite(bfd->fh,
751 1, /* Process Security */
752 &bfd->lpContext)) { /* Context */
753 bfd->lerror = GetLastError();
754 bfd->berrno = b_errno_win32;
755 errno = b_errno_win32;
759 if (!WriteFile(bfd->fh,
764 bfd->lerror = GetLastError();
765 bfd->berrno = b_errno_win32;
766 errno = b_errno_win32;
770 return (ssize_t)bfd->rw_bytes;
773 bool is_bopen(BFILE *bfd)
775 return bfd->mode != BF_CLOSED;
778 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
780 LONG offset_low = (LONG)offset;
781 LONG offset_high = (LONG)(offset >> 32);
784 if (bfd->cmd_plugin && plugin_blseek) {
785 return plugin_blseek(bfd, offset, whence);
788 dwResult = SetFilePointer(bfd->fh, offset_low, &offset_high, whence);
790 if (dwResult == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
791 return (boffset_t)-1;
794 return ((boffset_t)offset_high << 32) | dwResult;
797 #else /* Unix systems */
799 /* ===============================================================
803 * ===============================================================
805 void binit(BFILE *bfd)
807 memset(bfd, 0, sizeof(BFILE));
811 bool have_win32_api()
813 return false; /* no can do */
817 * Enables using the Backup API (win32_data).
818 * Returns true if function worked
819 * Returns false if failed (i.e. do not have Backup API on this machine)
821 bool set_win32_backup(BFILE *bfd)
823 return false; /* no can do */
827 bool set_portable_backup(BFILE *bfd)
829 return true; /* no problem */
833 * Return true if we are writing in portable format
834 * return false if not
836 bool is_portable_backup(BFILE *bfd)
838 return true; /* portable by definition */
841 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
846 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
848 bfd->cmd_plugin = true;
854 * This code is running on a non-Win32 machine
856 bool is_restore_stream_supported(int stream)
858 /* No Win32 backup on this machine */
861 case STREAM_GZIP_DATA:
862 case STREAM_SPARSE_GZIP_DATA:
863 case STREAM_WIN32_GZIP_DATA:
865 #ifndef HAVE_DARWIN_OS
866 case STREAM_MACOS_FORK_DATA:
867 case STREAM_HFSPLUS_ATTRIBUTES:
873 case STREAM_GZIP_DATA:
874 case STREAM_SPARSE_GZIP_DATA:
875 case STREAM_WIN32_GZIP_DATA:
877 case STREAM_WIN32_DATA:
878 case STREAM_UNIX_ATTRIBUTES:
879 case STREAM_FILE_DATA:
880 case STREAM_MD5_DIGEST:
881 case STREAM_UNIX_ATTRIBUTES_EX:
882 case STREAM_SPARSE_DATA:
883 case STREAM_PROGRAM_NAMES:
884 case STREAM_PROGRAM_DATA:
885 case STREAM_SHA1_DIGEST:
887 case STREAM_SHA256_DIGEST:
888 case STREAM_SHA512_DIGEST:
891 case STREAM_SIGNED_DIGEST:
892 case STREAM_ENCRYPTED_FILE_DATA:
893 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
894 case STREAM_ENCRYPTED_WIN32_DATA:
895 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
897 #ifdef HAVE_DARWIN_OS
898 case STREAM_MACOS_FORK_DATA:
899 case STREAM_HFSPLUS_ATTRIBUTES:
901 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
902 #endif /* HAVE_CRYPTO */
903 #endif /* HAVE_DARWIN_OS */
904 case 0: /* compatibility with old tapes */
911 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
913 if (bfd->cmd_plugin && plugin_bopen) {
914 Dmsg1(50, "call plugin_bopen fname=%s\n", fname);
915 bfd->fid = plugin_bopen(bfd, fname, flags, mode);
916 Dmsg1(50, "Plugin bopen stat=%d\n", bfd->fid);
920 /* Normal file open */
921 Dmsg1(dbglvl, "open file %s\n", fname);
923 /* We use fnctl to set O_NOATIME if requested to avoid open error */
924 bfd->fid = open(fname, flags & ~O_NOATIME, mode);
926 /* Set O_NOATIME if possible */
927 if (bfd->fid != -1 && flags & O_NOATIME) {
928 int oldflags = fcntl(bfd->fid, F_GETFL, 0);
929 if (oldflags == -1) {
934 int ret = fcntl(bfd->fid, F_SETFL, oldflags | O_NOATIME);
935 /* EPERM means setting O_NOATIME was not allowed */
936 if (ret == -1 && errno != EPERM) {
944 bfd->m_flags = flags;
945 Dmsg1(400, "Open file %d\n", bfd->fid);
948 bfd->win32DecompContext.bIsInData = false;
949 bfd->win32DecompContext.liNextHeader = 0;
951 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
952 if (bfd->fid != -1 && flags & O_RDONLY) {
953 int stat = posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_WILLNEED);
954 Dmsg2(400, "Did posix_fadvise on %s stat=%d\n", fname, stat);
961 #ifdef HAVE_DARWIN_OS
962 /* Open the resource fork of a file. */
963 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
967 rsrc_fname = get_pool_memory(PM_FNAME);
968 pm_strcpy(rsrc_fname, fname);
969 pm_strcat(rsrc_fname, _PATH_RSRCFORKSPEC);
970 bopen(bfd, rsrc_fname, flags, mode);
971 free_pool_memory(rsrc_fname);
975 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
982 int bclose(BFILE *bfd)
986 Dmsg1(400, "Close file %d\n", bfd->fid);
988 if (bfd->cmd_plugin && plugin_bclose) {
989 stat = plugin_bclose(bfd);
991 bfd->cmd_plugin = false;
994 if (bfd->fid == -1) {
997 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
998 if (bfd->m_flags & O_RDONLY) {
999 fdatasync(bfd->fid); /* sync the file */
1000 /* Tell OS we don't need it any more */
1001 posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_DONTNEED);
1005 /* Close normal file */
1006 stat = close(bfd->fid);
1007 bfd->berrno = errno;
1009 bfd->cmd_plugin = false;
1013 ssize_t bread(BFILE *bfd, void *buf, size_t count)
1017 if (bfd->cmd_plugin && plugin_bread) {
1018 return plugin_bread(bfd, buf, count);
1021 stat = read(bfd->fid, buf, count);
1022 bfd->berrno = errno;
1026 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
1030 if (bfd->cmd_plugin && plugin_bwrite) {
1031 return plugin_bwrite(bfd, buf, count);
1033 stat = write(bfd->fid, buf, count);
1034 bfd->berrno = errno;
1038 bool is_bopen(BFILE *bfd)
1040 return bfd->fid >= 0;
1043 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
1047 if (bfd->cmd_plugin && plugin_bwrite) {
1048 return plugin_blseek(bfd, offset, whence);
1050 pos = (boffset_t)lseek(bfd->fid, offset, whence);
1051 bfd->berrno = errno;