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_ACL_HURD_DEFAULT_ACL:
191 return _("GNU Hurd Specific Default ACL attribs");
192 case STREAM_ACL_HURD_ACCESS_ACL:
193 return _("GNU Hurd Specific Access ACL attribs");
194 case STREAM_XATTR_HURD:
195 return _("GNU Hurd Specific Extended attribs");
196 case STREAM_XATTR_IRIX:
197 return _("IRIX Specific Extended attribs");
198 case STREAM_XATTR_TRU64:
199 return _("TRU64 Specific Extended attribs");
200 case STREAM_XATTR_AIX:
201 return _("AIX Specific Extended attribs");
202 case STREAM_XATTR_OPENBSD:
203 return _("OpenBSD Specific Extended attribs");
204 case STREAM_XATTR_SOLARIS_SYS:
205 return _("Solaris Specific Extensible attribs or System Extended attribs");
206 case STREAM_XATTR_SOLARIS:
207 return _("Solaris Specific Extended attribs");
208 case STREAM_XATTR_DARWIN:
209 return _("Darwin Specific Extended attribs");
210 case STREAM_XATTR_FREEBSD:
211 return _("FreeBSD Specific Extended attribs");
212 case STREAM_XATTR_LINUX:
213 return _("Linux Specific Extended attribs");
214 case STREAM_XATTR_NETBSD:
215 return _("NetBSD Specific Extended attribs");
217 sprintf(buf, "%d", stream);
218 return (const char *)buf;
223 * Convert a 64 bit little endian to a big endian
225 void int64_LE2BE(int64_t* pBE, const int64_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(int64_t));
232 uint8_t rv[sizeof(int64_t)];
233 uint8_t *pv = (uint8_t *) &v;
235 for (i = 0; i < 8; i++) {
238 memcpy(pBE, &rv, sizeof(int64_t));
243 * Convert a 32 bit little endian to a big endian
245 void int32_LE2BE(int32_t* pBE, const int32_t v)
247 /* convert little endian to big endian */
248 if (htonl(1) != 1L) { /* no work if on little endian machine */
249 memcpy(pBE, &v, sizeof(int32_t));
252 uint8_t rv[sizeof(int32_t)];
253 uint8_t *pv = (uint8_t *) &v;
255 for (i = 0; i < 4; i++) {
258 memcpy(pBE, &rv, sizeof(int32_t));
264 * Read a BackupRead block and pull out the file data
266 bool processWin32BackupAPIBlock (BFILE *bfd, void *pBuffer, ssize_t dwSize)
268 /* pByte contains the buffer
269 dwSize the len to be processed. function assumes to be
270 called in successive incremental order over the complete
271 BackupRead stream beginning at pos 0 and ending at the end.
274 PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT* pContext = &(bfd->win32DecompContext);
275 bool bContinue = false;
276 int64_t dwDataOffset = 0;
279 /* Win32 Stream Header size without name of stream.
280 * = sizeof (WIN32_STREAM_ID)- sizeof(WCHAR*);
282 int32_t dwSizeHeader = 20;
285 if (pContext->liNextHeader >= dwSize) {
286 dwDataLen = dwSize-dwDataOffset;
287 bContinue = false; /* 1 iteration is enough */
289 dwDataLen = pContext->liNextHeader-dwDataOffset;
290 bContinue = true; /* multiple iterations may be necessary */
294 /* copy block of real DATA */
295 if (pContext->bIsInData) {
296 if (bwrite(bfd, ((char *)pBuffer)+dwDataOffset, dwDataLen) != (ssize_t)dwDataLen)
300 if (pContext->liNextHeader < dwSize) {/* is a header in this block ? */
301 int32_t dwOffsetTarget;
302 int32_t dwOffsetSource;
304 if (pContext->liNextHeader < 0) {
305 /* start of header was before this block, so we
306 * continue with the part in the current block
308 dwOffsetTarget = -pContext->liNextHeader;
311 /* start of header is inside of this block */
313 dwOffsetSource = pContext->liNextHeader;
316 int32_t dwHeaderPartLen = dwSizeHeader-dwOffsetTarget;
317 bool bHeaderIsComplete;
319 if (dwHeaderPartLen <= dwSize-dwOffsetSource) {
320 /* header (or rest of header) is completely available
323 bHeaderIsComplete = true;
325 /* header will continue in next block */
326 bHeaderIsComplete = false;
327 dwHeaderPartLen = dwSize-dwOffsetSource;
330 /* copy the available portion of header to persistent copy */
331 memcpy(((char *)&pContext->header_stream)+dwOffsetTarget, ((char *)pBuffer)+dwOffsetSource, dwHeaderPartLen);
333 /* recalculate position of next header */
334 if (bHeaderIsComplete) {
335 /* convert stream name size (32 bit little endian) to machine type */
337 int32_LE2BE (&dwNameSize, pContext->header_stream.dwStreamNameSize);
338 dwDataOffset = dwNameSize+pContext->liNextHeader+dwSizeHeader;
340 /* convert stream size (64 bit little endian) to machine type */
341 int64_LE2BE (&(pContext->liNextHeader), pContext->header_stream.Size);
342 pContext->liNextHeader += dwDataOffset;
344 pContext->bIsInData = pContext->header_stream.dwStreamId == WIN32_BACKUP_DATA;
345 if (dwDataOffset == dwSize)
348 /* stop and continue with next block */
350 pContext->bIsInData = false;
355 /* set "NextHeader" relative to the beginning of the next block */
356 pContext->liNextHeader-= dwSize;
363 /* ===============================================================
367 * ===============================================================
370 #if defined(HAVE_WIN32)
372 void unix_name_to_win32(POOLMEM **win32_name, char *name);
373 extern "C" HANDLE get_osfhandle(int fd);
376 void binit(BFILE *bfd)
378 memset(bfd, 0, sizeof(BFILE));
380 bfd->mode = BF_CLOSED;
381 bfd->use_backup_api = have_win32_api();
382 bfd->cmd_plugin = false;
386 * Enables using the Backup API (win32_data).
387 * Returns 1 if function worked
388 * Returns 0 if failed (i.e. do not have Backup API on this machine)
390 bool set_win32_backup(BFILE *bfd)
392 /* We enable if possible here */
393 bfd->use_backup_api = have_win32_api();
394 return bfd->use_backup_api;
398 bool set_portable_backup(BFILE *bfd)
400 bfd->use_backup_api = false;
404 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
406 bfd->cmd_plugin = true;
412 * Return 1 if we are NOT using Win32 BackupWrite()
415 bool is_portable_backup(BFILE *bfd)
417 return !bfd->use_backup_api;
420 bool have_win32_api()
422 return p_BackupRead && p_BackupWrite;
427 * Return true if we support the stream
428 * false if we do not support the stream
430 * This code is running under Win32, so we
431 * do not need #ifdef on MACOS ...
433 bool is_restore_stream_supported(int stream)
437 /* Streams known not to be supported */
439 case STREAM_GZIP_DATA:
440 case STREAM_SPARSE_GZIP_DATA:
441 case STREAM_WIN32_GZIP_DATA:
444 case STREAM_COMPRESSED_DATA:
445 case STREAM_SPARSE_COMPRESSED_DATA:
446 case STREAM_WIN32_COMPRESSED_DATA:
447 case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
448 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
450 case STREAM_MACOS_FORK_DATA:
451 case STREAM_HFSPLUS_ATTRIBUTES:
452 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
457 case STREAM_GZIP_DATA:
458 case STREAM_SPARSE_GZIP_DATA:
459 case STREAM_WIN32_GZIP_DATA:
462 case STREAM_COMPRESSED_DATA:
463 case STREAM_SPARSE_COMPRESSED_DATA:
464 case STREAM_WIN32_COMPRESSED_DATA:
466 case STREAM_WIN32_DATA:
467 case STREAM_UNIX_ATTRIBUTES:
468 case STREAM_FILE_DATA:
469 case STREAM_MD5_DIGEST:
470 case STREAM_UNIX_ATTRIBUTES_EX:
471 case STREAM_SPARSE_DATA:
472 case STREAM_PROGRAM_NAMES:
473 case STREAM_PROGRAM_DATA:
474 case STREAM_SHA1_DIGEST:
476 case STREAM_SHA256_DIGEST:
477 case STREAM_SHA512_DIGEST:
480 case STREAM_SIGNED_DIGEST:
481 case STREAM_ENCRYPTED_FILE_DATA:
482 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
483 case STREAM_ENCRYPTED_WIN32_DATA:
484 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
486 case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
487 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
489 #endif /* !HAVE_CRYPTO */
490 case 0: /* compatibility with old tapes */
496 HANDLE bget_handle(BFILE *bfd)
501 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
503 POOLMEM *win32_fname;
504 POOLMEM *win32_fname_wchar;
506 DWORD dwaccess, dwflags, dwshare;
508 /* Convert to Windows path format */
509 win32_fname = get_pool_memory(PM_FNAME);
510 win32_fname_wchar = get_pool_memory(PM_FNAME);
512 unix_name_to_win32(&win32_fname, (char *)fname);
514 if (bfd->cmd_plugin && plugin_bopen) {
516 Dmsg1(50, "call plugin_bopen fname=%s\n", fname);
517 rtnstat = plugin_bopen(bfd, fname, flags, mode);
518 Dmsg1(50, "return from plugin_bopen status=%d\n", rtnstat);
520 if (flags & O_CREAT || flags & O_WRONLY) { /* Open existing for write */
521 Dmsg1(50, "plugin_open for write OK file=%s.\n", fname);
522 bfd->mode = BF_WRITE;
524 Dmsg1(50, "plugin_open for read OK file=%s.\n", fname);
528 bfd->mode = BF_CLOSED;
529 Dmsg1(000, "==== plugin_bopen returned bad status=%d\n", rtnstat);
531 free_pool_memory(win32_fname_wchar);
532 free_pool_memory(win32_fname);
533 return bfd->mode == BF_CLOSED ? -1 : 1;
535 Dmsg0(50, "=== NO plugin\n");
537 if (!(p_CreateFileA || p_CreateFileW)) {
538 Dmsg0(50, "No CreateFileA and no CreateFileW!!!!!\n");
542 if (p_CreateFileW && p_MultiByteToWideChar) {
543 make_win32_path_UTF8_2_wchar(&win32_fname_wchar, fname);
546 if (flags & O_CREAT) { /* Create */
547 if (bfd->use_backup_api) {
548 dwaccess = GENERIC_WRITE|FILE_ALL_ACCESS|WRITE_OWNER|WRITE_DAC|ACCESS_SYSTEM_SECURITY;
549 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
551 dwaccess = GENERIC_WRITE;
555 if (p_CreateFileW && p_MultiByteToWideChar) {
556 // unicode open for create write
557 Dmsg1(100, "Create CreateFileW=%s\n", win32_fname);
558 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
559 dwaccess, /* Requested access */
561 NULL, /* SecurityAttributes */
562 CREATE_ALWAYS, /* CreationDisposition */
563 dwflags, /* Flags and attributes */
564 NULL); /* TemplateFile */
567 Dmsg1(100, "Create CreateFileA=%s\n", win32_fname);
568 bfd->fh = p_CreateFileA(win32_fname,
569 dwaccess, /* Requested access */
571 NULL, /* SecurityAttributes */
572 CREATE_ALWAYS, /* CreationDisposition */
573 dwflags, /* Flags and attributes */
574 NULL); /* TemplateFile */
577 bfd->mode = BF_WRITE;
579 } else if (flags & O_WRONLY) { /* Open existing for write */
580 if (bfd->use_backup_api) {
581 dwaccess = GENERIC_WRITE|WRITE_OWNER|WRITE_DAC;
582 dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT;
584 dwaccess = GENERIC_WRITE;
588 if (p_CreateFileW && p_MultiByteToWideChar) {
589 // unicode open for open existing write
590 Dmsg1(100, "Write only CreateFileW=%s\n", win32_fname);
591 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
592 dwaccess, /* Requested access */
594 NULL, /* SecurityAttributes */
595 OPEN_EXISTING, /* CreationDisposition */
596 dwflags, /* Flags and attributes */
597 NULL); /* TemplateFile */
600 Dmsg1(100, "Write only CreateFileA=%s\n", win32_fname);
601 bfd->fh = p_CreateFileA(win32_fname,
602 dwaccess, /* Requested access */
604 NULL, /* SecurityAttributes */
605 OPEN_EXISTING, /* CreationDisposition */
606 dwflags, /* Flags and attributes */
607 NULL); /* TemplateFile */
611 bfd->mode = BF_WRITE;
614 if (bfd->use_backup_api) {
615 dwaccess = GENERIC_READ|READ_CONTROL|ACCESS_SYSTEM_SECURITY;
616 dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_SEQUENTIAL_SCAN |
617 FILE_FLAG_OPEN_REPARSE_POINT;
618 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
620 dwaccess = GENERIC_READ;
622 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE;
625 if (p_CreateFileW && p_MultiByteToWideChar) {
626 // unicode open for open existing read
627 Dmsg1(100, "Read CreateFileW=%s\n", win32_fname);
628 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
629 dwaccess, /* Requested access */
630 dwshare, /* Share modes */
631 NULL, /* SecurityAttributes */
632 OPEN_EXISTING, /* CreationDisposition */
633 dwflags, /* Flags and attributes */
634 NULL); /* TemplateFile */
637 Dmsg1(100, "Read CreateFileA=%s\n", win32_fname);
638 bfd->fh = p_CreateFileA(win32_fname,
639 dwaccess, /* Requested access */
640 dwshare, /* Share modes */
641 NULL, /* SecurityAttributes */
642 OPEN_EXISTING, /* CreationDisposition */
643 dwflags, /* Flags and attributes */
644 NULL); /* TemplateFile */
650 if (bfd->fh == INVALID_HANDLE_VALUE) {
651 bfd->lerror = GetLastError();
652 bfd->berrno = b_errno_win32;
653 errno = b_errno_win32;
654 bfd->mode = BF_CLOSED;
657 bfd->lpContext = NULL;
658 bfd->win32DecompContext.bIsInData = false;
659 bfd->win32DecompContext.liNextHeader = 0;
660 free_pool_memory(win32_fname_wchar);
661 free_pool_memory(win32_fname);
662 return bfd->mode == BF_CLOSED ? -1 : 1;
666 * Returns 0 on success
669 int bclose(BFILE *bfd)
673 if (bfd->mode == BF_CLOSED) {
674 Dmsg0(50, "=== BFD already closed.\n");
678 if (bfd->cmd_plugin && plugin_bclose) {
679 stat = plugin_bclose(bfd);
680 Dmsg0(50, "==== BFD closed!!!\n");
685 * We need to tell the API to release the buffer it
686 * allocated in lpContext. We do so by calling the
687 * API one more time, but with the Abort bit set.
689 if (bfd->use_backup_api && bfd->mode == BF_READ) {
691 if (bfd->lpContext && !p_BackupRead(bfd->fh,
693 (DWORD)0, /* bytes to read */
694 &bfd->rw_bytes, /* bytes read */
696 1, /* ProcessSecurity */
697 &bfd->lpContext)) { /* Read context */
698 errno = b_errno_win32;
701 } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
703 if (bfd->lpContext && !p_BackupWrite(bfd->fh,
705 (DWORD)0, /* bytes to read */
706 &bfd->rw_bytes, /* bytes written */
708 1, /* ProcessSecurity */
709 &bfd->lpContext)) { /* Write context */
710 errno = b_errno_win32;
714 if (!CloseHandle(bfd->fh)) {
716 errno = b_errno_win32;
721 free_pool_memory(bfd->errmsg);
724 bfd->mode = BF_CLOSED;
725 bfd->lpContext = NULL;
726 bfd->cmd_plugin = false;
730 /* Returns: bytes read on success
734 ssize_t bread(BFILE *bfd, void *buf, size_t count)
738 if (bfd->cmd_plugin && plugin_bread) {
739 return plugin_bread(bfd, buf, count);
742 if (bfd->use_backup_api) {
743 if (!p_BackupRead(bfd->fh,
748 1, /* Process Security */
749 &bfd->lpContext)) { /* Context */
750 bfd->lerror = GetLastError();
751 bfd->berrno = b_errno_win32;
752 errno = b_errno_win32;
756 if (!ReadFile(bfd->fh,
761 bfd->lerror = GetLastError();
762 bfd->berrno = b_errno_win32;
763 errno = b_errno_win32;
768 return (ssize_t)bfd->rw_bytes;
771 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
775 if (bfd->cmd_plugin && plugin_bwrite) {
776 return plugin_bwrite(bfd, buf, count);
779 if (bfd->use_backup_api) {
780 if (!p_BackupWrite(bfd->fh,
785 1, /* Process Security */
786 &bfd->lpContext)) { /* Context */
787 bfd->lerror = GetLastError();
788 bfd->berrno = b_errno_win32;
789 errno = b_errno_win32;
793 if (!WriteFile(bfd->fh,
798 bfd->lerror = GetLastError();
799 bfd->berrno = b_errno_win32;
800 errno = b_errno_win32;
804 return (ssize_t)bfd->rw_bytes;
807 bool is_bopen(BFILE *bfd)
809 return bfd->mode != BF_CLOSED;
812 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
814 LONG offset_low = (LONG)offset;
815 LONG offset_high = (LONG)(offset >> 32);
818 if (bfd->cmd_plugin && plugin_blseek) {
819 return plugin_blseek(bfd, offset, whence);
822 dwResult = SetFilePointer(bfd->fh, offset_low, &offset_high, whence);
824 if (dwResult == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
825 return (boffset_t)-1;
828 return ((boffset_t)offset_high << 32) | dwResult;
831 #else /* Unix systems */
833 /* ===============================================================
837 * ===============================================================
839 void binit(BFILE *bfd)
841 memset(bfd, 0, sizeof(BFILE));
845 bool have_win32_api()
847 return false; /* no can do */
851 * Enables using the Backup API (win32_data).
852 * Returns true if function worked
853 * Returns false if failed (i.e. do not have Backup API on this machine)
855 bool set_win32_backup(BFILE *bfd)
857 return false; /* no can do */
861 bool set_portable_backup(BFILE *bfd)
863 return true; /* no problem */
867 * Return true if we are writing in portable format
868 * return false if not
870 bool is_portable_backup(BFILE *bfd)
872 return true; /* portable by definition */
875 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
880 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
882 bfd->cmd_plugin = true;
888 * This code is running on a non-Win32 machine
890 bool is_restore_stream_supported(int stream)
892 /* No Win32 backup on this machine */
895 case STREAM_GZIP_DATA:
896 case STREAM_SPARSE_GZIP_DATA:
897 case STREAM_WIN32_GZIP_DATA:
900 case STREAM_COMPRESSED_DATA:
901 case STREAM_SPARSE_COMPRESSED_DATA:
902 case STREAM_WIN32_COMPRESSED_DATA:
903 case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
904 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
906 #ifndef HAVE_DARWIN_OS
907 case STREAM_MACOS_FORK_DATA:
908 case STREAM_HFSPLUS_ATTRIBUTES:
914 case STREAM_GZIP_DATA:
915 case STREAM_SPARSE_GZIP_DATA:
916 case STREAM_WIN32_GZIP_DATA:
919 case STREAM_COMPRESSED_DATA:
920 case STREAM_SPARSE_COMPRESSED_DATA:
921 case STREAM_WIN32_COMPRESSED_DATA:
922 case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
923 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
925 case STREAM_WIN32_DATA:
926 case STREAM_UNIX_ATTRIBUTES:
927 case STREAM_FILE_DATA:
928 case STREAM_MD5_DIGEST:
929 case STREAM_UNIX_ATTRIBUTES_EX:
930 case STREAM_SPARSE_DATA:
931 case STREAM_PROGRAM_NAMES:
932 case STREAM_PROGRAM_DATA:
933 case STREAM_SHA1_DIGEST:
935 case STREAM_SHA256_DIGEST:
936 case STREAM_SHA512_DIGEST:
939 case STREAM_SIGNED_DIGEST:
940 case STREAM_ENCRYPTED_FILE_DATA:
941 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
942 case STREAM_ENCRYPTED_WIN32_DATA:
943 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
945 #ifdef HAVE_DARWIN_OS
946 case STREAM_MACOS_FORK_DATA:
947 case STREAM_HFSPLUS_ATTRIBUTES:
949 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
950 #endif /* HAVE_CRYPTO */
951 #endif /* HAVE_DARWIN_OS */
952 case 0: /* compatibility with old tapes */
959 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
961 if (bfd->cmd_plugin && plugin_bopen) {
962 Dmsg1(400, "call plugin_bopen fname=%s\n", fname);
963 bfd->fid = plugin_bopen(bfd, fname, flags, mode);
964 Dmsg1(400, "Plugin bopen stat=%d\n", bfd->fid);
968 /* Normal file open */
969 Dmsg1(dbglvl, "open file %s\n", fname);
971 /* We use fnctl to set O_NOATIME if requested to avoid open error */
972 bfd->fid = open(fname, flags & ~O_NOATIME, mode);
974 /* Set O_NOATIME if possible */
975 if (bfd->fid != -1 && flags & O_NOATIME) {
976 int oldflags = fcntl(bfd->fid, F_GETFL, 0);
977 if (oldflags == -1) {
982 int ret = fcntl(bfd->fid, F_SETFL, oldflags | O_NOATIME);
983 /* EPERM means setting O_NOATIME was not allowed */
984 if (ret == -1 && errno != EPERM) {
992 bfd->m_flags = flags;
993 Dmsg1(400, "Open file %d\n", bfd->fid);
996 bfd->win32DecompContext.bIsInData = false;
997 bfd->win32DecompContext.liNextHeader = 0;
999 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
1000 if (bfd->fid != -1 && flags & O_RDONLY) {
1001 int stat = posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_WILLNEED);
1002 Dmsg2(400, "Did posix_fadvise on %s stat=%d\n", fname, stat);
1009 #ifdef HAVE_DARWIN_OS
1010 /* Open the resource fork of a file. */
1011 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
1013 POOLMEM *rsrc_fname;
1015 rsrc_fname = get_pool_memory(PM_FNAME);
1016 pm_strcpy(rsrc_fname, fname);
1017 pm_strcat(rsrc_fname, _PATH_RSRCFORKSPEC);
1018 bopen(bfd, rsrc_fname, flags, mode);
1019 free_pool_memory(rsrc_fname);
1023 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
1030 int bclose(BFILE *bfd)
1034 Dmsg1(400, "Close file %d\n", bfd->fid);
1036 if (bfd->cmd_plugin && plugin_bclose) {
1037 stat = plugin_bclose(bfd);
1039 bfd->cmd_plugin = false;
1042 if (bfd->fid == -1) {
1045 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
1046 if (bfd->m_flags & O_RDONLY) {
1047 fdatasync(bfd->fid); /* sync the file */
1048 /* Tell OS we don't need it any more */
1049 posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_DONTNEED);
1053 /* Close normal file */
1054 stat = close(bfd->fid);
1055 bfd->berrno = errno;
1057 bfd->cmd_plugin = false;
1061 ssize_t bread(BFILE *bfd, void *buf, size_t count)
1065 if (bfd->cmd_plugin && plugin_bread) {
1066 return plugin_bread(bfd, buf, count);
1069 stat = read(bfd->fid, buf, count);
1070 bfd->berrno = errno;
1074 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
1078 if (bfd->cmd_plugin && plugin_bwrite) {
1079 return plugin_bwrite(bfd, buf, count);
1081 stat = write(bfd->fid, buf, count);
1082 bfd->berrno = errno;
1086 bool is_bopen(BFILE *bfd)
1088 return bfd->fid >= 0;
1091 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
1095 if (bfd->cmd_plugin && plugin_bwrite) {
1096 return plugin_blseek(bfd, offset, whence);
1098 pos = (boffset_t)lseek(bfd->fid, offset, whence);
1099 bfd->berrno = errno;