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 _("OSF1 Specific Default ACL attribs");
164 case STREAM_ACL_TRU64_ACCESS_ACL:
165 return _("OSF1 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_AIX:
177 return _("AIX Specific Extended attribs");
178 case STREAM_XATTR_OPENBSD:
179 return _("OpenBSD Specific Extended attribs");
180 case STREAM_XATTR_SOLARIS_SYS:
181 return _("Solaris Specific Extensible attribs or System Extended attribs");
182 case STREAM_XATTR_SOLARIS:
183 return _("Solaris Specific Extended attribs");
184 case STREAM_XATTR_DARWIN:
185 return _("Darwin Specific Extended attribs");
186 case STREAM_XATTR_FREEBSD:
187 return _("FreeBSD Specific Extended attribs");
188 case STREAM_XATTR_LINUX:
189 return _("Linux Specific Extended attribs");
190 case STREAM_XATTR_NETBSD:
191 return _("NetBSD Specific Extended attribs");
193 sprintf(buf, "%d", stream);
194 return (const char *)buf;
199 * Convert a 64 bit little endian to a big endian
201 void int64_LE2BE(int64_t* pBE, const int64_t v)
203 /* convert little endian to big endian */
204 if (htonl(1) != 1L) { /* no work if on little endian machine */
205 memcpy(pBE, &v, sizeof(int64_t));
208 uint8_t rv[sizeof(int64_t)];
209 uint8_t *pv = (uint8_t *) &v;
211 for (i = 0; i < 8; i++) {
214 memcpy(pBE, &rv, sizeof(int64_t));
219 * Convert a 32 bit little endian to a big endian
221 void int32_LE2BE(int32_t* pBE, const int32_t v)
223 /* convert little endian to big endian */
224 if (htonl(1) != 1L) { /* no work if on little endian machine */
225 memcpy(pBE, &v, sizeof(int32_t));
228 uint8_t rv[sizeof(int32_t)];
229 uint8_t *pv = (uint8_t *) &v;
231 for (i = 0; i < 4; i++) {
234 memcpy(pBE, &rv, sizeof(int32_t));
240 * Read a BackupRead block and pull out the file data
242 bool processWin32BackupAPIBlock (BFILE *bfd, void *pBuffer, ssize_t dwSize)
244 /* pByte contains the buffer
245 dwSize the len to be processed. function assumes to be
246 called in successive incremental order over the complete
247 BackupRead stream beginning at pos 0 and ending at the end.
250 PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT* pContext = &(bfd->win32DecompContext);
251 bool bContinue = false;
252 int64_t dwDataOffset = 0;
255 /* Win32 Stream Header size without name of stream.
256 * = sizeof (WIN32_STREAM_ID)- sizeof(WCHAR*);
258 int32_t dwSizeHeader = 20;
261 if (pContext->liNextHeader >= dwSize) {
262 dwDataLen = dwSize-dwDataOffset;
263 bContinue = false; /* 1 iteration is enough */
265 dwDataLen = pContext->liNextHeader-dwDataOffset;
266 bContinue = true; /* multiple iterations may be necessary */
270 /* copy block of real DATA */
271 if (pContext->bIsInData) {
272 if (bwrite(bfd, ((char *)pBuffer)+dwDataOffset, dwDataLen) != (ssize_t)dwDataLen)
276 if (pContext->liNextHeader < dwSize) {/* is a header in this block ? */
277 int32_t dwOffsetTarget;
278 int32_t dwOffsetSource;
280 if (pContext->liNextHeader < 0) {
281 /* start of header was before this block, so we
282 * continue with the part in the current block
284 dwOffsetTarget = -pContext->liNextHeader;
287 /* start of header is inside of this block */
289 dwOffsetSource = pContext->liNextHeader;
292 int32_t dwHeaderPartLen = dwSizeHeader-dwOffsetTarget;
293 bool bHeaderIsComplete;
295 if (dwHeaderPartLen <= dwSize-dwOffsetSource) {
296 /* header (or rest of header) is completely available
299 bHeaderIsComplete = true;
301 /* header will continue in next block */
302 bHeaderIsComplete = false;
303 dwHeaderPartLen = dwSize-dwOffsetSource;
306 /* copy the available portion of header to persistent copy */
307 memcpy(((char *)&pContext->header_stream)+dwOffsetTarget, ((char *)pBuffer)+dwOffsetSource, dwHeaderPartLen);
309 /* recalculate position of next header */
310 if (bHeaderIsComplete) {
311 /* convert stream name size (32 bit little endian) to machine type */
313 int32_LE2BE (&dwNameSize, pContext->header_stream.dwStreamNameSize);
314 dwDataOffset = dwNameSize+pContext->liNextHeader+dwSizeHeader;
316 /* convert stream size (64 bit little endian) to machine type */
317 int64_LE2BE (&(pContext->liNextHeader), pContext->header_stream.Size);
318 pContext->liNextHeader += dwDataOffset;
320 pContext->bIsInData = pContext->header_stream.dwStreamId == WIN32_BACKUP_DATA;
321 if (dwDataOffset == dwSize)
324 /* stop and continue with next block */
326 pContext->bIsInData = false;
331 /* set "NextHeader" relative to the beginning of the next block */
332 pContext->liNextHeader-= dwSize;
339 /* ===============================================================
343 * ===============================================================
346 #if defined(HAVE_WIN32)
348 void unix_name_to_win32(POOLMEM **win32_name, char *name);
349 extern "C" HANDLE get_osfhandle(int fd);
352 void binit(BFILE *bfd)
354 memset(bfd, 0, sizeof(BFILE));
356 bfd->mode = BF_CLOSED;
357 bfd->use_backup_api = have_win32_api();
358 bfd->cmd_plugin = false;
362 * Enables using the Backup API (win32_data).
363 * Returns 1 if function worked
364 * Returns 0 if failed (i.e. do not have Backup API on this machine)
366 bool set_win32_backup(BFILE *bfd)
368 /* We enable if possible here */
369 bfd->use_backup_api = have_win32_api();
370 return bfd->use_backup_api;
374 bool set_portable_backup(BFILE *bfd)
376 bfd->use_backup_api = false;
380 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
382 bfd->cmd_plugin = true;
388 * Return 1 if we are NOT using Win32 BackupWrite()
391 bool is_portable_backup(BFILE *bfd)
393 return !bfd->use_backup_api;
396 bool have_win32_api()
398 return p_BackupRead && p_BackupWrite;
403 * Return true if we support the stream
404 * false if we do not support the stream
406 * This code is running under Win32, so we
407 * do not need #ifdef on MACOS ...
409 bool is_restore_stream_supported(int stream)
413 /* Streams known not to be supported */
415 case STREAM_GZIP_DATA:
416 case STREAM_SPARSE_GZIP_DATA:
417 case STREAM_WIN32_GZIP_DATA:
419 case STREAM_MACOS_FORK_DATA:
420 case STREAM_HFSPLUS_ATTRIBUTES:
421 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
426 case STREAM_GZIP_DATA:
427 case STREAM_SPARSE_GZIP_DATA:
428 case STREAM_WIN32_GZIP_DATA:
430 case STREAM_WIN32_DATA:
431 case STREAM_UNIX_ATTRIBUTES:
432 case STREAM_FILE_DATA:
433 case STREAM_MD5_DIGEST:
434 case STREAM_UNIX_ATTRIBUTES_EX:
435 case STREAM_SPARSE_DATA:
436 case STREAM_PROGRAM_NAMES:
437 case STREAM_PROGRAM_DATA:
438 case STREAM_SHA1_DIGEST:
440 case STREAM_SHA256_DIGEST:
441 case STREAM_SHA512_DIGEST:
444 case STREAM_SIGNED_DIGEST:
445 case STREAM_ENCRYPTED_FILE_DATA:
446 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
447 case STREAM_ENCRYPTED_WIN32_DATA:
448 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
450 case 0: /* compatibility with old tapes */
456 HANDLE bget_handle(BFILE *bfd)
461 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
463 POOLMEM *win32_fname;
464 POOLMEM *win32_fname_wchar;
466 DWORD dwaccess, dwflags, dwshare;
468 /* Convert to Windows path format */
469 win32_fname = get_pool_memory(PM_FNAME);
470 win32_fname_wchar = get_pool_memory(PM_FNAME);
472 unix_name_to_win32(&win32_fname, (char *)fname);
474 if (bfd->cmd_plugin && plugin_bopen) {
476 Dmsg1(50, "call plugin_bopen fname=%s\n", fname);
477 rtnstat = plugin_bopen(bfd, fname, flags, mode);
478 Dmsg1(50, "return from plugin_bopen status=%d\n", rtnstat);
480 if (flags & O_CREAT || flags & O_WRONLY) { /* Open existing for write */
481 Dmsg1(50, "plugin_open for write OK file=%s.\n", fname);
482 bfd->mode = BF_WRITE;
484 Dmsg1(50, "plugin_open for read OK file=%s.\n", fname);
488 bfd->mode = BF_CLOSED;
489 Dmsg1(000, "==== plugin_bopen returned bad status=%d\n", rtnstat);
491 free_pool_memory(win32_fname_wchar);
492 free_pool_memory(win32_fname);
493 return bfd->mode == BF_CLOSED ? -1 : 1;
495 Dmsg0(50, "=== NO plugin\n");
497 if (!(p_CreateFileA || p_CreateFileW)) {
498 Dmsg0(50, "No CreateFileA and no CreateFileW!!!!!\n");
502 if (p_CreateFileW && p_MultiByteToWideChar) {
503 make_win32_path_UTF8_2_wchar(&win32_fname_wchar, fname);
506 if (flags & O_CREAT) { /* Create */
507 if (bfd->use_backup_api) {
508 dwaccess = GENERIC_WRITE|FILE_ALL_ACCESS|WRITE_OWNER|WRITE_DAC|ACCESS_SYSTEM_SECURITY;
509 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
511 dwaccess = GENERIC_WRITE;
515 if (p_CreateFileW && p_MultiByteToWideChar) {
516 // unicode open for create write
517 Dmsg1(100, "Create CreateFileW=%s\n", win32_fname);
518 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
519 dwaccess, /* Requested access */
521 NULL, /* SecurityAttributes */
522 CREATE_ALWAYS, /* CreationDisposition */
523 dwflags, /* Flags and attributes */
524 NULL); /* TemplateFile */
527 Dmsg1(100, "Create CreateFileA=%s\n", win32_fname);
528 bfd->fh = p_CreateFileA(win32_fname,
529 dwaccess, /* Requested access */
531 NULL, /* SecurityAttributes */
532 CREATE_ALWAYS, /* CreationDisposition */
533 dwflags, /* Flags and attributes */
534 NULL); /* TemplateFile */
537 bfd->mode = BF_WRITE;
539 } else if (flags & O_WRONLY) { /* Open existing for write */
540 if (bfd->use_backup_api) {
541 dwaccess = GENERIC_WRITE|WRITE_OWNER|WRITE_DAC;
542 dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT;
544 dwaccess = GENERIC_WRITE;
548 if (p_CreateFileW && p_MultiByteToWideChar) {
549 // unicode open for open existing write
550 Dmsg1(100, "Write only CreateFileW=%s\n", win32_fname);
551 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
552 dwaccess, /* Requested access */
554 NULL, /* SecurityAttributes */
555 OPEN_EXISTING, /* CreationDisposition */
556 dwflags, /* Flags and attributes */
557 NULL); /* TemplateFile */
560 Dmsg1(100, "Write only CreateFileA=%s\n", win32_fname);
561 bfd->fh = p_CreateFileA(win32_fname,
562 dwaccess, /* Requested access */
564 NULL, /* SecurityAttributes */
565 OPEN_EXISTING, /* CreationDisposition */
566 dwflags, /* Flags and attributes */
567 NULL); /* TemplateFile */
571 bfd->mode = BF_WRITE;
574 if (bfd->use_backup_api) {
575 dwaccess = GENERIC_READ|READ_CONTROL|ACCESS_SYSTEM_SECURITY;
576 dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_SEQUENTIAL_SCAN |
577 FILE_FLAG_OPEN_REPARSE_POINT;
578 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
580 dwaccess = GENERIC_READ;
582 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE;
585 if (p_CreateFileW && p_MultiByteToWideChar) {
586 // unicode open for open existing read
587 Dmsg1(100, "Read CreateFileW=%s\n", win32_fname);
588 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
589 dwaccess, /* Requested access */
590 dwshare, /* Share modes */
591 NULL, /* SecurityAttributes */
592 OPEN_EXISTING, /* CreationDisposition */
593 dwflags, /* Flags and attributes */
594 NULL); /* TemplateFile */
597 Dmsg1(100, "Read CreateFileA=%s\n", win32_fname);
598 bfd->fh = p_CreateFileA(win32_fname,
599 dwaccess, /* Requested access */
600 dwshare, /* Share modes */
601 NULL, /* SecurityAttributes */
602 OPEN_EXISTING, /* CreationDisposition */
603 dwflags, /* Flags and attributes */
604 NULL); /* TemplateFile */
610 if (bfd->fh == INVALID_HANDLE_VALUE) {
611 bfd->lerror = GetLastError();
612 bfd->berrno = b_errno_win32;
613 errno = b_errno_win32;
614 bfd->mode = BF_CLOSED;
617 bfd->lpContext = NULL;
618 bfd->win32DecompContext.bIsInData = false;
619 bfd->win32DecompContext.liNextHeader = 0;
620 free_pool_memory(win32_fname_wchar);
621 free_pool_memory(win32_fname);
622 return bfd->mode == BF_CLOSED ? -1 : 1;
626 * Returns 0 on success
629 int bclose(BFILE *bfd)
633 if (bfd->mode == BF_CLOSED) {
634 Dmsg0(50, "=== BFD already closed.\n");
638 if (bfd->cmd_plugin && plugin_bclose) {
639 stat = plugin_bclose(bfd);
640 Dmsg0(50, "==== BFD closed!!!\n");
645 * We need to tell the API to release the buffer it
646 * allocated in lpContext. We do so by calling the
647 * API one more time, but with the Abort bit set.
649 if (bfd->use_backup_api && bfd->mode == BF_READ) {
651 if (bfd->lpContext && !p_BackupRead(bfd->fh,
653 (DWORD)0, /* bytes to read */
654 &bfd->rw_bytes, /* bytes read */
656 1, /* ProcessSecurity */
657 &bfd->lpContext)) { /* Read context */
658 errno = b_errno_win32;
661 } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
663 if (bfd->lpContext && !p_BackupWrite(bfd->fh,
665 (DWORD)0, /* bytes to read */
666 &bfd->rw_bytes, /* bytes written */
668 1, /* ProcessSecurity */
669 &bfd->lpContext)) { /* Write context */
670 errno = b_errno_win32;
674 if (!CloseHandle(bfd->fh)) {
676 errno = b_errno_win32;
681 free_pool_memory(bfd->errmsg);
684 bfd->mode = BF_CLOSED;
685 bfd->lpContext = NULL;
686 bfd->cmd_plugin = false;
690 /* Returns: bytes read on success
694 ssize_t bread(BFILE *bfd, void *buf, size_t count)
698 if (bfd->cmd_plugin && plugin_bread) {
699 return plugin_bread(bfd, buf, count);
702 if (bfd->use_backup_api) {
703 if (!p_BackupRead(bfd->fh,
708 1, /* Process Security */
709 &bfd->lpContext)) { /* Context */
710 bfd->lerror = GetLastError();
711 bfd->berrno = b_errno_win32;
712 errno = b_errno_win32;
716 if (!ReadFile(bfd->fh,
721 bfd->lerror = GetLastError();
722 bfd->berrno = b_errno_win32;
723 errno = b_errno_win32;
728 return (ssize_t)bfd->rw_bytes;
731 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
735 if (bfd->cmd_plugin && plugin_bwrite) {
736 return plugin_bwrite(bfd, buf, count);
739 if (bfd->use_backup_api) {
740 if (!p_BackupWrite(bfd->fh,
745 1, /* Process Security */
746 &bfd->lpContext)) { /* Context */
747 bfd->lerror = GetLastError();
748 bfd->berrno = b_errno_win32;
749 errno = b_errno_win32;
753 if (!WriteFile(bfd->fh,
758 bfd->lerror = GetLastError();
759 bfd->berrno = b_errno_win32;
760 errno = b_errno_win32;
764 return (ssize_t)bfd->rw_bytes;
767 bool is_bopen(BFILE *bfd)
769 return bfd->mode != BF_CLOSED;
772 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
774 LONG offset_low = (LONG)offset;
775 LONG offset_high = (LONG)(offset >> 32);
778 if (bfd->cmd_plugin && plugin_blseek) {
779 return plugin_blseek(bfd, offset, whence);
782 dwResult = SetFilePointer(bfd->fh, offset_low, &offset_high, whence);
784 if (dwResult == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
785 return (boffset_t)-1;
788 return ((boffset_t)offset_high << 32) | dwResult;
791 #else /* Unix systems */
793 /* ===============================================================
797 * ===============================================================
799 void binit(BFILE *bfd)
801 memset(bfd, 0, sizeof(BFILE));
805 bool have_win32_api()
807 return false; /* no can do */
811 * Enables using the Backup API (win32_data).
812 * Returns true if function worked
813 * Returns false if failed (i.e. do not have Backup API on this machine)
815 bool set_win32_backup(BFILE *bfd)
817 return false; /* no can do */
821 bool set_portable_backup(BFILE *bfd)
823 return true; /* no problem */
827 * Return true if we are writing in portable format
828 * return false if not
830 bool is_portable_backup(BFILE *bfd)
832 return true; /* portable by definition */
835 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
840 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
842 bfd->cmd_plugin = true;
848 * This code is running on a non-Win32 machine
850 bool is_restore_stream_supported(int stream)
852 /* No Win32 backup on this machine */
855 case STREAM_GZIP_DATA:
856 case STREAM_SPARSE_GZIP_DATA:
857 case STREAM_WIN32_GZIP_DATA:
859 #ifndef HAVE_DARWIN_OS
860 case STREAM_MACOS_FORK_DATA:
861 case STREAM_HFSPLUS_ATTRIBUTES:
867 case STREAM_GZIP_DATA:
868 case STREAM_SPARSE_GZIP_DATA:
869 case STREAM_WIN32_GZIP_DATA:
871 case STREAM_WIN32_DATA:
872 case STREAM_UNIX_ATTRIBUTES:
873 case STREAM_FILE_DATA:
874 case STREAM_MD5_DIGEST:
875 case STREAM_UNIX_ATTRIBUTES_EX:
876 case STREAM_SPARSE_DATA:
877 case STREAM_PROGRAM_NAMES:
878 case STREAM_PROGRAM_DATA:
879 case STREAM_SHA1_DIGEST:
881 case STREAM_SHA256_DIGEST:
882 case STREAM_SHA512_DIGEST:
885 case STREAM_SIGNED_DIGEST:
886 case STREAM_ENCRYPTED_FILE_DATA:
887 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
888 case STREAM_ENCRYPTED_WIN32_DATA:
889 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
891 #ifdef HAVE_DARWIN_OS
892 case STREAM_MACOS_FORK_DATA:
893 case STREAM_HFSPLUS_ATTRIBUTES:
895 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
896 #endif /* HAVE_CRYPTO */
897 #endif /* HAVE_DARWIN_OS */
898 case 0: /* compatibility with old tapes */
905 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
907 if (bfd->cmd_plugin && plugin_bopen) {
908 Dmsg1(50, "call plugin_bopen fname=%s\n", fname);
909 bfd->fid = plugin_bopen(bfd, fname, flags, mode);
910 Dmsg1(50, "Plugin bopen stat=%d\n", bfd->fid);
914 /* Normal file open */
915 Dmsg1(dbglvl, "open file %s\n", fname);
917 /* We use fnctl to set O_NOATIME if requested to avoid open error */
918 bfd->fid = open(fname, flags & ~O_NOATIME, mode);
920 /* Set O_NOATIME if possible */
921 if (bfd->fid != -1 && flags & O_NOATIME) {
922 int oldflags = fcntl(bfd->fid, F_GETFL, 0);
923 if (oldflags == -1) {
928 int ret = fcntl(bfd->fid, F_SETFL, oldflags | O_NOATIME);
929 /* EPERM means setting O_NOATIME was not allowed */
930 if (ret == -1 && errno != EPERM) {
938 bfd->m_flags = flags;
939 Dmsg1(400, "Open file %d\n", bfd->fid);
942 bfd->win32DecompContext.bIsInData = false;
943 bfd->win32DecompContext.liNextHeader = 0;
945 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
946 if (bfd->fid != -1 && flags & O_RDONLY) {
947 int stat = posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_WILLNEED);
948 Dmsg2(400, "Did posix_fadvise on %s stat=%d\n", fname, stat);
955 #ifdef HAVE_DARWIN_OS
956 /* Open the resource fork of a file. */
957 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
961 rsrc_fname = get_pool_memory(PM_FNAME);
962 pm_strcpy(rsrc_fname, fname);
963 pm_strcat(rsrc_fname, _PATH_RSRCFORKSPEC);
964 bopen(bfd, rsrc_fname, flags, mode);
965 free_pool_memory(rsrc_fname);
969 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
976 int bclose(BFILE *bfd)
980 Dmsg1(400, "Close file %d\n", bfd->fid);
982 if (bfd->cmd_plugin && plugin_bclose) {
983 stat = plugin_bclose(bfd);
985 bfd->cmd_plugin = false;
988 if (bfd->fid == -1) {
991 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
992 if (bfd->m_flags & O_RDONLY) {
993 fdatasync(bfd->fid); /* sync the file */
994 /* Tell OS we don't need it any more */
995 posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_DONTNEED);
999 /* Close normal file */
1000 stat = close(bfd->fid);
1001 bfd->berrno = errno;
1003 bfd->cmd_plugin = false;
1007 ssize_t bread(BFILE *bfd, void *buf, size_t count)
1011 if (bfd->cmd_plugin && plugin_bread) {
1012 return plugin_bread(bfd, buf, count);
1015 stat = read(bfd->fid, buf, count);
1016 bfd->berrno = errno;
1020 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
1024 if (bfd->cmd_plugin && plugin_bwrite) {
1025 return plugin_bwrite(bfd, buf, count);
1027 stat = write(bfd->fid, buf, count);
1028 bfd->berrno = errno;
1032 bool is_bopen(BFILE *bfd)
1034 return bfd->fid >= 0;
1037 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
1041 if (bfd->cmd_plugin && plugin_bwrite) {
1042 return plugin_blseek(bfd, offset, whence);
1044 pos = (boffset_t)lseek(bfd->fid, offset, whence);
1045 bfd->berrno = errno;