2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2018 Kern Sibbald
6 The original author of Bacula is Kern Sibbald, with contributions
7 from many others, a complete list can be found in the file AUTHORS.
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
17 Bacula(R) is a registered trademark of Kern Sibbald.
20 * Bacula low level File I/O routines. This routine simulates
21 * open(), read(), write(), and close(), but using native routines.
22 * I.e. on Windows, we use Windows APIs.
24 * Kern Sibbald, April MMIII
31 const int dbglvl = 200;
33 int (*plugin_bopen)(BFILE *bfd, const char *fname, uint64_t flags, mode_t mode) = NULL;
34 int (*plugin_bclose)(BFILE *bfd) = NULL;
35 ssize_t (*plugin_bread)(BFILE *bfd, void *buf, size_t count) = NULL;
36 ssize_t (*plugin_bwrite)(BFILE *bfd, void *buf, size_t count) = NULL;
37 boffset_t (*plugin_blseek)(BFILE *bfd, boffset_t offset, int whence) = NULL;
41 #include <sys/paths.h>
44 #if !defined(HAVE_FDATASYNC)
49 void pause_msg(const char *file, const char *func, int line, const char *msg)
53 bsnprintf(buf, sizeof(buf), "%s:%s:%d %s", file, func, line, msg);
55 bsnprintf(buf, sizeof(buf), "%s:%s:%d", file, func, line);
57 MessageBox(NULL, buf, "Pause", MB_OK);
61 /* ===============================================================
63 * U N I X AND W I N D O W S
65 * ===============================================================
68 bool is_win32_stream(int stream)
71 case STREAM_WIN32_DATA:
72 case STREAM_WIN32_GZIP_DATA:
73 case STREAM_WIN32_COMPRESSED_DATA:
74 case STREAM_ENCRYPTED_WIN32_DATA:
75 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
76 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
82 const char *stream_to_ascii(int stream)
86 switch (stream & STREAMMASK_TYPE) {
87 case STREAM_UNIX_ATTRIBUTES:
88 return _("Unix attributes");
89 case STREAM_FILE_DATA:
90 return _("File data");
91 case STREAM_MD5_DIGEST:
92 return _("MD5 digest");
93 case STREAM_GZIP_DATA:
94 return _("GZIP data");
95 case STREAM_COMPRESSED_DATA:
96 return _("Compressed data");
97 case STREAM_UNIX_ATTRIBUTES_EX:
98 return _("Extended attributes");
99 case STREAM_SPARSE_DATA:
100 return _("Sparse data");
101 case STREAM_SPARSE_GZIP_DATA:
102 return _("GZIP sparse data");
103 case STREAM_SPARSE_COMPRESSED_DATA:
104 return _("Compressed sparse data");
105 case STREAM_PROGRAM_NAMES:
106 return _("Program names");
107 case STREAM_PROGRAM_DATA:
108 return _("Program data");
109 case STREAM_SHA1_DIGEST:
110 return _("SHA1 digest");
111 case STREAM_WIN32_DATA:
112 return _("Win32 data");
113 case STREAM_WIN32_GZIP_DATA:
114 return _("Win32 GZIP data");
115 case STREAM_WIN32_COMPRESSED_DATA:
116 return _("Win32 compressed data");
117 case STREAM_MACOS_FORK_DATA:
118 return _("MacOS Fork data");
119 case STREAM_HFSPLUS_ATTRIBUTES:
120 return _("HFS+ attribs");
121 case STREAM_UNIX_ACCESS_ACL:
122 return _("Standard Unix ACL attribs");
123 case STREAM_UNIX_DEFAULT_ACL:
124 return _("Default Unix ACL attribs");
125 case STREAM_SHA256_DIGEST:
126 return _("SHA256 digest");
127 case STREAM_SHA512_DIGEST:
128 return _("SHA512 digest");
129 case STREAM_SIGNED_DIGEST:
130 return _("Signed digest");
131 case STREAM_ENCRYPTED_FILE_DATA:
132 return _("Encrypted File data");
133 case STREAM_ENCRYPTED_WIN32_DATA:
134 return _("Encrypted Win32 data");
135 case STREAM_ENCRYPTED_SESSION_DATA:
136 return _("Encrypted session data");
137 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
138 return _("Encrypted GZIP data");
139 case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
140 return _("Encrypted compressed data");
141 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
142 return _("Encrypted Win32 GZIP data");
143 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
144 return _("Encrypted Win32 Compressed data");
145 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
146 return _("Encrypted MacOS fork data");
147 case STREAM_PLUGIN_NAME:
148 return _("Plugin Name");
149 case STREAM_PLUGIN_DATA:
150 return _("Plugin Data");
151 case STREAM_RESTORE_OBJECT:
152 return _("Restore Object");
153 case STREAM_XACL_AIX_TEXT:
154 return _("AIX ACL attribs");
155 case STREAM_XACL_DARWIN_ACCESS:
156 return _("Darwin ACL attribs");
157 case STREAM_XACL_FREEBSD_DEFAULT:
158 return _("FreeBSD Default ACL attribs");
159 case STREAM_XACL_FREEBSD_ACCESS:
160 return _("FreeBSD Access ACL attribs");
161 case STREAM_XACL_HPUX_ACL_ENTRY:
162 return _("HPUX ACL attribs");
163 case STREAM_XACL_IRIX_DEFAULT:
164 return _("Irix Default ACL attribs");
165 case STREAM_XACL_IRIX_ACCESS:
166 return _("Irix Access ACL attribs");
167 case STREAM_XACL_LINUX_DEFAULT:
168 return _("Linux Default ACL attribs");
169 case STREAM_XACL_LINUX_ACCESS:
170 return _("Linux Access ACL attribs");
171 case STREAM_XACL_TRU64_DEFAULT:
172 return _("TRU64 Default ACL attribs");
173 case STREAM_XACL_TRU64_ACCESS:
174 return _("TRU64 Access ACL attribs");
175 case STREAM_XACL_SOLARIS_POSIX:
176 return _("Solaris POSIX ACL attribs");
177 case STREAM_XACL_SOLARIS_NFS4:
178 return _("Solaris NFSv4/ZFS ACL attribs");
179 case STREAM_XACL_AFS_TEXT:
180 return _("AFS ACL attribs");
181 case STREAM_XACL_AIX_AIXC:
182 return _("AIX POSIX ACL attribs");
183 case STREAM_XACL_AIX_NFS4:
184 return _("AIX NFSv4 ACL attribs");
185 case STREAM_XACL_FREEBSD_NFS4:
186 return _("FreeBSD NFSv4/ZFS ACL attribs");
187 case STREAM_XACL_HURD_DEFAULT:
188 return _("GNU Hurd Default ACL attribs");
189 case STREAM_XACL_HURD_ACCESS:
190 return _("GNU Hurd Access ACL attribs");
191 case STREAM_XACL_HURD_XATTR:
192 return _("GNU Hurd Extended attribs");
193 case STREAM_XACL_IRIX_XATTR:
194 return _("IRIX Extended attribs");
195 case STREAM_XACL_TRU64_XATTR:
196 return _("TRU64 Extended attribs");
197 case STREAM_XACL_AIX_XATTR:
198 return _("AIX Extended attribs");
199 case STREAM_XACL_OPENBSD_XATTR:
200 return _("OpenBSD Extended attribs");
201 case STREAM_XACL_SOLARIS_SYS_XATTR:
202 return _("Solaris Extensible attribs or System Extended attribs");
203 case STREAM_XACL_SOLARIS_XATTR:
204 return _("Solaris Extended attribs");
205 case STREAM_XACL_DARWIN_XATTR:
206 return _("Darwin Extended attribs");
207 case STREAM_XACL_FREEBSD_XATTR:
208 return _("FreeBSD Extended attribs");
209 case STREAM_XACL_LINUX_XATTR:
210 return _("Linux Extended attribs");
211 case STREAM_XACL_NETBSD_XATTR:
212 return _("NetBSD Extended attribs");
214 sprintf(buf, "%d", stream);
215 return (const char *)buf;
220 * Convert a 64 bit little endian to a big endian
222 void int64_LE2BE(int64_t* pBE, const int64_t v)
224 /* convert little endian to big endian */
225 if (htonl(1) != 1L) { /* no work if on little endian machine */
226 memcpy(pBE, &v, sizeof(int64_t));
229 uint8_t rv[sizeof(int64_t)];
230 uint8_t *pv = (uint8_t *) &v;
232 for (i = 0; i < 8; i++) {
235 memcpy(pBE, &rv, sizeof(int64_t));
240 * Convert a 32 bit little endian to a big endian
242 void int32_LE2BE(int32_t* pBE, const int32_t v)
244 /* convert little endian to big endian */
245 if (htonl(1) != 1L) { /* no work if on little endian machine */
246 memcpy(pBE, &v, sizeof(int32_t));
249 uint8_t rv[sizeof(int32_t)];
250 uint8_t *pv = (uint8_t *) &v;
252 for (i = 0; i < 4; i++) {
255 memcpy(pBE, &rv, sizeof(int32_t));
261 * Read a BackupRead block and pull out the file data
263 bool processWin32BackupAPIBlock (BFILE *bfd, void *pBuffer, ssize_t dwSize)
265 int64_t len = dwSize;
266 char *dat=(char *)pBuffer;
269 while (len>0 && bfd->win32filter.have_data(&dat, &len, &use_len)) {
270 if (bwrite(bfd, dat, use_len) != (ssize_t)use_len) {
278 /* ===============================================================
282 * ===============================================================
285 #if defined(HAVE_WIN32)
287 void unix_name_to_win32(POOLMEM **win32_name, const char *name);
288 extern "C" HANDLE get_osfhandle(int fd);
291 void binit(BFILE *bfd)
293 memset(bfd, 0, sizeof(BFILE));
295 bfd->mode = BF_CLOSED;
296 bfd->use_backup_api = have_win32_api();
297 bfd->cmd_plugin = false;
301 * Enables using the Backup API (win32_data).
302 * Returns 1 if function worked
303 * Returns 0 if failed (i.e. do not have Backup API on this machine)
305 bool set_win32_backup(BFILE *bfd)
307 /* We enable if possible here */
308 bfd->use_backup_api = have_win32_api();
309 return bfd->use_backup_api;
312 void set_fattrs(BFILE *bfd, struct stat *statp)
314 bfd->fattrs = statp->st_fattrs;
315 Dmsg1(200, "set_fattrs 0x%x\n", bfd->fattrs);
318 bool set_portable_backup(BFILE *bfd)
320 bfd->use_backup_api = false;
324 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
326 bfd->cmd_plugin = true;
332 * Return 1 if we are NOT using Win32 BackupWrite()
335 bool is_portable_backup(BFILE *bfd)
337 return !bfd->use_backup_api;
340 bool have_win32_api()
342 return p_BackupRead && p_BackupWrite;
347 * Return true if we support the stream
348 * false if we do not support the stream
350 * This code is running under Win32, so we
351 * do not need #ifdef on MACOS ...
353 bool is_restore_stream_supported(int stream)
357 /* Streams known not to be supported */
359 case STREAM_GZIP_DATA:
360 case STREAM_SPARSE_GZIP_DATA:
361 case STREAM_WIN32_GZIP_DATA:
364 case STREAM_COMPRESSED_DATA:
365 case STREAM_SPARSE_COMPRESSED_DATA:
366 case STREAM_WIN32_COMPRESSED_DATA:
367 case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
368 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
370 case STREAM_MACOS_FORK_DATA:
371 case STREAM_HFSPLUS_ATTRIBUTES:
372 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
377 case STREAM_GZIP_DATA:
378 case STREAM_SPARSE_GZIP_DATA:
379 case STREAM_WIN32_GZIP_DATA:
382 case STREAM_COMPRESSED_DATA:
383 case STREAM_SPARSE_COMPRESSED_DATA:
384 case STREAM_WIN32_COMPRESSED_DATA:
386 case STREAM_WIN32_DATA:
387 case STREAM_UNIX_ATTRIBUTES:
388 case STREAM_FILE_DATA:
389 case STREAM_MD5_DIGEST:
390 case STREAM_UNIX_ATTRIBUTES_EX:
391 case STREAM_SPARSE_DATA:
392 case STREAM_PROGRAM_NAMES:
393 case STREAM_PROGRAM_DATA:
394 case STREAM_SHA1_DIGEST:
396 case STREAM_SHA256_DIGEST:
397 case STREAM_SHA512_DIGEST:
400 case STREAM_SIGNED_DIGEST:
401 case STREAM_ENCRYPTED_FILE_DATA:
402 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
403 case STREAM_ENCRYPTED_WIN32_DATA:
404 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
406 case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
407 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
409 #endif /* !HAVE_CRYPTO */
410 case 0: /* compatibility with old tapes */
416 HANDLE bget_handle(BFILE *bfd)
422 * The following code was contributed by Graham Keeling from his
423 * burp project. August 2014
425 static int encrypt_bopen(BFILE *bfd, const char *fname, uint64_t flags, mode_t mode)
428 POOLMEM *win32_fname;
429 POOLMEM *win32_fname_wchar;
431 bfd->mode = BF_CLOSED;
434 if (!(p_OpenEncryptedFileRawA || p_OpenEncryptedFileRawW)) {
435 Dmsg0(50, "No OpenEncryptedFileRawA and no OpenEncryptedFileRawW APIs!!!\n");
439 /* Convert to Windows path format */
440 win32_fname = get_pool_memory(PM_FNAME);
441 win32_fname_wchar = get_pool_memory(PM_FNAME);
443 unix_name_to_win32(&win32_fname, (char *)fname);
445 if (p_CreateFileW && p_MultiByteToWideChar) {
446 make_win32_path_UTF8_2_wchar(&win32_fname_wchar, fname);
449 if ((flags & O_CREAT) || (flags & O_WRONLY)) {
450 ulFlags = CREATE_FOR_IMPORT | OVERWRITE_HIDDEN;
451 if (bfd->fattrs & FILE_ATTRIBUTE_DIRECTORY) {
453 ulFlags |= CREATE_FOR_DIR;
455 bfd->mode = BF_WRITE;
456 Dmsg0(200, "encrypt_bopen for write.\n");
458 /* Open existing for read */
459 ulFlags = CREATE_FOR_EXPORT;
461 Dmsg0(200, "encrypt_bopen for read.\n");
464 if (p_OpenEncryptedFileRawW && p_MultiByteToWideChar) {
466 if (p_OpenEncryptedFileRawW((LPCWSTR)win32_fname_wchar,
467 ulFlags, &(bfd->pvContext))) {
468 bfd->mode = BF_CLOSED;
469 errno = b_errno_win32;
470 bfd->berrno = b_errno_win32;
474 if (p_OpenEncryptedFileRawA(win32_fname, ulFlags, &(bfd->pvContext))) {
475 bfd->mode = BF_CLOSED;
476 errno = b_errno_win32;
477 bfd->berrno = b_errno_win32;
480 free_pool_memory(win32_fname_wchar);
481 free_pool_memory(win32_fname);
482 bfd->fid = (bfd->mode == BF_CLOSED) ? -1 : 0;
483 return bfd->mode==BF_CLOSED ? -1: 1;
486 static int encrypt_bclose(BFILE *bfd)
488 Dmsg0(200, "encrypt_bclose\n");
489 if (p_CloseEncryptedFileRaw) {
490 p_CloseEncryptedFileRaw(bfd->pvContext);
492 bfd->pvContext = NULL;
493 bfd->mode = BF_CLOSED;
500 int bopen(BFILE *bfd, const char *fname, uint64_t flags, mode_t mode)
502 POOLMEM *win32_fname;
503 POOLMEM *win32_fname_wchar;
505 DWORD dwaccess, dwflags, dwshare;
507 if (bfd->fattrs & FILE_ATTRIBUTE_ENCRYPTED) {
508 return encrypt_bopen(bfd, fname, flags, mode);
511 /* Convert to Windows path format */
512 win32_fname = get_pool_memory(PM_FNAME);
513 win32_fname_wchar = get_pool_memory(PM_FNAME);
515 unix_name_to_win32(&win32_fname, (char *)fname);
517 if (bfd->cmd_plugin && plugin_bopen) {
519 Dmsg1(50, "call plugin_bopen fname=%s\n", fname);
520 rtnstat = plugin_bopen(bfd, fname, flags, mode);
521 Dmsg1(50, "return from plugin_bopen status=%d\n", rtnstat);
523 if (flags & O_CREAT || flags & O_WRONLY) { /* Open existing for write */
524 Dmsg1(50, "plugin_open for write OK file=%s.\n", fname);
525 bfd->mode = BF_WRITE;
527 Dmsg1(50, "plugin_open for read OK file=%s.\n", fname);
530 bfd->fid = -1; /* The file descriptor is invalid */
532 bfd->mode = BF_CLOSED;
534 Dmsg1(000, "==== plugin_bopen returned bad status=%d\n", rtnstat);
536 free_pool_memory(win32_fname_wchar);
537 free_pool_memory(win32_fname);
538 return bfd->mode == BF_CLOSED ? -1 : 1;
540 Dmsg0(100, "=== NO plugin\n");
542 if (!(p_CreateFileA || p_CreateFileW)) {
543 Dmsg0(50, "No CreateFileA and no CreateFileW!!!!!\n");
547 if (p_CreateFileW && p_MultiByteToWideChar) {
548 make_win32_path_UTF8_2_wchar(&win32_fname_wchar, fname);
551 if (flags & O_CREAT) { /* Create */
552 if (bfd->use_backup_api) {
553 dwaccess = GENERIC_WRITE|FILE_ALL_ACCESS|WRITE_OWNER|WRITE_DAC|ACCESS_SYSTEM_SECURITY;
554 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
556 dwaccess = GENERIC_WRITE;
560 if (p_CreateFileW && p_MultiByteToWideChar) {
561 // unicode open for create write
562 Dmsg1(100, "Create CreateFileW=%ls\n", win32_fname_wchar);
563 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
564 dwaccess, /* Requested access */
566 NULL, /* SecurityAttributes */
567 CREATE_ALWAYS, /* CreationDisposition */
568 dwflags, /* Flags and attributes */
569 NULL); /* TemplateFile */
572 Dmsg1(100, "Create CreateFileA=%s\n", win32_fname);
573 bfd->fh = p_CreateFileA(win32_fname,
574 dwaccess, /* Requested access */
576 NULL, /* SecurityAttributes */
577 CREATE_ALWAYS, /* CreationDisposition */
578 dwflags, /* Flags and attributes */
579 NULL); /* TemplateFile */
582 bfd->mode = BF_WRITE;
584 } else if (flags & O_WRONLY) { /* Open existing for write */
585 if (bfd->use_backup_api) {
586 dwaccess = GENERIC_READ|GENERIC_WRITE|WRITE_OWNER|WRITE_DAC;
587 /* If deduped we do not want to open the reparse point */
588 if (bfd->fattrs & FILE_ATTRIBUTE_DEDUP) {
589 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
591 dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT;
594 dwaccess = GENERIC_READ|GENERIC_WRITE;
598 if (p_CreateFileW && p_MultiByteToWideChar) {
599 // unicode open for open existing write
600 Dmsg1(100, "Write only CreateFileW=%s\n", win32_fname);
601 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
602 dwaccess, /* Requested access */
604 NULL, /* SecurityAttributes */
605 OPEN_EXISTING, /* CreationDisposition */
606 dwflags, /* Flags and attributes */
607 NULL); /* TemplateFile */
610 Dmsg1(100, "Write only CreateFileA=%s\n", win32_fname);
611 bfd->fh = p_CreateFileA(win32_fname,
612 dwaccess, /* Requested access */
614 NULL, /* SecurityAttributes */
615 OPEN_EXISTING, /* CreationDisposition */
616 dwflags, /* Flags and attributes */
617 NULL); /* TemplateFile */
621 bfd->mode = BF_WRITE;
624 if (bfd->use_backup_api) {
625 dwaccess = GENERIC_READ|READ_CONTROL|ACCESS_SYSTEM_SECURITY;
626 dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_SEQUENTIAL_SCAN |
627 FILE_FLAG_OPEN_REPARSE_POINT;
628 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
630 dwaccess = GENERIC_READ;
632 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE;
635 if (p_CreateFileW && p_MultiByteToWideChar) {
636 // unicode open for open existing read
637 Dmsg1(100, "Read CreateFileW=%ls\n", win32_fname_wchar);
638 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
639 dwaccess, /* Requested access */
640 dwshare, /* Share modes */
641 NULL, /* SecurityAttributes */
642 OPEN_EXISTING, /* CreationDisposition */
643 dwflags, /* Flags and attributes */
644 NULL); /* TemplateFile */
647 Dmsg1(100, "Read CreateFileA=%s\n", win32_fname);
648 bfd->fh = p_CreateFileA(win32_fname,
649 dwaccess, /* Requested access */
650 dwshare, /* Share modes */
651 NULL, /* SecurityAttributes */
652 OPEN_EXISTING, /* CreationDisposition */
653 dwflags, /* Flags and attributes */
654 NULL); /* TemplateFile */
660 if (bfd->fh == INVALID_HANDLE_VALUE) {
662 bfd->lerror = GetLastError();
663 bfd->berrno = b_errno_win32;
664 errno = b_errno_win32;
665 bfd->mode = BF_CLOSED;
666 Dmsg1(100, "Open failed: %s\n", be.bstrerror());
669 bfd->total_bytes = 0;
671 bfd->lpContext = NULL;
672 bfd->win32filter.init();
673 free_pool_memory(win32_fname_wchar);
674 free_pool_memory(win32_fname);
675 bfd->fid = (bfd->mode == BF_CLOSED) ? -1 : 0;
676 return bfd->mode == BF_CLOSED ? -1 : 1;
680 * Returns 0 on success
684 int bclose(BFILE *bfd)
688 if (bfd->mode == BF_CLOSED) {
689 Dmsg0(50, "=== BFD already closed.\n");
693 if (bfd->cmd_plugin && plugin_bclose) {
694 stat = plugin_bclose(bfd);
695 Dmsg0(50, "==== BFD closed!!!\n");
699 if (bfd->fattrs & FILE_ATTRIBUTE_ENCRYPTED) {
700 return encrypt_bclose(bfd);
704 * We need to tell the API to release the buffer it
705 * allocated in lpContext. We do so by calling the
706 * API one more time, but with the Abort bit set.
708 if (bfd->use_backup_api && bfd->mode == BF_READ) {
710 if (bfd->lpContext && !p_BackupRead(bfd->fh,
712 (DWORD)0, /* bytes to read */
713 &bfd->rw_bytes, /* bytes read */
715 1, /* ProcessSecurity */
716 &bfd->lpContext)) { /* Read context */
717 errno = b_errno_win32;
720 } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
722 if (bfd->lpContext && !p_BackupWrite(bfd->fh,
724 (DWORD)0, /* bytes to read */
725 &bfd->rw_bytes, /* bytes written */
727 1, /* ProcessSecurity */
728 &bfd->lpContext)) { /* Write context */
729 errno = b_errno_win32;
733 if (!CloseHandle(bfd->fh)) {
735 errno = b_errno_win32;
740 free_pool_memory(bfd->errmsg);
743 bfd->mode = BF_CLOSED;
746 bfd->lpContext = NULL;
747 bfd->cmd_plugin = false;
751 /* Returns: bytes read on success
756 ssize_t bread(BFILE *bfd, void *buf, size_t count)
760 if (bfd->cmd_plugin && plugin_bread) {
761 return plugin_bread(bfd, buf, count);
764 if (bfd->use_backup_api) {
765 if (!p_BackupRead(bfd->fh,
770 1, /* Process Security */
771 &bfd->lpContext)) { /* Context */
773 bfd->lerror = GetLastError();
774 bfd->berrno = b_errno_win32;
775 errno = b_errno_win32;
776 Dmsg1(100, "Read failed: %s\n", be.bstrerror());
780 if (!ReadFile(bfd->fh,
785 bfd->lerror = GetLastError();
786 bfd->berrno = b_errno_win32;
787 errno = b_errno_win32;
792 if (bfd->rw_bytes > 0) {
793 bfd->total_bytes += bfd->rw_bytes;
795 return (ssize_t)bfd->rw_bytes;
799 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
803 if (bfd->cmd_plugin && plugin_bwrite) {
804 return plugin_bwrite(bfd, buf, count);
807 if (bfd->use_backup_api) {
808 if (!p_BackupWrite(bfd->fh,
813 1, /* Process Security */
814 &bfd->lpContext)) { /* Context */
816 bfd->lerror = GetLastError();
817 bfd->berrno = b_errno_win32;
818 errno = b_errno_win32;
819 Dmsg1(100, "Write failed: %s\n", be.bstrerror());
823 if (!WriteFile(bfd->fh,
828 bfd->lerror = GetLastError();
829 bfd->berrno = b_errno_win32;
830 errno = b_errno_win32;
835 if (bfd->rw_bytes > 0) {
836 bfd->total_bytes += bfd->rw_bytes;
838 return (ssize_t)bfd->rw_bytes;
842 bool is_bopen(BFILE *bfd)
844 return bfd->mode != BF_CLOSED;
848 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
850 LONG offset_low = (LONG)offset;
851 LONG offset_high = (LONG)(offset >> 32);
854 if (bfd->cmd_plugin && plugin_blseek) {
855 return plugin_blseek(bfd, offset, whence);
858 dwResult = SetFilePointer(bfd->fh, offset_low, &offset_high, whence);
860 if (dwResult == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
861 return (boffset_t)-1;
864 return ((boffset_t)offset_high << 32) | dwResult;
867 #else /* Unix systems */
869 /* ===============================================================
873 * ===============================================================
876 void binit(BFILE *bfd)
878 memset(bfd, 0, sizeof(BFILE));
883 bool have_win32_api()
885 return false; /* no can do */
889 * Enables using the Backup API (win32_data).
890 * Returns true if function worked
891 * Returns false if failed (i.e. do not have Backup API on this machine)
894 bool set_win32_backup(BFILE *bfd)
896 return false; /* no can do */
901 bool set_portable_backup(BFILE *bfd)
903 return true; /* no problem */
907 * Return true if we are writing in portable format
908 * return false if not
911 bool is_portable_backup(BFILE *bfd)
913 return true; /* portable by definition */
917 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
923 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
925 bfd->cmd_plugin = true;
931 * This code is running on a non-Win32 machine
934 bool is_restore_stream_supported(int stream)
936 /* No Win32 backup on this machine */
939 case STREAM_GZIP_DATA:
940 case STREAM_SPARSE_GZIP_DATA:
941 case STREAM_WIN32_GZIP_DATA:
944 case STREAM_COMPRESSED_DATA:
945 case STREAM_SPARSE_COMPRESSED_DATA:
946 case STREAM_WIN32_COMPRESSED_DATA:
947 case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
948 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
950 #ifndef HAVE_DARWIN_OS
951 case STREAM_MACOS_FORK_DATA:
952 case STREAM_HFSPLUS_ATTRIBUTES:
958 case STREAM_GZIP_DATA:
959 case STREAM_SPARSE_GZIP_DATA:
960 case STREAM_WIN32_GZIP_DATA:
963 case STREAM_COMPRESSED_DATA:
964 case STREAM_SPARSE_COMPRESSED_DATA:
965 case STREAM_WIN32_COMPRESSED_DATA:
966 case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
967 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
969 case STREAM_WIN32_DATA:
970 case STREAM_UNIX_ATTRIBUTES:
971 case STREAM_FILE_DATA:
972 case STREAM_MD5_DIGEST:
973 case STREAM_UNIX_ATTRIBUTES_EX:
974 case STREAM_SPARSE_DATA:
975 case STREAM_PROGRAM_NAMES:
976 case STREAM_PROGRAM_DATA:
977 case STREAM_SHA1_DIGEST:
979 case STREAM_SHA256_DIGEST:
980 case STREAM_SHA512_DIGEST:
983 case STREAM_SIGNED_DIGEST:
984 case STREAM_ENCRYPTED_FILE_DATA:
985 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
986 case STREAM_ENCRYPTED_WIN32_DATA:
987 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
989 #ifdef HAVE_DARWIN_OS
990 case STREAM_MACOS_FORK_DATA:
991 case STREAM_HFSPLUS_ATTRIBUTES:
993 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
994 #endif /* HAVE_CRYPTO */
995 #endif /* HAVE_DARWIN_OS */
996 case 0: /* compatibility with old tapes */
1004 int bopen(BFILE *bfd, const char *fname, uint64_t flags, mode_t mode)
1006 if (bfd->cmd_plugin && plugin_bopen) {
1007 Dmsg1(400, "call plugin_bopen fname=%s\n", fname);
1008 bfd->fid = plugin_bopen(bfd, fname, flags, mode);
1009 Dmsg2(400, "Plugin bopen fid=%d file=%s\n", bfd->fid, fname);
1013 /* Normal file open */
1014 Dmsg1(dbglvl, "open file %s\n", fname);
1016 /* We use fnctl to set O_NOATIME if requested to avoid open error */
1017 bfd->fid = open(fname, flags & ~O_NOATIME, mode);
1019 /* Set O_NOATIME if possible */
1020 if (bfd->fid != -1 && flags & O_NOATIME) {
1021 int oldflags = fcntl(bfd->fid, F_GETFL, 0);
1022 if (oldflags == -1) {
1023 bfd->berrno = errno;
1027 int ret = fcntl(bfd->fid, F_SETFL, oldflags | O_NOATIME);
1028 /* EPERM means setting O_NOATIME was not allowed */
1029 if (ret == -1 && errno != EPERM) {
1030 bfd->berrno = errno;
1036 bfd->berrno = errno;
1037 bfd->m_flags = flags;
1039 bfd->total_bytes = 0;
1040 Dmsg1(400, "Open file %d\n", bfd->fid);
1041 errno = bfd->berrno;
1043 bfd->win32filter.init();
1045 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
1046 /* If not RDWR or WRONLY must be Read Only */
1047 if (bfd->fid != -1 && !(flags & (O_RDWR|O_WRONLY))) {
1048 int stat = posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_WILLNEED);
1049 Dmsg3(400, "Did posix_fadvise WILLNEED on %s fid=%d stat=%d\n", fname, bfd->fid, stat);
1056 #ifdef HAVE_DARWIN_OS
1057 /* Open the resource fork of a file. */
1058 int bopen_rsrc(BFILE *bfd, const char *fname, uint64_t flags, mode_t mode)
1060 POOLMEM *rsrc_fname;
1062 rsrc_fname = get_pool_memory(PM_FNAME);
1063 pm_strcpy(rsrc_fname, fname);
1064 pm_strcat(rsrc_fname, _PATH_RSRCFORKSPEC);
1065 bopen(bfd, rsrc_fname, flags, mode);
1066 free_pool_memory(rsrc_fname);
1072 int bopen_rsrc(BFILE *bfd, const char *fname, uint64_t flags, mode_t mode)
1079 int bclose(BFILE *bfd)
1083 Dmsg2(400, "Close bfd=%p file %d\n", bfd, bfd->fid);
1085 if (bfd->fid == -1) {
1088 if (bfd->cmd_plugin && plugin_bclose) {
1089 stat = plugin_bclose(bfd);
1091 bfd->cmd_plugin = false;
1094 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
1095 /* If not RDWR or WRONLY must be Read Only */
1096 if (!(bfd->m_flags & (O_RDWR|O_WRONLY))) {
1097 fdatasync(bfd->fid); /* sync the file */
1098 /* Tell OS we don't need it any more */
1099 posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_DONTNEED);
1100 Dmsg1(400, "Did posix_fadvise DONTNEED on fid=%d\n", bfd->fid);
1104 /* Close normal file */
1105 stat = close(bfd->fid);
1106 bfd->berrno = errno;
1108 bfd->cmd_plugin = false;
1113 ssize_t bread(BFILE *bfd, void *buf, size_t count)
1117 if (bfd->cmd_plugin && plugin_bread) {
1118 return plugin_bread(bfd, buf, count);
1121 stat = read(bfd->fid, buf, count);
1122 bfd->berrno = errno;
1125 bfd->total_bytes += stat;
1131 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
1135 if (bfd->cmd_plugin && plugin_bwrite) {
1136 return plugin_bwrite(bfd, buf, count);
1138 stat = write(bfd->fid, buf, count);
1139 bfd->berrno = errno;
1142 bfd->total_bytes += stat;
1148 bool is_bopen(BFILE *bfd)
1150 return bfd->fid >= 0;
1154 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
1158 if (bfd->cmd_plugin && plugin_bwrite) {
1159 return plugin_blseek(bfd, offset, whence);
1161 pos = (boffset_t)lseek(bfd->fid, offset, whence);
1162 bfd->berrno = errno;