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 two of the GNU 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 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_XATTR_OPENBSD:
171 return _("OpenBSD Specific Extended attribs");
172 case STREAM_XATTR_SOLARIS_SYS:
173 return _("Solaris Specific Extensible attribs or System Extended attribs");
174 case STREAM_XATTR_SOLARIS:
175 return _("Solaris Specific Extended attribs");
176 case STREAM_XATTR_DARWIN:
177 return _("Darwin Specific Extended attribs");
178 case STREAM_XATTR_FREEBSD:
179 return _("FreeBSD Specific Extended attribs");
180 case STREAM_XATTR_LINUX:
181 return _("Linux Specific Extended attribs");
182 case STREAM_XATTR_NETBSD:
183 return _("NetBSD Specific Extended attribs");
185 sprintf(buf, "%d", stream);
186 return (const char *)buf;
191 * Convert a 64 bit little endian to a big endian
193 void int64_LE2BE(int64_t* pBE, const int64_t v)
195 /* convert little endian to big endian */
196 if (htonl(1) != 1L) { /* no work if on little endian machine */
197 memcpy(pBE, &v, sizeof(int64_t));
200 uint8_t rv[sizeof(int64_t)];
201 uint8_t *pv = (uint8_t *) &v;
203 for (i = 0; i < 8; i++) {
206 memcpy(pBE, &rv, sizeof(int64_t));
211 * Convert a 32 bit little endian to a big endian
213 void int32_LE2BE(int32_t* pBE, const int32_t v)
215 /* convert little endian to big endian */
216 if (htonl(1) != 1L) { /* no work if on little endian machine */
217 memcpy(pBE, &v, sizeof(int32_t));
220 uint8_t rv[sizeof(int32_t)];
221 uint8_t *pv = (uint8_t *) &v;
223 for (i = 0; i < 4; i++) {
226 memcpy(pBE, &rv, sizeof(int32_t));
232 * Read a BackupRead block and pull out the file data
234 bool processWin32BackupAPIBlock (BFILE *bfd, void *pBuffer, ssize_t dwSize)
236 /* pByte contains the buffer
237 dwSize the len to be processed. function assumes to be
238 called in successive incremental order over the complete
239 BackupRead stream beginning at pos 0 and ending at the end.
242 PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT* pContext = &(bfd->win32DecompContext);
243 bool bContinue = false;
244 int64_t dwDataOffset = 0;
247 /* Win32 Stream Header size without name of stream.
248 * = sizeof (WIN32_STREAM_ID)- sizeof(WCHAR*);
250 int32_t dwSizeHeader = 20;
253 if (pContext->liNextHeader >= dwSize) {
254 dwDataLen = dwSize-dwDataOffset;
255 bContinue = false; /* 1 iteration is enough */
257 dwDataLen = pContext->liNextHeader-dwDataOffset;
258 bContinue = true; /* multiple iterations may be necessary */
262 /* copy block of real DATA */
263 if (pContext->bIsInData) {
264 if (bwrite(bfd, ((char *)pBuffer)+dwDataOffset, dwDataLen) != (ssize_t)dwDataLen)
268 if (pContext->liNextHeader < dwSize) {/* is a header in this block ? */
269 int32_t dwOffsetTarget;
270 int32_t dwOffsetSource;
272 if (pContext->liNextHeader < 0) {
273 /* start of header was before this block, so we
274 * continue with the part in the current block
276 dwOffsetTarget = -pContext->liNextHeader;
279 /* start of header is inside of this block */
281 dwOffsetSource = pContext->liNextHeader;
284 int32_t dwHeaderPartLen = dwSizeHeader-dwOffsetTarget;
285 bool bHeaderIsComplete;
287 if (dwHeaderPartLen <= dwSize-dwOffsetSource) {
288 /* header (or rest of header) is completely available
291 bHeaderIsComplete = true;
293 /* header will continue in next block */
294 bHeaderIsComplete = false;
295 dwHeaderPartLen = dwSize-dwOffsetSource;
298 /* copy the available portion of header to persistent copy */
299 memcpy(((char *)&pContext->header_stream)+dwOffsetTarget, ((char *)pBuffer)+dwOffsetSource, dwHeaderPartLen);
301 /* recalculate position of next header */
302 if (bHeaderIsComplete) {
303 /* convert stream name size (32 bit little endian) to machine type */
305 int32_LE2BE (&dwNameSize, pContext->header_stream.dwStreamNameSize);
306 dwDataOffset = dwNameSize+pContext->liNextHeader+dwSizeHeader;
308 /* convert stream size (64 bit little endian) to machine type */
309 int64_LE2BE (&(pContext->liNextHeader), pContext->header_stream.Size);
310 pContext->liNextHeader += dwDataOffset;
312 pContext->bIsInData = pContext->header_stream.dwStreamId == WIN32_BACKUP_DATA;
313 if (dwDataOffset == dwSize)
316 /* stop and continue with next block */
318 pContext->bIsInData = false;
323 /* set "NextHeader" relative to the beginning of the next block */
324 pContext->liNextHeader-= dwSize;
331 /* ===============================================================
335 * ===============================================================
338 #if defined(HAVE_WIN32)
340 void unix_name_to_win32(POOLMEM **win32_name, char *name);
341 extern "C" HANDLE get_osfhandle(int fd);
344 void binit(BFILE *bfd)
346 memset(bfd, 0, sizeof(BFILE));
348 bfd->mode = BF_CLOSED;
349 bfd->use_backup_api = have_win32_api();
350 bfd->cmd_plugin = false;
354 * Enables using the Backup API (win32_data).
355 * Returns 1 if function worked
356 * Returns 0 if failed (i.e. do not have Backup API on this machine)
358 bool set_win32_backup(BFILE *bfd)
360 /* We enable if possible here */
361 bfd->use_backup_api = have_win32_api();
362 return bfd->use_backup_api;
366 bool set_portable_backup(BFILE *bfd)
368 bfd->use_backup_api = false;
372 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
374 bfd->cmd_plugin = true;
380 * Return 1 if we are NOT using Win32 BackupWrite()
383 bool is_portable_backup(BFILE *bfd)
385 return !bfd->use_backup_api;
388 bool have_win32_api()
390 return p_BackupRead && p_BackupWrite;
395 * Return true if we support the stream
396 * false if we do not support the stream
398 * This code is running under Win32, so we
399 * do not need #ifdef on MACOS ...
401 bool is_restore_stream_supported(int stream)
405 /* Streams known not to be supported */
407 case STREAM_GZIP_DATA:
408 case STREAM_SPARSE_GZIP_DATA:
409 case STREAM_WIN32_GZIP_DATA:
411 case STREAM_MACOS_FORK_DATA:
412 case STREAM_HFSPLUS_ATTRIBUTES:
413 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
418 case STREAM_GZIP_DATA:
419 case STREAM_SPARSE_GZIP_DATA:
420 case STREAM_WIN32_GZIP_DATA:
422 case STREAM_WIN32_DATA:
423 case STREAM_UNIX_ATTRIBUTES:
424 case STREAM_FILE_DATA:
425 case STREAM_MD5_DIGEST:
426 case STREAM_UNIX_ATTRIBUTES_EX:
427 case STREAM_SPARSE_DATA:
428 case STREAM_PROGRAM_NAMES:
429 case STREAM_PROGRAM_DATA:
430 case STREAM_SHA1_DIGEST:
432 case STREAM_SHA256_DIGEST:
433 case STREAM_SHA512_DIGEST:
436 case STREAM_SIGNED_DIGEST:
437 case STREAM_ENCRYPTED_FILE_DATA:
438 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
439 case STREAM_ENCRYPTED_WIN32_DATA:
440 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
442 case 0: /* compatibility with old tapes */
448 HANDLE bget_handle(BFILE *bfd)
453 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
455 POOLMEM *win32_fname;
456 POOLMEM *win32_fname_wchar;
458 DWORD dwaccess, dwflags, dwshare;
460 /* Convert to Windows path format */
461 win32_fname = get_pool_memory(PM_FNAME);
462 win32_fname_wchar = get_pool_memory(PM_FNAME);
464 unix_name_to_win32(&win32_fname, (char *)fname);
466 if (bfd->cmd_plugin && plugin_bopen) {
468 Dmsg1(50, "call plugin_bopen fname=%s\n", fname);
469 rtnstat = plugin_bopen(bfd, fname, flags, mode);
470 Dmsg1(50, "return from plugin_bopen status=%d\n", rtnstat);
472 if (flags & O_CREAT || flags & O_WRONLY) { /* Open existing for write */
473 Dmsg1(50, "plugin_open for write OK file=%s.\n", fname);
474 bfd->mode = BF_WRITE;
476 Dmsg1(50, "plugin_open for read OK file=%s.\n", fname);
480 bfd->mode = BF_CLOSED;
481 Dmsg1(000, "==== plugin_bopen returned bad status=%d\n", rtnstat);
483 free_pool_memory(win32_fname_wchar);
484 free_pool_memory(win32_fname);
485 return bfd->mode == BF_CLOSED ? -1 : 1;
487 Dmsg0(50, "=== NO plugin\n");
489 if (!(p_CreateFileA || p_CreateFileW)) {
490 Dmsg0(50, "No CreateFileA and no CreateFileW!!!!!\n");
494 if (p_CreateFileW && p_MultiByteToWideChar) {
495 make_win32_path_UTF8_2_wchar(&win32_fname_wchar, fname);
498 if (flags & O_CREAT) { /* Create */
499 if (bfd->use_backup_api) {
500 dwaccess = GENERIC_WRITE|FILE_ALL_ACCESS|WRITE_OWNER|WRITE_DAC|ACCESS_SYSTEM_SECURITY;
501 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
503 dwaccess = GENERIC_WRITE;
507 if (p_CreateFileW && p_MultiByteToWideChar) {
508 // unicode open for create write
509 Dmsg1(100, "Create CreateFileW=%s\n", win32_fname);
510 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
511 dwaccess, /* Requested access */
513 NULL, /* SecurityAttributes */
514 CREATE_ALWAYS, /* CreationDisposition */
515 dwflags, /* Flags and attributes */
516 NULL); /* TemplateFile */
519 Dmsg1(100, "Create CreateFileA=%s\n", win32_fname);
520 bfd->fh = p_CreateFileA(win32_fname,
521 dwaccess, /* Requested access */
523 NULL, /* SecurityAttributes */
524 CREATE_ALWAYS, /* CreationDisposition */
525 dwflags, /* Flags and attributes */
526 NULL); /* TemplateFile */
529 bfd->mode = BF_WRITE;
531 } else if (flags & O_WRONLY) { /* Open existing for write */
532 if (bfd->use_backup_api) {
533 dwaccess = GENERIC_WRITE|WRITE_OWNER|WRITE_DAC;
534 dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT;
536 dwaccess = GENERIC_WRITE;
540 if (p_CreateFileW && p_MultiByteToWideChar) {
541 // unicode open for open existing write
542 Dmsg1(100, "Write only CreateFileW=%s\n", win32_fname);
543 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
544 dwaccess, /* Requested access */
546 NULL, /* SecurityAttributes */
547 OPEN_EXISTING, /* CreationDisposition */
548 dwflags, /* Flags and attributes */
549 NULL); /* TemplateFile */
552 Dmsg1(100, "Write only CreateFileA=%s\n", win32_fname);
553 bfd->fh = p_CreateFileA(win32_fname,
554 dwaccess, /* Requested access */
556 NULL, /* SecurityAttributes */
557 OPEN_EXISTING, /* CreationDisposition */
558 dwflags, /* Flags and attributes */
559 NULL); /* TemplateFile */
563 bfd->mode = BF_WRITE;
566 if (bfd->use_backup_api) {
567 dwaccess = GENERIC_READ|READ_CONTROL|ACCESS_SYSTEM_SECURITY;
568 dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_SEQUENTIAL_SCAN |
569 FILE_FLAG_OPEN_REPARSE_POINT;
570 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
572 dwaccess = GENERIC_READ;
574 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE;
577 if (p_CreateFileW && p_MultiByteToWideChar) {
578 // unicode open for open existing read
579 Dmsg1(100, "Read CreateFileW=%s\n", win32_fname);
580 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
581 dwaccess, /* Requested access */
582 dwshare, /* Share modes */
583 NULL, /* SecurityAttributes */
584 OPEN_EXISTING, /* CreationDisposition */
585 dwflags, /* Flags and attributes */
586 NULL); /* TemplateFile */
589 Dmsg1(100, "Read CreateFileA=%s\n", win32_fname);
590 bfd->fh = p_CreateFileA(win32_fname,
591 dwaccess, /* Requested access */
592 dwshare, /* Share modes */
593 NULL, /* SecurityAttributes */
594 OPEN_EXISTING, /* CreationDisposition */
595 dwflags, /* Flags and attributes */
596 NULL); /* TemplateFile */
602 if (bfd->fh == INVALID_HANDLE_VALUE) {
603 bfd->lerror = GetLastError();
604 bfd->berrno = b_errno_win32;
605 errno = b_errno_win32;
606 bfd->mode = BF_CLOSED;
609 bfd->lpContext = NULL;
610 bfd->win32DecompContext.bIsInData = false;
611 bfd->win32DecompContext.liNextHeader = 0;
612 free_pool_memory(win32_fname_wchar);
613 free_pool_memory(win32_fname);
614 return bfd->mode == BF_CLOSED ? -1 : 1;
618 * Returns 0 on success
621 int bclose(BFILE *bfd)
625 if (bfd->mode == BF_CLOSED) {
626 Dmsg0(50, "=== BFD already closed.\n");
630 if (bfd->cmd_plugin && plugin_bclose) {
631 stat = plugin_bclose(bfd);
632 Dmsg0(50, "==== BFD closed!!!\n");
637 * We need to tell the API to release the buffer it
638 * allocated in lpContext. We do so by calling the
639 * API one more time, but with the Abort bit set.
641 if (bfd->use_backup_api && bfd->mode == BF_READ) {
643 if (bfd->lpContext && !p_BackupRead(bfd->fh,
645 (DWORD)0, /* bytes to read */
646 &bfd->rw_bytes, /* bytes read */
648 1, /* ProcessSecurity */
649 &bfd->lpContext)) { /* Read context */
650 errno = b_errno_win32;
653 } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
655 if (bfd->lpContext && !p_BackupWrite(bfd->fh,
657 (DWORD)0, /* bytes to read */
658 &bfd->rw_bytes, /* bytes written */
660 1, /* ProcessSecurity */
661 &bfd->lpContext)) { /* Write context */
662 errno = b_errno_win32;
666 if (!CloseHandle(bfd->fh)) {
668 errno = b_errno_win32;
673 free_pool_memory(bfd->errmsg);
676 bfd->mode = BF_CLOSED;
677 bfd->lpContext = NULL;
678 bfd->cmd_plugin = false;
682 /* Returns: bytes read on success
686 ssize_t bread(BFILE *bfd, void *buf, size_t count)
690 if (bfd->cmd_plugin && plugin_bread) {
691 return plugin_bread(bfd, buf, count);
694 if (bfd->use_backup_api) {
695 if (!p_BackupRead(bfd->fh,
700 1, /* Process Security */
701 &bfd->lpContext)) { /* Context */
702 bfd->lerror = GetLastError();
703 bfd->berrno = b_errno_win32;
704 errno = b_errno_win32;
708 if (!ReadFile(bfd->fh,
713 bfd->lerror = GetLastError();
714 bfd->berrno = b_errno_win32;
715 errno = b_errno_win32;
720 return (ssize_t)bfd->rw_bytes;
723 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
727 if (bfd->cmd_plugin && plugin_bwrite) {
728 return plugin_bwrite(bfd, buf, count);
731 if (bfd->use_backup_api) {
732 if (!p_BackupWrite(bfd->fh,
737 1, /* Process Security */
738 &bfd->lpContext)) { /* Context */
739 bfd->lerror = GetLastError();
740 bfd->berrno = b_errno_win32;
741 errno = b_errno_win32;
745 if (!WriteFile(bfd->fh,
750 bfd->lerror = GetLastError();
751 bfd->berrno = b_errno_win32;
752 errno = b_errno_win32;
756 return (ssize_t)bfd->rw_bytes;
759 bool is_bopen(BFILE *bfd)
761 return bfd->mode != BF_CLOSED;
764 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
766 LONG offset_low = (LONG)offset;
767 LONG offset_high = (LONG)(offset >> 32);
770 if (bfd->cmd_plugin && plugin_blseek) {
771 return plugin_blseek(bfd, offset, whence);
774 dwResult = SetFilePointer(bfd->fh, offset_low, &offset_high, whence);
776 if (dwResult == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
777 return (boffset_t)-1;
780 return ((boffset_t)offset_high << 32) | dwResult;
783 #else /* Unix systems */
785 /* ===============================================================
789 * ===============================================================
791 void binit(BFILE *bfd)
793 memset(bfd, 0, sizeof(BFILE));
797 bool have_win32_api()
799 return false; /* no can do */
803 * Enables using the Backup API (win32_data).
804 * Returns true if function worked
805 * Returns false if failed (i.e. do not have Backup API on this machine)
807 bool set_win32_backup(BFILE *bfd)
809 return false; /* no can do */
813 bool set_portable_backup(BFILE *bfd)
815 return true; /* no problem */
819 * Return true if we are writing in portable format
820 * return false if not
822 bool is_portable_backup(BFILE *bfd)
824 return true; /* portable by definition */
827 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
832 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
834 bfd->cmd_plugin = true;
840 * This code is running on a non-Win32 machine
842 bool is_restore_stream_supported(int stream)
844 /* No Win32 backup on this machine */
847 case STREAM_GZIP_DATA:
848 case STREAM_SPARSE_GZIP_DATA:
849 case STREAM_WIN32_GZIP_DATA:
851 #ifndef HAVE_DARWIN_OS
852 case STREAM_MACOS_FORK_DATA:
853 case STREAM_HFSPLUS_ATTRIBUTES:
859 case STREAM_GZIP_DATA:
860 case STREAM_SPARSE_GZIP_DATA:
861 case STREAM_WIN32_GZIP_DATA:
863 case STREAM_WIN32_DATA:
864 case STREAM_UNIX_ATTRIBUTES:
865 case STREAM_FILE_DATA:
866 case STREAM_MD5_DIGEST:
867 case STREAM_UNIX_ATTRIBUTES_EX:
868 case STREAM_SPARSE_DATA:
869 case STREAM_PROGRAM_NAMES:
870 case STREAM_PROGRAM_DATA:
871 case STREAM_SHA1_DIGEST:
873 case STREAM_SHA256_DIGEST:
874 case STREAM_SHA512_DIGEST:
877 case STREAM_SIGNED_DIGEST:
878 case STREAM_ENCRYPTED_FILE_DATA:
879 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
880 case STREAM_ENCRYPTED_WIN32_DATA:
881 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
883 #ifdef HAVE_DARWIN_OS
884 case STREAM_MACOS_FORK_DATA:
885 case STREAM_HFSPLUS_ATTRIBUTES:
887 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
888 #endif /* HAVE_CRYPTO */
889 #endif /* HAVE_DARWIN_OS */
890 case 0: /* compatibility with old tapes */
897 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
899 if (bfd->cmd_plugin && plugin_bopen) {
900 Dmsg1(50, "call plugin_bopen fname=%s\n", fname);
901 bfd->fid = plugin_bopen(bfd, fname, flags, mode);
902 Dmsg1(50, "Plugin bopen stat=%d\n", bfd->fid);
906 /* Normal file open */
907 Dmsg1(dbglvl, "open file %s\n", fname);
909 /* We use fnctl to set O_NOATIME if requested to avoid open error */
910 bfd->fid = open(fname, flags & ~O_NOATIME, mode);
912 /* Set O_NOATIME if possible */
913 if (bfd->fid != -1 && flags & O_NOATIME) {
914 int oldflags = fcntl(bfd->fid, F_GETFL, 0);
915 if (oldflags == -1) {
920 int ret = fcntl(bfd->fid, F_SETFL, oldflags | O_NOATIME);
921 /* EPERM means setting O_NOATIME was not allowed */
922 if (ret == -1 && errno != EPERM) {
930 bfd->m_flags = flags;
931 Dmsg1(400, "Open file %d\n", bfd->fid);
934 bfd->win32DecompContext.bIsInData = false;
935 bfd->win32DecompContext.liNextHeader = 0;
937 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
938 if (bfd->fid != -1 && flags & O_RDONLY) {
939 int stat = posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_WILLNEED);
940 Dmsg2(400, "Did posix_fadvise on %s stat=%d\n", fname, stat);
947 #ifdef HAVE_DARWIN_OS
948 /* Open the resource fork of a file. */
949 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
953 rsrc_fname = get_pool_memory(PM_FNAME);
954 pm_strcpy(rsrc_fname, fname);
955 pm_strcat(rsrc_fname, _PATH_RSRCFORKSPEC);
956 bopen(bfd, rsrc_fname, flags, mode);
957 free_pool_memory(rsrc_fname);
961 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
968 int bclose(BFILE *bfd)
972 Dmsg1(400, "Close file %d\n", bfd->fid);
974 if (bfd->cmd_plugin && plugin_bclose) {
975 stat = plugin_bclose(bfd);
977 bfd->cmd_plugin = false;
980 if (bfd->fid == -1) {
983 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
984 if (bfd->m_flags & O_RDONLY) {
985 fdatasync(bfd->fid); /* sync the file */
986 /* Tell OS we don't need it any more */
987 posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_DONTNEED);
991 /* Close normal file */
992 stat = close(bfd->fid);
995 bfd->cmd_plugin = false;
999 ssize_t bread(BFILE *bfd, void *buf, size_t count)
1003 if (bfd->cmd_plugin && plugin_bread) {
1004 return plugin_bread(bfd, buf, count);
1007 stat = read(bfd->fid, buf, count);
1008 bfd->berrno = errno;
1012 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
1016 if (bfd->cmd_plugin && plugin_bwrite) {
1017 return plugin_bwrite(bfd, buf, count);
1019 stat = write(bfd->fid, buf, count);
1020 bfd->berrno = errno;
1024 bool is_bopen(BFILE *bfd)
1026 return bfd->fid >= 0;
1029 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
1033 if (bfd->cmd_plugin && plugin_bwrite) {
1034 return plugin_blseek(bfd, offset, whence);
1036 pos = (boffset_t)lseek(bfd->fid, offset, whence);
1037 bfd->berrno = errno;