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_WIN32_COMPRESSED_DATA:
83 case STREAM_ENCRYPTED_WIN32_DATA:
84 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
85 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
91 const char *stream_to_ascii(int stream)
95 switch (stream & STREAMMASK_TYPE) {
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_COMPRESSED_DATA:
105 return _("Compressed data");
106 case STREAM_UNIX_ATTRIBUTES_EX:
107 return _("Extended attributes");
108 case STREAM_SPARSE_DATA:
109 return _("Sparse data");
110 case STREAM_SPARSE_GZIP_DATA:
111 return _("GZIP sparse data");
112 case STREAM_SPARSE_COMPRESSED_DATA:
113 return _("Compressed sparse data");
114 case STREAM_PROGRAM_NAMES:
115 return _("Program names");
116 case STREAM_PROGRAM_DATA:
117 return _("Program data");
118 case STREAM_SHA1_DIGEST:
119 return _("SHA1 digest");
120 case STREAM_WIN32_DATA:
121 return _("Win32 data");
122 case STREAM_WIN32_GZIP_DATA:
123 return _("Win32 GZIP data");
124 case STREAM_WIN32_COMPRESSED_DATA:
125 return _("Win32 compressed data");
126 case STREAM_MACOS_FORK_DATA:
127 return _("MacOS Fork data");
128 case STREAM_HFSPLUS_ATTRIBUTES:
129 return _("HFS+ attribs");
130 case STREAM_UNIX_ACCESS_ACL:
131 return _("Standard Unix ACL attribs");
132 case STREAM_UNIX_DEFAULT_ACL:
133 return _("Default Unix ACL attribs");
134 case STREAM_SHA256_DIGEST:
135 return _("SHA256 digest");
136 case STREAM_SHA512_DIGEST:
137 return _("SHA512 digest");
138 case STREAM_SIGNED_DIGEST:
139 return _("Signed digest");
140 case STREAM_ENCRYPTED_FILE_DATA:
141 return _("Encrypted File data");
142 case STREAM_ENCRYPTED_WIN32_DATA:
143 return _("Encrypted Win32 data");
144 case STREAM_ENCRYPTED_SESSION_DATA:
145 return _("Encrypted session data");
146 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
147 return _("Encrypted GZIP data");
148 case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
149 return _("Encrypted compressed data");
150 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
151 return _("Encrypted Win32 GZIP data");
152 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
153 return _("Encrypted Win32 Compressed data");
154 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
155 return _("Encrypted MacOS fork data");
156 case STREAM_ACL_AIX_TEXT:
157 return _("AIX Specific ACL attribs");
158 case STREAM_ACL_DARWIN_ACCESS_ACL:
159 return _("Darwin Specific ACL attribs");
160 case STREAM_ACL_FREEBSD_DEFAULT_ACL:
161 return _("FreeBSD Specific Default ACL attribs");
162 case STREAM_ACL_FREEBSD_ACCESS_ACL:
163 return _("FreeBSD Specific Access ACL attribs");
164 case STREAM_ACL_HPUX_ACL_ENTRY:
165 return _("HPUX Specific ACL attribs");
166 case STREAM_ACL_IRIX_DEFAULT_ACL:
167 return _("Irix Specific Default ACL attribs");
168 case STREAM_ACL_IRIX_ACCESS_ACL:
169 return _("Irix Specific Access ACL attribs");
170 case STREAM_ACL_LINUX_DEFAULT_ACL:
171 return _("Linux Specific Default ACL attribs");
172 case STREAM_ACL_LINUX_ACCESS_ACL:
173 return _("Linux Specific Access ACL attribs");
174 case STREAM_ACL_TRU64_DEFAULT_ACL:
175 return _("TRU64 Specific Default ACL attribs");
176 case STREAM_ACL_TRU64_ACCESS_ACL:
177 return _("TRU64 Specific Access ACL attribs");
178 case STREAM_ACL_SOLARIS_ACLENT:
179 return _("Solaris Specific POSIX ACL attribs");
180 case STREAM_ACL_SOLARIS_ACE:
181 return _("Solaris Specific NFSv4/ZFS ACL attribs");
182 case STREAM_ACL_AFS_TEXT:
183 return _("AFS Specific ACL attribs");
184 case STREAM_ACL_AIX_AIXC:
185 return _("AIX Specific POSIX ACL attribs");
186 case STREAM_ACL_AIX_NFS4:
187 return _("AIX Specific NFSv4 ACL attribs");
188 case STREAM_ACL_FREEBSD_NFS4_ACL:
189 return _("FreeBSD Specific NFSv4/ZFS ACL attribs");
190 case STREAM_XATTR_IRIX:
191 return _("IRIX Specific Extended attribs");
192 case STREAM_XATTR_TRU64:
193 return _("TRU64 Specific Extended attribs");
194 case STREAM_XATTR_AIX:
195 return _("AIX Specific Extended attribs");
196 case STREAM_XATTR_OPENBSD:
197 return _("OpenBSD Specific Extended attribs");
198 case STREAM_XATTR_SOLARIS_SYS:
199 return _("Solaris Specific Extensible attribs or System Extended attribs");
200 case STREAM_XATTR_SOLARIS:
201 return _("Solaris Specific Extended attribs");
202 case STREAM_XATTR_DARWIN:
203 return _("Darwin Specific Extended attribs");
204 case STREAM_XATTR_FREEBSD:
205 return _("FreeBSD Specific Extended attribs");
206 case STREAM_XATTR_LINUX:
207 return _("Linux Specific Extended attribs");
208 case STREAM_XATTR_NETBSD:
209 return _("NetBSD Specific Extended attribs");
211 sprintf(buf, "%d", stream);
212 return (const char *)buf;
217 * Convert a 64 bit little endian to a big endian
219 void int64_LE2BE(int64_t* pBE, const int64_t v)
221 /* convert little endian to big endian */
222 if (htonl(1) != 1L) { /* no work if on little endian machine */
223 memcpy(pBE, &v, sizeof(int64_t));
226 uint8_t rv[sizeof(int64_t)];
227 uint8_t *pv = (uint8_t *) &v;
229 for (i = 0; i < 8; i++) {
232 memcpy(pBE, &rv, sizeof(int64_t));
237 * Convert a 32 bit little endian to a big endian
239 void int32_LE2BE(int32_t* pBE, const int32_t v)
241 /* convert little endian to big endian */
242 if (htonl(1) != 1L) { /* no work if on little endian machine */
243 memcpy(pBE, &v, sizeof(int32_t));
246 uint8_t rv[sizeof(int32_t)];
247 uint8_t *pv = (uint8_t *) &v;
249 for (i = 0; i < 4; i++) {
252 memcpy(pBE, &rv, sizeof(int32_t));
258 * Read a BackupRead block and pull out the file data
260 bool processWin32BackupAPIBlock (BFILE *bfd, void *pBuffer, ssize_t dwSize)
262 /* pByte contains the buffer
263 dwSize the len to be processed. function assumes to be
264 called in successive incremental order over the complete
265 BackupRead stream beginning at pos 0 and ending at the end.
268 PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT* pContext = &(bfd->win32DecompContext);
269 bool bContinue = false;
270 int64_t dwDataOffset = 0;
273 /* Win32 Stream Header size without name of stream.
274 * = sizeof (WIN32_STREAM_ID)- sizeof(WCHAR*);
276 int32_t dwSizeHeader = 20;
279 if (pContext->liNextHeader >= dwSize) {
280 dwDataLen = dwSize-dwDataOffset;
281 bContinue = false; /* 1 iteration is enough */
283 dwDataLen = pContext->liNextHeader-dwDataOffset;
284 bContinue = true; /* multiple iterations may be necessary */
288 /* copy block of real DATA */
289 if (pContext->bIsInData) {
290 if (bwrite(bfd, ((char *)pBuffer)+dwDataOffset, dwDataLen) != (ssize_t)dwDataLen)
294 if (pContext->liNextHeader < dwSize) {/* is a header in this block ? */
295 int32_t dwOffsetTarget;
296 int32_t dwOffsetSource;
298 if (pContext->liNextHeader < 0) {
299 /* start of header was before this block, so we
300 * continue with the part in the current block
302 dwOffsetTarget = -pContext->liNextHeader;
305 /* start of header is inside of this block */
307 dwOffsetSource = pContext->liNextHeader;
310 int32_t dwHeaderPartLen = dwSizeHeader-dwOffsetTarget;
311 bool bHeaderIsComplete;
313 if (dwHeaderPartLen <= dwSize-dwOffsetSource) {
314 /* header (or rest of header) is completely available
317 bHeaderIsComplete = true;
319 /* header will continue in next block */
320 bHeaderIsComplete = false;
321 dwHeaderPartLen = dwSize-dwOffsetSource;
324 /* copy the available portion of header to persistent copy */
325 memcpy(((char *)&pContext->header_stream)+dwOffsetTarget, ((char *)pBuffer)+dwOffsetSource, dwHeaderPartLen);
327 /* recalculate position of next header */
328 if (bHeaderIsComplete) {
329 /* convert stream name size (32 bit little endian) to machine type */
331 int32_LE2BE (&dwNameSize, pContext->header_stream.dwStreamNameSize);
332 dwDataOffset = dwNameSize+pContext->liNextHeader+dwSizeHeader;
334 /* convert stream size (64 bit little endian) to machine type */
335 int64_LE2BE (&(pContext->liNextHeader), pContext->header_stream.Size);
336 pContext->liNextHeader += dwDataOffset;
338 pContext->bIsInData = pContext->header_stream.dwStreamId == WIN32_BACKUP_DATA;
339 if (dwDataOffset == dwSize)
342 /* stop and continue with next block */
344 pContext->bIsInData = false;
349 /* set "NextHeader" relative to the beginning of the next block */
350 pContext->liNextHeader-= dwSize;
357 /* ===============================================================
361 * ===============================================================
364 #if defined(HAVE_WIN32)
366 void unix_name_to_win32(POOLMEM **win32_name, char *name);
367 extern "C" HANDLE get_osfhandle(int fd);
370 void binit(BFILE *bfd)
372 memset(bfd, 0, sizeof(BFILE));
374 bfd->mode = BF_CLOSED;
375 bfd->use_backup_api = have_win32_api();
376 bfd->cmd_plugin = false;
380 * Enables using the Backup API (win32_data).
381 * Returns 1 if function worked
382 * Returns 0 if failed (i.e. do not have Backup API on this machine)
384 bool set_win32_backup(BFILE *bfd)
386 /* We enable if possible here */
387 bfd->use_backup_api = have_win32_api();
388 return bfd->use_backup_api;
392 bool set_portable_backup(BFILE *bfd)
394 bfd->use_backup_api = false;
398 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
400 bfd->cmd_plugin = true;
406 * Return 1 if we are NOT using Win32 BackupWrite()
409 bool is_portable_backup(BFILE *bfd)
411 return !bfd->use_backup_api;
414 bool have_win32_api()
416 return p_BackupRead && p_BackupWrite;
421 * Return true if we support the stream
422 * false if we do not support the stream
424 * This code is running under Win32, so we
425 * do not need #ifdef on MACOS ...
427 bool is_restore_stream_supported(int stream)
431 /* Streams known not to be supported */
433 case STREAM_GZIP_DATA:
434 case STREAM_SPARSE_GZIP_DATA:
435 case STREAM_WIN32_GZIP_DATA:
438 case STREAM_COMPRESSED_DATA:
439 case STREAM_SPARSE_COMPRESSED_DATA:
440 case STREAM_WIN32_COMPRESSED_DATA:
441 case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
442 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
444 case STREAM_MACOS_FORK_DATA:
445 case STREAM_HFSPLUS_ATTRIBUTES:
446 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
451 case STREAM_GZIP_DATA:
452 case STREAM_SPARSE_GZIP_DATA:
453 case STREAM_WIN32_GZIP_DATA:
456 case STREAM_COMPRESSED_DATA:
457 case STREAM_SPARSE_COMPRESSED_DATA:
458 case STREAM_WIN32_COMPRESSED_DATA:
460 case STREAM_WIN32_DATA:
461 case STREAM_UNIX_ATTRIBUTES:
462 case STREAM_FILE_DATA:
463 case STREAM_MD5_DIGEST:
464 case STREAM_UNIX_ATTRIBUTES_EX:
465 case STREAM_SPARSE_DATA:
466 case STREAM_PROGRAM_NAMES:
467 case STREAM_PROGRAM_DATA:
468 case STREAM_SHA1_DIGEST:
470 case STREAM_SHA256_DIGEST:
471 case STREAM_SHA512_DIGEST:
474 case STREAM_SIGNED_DIGEST:
475 case STREAM_ENCRYPTED_FILE_DATA:
476 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
477 case STREAM_ENCRYPTED_WIN32_DATA:
478 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
480 case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
481 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
483 #endif /* !HAVE_CRYPTO */
484 case 0: /* compatibility with old tapes */
490 HANDLE bget_handle(BFILE *bfd)
495 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
497 POOLMEM *win32_fname;
498 POOLMEM *win32_fname_wchar;
500 DWORD dwaccess, dwflags, dwshare;
502 /* Convert to Windows path format */
503 win32_fname = get_pool_memory(PM_FNAME);
504 win32_fname_wchar = get_pool_memory(PM_FNAME);
506 unix_name_to_win32(&win32_fname, (char *)fname);
508 if (bfd->cmd_plugin && plugin_bopen) {
510 Dmsg1(50, "call plugin_bopen fname=%s\n", fname);
511 rtnstat = plugin_bopen(bfd, fname, flags, mode);
512 Dmsg1(50, "return from plugin_bopen status=%d\n", rtnstat);
514 if (flags & O_CREAT || flags & O_WRONLY) { /* Open existing for write */
515 Dmsg1(50, "plugin_open for write OK file=%s.\n", fname);
516 bfd->mode = BF_WRITE;
518 Dmsg1(50, "plugin_open for read OK file=%s.\n", fname);
522 bfd->mode = BF_CLOSED;
523 Dmsg1(000, "==== plugin_bopen returned bad status=%d\n", rtnstat);
525 free_pool_memory(win32_fname_wchar);
526 free_pool_memory(win32_fname);
527 return bfd->mode == BF_CLOSED ? -1 : 1;
529 Dmsg0(50, "=== NO plugin\n");
531 if (!(p_CreateFileA || p_CreateFileW)) {
532 Dmsg0(50, "No CreateFileA and no CreateFileW!!!!!\n");
536 if (p_CreateFileW && p_MultiByteToWideChar) {
537 make_win32_path_UTF8_2_wchar(&win32_fname_wchar, fname);
540 if (flags & O_CREAT) { /* Create */
541 if (bfd->use_backup_api) {
542 dwaccess = GENERIC_WRITE|FILE_ALL_ACCESS|WRITE_OWNER|WRITE_DAC|ACCESS_SYSTEM_SECURITY;
543 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
545 dwaccess = GENERIC_WRITE;
549 if (p_CreateFileW && p_MultiByteToWideChar) {
550 // unicode open for create write
551 Dmsg1(100, "Create CreateFileW=%s\n", win32_fname);
552 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
553 dwaccess, /* Requested access */
555 NULL, /* SecurityAttributes */
556 CREATE_ALWAYS, /* CreationDisposition */
557 dwflags, /* Flags and attributes */
558 NULL); /* TemplateFile */
561 Dmsg1(100, "Create CreateFileA=%s\n", win32_fname);
562 bfd->fh = p_CreateFileA(win32_fname,
563 dwaccess, /* Requested access */
565 NULL, /* SecurityAttributes */
566 CREATE_ALWAYS, /* CreationDisposition */
567 dwflags, /* Flags and attributes */
568 NULL); /* TemplateFile */
571 bfd->mode = BF_WRITE;
573 } else if (flags & O_WRONLY) { /* Open existing for write */
574 if (bfd->use_backup_api) {
575 dwaccess = GENERIC_WRITE|WRITE_OWNER|WRITE_DAC;
576 dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT;
578 dwaccess = GENERIC_WRITE;
582 if (p_CreateFileW && p_MultiByteToWideChar) {
583 // unicode open for open existing write
584 Dmsg1(100, "Write only CreateFileW=%s\n", win32_fname);
585 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
586 dwaccess, /* Requested access */
588 NULL, /* SecurityAttributes */
589 OPEN_EXISTING, /* CreationDisposition */
590 dwflags, /* Flags and attributes */
591 NULL); /* TemplateFile */
594 Dmsg1(100, "Write only CreateFileA=%s\n", win32_fname);
595 bfd->fh = p_CreateFileA(win32_fname,
596 dwaccess, /* Requested access */
598 NULL, /* SecurityAttributes */
599 OPEN_EXISTING, /* CreationDisposition */
600 dwflags, /* Flags and attributes */
601 NULL); /* TemplateFile */
605 bfd->mode = BF_WRITE;
608 if (bfd->use_backup_api) {
609 dwaccess = GENERIC_READ|READ_CONTROL|ACCESS_SYSTEM_SECURITY;
610 dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_SEQUENTIAL_SCAN |
611 FILE_FLAG_OPEN_REPARSE_POINT;
612 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
614 dwaccess = GENERIC_READ;
616 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE;
619 if (p_CreateFileW && p_MultiByteToWideChar) {
620 // unicode open for open existing read
621 Dmsg1(100, "Read CreateFileW=%s\n", win32_fname);
622 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
623 dwaccess, /* Requested access */
624 dwshare, /* Share modes */
625 NULL, /* SecurityAttributes */
626 OPEN_EXISTING, /* CreationDisposition */
627 dwflags, /* Flags and attributes */
628 NULL); /* TemplateFile */
631 Dmsg1(100, "Read CreateFileA=%s\n", win32_fname);
632 bfd->fh = p_CreateFileA(win32_fname,
633 dwaccess, /* Requested access */
634 dwshare, /* Share modes */
635 NULL, /* SecurityAttributes */
636 OPEN_EXISTING, /* CreationDisposition */
637 dwflags, /* Flags and attributes */
638 NULL); /* TemplateFile */
644 if (bfd->fh == INVALID_HANDLE_VALUE) {
645 bfd->lerror = GetLastError();
646 bfd->berrno = b_errno_win32;
647 errno = b_errno_win32;
648 bfd->mode = BF_CLOSED;
651 bfd->lpContext = NULL;
652 bfd->win32DecompContext.bIsInData = false;
653 bfd->win32DecompContext.liNextHeader = 0;
654 free_pool_memory(win32_fname_wchar);
655 free_pool_memory(win32_fname);
656 return bfd->mode == BF_CLOSED ? -1 : 1;
660 * Returns 0 on success
663 int bclose(BFILE *bfd)
667 if (bfd->mode == BF_CLOSED) {
668 Dmsg0(50, "=== BFD already closed.\n");
672 if (bfd->cmd_plugin && plugin_bclose) {
673 stat = plugin_bclose(bfd);
674 Dmsg0(50, "==== BFD closed!!!\n");
679 * We need to tell the API to release the buffer it
680 * allocated in lpContext. We do so by calling the
681 * API one more time, but with the Abort bit set.
683 if (bfd->use_backup_api && bfd->mode == BF_READ) {
685 if (bfd->lpContext && !p_BackupRead(bfd->fh,
687 (DWORD)0, /* bytes to read */
688 &bfd->rw_bytes, /* bytes read */
690 1, /* ProcessSecurity */
691 &bfd->lpContext)) { /* Read context */
692 errno = b_errno_win32;
695 } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
697 if (bfd->lpContext && !p_BackupWrite(bfd->fh,
699 (DWORD)0, /* bytes to read */
700 &bfd->rw_bytes, /* bytes written */
702 1, /* ProcessSecurity */
703 &bfd->lpContext)) { /* Write context */
704 errno = b_errno_win32;
708 if (!CloseHandle(bfd->fh)) {
710 errno = b_errno_win32;
715 free_pool_memory(bfd->errmsg);
718 bfd->mode = BF_CLOSED;
719 bfd->lpContext = NULL;
720 bfd->cmd_plugin = false;
724 /* Returns: bytes read on success
728 ssize_t bread(BFILE *bfd, void *buf, size_t count)
732 if (bfd->cmd_plugin && plugin_bread) {
733 return plugin_bread(bfd, buf, count);
736 if (bfd->use_backup_api) {
737 if (!p_BackupRead(bfd->fh,
742 1, /* Process Security */
743 &bfd->lpContext)) { /* Context */
744 bfd->lerror = GetLastError();
745 bfd->berrno = b_errno_win32;
746 errno = b_errno_win32;
750 if (!ReadFile(bfd->fh,
755 bfd->lerror = GetLastError();
756 bfd->berrno = b_errno_win32;
757 errno = b_errno_win32;
762 return (ssize_t)bfd->rw_bytes;
765 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
769 if (bfd->cmd_plugin && plugin_bwrite) {
770 return plugin_bwrite(bfd, buf, count);
773 if (bfd->use_backup_api) {
774 if (!p_BackupWrite(bfd->fh,
779 1, /* Process Security */
780 &bfd->lpContext)) { /* Context */
781 bfd->lerror = GetLastError();
782 bfd->berrno = b_errno_win32;
783 errno = b_errno_win32;
787 if (!WriteFile(bfd->fh,
792 bfd->lerror = GetLastError();
793 bfd->berrno = b_errno_win32;
794 errno = b_errno_win32;
798 return (ssize_t)bfd->rw_bytes;
801 bool is_bopen(BFILE *bfd)
803 return bfd->mode != BF_CLOSED;
806 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
808 LONG offset_low = (LONG)offset;
809 LONG offset_high = (LONG)(offset >> 32);
812 if (bfd->cmd_plugin && plugin_blseek) {
813 return plugin_blseek(bfd, offset, whence);
816 dwResult = SetFilePointer(bfd->fh, offset_low, &offset_high, whence);
818 if (dwResult == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
819 return (boffset_t)-1;
822 return ((boffset_t)offset_high << 32) | dwResult;
825 #else /* Unix systems */
827 /* ===============================================================
831 * ===============================================================
833 void binit(BFILE *bfd)
835 memset(bfd, 0, sizeof(BFILE));
839 bool have_win32_api()
841 return false; /* no can do */
845 * Enables using the Backup API (win32_data).
846 * Returns true if function worked
847 * Returns false if failed (i.e. do not have Backup API on this machine)
849 bool set_win32_backup(BFILE *bfd)
851 return false; /* no can do */
855 bool set_portable_backup(BFILE *bfd)
857 return true; /* no problem */
861 * Return true if we are writing in portable format
862 * return false if not
864 bool is_portable_backup(BFILE *bfd)
866 return true; /* portable by definition */
869 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
874 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
876 bfd->cmd_plugin = true;
882 * This code is running on a non-Win32 machine
884 bool is_restore_stream_supported(int stream)
886 /* No Win32 backup on this machine */
889 case STREAM_GZIP_DATA:
890 case STREAM_SPARSE_GZIP_DATA:
891 case STREAM_WIN32_GZIP_DATA:
894 case STREAM_COMPRESSED_DATA:
895 case STREAM_SPARSE_COMPRESSED_DATA:
896 case STREAM_WIN32_COMPRESSED_DATA:
897 case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
898 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
900 #ifndef HAVE_DARWIN_OS
901 case STREAM_MACOS_FORK_DATA:
902 case STREAM_HFSPLUS_ATTRIBUTES:
908 case STREAM_GZIP_DATA:
909 case STREAM_SPARSE_GZIP_DATA:
910 case STREAM_WIN32_GZIP_DATA:
913 case STREAM_COMPRESSED_DATA:
914 case STREAM_SPARSE_COMPRESSED_DATA:
915 case STREAM_WIN32_COMPRESSED_DATA:
916 case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
917 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
919 case STREAM_WIN32_DATA:
920 case STREAM_UNIX_ATTRIBUTES:
921 case STREAM_FILE_DATA:
922 case STREAM_MD5_DIGEST:
923 case STREAM_UNIX_ATTRIBUTES_EX:
924 case STREAM_SPARSE_DATA:
925 case STREAM_PROGRAM_NAMES:
926 case STREAM_PROGRAM_DATA:
927 case STREAM_SHA1_DIGEST:
929 case STREAM_SHA256_DIGEST:
930 case STREAM_SHA512_DIGEST:
933 case STREAM_SIGNED_DIGEST:
934 case STREAM_ENCRYPTED_FILE_DATA:
935 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
936 case STREAM_ENCRYPTED_WIN32_DATA:
937 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
939 #ifdef HAVE_DARWIN_OS
940 case STREAM_MACOS_FORK_DATA:
941 case STREAM_HFSPLUS_ATTRIBUTES:
943 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
944 #endif /* HAVE_CRYPTO */
945 #endif /* HAVE_DARWIN_OS */
946 case 0: /* compatibility with old tapes */
953 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
955 if (bfd->cmd_plugin && plugin_bopen) {
956 Dmsg1(50, "call plugin_bopen fname=%s\n", fname);
957 bfd->fid = plugin_bopen(bfd, fname, flags, mode);
958 Dmsg1(50, "Plugin bopen stat=%d\n", bfd->fid);
962 /* Normal file open */
963 Dmsg1(dbglvl, "open file %s\n", fname);
965 /* We use fnctl to set O_NOATIME if requested to avoid open error */
966 bfd->fid = open(fname, flags & ~O_NOATIME, mode);
968 /* Set O_NOATIME if possible */
969 if (bfd->fid != -1 && flags & O_NOATIME) {
970 int oldflags = fcntl(bfd->fid, F_GETFL, 0);
971 if (oldflags == -1) {
976 int ret = fcntl(bfd->fid, F_SETFL, oldflags | O_NOATIME);
977 /* EPERM means setting O_NOATIME was not allowed */
978 if (ret == -1 && errno != EPERM) {
986 bfd->m_flags = flags;
987 Dmsg1(400, "Open file %d\n", bfd->fid);
990 bfd->win32DecompContext.bIsInData = false;
991 bfd->win32DecompContext.liNextHeader = 0;
993 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
994 if (bfd->fid != -1 && flags & O_RDONLY) {
995 int stat = posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_WILLNEED);
996 Dmsg2(400, "Did posix_fadvise on %s stat=%d\n", fname, stat);
1003 #ifdef HAVE_DARWIN_OS
1004 /* Open the resource fork of a file. */
1005 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
1007 POOLMEM *rsrc_fname;
1009 rsrc_fname = get_pool_memory(PM_FNAME);
1010 pm_strcpy(rsrc_fname, fname);
1011 pm_strcat(rsrc_fname, _PATH_RSRCFORKSPEC);
1012 bopen(bfd, rsrc_fname, flags, mode);
1013 free_pool_memory(rsrc_fname);
1017 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
1024 int bclose(BFILE *bfd)
1028 Dmsg1(400, "Close file %d\n", bfd->fid);
1030 if (bfd->cmd_plugin && plugin_bclose) {
1031 stat = plugin_bclose(bfd);
1033 bfd->cmd_plugin = false;
1036 if (bfd->fid == -1) {
1039 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
1040 if (bfd->m_flags & O_RDONLY) {
1041 fdatasync(bfd->fid); /* sync the file */
1042 /* Tell OS we don't need it any more */
1043 posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_DONTNEED);
1047 /* Close normal file */
1048 stat = close(bfd->fid);
1049 bfd->berrno = errno;
1051 bfd->cmd_plugin = false;
1055 ssize_t bread(BFILE *bfd, void *buf, size_t count)
1059 if (bfd->cmd_plugin && plugin_bread) {
1060 return plugin_bread(bfd, buf, count);
1063 stat = read(bfd->fid, buf, count);
1064 bfd->berrno = errno;
1068 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
1072 if (bfd->cmd_plugin && plugin_bwrite) {
1073 return plugin_bwrite(bfd, buf, count);
1075 stat = write(bfd->fid, buf, count);
1076 bfd->berrno = errno;
1080 bool is_bopen(BFILE *bfd)
1082 return bfd->fid >= 0;
1085 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
1089 if (bfd->cmd_plugin && plugin_bwrite) {
1090 return plugin_blseek(bfd, offset, whence);
1092 pos = (boffset_t)lseek(bfd->fid, offset, whence);
1093 bfd->berrno = errno;