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_TRU64:
177 return _("TRU64 Specific Extended attribs");
178 case STREAM_XATTR_AIX:
179 return _("AIX Specific Extended attribs");
180 case STREAM_XATTR_OPENBSD:
181 return _("OpenBSD Specific Extended attribs");
182 case STREAM_XATTR_SOLARIS_SYS:
183 return _("Solaris Specific Extensible attribs or System Extended attribs");
184 case STREAM_XATTR_SOLARIS:
185 return _("Solaris Specific Extended attribs");
186 case STREAM_XATTR_DARWIN:
187 return _("Darwin Specific Extended attribs");
188 case STREAM_XATTR_FREEBSD:
189 return _("FreeBSD Specific Extended attribs");
190 case STREAM_XATTR_LINUX:
191 return _("Linux Specific Extended attribs");
192 case STREAM_XATTR_NETBSD:
193 return _("NetBSD Specific Extended attribs");
195 sprintf(buf, "%d", stream);
196 return (const char *)buf;
201 * Convert a 64 bit little endian to a big endian
203 void int64_LE2BE(int64_t* pBE, const int64_t v)
205 /* convert little endian to big endian */
206 if (htonl(1) != 1L) { /* no work if on little endian machine */
207 memcpy(pBE, &v, sizeof(int64_t));
210 uint8_t rv[sizeof(int64_t)];
211 uint8_t *pv = (uint8_t *) &v;
213 for (i = 0; i < 8; i++) {
216 memcpy(pBE, &rv, sizeof(int64_t));
221 * Convert a 32 bit little endian to a big endian
223 void int32_LE2BE(int32_t* pBE, const int32_t v)
225 /* convert little endian to big endian */
226 if (htonl(1) != 1L) { /* no work if on little endian machine */
227 memcpy(pBE, &v, sizeof(int32_t));
230 uint8_t rv[sizeof(int32_t)];
231 uint8_t *pv = (uint8_t *) &v;
233 for (i = 0; i < 4; i++) {
236 memcpy(pBE, &rv, sizeof(int32_t));
242 * Read a BackupRead block and pull out the file data
244 bool processWin32BackupAPIBlock (BFILE *bfd, void *pBuffer, ssize_t dwSize)
246 /* pByte contains the buffer
247 dwSize the len to be processed. function assumes to be
248 called in successive incremental order over the complete
249 BackupRead stream beginning at pos 0 and ending at the end.
252 PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT* pContext = &(bfd->win32DecompContext);
253 bool bContinue = false;
254 int64_t dwDataOffset = 0;
257 /* Win32 Stream Header size without name of stream.
258 * = sizeof (WIN32_STREAM_ID)- sizeof(WCHAR*);
260 int32_t dwSizeHeader = 20;
263 if (pContext->liNextHeader >= dwSize) {
264 dwDataLen = dwSize-dwDataOffset;
265 bContinue = false; /* 1 iteration is enough */
267 dwDataLen = pContext->liNextHeader-dwDataOffset;
268 bContinue = true; /* multiple iterations may be necessary */
272 /* copy block of real DATA */
273 if (pContext->bIsInData) {
274 if (bwrite(bfd, ((char *)pBuffer)+dwDataOffset, dwDataLen) != (ssize_t)dwDataLen)
278 if (pContext->liNextHeader < dwSize) {/* is a header in this block ? */
279 int32_t dwOffsetTarget;
280 int32_t dwOffsetSource;
282 if (pContext->liNextHeader < 0) {
283 /* start of header was before this block, so we
284 * continue with the part in the current block
286 dwOffsetTarget = -pContext->liNextHeader;
289 /* start of header is inside of this block */
291 dwOffsetSource = pContext->liNextHeader;
294 int32_t dwHeaderPartLen = dwSizeHeader-dwOffsetTarget;
295 bool bHeaderIsComplete;
297 if (dwHeaderPartLen <= dwSize-dwOffsetSource) {
298 /* header (or rest of header) is completely available
301 bHeaderIsComplete = true;
303 /* header will continue in next block */
304 bHeaderIsComplete = false;
305 dwHeaderPartLen = dwSize-dwOffsetSource;
308 /* copy the available portion of header to persistent copy */
309 memcpy(((char *)&pContext->header_stream)+dwOffsetTarget, ((char *)pBuffer)+dwOffsetSource, dwHeaderPartLen);
311 /* recalculate position of next header */
312 if (bHeaderIsComplete) {
313 /* convert stream name size (32 bit little endian) to machine type */
315 int32_LE2BE (&dwNameSize, pContext->header_stream.dwStreamNameSize);
316 dwDataOffset = dwNameSize+pContext->liNextHeader+dwSizeHeader;
318 /* convert stream size (64 bit little endian) to machine type */
319 int64_LE2BE (&(pContext->liNextHeader), pContext->header_stream.Size);
320 pContext->liNextHeader += dwDataOffset;
322 pContext->bIsInData = pContext->header_stream.dwStreamId == WIN32_BACKUP_DATA;
323 if (dwDataOffset == dwSize)
326 /* stop and continue with next block */
328 pContext->bIsInData = false;
333 /* set "NextHeader" relative to the beginning of the next block */
334 pContext->liNextHeader-= dwSize;
341 /* ===============================================================
345 * ===============================================================
348 #if defined(HAVE_WIN32)
350 void unix_name_to_win32(POOLMEM **win32_name, char *name);
351 extern "C" HANDLE get_osfhandle(int fd);
354 void binit(BFILE *bfd)
356 memset(bfd, 0, sizeof(BFILE));
358 bfd->mode = BF_CLOSED;
359 bfd->use_backup_api = have_win32_api();
360 bfd->cmd_plugin = false;
364 * Enables using the Backup API (win32_data).
365 * Returns 1 if function worked
366 * Returns 0 if failed (i.e. do not have Backup API on this machine)
368 bool set_win32_backup(BFILE *bfd)
370 /* We enable if possible here */
371 bfd->use_backup_api = have_win32_api();
372 return bfd->use_backup_api;
376 bool set_portable_backup(BFILE *bfd)
378 bfd->use_backup_api = false;
382 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
384 bfd->cmd_plugin = true;
390 * Return 1 if we are NOT using Win32 BackupWrite()
393 bool is_portable_backup(BFILE *bfd)
395 return !bfd->use_backup_api;
398 bool have_win32_api()
400 return p_BackupRead && p_BackupWrite;
405 * Return true if we support the stream
406 * false if we do not support the stream
408 * This code is running under Win32, so we
409 * do not need #ifdef on MACOS ...
411 bool is_restore_stream_supported(int stream)
415 /* Streams known not to be supported */
417 case STREAM_GZIP_DATA:
418 case STREAM_SPARSE_GZIP_DATA:
419 case STREAM_WIN32_GZIP_DATA:
421 case STREAM_MACOS_FORK_DATA:
422 case STREAM_HFSPLUS_ATTRIBUTES:
423 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
428 case STREAM_GZIP_DATA:
429 case STREAM_SPARSE_GZIP_DATA:
430 case STREAM_WIN32_GZIP_DATA:
432 case STREAM_WIN32_DATA:
433 case STREAM_UNIX_ATTRIBUTES:
434 case STREAM_FILE_DATA:
435 case STREAM_MD5_DIGEST:
436 case STREAM_UNIX_ATTRIBUTES_EX:
437 case STREAM_SPARSE_DATA:
438 case STREAM_PROGRAM_NAMES:
439 case STREAM_PROGRAM_DATA:
440 case STREAM_SHA1_DIGEST:
442 case STREAM_SHA256_DIGEST:
443 case STREAM_SHA512_DIGEST:
446 case STREAM_SIGNED_DIGEST:
447 case STREAM_ENCRYPTED_FILE_DATA:
448 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
449 case STREAM_ENCRYPTED_WIN32_DATA:
450 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
452 case 0: /* compatibility with old tapes */
458 HANDLE bget_handle(BFILE *bfd)
463 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
465 POOLMEM *win32_fname;
466 POOLMEM *win32_fname_wchar;
468 DWORD dwaccess, dwflags, dwshare;
470 /* Convert to Windows path format */
471 win32_fname = get_pool_memory(PM_FNAME);
472 win32_fname_wchar = get_pool_memory(PM_FNAME);
474 unix_name_to_win32(&win32_fname, (char *)fname);
476 if (bfd->cmd_plugin && plugin_bopen) {
478 Dmsg1(50, "call plugin_bopen fname=%s\n", fname);
479 rtnstat = plugin_bopen(bfd, fname, flags, mode);
480 Dmsg1(50, "return from plugin_bopen status=%d\n", rtnstat);
482 if (flags & O_CREAT || flags & O_WRONLY) { /* Open existing for write */
483 Dmsg1(50, "plugin_open for write OK file=%s.\n", fname);
484 bfd->mode = BF_WRITE;
486 Dmsg1(50, "plugin_open for read OK file=%s.\n", fname);
490 bfd->mode = BF_CLOSED;
491 Dmsg1(000, "==== plugin_bopen returned bad status=%d\n", rtnstat);
493 free_pool_memory(win32_fname_wchar);
494 free_pool_memory(win32_fname);
495 return bfd->mode == BF_CLOSED ? -1 : 1;
497 Dmsg0(50, "=== NO plugin\n");
499 if (!(p_CreateFileA || p_CreateFileW)) {
500 Dmsg0(50, "No CreateFileA and no CreateFileW!!!!!\n");
504 if (p_CreateFileW && p_MultiByteToWideChar) {
505 make_win32_path_UTF8_2_wchar(&win32_fname_wchar, fname);
508 if (flags & O_CREAT) { /* Create */
509 if (bfd->use_backup_api) {
510 dwaccess = GENERIC_WRITE|FILE_ALL_ACCESS|WRITE_OWNER|WRITE_DAC|ACCESS_SYSTEM_SECURITY;
511 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
513 dwaccess = GENERIC_WRITE;
517 if (p_CreateFileW && p_MultiByteToWideChar) {
518 // unicode open for create write
519 Dmsg1(100, "Create CreateFileW=%s\n", win32_fname);
520 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
521 dwaccess, /* Requested access */
523 NULL, /* SecurityAttributes */
524 CREATE_ALWAYS, /* CreationDisposition */
525 dwflags, /* Flags and attributes */
526 NULL); /* TemplateFile */
529 Dmsg1(100, "Create CreateFileA=%s\n", win32_fname);
530 bfd->fh = p_CreateFileA(win32_fname,
531 dwaccess, /* Requested access */
533 NULL, /* SecurityAttributes */
534 CREATE_ALWAYS, /* CreationDisposition */
535 dwflags, /* Flags and attributes */
536 NULL); /* TemplateFile */
539 bfd->mode = BF_WRITE;
541 } else if (flags & O_WRONLY) { /* Open existing for write */
542 if (bfd->use_backup_api) {
543 dwaccess = GENERIC_WRITE|WRITE_OWNER|WRITE_DAC;
544 dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT;
546 dwaccess = GENERIC_WRITE;
550 if (p_CreateFileW && p_MultiByteToWideChar) {
551 // unicode open for open existing write
552 Dmsg1(100, "Write only CreateFileW=%s\n", win32_fname);
553 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
554 dwaccess, /* Requested access */
556 NULL, /* SecurityAttributes */
557 OPEN_EXISTING, /* CreationDisposition */
558 dwflags, /* Flags and attributes */
559 NULL); /* TemplateFile */
562 Dmsg1(100, "Write only CreateFileA=%s\n", win32_fname);
563 bfd->fh = p_CreateFileA(win32_fname,
564 dwaccess, /* Requested access */
566 NULL, /* SecurityAttributes */
567 OPEN_EXISTING, /* CreationDisposition */
568 dwflags, /* Flags and attributes */
569 NULL); /* TemplateFile */
573 bfd->mode = BF_WRITE;
576 if (bfd->use_backup_api) {
577 dwaccess = GENERIC_READ|READ_CONTROL|ACCESS_SYSTEM_SECURITY;
578 dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_SEQUENTIAL_SCAN |
579 FILE_FLAG_OPEN_REPARSE_POINT;
580 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
582 dwaccess = GENERIC_READ;
584 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE;
587 if (p_CreateFileW && p_MultiByteToWideChar) {
588 // unicode open for open existing read
589 Dmsg1(100, "Read CreateFileW=%s\n", win32_fname);
590 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
591 dwaccess, /* Requested access */
592 dwshare, /* Share modes */
593 NULL, /* SecurityAttributes */
594 OPEN_EXISTING, /* CreationDisposition */
595 dwflags, /* Flags and attributes */
596 NULL); /* TemplateFile */
599 Dmsg1(100, "Read CreateFileA=%s\n", win32_fname);
600 bfd->fh = p_CreateFileA(win32_fname,
601 dwaccess, /* Requested access */
602 dwshare, /* Share modes */
603 NULL, /* SecurityAttributes */
604 OPEN_EXISTING, /* CreationDisposition */
605 dwflags, /* Flags and attributes */
606 NULL); /* TemplateFile */
612 if (bfd->fh == INVALID_HANDLE_VALUE) {
613 bfd->lerror = GetLastError();
614 bfd->berrno = b_errno_win32;
615 errno = b_errno_win32;
616 bfd->mode = BF_CLOSED;
619 bfd->lpContext = NULL;
620 bfd->win32DecompContext.bIsInData = false;
621 bfd->win32DecompContext.liNextHeader = 0;
622 free_pool_memory(win32_fname_wchar);
623 free_pool_memory(win32_fname);
624 return bfd->mode == BF_CLOSED ? -1 : 1;
628 * Returns 0 on success
631 int bclose(BFILE *bfd)
635 if (bfd->mode == BF_CLOSED) {
636 Dmsg0(50, "=== BFD already closed.\n");
640 if (bfd->cmd_plugin && plugin_bclose) {
641 stat = plugin_bclose(bfd);
642 Dmsg0(50, "==== BFD closed!!!\n");
647 * We need to tell the API to release the buffer it
648 * allocated in lpContext. We do so by calling the
649 * API one more time, but with the Abort bit set.
651 if (bfd->use_backup_api && bfd->mode == BF_READ) {
653 if (bfd->lpContext && !p_BackupRead(bfd->fh,
655 (DWORD)0, /* bytes to read */
656 &bfd->rw_bytes, /* bytes read */
658 1, /* ProcessSecurity */
659 &bfd->lpContext)) { /* Read context */
660 errno = b_errno_win32;
663 } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
665 if (bfd->lpContext && !p_BackupWrite(bfd->fh,
667 (DWORD)0, /* bytes to read */
668 &bfd->rw_bytes, /* bytes written */
670 1, /* ProcessSecurity */
671 &bfd->lpContext)) { /* Write context */
672 errno = b_errno_win32;
676 if (!CloseHandle(bfd->fh)) {
678 errno = b_errno_win32;
683 free_pool_memory(bfd->errmsg);
686 bfd->mode = BF_CLOSED;
687 bfd->lpContext = NULL;
688 bfd->cmd_plugin = false;
692 /* Returns: bytes read on success
696 ssize_t bread(BFILE *bfd, void *buf, size_t count)
700 if (bfd->cmd_plugin && plugin_bread) {
701 return plugin_bread(bfd, buf, count);
704 if (bfd->use_backup_api) {
705 if (!p_BackupRead(bfd->fh,
710 1, /* Process Security */
711 &bfd->lpContext)) { /* Context */
712 bfd->lerror = GetLastError();
713 bfd->berrno = b_errno_win32;
714 errno = b_errno_win32;
718 if (!ReadFile(bfd->fh,
723 bfd->lerror = GetLastError();
724 bfd->berrno = b_errno_win32;
725 errno = b_errno_win32;
730 return (ssize_t)bfd->rw_bytes;
733 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
737 if (bfd->cmd_plugin && plugin_bwrite) {
738 return plugin_bwrite(bfd, buf, count);
741 if (bfd->use_backup_api) {
742 if (!p_BackupWrite(bfd->fh,
747 1, /* Process Security */
748 &bfd->lpContext)) { /* Context */
749 bfd->lerror = GetLastError();
750 bfd->berrno = b_errno_win32;
751 errno = b_errno_win32;
755 if (!WriteFile(bfd->fh,
760 bfd->lerror = GetLastError();
761 bfd->berrno = b_errno_win32;
762 errno = b_errno_win32;
766 return (ssize_t)bfd->rw_bytes;
769 bool is_bopen(BFILE *bfd)
771 return bfd->mode != BF_CLOSED;
774 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
776 LONG offset_low = (LONG)offset;
777 LONG offset_high = (LONG)(offset >> 32);
780 if (bfd->cmd_plugin && plugin_blseek) {
781 return plugin_blseek(bfd, offset, whence);
784 dwResult = SetFilePointer(bfd->fh, offset_low, &offset_high, whence);
786 if (dwResult == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
787 return (boffset_t)-1;
790 return ((boffset_t)offset_high << 32) | dwResult;
793 #else /* Unix systems */
795 /* ===============================================================
799 * ===============================================================
801 void binit(BFILE *bfd)
803 memset(bfd, 0, sizeof(BFILE));
807 bool have_win32_api()
809 return false; /* no can do */
813 * Enables using the Backup API (win32_data).
814 * Returns true if function worked
815 * Returns false if failed (i.e. do not have Backup API on this machine)
817 bool set_win32_backup(BFILE *bfd)
819 return false; /* no can do */
823 bool set_portable_backup(BFILE *bfd)
825 return true; /* no problem */
829 * Return true if we are writing in portable format
830 * return false if not
832 bool is_portable_backup(BFILE *bfd)
834 return true; /* portable by definition */
837 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
842 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
844 bfd->cmd_plugin = true;
850 * This code is running on a non-Win32 machine
852 bool is_restore_stream_supported(int stream)
854 /* No Win32 backup on this machine */
857 case STREAM_GZIP_DATA:
858 case STREAM_SPARSE_GZIP_DATA:
859 case STREAM_WIN32_GZIP_DATA:
861 #ifndef HAVE_DARWIN_OS
862 case STREAM_MACOS_FORK_DATA:
863 case STREAM_HFSPLUS_ATTRIBUTES:
869 case STREAM_GZIP_DATA:
870 case STREAM_SPARSE_GZIP_DATA:
871 case STREAM_WIN32_GZIP_DATA:
873 case STREAM_WIN32_DATA:
874 case STREAM_UNIX_ATTRIBUTES:
875 case STREAM_FILE_DATA:
876 case STREAM_MD5_DIGEST:
877 case STREAM_UNIX_ATTRIBUTES_EX:
878 case STREAM_SPARSE_DATA:
879 case STREAM_PROGRAM_NAMES:
880 case STREAM_PROGRAM_DATA:
881 case STREAM_SHA1_DIGEST:
883 case STREAM_SHA256_DIGEST:
884 case STREAM_SHA512_DIGEST:
887 case STREAM_SIGNED_DIGEST:
888 case STREAM_ENCRYPTED_FILE_DATA:
889 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
890 case STREAM_ENCRYPTED_WIN32_DATA:
891 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
893 #ifdef HAVE_DARWIN_OS
894 case STREAM_MACOS_FORK_DATA:
895 case STREAM_HFSPLUS_ATTRIBUTES:
897 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
898 #endif /* HAVE_CRYPTO */
899 #endif /* HAVE_DARWIN_OS */
900 case 0: /* compatibility with old tapes */
907 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
909 if (bfd->cmd_plugin && plugin_bopen) {
910 Dmsg1(50, "call plugin_bopen fname=%s\n", fname);
911 bfd->fid = plugin_bopen(bfd, fname, flags, mode);
912 Dmsg1(50, "Plugin bopen stat=%d\n", bfd->fid);
916 /* Normal file open */
917 Dmsg1(dbglvl, "open file %s\n", fname);
919 /* We use fnctl to set O_NOATIME if requested to avoid open error */
920 bfd->fid = open(fname, flags & ~O_NOATIME, mode);
922 /* Set O_NOATIME if possible */
923 if (bfd->fid != -1 && flags & O_NOATIME) {
924 int oldflags = fcntl(bfd->fid, F_GETFL, 0);
925 if (oldflags == -1) {
930 int ret = fcntl(bfd->fid, F_SETFL, oldflags | O_NOATIME);
931 /* EPERM means setting O_NOATIME was not allowed */
932 if (ret == -1 && errno != EPERM) {
940 bfd->m_flags = flags;
941 Dmsg1(400, "Open file %d\n", bfd->fid);
944 bfd->win32DecompContext.bIsInData = false;
945 bfd->win32DecompContext.liNextHeader = 0;
947 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
948 if (bfd->fid != -1 && flags & O_RDONLY) {
949 int stat = posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_WILLNEED);
950 Dmsg2(400, "Did posix_fadvise on %s stat=%d\n", fname, stat);
957 #ifdef HAVE_DARWIN_OS
958 /* Open the resource fork of a file. */
959 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
963 rsrc_fname = get_pool_memory(PM_FNAME);
964 pm_strcpy(rsrc_fname, fname);
965 pm_strcat(rsrc_fname, _PATH_RSRCFORKSPEC);
966 bopen(bfd, rsrc_fname, flags, mode);
967 free_pool_memory(rsrc_fname);
971 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
978 int bclose(BFILE *bfd)
982 Dmsg1(400, "Close file %d\n", bfd->fid);
984 if (bfd->cmd_plugin && plugin_bclose) {
985 stat = plugin_bclose(bfd);
987 bfd->cmd_plugin = false;
990 if (bfd->fid == -1) {
993 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
994 if (bfd->m_flags & O_RDONLY) {
995 fdatasync(bfd->fid); /* sync the file */
996 /* Tell OS we don't need it any more */
997 posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_DONTNEED);
1001 /* Close normal file */
1002 stat = close(bfd->fid);
1003 bfd->berrno = errno;
1005 bfd->cmd_plugin = false;
1009 ssize_t bread(BFILE *bfd, void *buf, size_t count)
1013 if (bfd->cmd_plugin && plugin_bread) {
1014 return plugin_bread(bfd, buf, count);
1017 stat = read(bfd->fid, buf, count);
1018 bfd->berrno = errno;
1022 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
1026 if (bfd->cmd_plugin && plugin_bwrite) {
1027 return plugin_bwrite(bfd, buf, count);
1029 stat = write(bfd->fid, buf, count);
1030 bfd->berrno = errno;
1034 bool is_bopen(BFILE *bfd)
1036 return bfd->fid >= 0;
1039 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
1043 if (bfd->cmd_plugin && plugin_bwrite) {
1044 return plugin_blseek(bfd, offset, whence);
1046 pos = (boffset_t)lseek(bfd->fid, offset, whence);
1047 bfd->berrno = errno;