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_XATTR_AIX:
171 return _("AIX Specific Extended attribs");
172 case STREAM_XATTR_OPENBSD:
173 return _("OpenBSD Specific Extended attribs");
174 case STREAM_XATTR_SOLARIS_SYS:
175 return _("Solaris Specific Extensible attribs or System Extended attribs");
176 case STREAM_XATTR_SOLARIS:
177 return _("Solaris Specific Extended attribs");
178 case STREAM_XATTR_DARWIN:
179 return _("Darwin Specific Extended attribs");
180 case STREAM_XATTR_FREEBSD:
181 return _("FreeBSD Specific Extended attribs");
182 case STREAM_XATTR_LINUX:
183 return _("Linux Specific Extended attribs");
184 case STREAM_XATTR_NETBSD:
185 return _("NetBSD Specific Extended attribs");
187 sprintf(buf, "%d", stream);
188 return (const char *)buf;
193 * Convert a 64 bit little endian to a big endian
195 void int64_LE2BE(int64_t* pBE, const int64_t v)
197 /* convert little endian to big endian */
198 if (htonl(1) != 1L) { /* no work if on little endian machine */
199 memcpy(pBE, &v, sizeof(int64_t));
202 uint8_t rv[sizeof(int64_t)];
203 uint8_t *pv = (uint8_t *) &v;
205 for (i = 0; i < 8; i++) {
208 memcpy(pBE, &rv, sizeof(int64_t));
213 * Convert a 32 bit little endian to a big endian
215 void int32_LE2BE(int32_t* pBE, const int32_t v)
217 /* convert little endian to big endian */
218 if (htonl(1) != 1L) { /* no work if on little endian machine */
219 memcpy(pBE, &v, sizeof(int32_t));
222 uint8_t rv[sizeof(int32_t)];
223 uint8_t *pv = (uint8_t *) &v;
225 for (i = 0; i < 4; i++) {
228 memcpy(pBE, &rv, sizeof(int32_t));
234 * Read a BackupRead block and pull out the file data
236 bool processWin32BackupAPIBlock (BFILE *bfd, void *pBuffer, ssize_t dwSize)
238 /* pByte contains the buffer
239 dwSize the len to be processed. function assumes to be
240 called in successive incremental order over the complete
241 BackupRead stream beginning at pos 0 and ending at the end.
244 PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT* pContext = &(bfd->win32DecompContext);
245 bool bContinue = false;
246 int64_t dwDataOffset = 0;
249 /* Win32 Stream Header size without name of stream.
250 * = sizeof (WIN32_STREAM_ID)- sizeof(WCHAR*);
252 int32_t dwSizeHeader = 20;
255 if (pContext->liNextHeader >= dwSize) {
256 dwDataLen = dwSize-dwDataOffset;
257 bContinue = false; /* 1 iteration is enough */
259 dwDataLen = pContext->liNextHeader-dwDataOffset;
260 bContinue = true; /* multiple iterations may be necessary */
264 /* copy block of real DATA */
265 if (pContext->bIsInData) {
266 if (bwrite(bfd, ((char *)pBuffer)+dwDataOffset, dwDataLen) != (ssize_t)dwDataLen)
270 if (pContext->liNextHeader < dwSize) {/* is a header in this block ? */
271 int32_t dwOffsetTarget;
272 int32_t dwOffsetSource;
274 if (pContext->liNextHeader < 0) {
275 /* start of header was before this block, so we
276 * continue with the part in the current block
278 dwOffsetTarget = -pContext->liNextHeader;
281 /* start of header is inside of this block */
283 dwOffsetSource = pContext->liNextHeader;
286 int32_t dwHeaderPartLen = dwSizeHeader-dwOffsetTarget;
287 bool bHeaderIsComplete;
289 if (dwHeaderPartLen <= dwSize-dwOffsetSource) {
290 /* header (or rest of header) is completely available
293 bHeaderIsComplete = true;
295 /* header will continue in next block */
296 bHeaderIsComplete = false;
297 dwHeaderPartLen = dwSize-dwOffsetSource;
300 /* copy the available portion of header to persistent copy */
301 memcpy(((char *)&pContext->header_stream)+dwOffsetTarget, ((char *)pBuffer)+dwOffsetSource, dwHeaderPartLen);
303 /* recalculate position of next header */
304 if (bHeaderIsComplete) {
305 /* convert stream name size (32 bit little endian) to machine type */
307 int32_LE2BE (&dwNameSize, pContext->header_stream.dwStreamNameSize);
308 dwDataOffset = dwNameSize+pContext->liNextHeader+dwSizeHeader;
310 /* convert stream size (64 bit little endian) to machine type */
311 int64_LE2BE (&(pContext->liNextHeader), pContext->header_stream.Size);
312 pContext->liNextHeader += dwDataOffset;
314 pContext->bIsInData = pContext->header_stream.dwStreamId == WIN32_BACKUP_DATA;
315 if (dwDataOffset == dwSize)
318 /* stop and continue with next block */
320 pContext->bIsInData = false;
325 /* set "NextHeader" relative to the beginning of the next block */
326 pContext->liNextHeader-= dwSize;
333 /* ===============================================================
337 * ===============================================================
340 #if defined(HAVE_WIN32)
342 void unix_name_to_win32(POOLMEM **win32_name, char *name);
343 extern "C" HANDLE get_osfhandle(int fd);
346 void binit(BFILE *bfd)
348 memset(bfd, 0, sizeof(BFILE));
350 bfd->mode = BF_CLOSED;
351 bfd->use_backup_api = have_win32_api();
352 bfd->cmd_plugin = false;
356 * Enables using the Backup API (win32_data).
357 * Returns 1 if function worked
358 * Returns 0 if failed (i.e. do not have Backup API on this machine)
360 bool set_win32_backup(BFILE *bfd)
362 /* We enable if possible here */
363 bfd->use_backup_api = have_win32_api();
364 return bfd->use_backup_api;
368 bool set_portable_backup(BFILE *bfd)
370 bfd->use_backup_api = false;
374 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
376 bfd->cmd_plugin = true;
382 * Return 1 if we are NOT using Win32 BackupWrite()
385 bool is_portable_backup(BFILE *bfd)
387 return !bfd->use_backup_api;
390 bool have_win32_api()
392 return p_BackupRead && p_BackupWrite;
397 * Return true if we support the stream
398 * false if we do not support the stream
400 * This code is running under Win32, so we
401 * do not need #ifdef on MACOS ...
403 bool is_restore_stream_supported(int stream)
407 /* Streams known not to be supported */
409 case STREAM_GZIP_DATA:
410 case STREAM_SPARSE_GZIP_DATA:
411 case STREAM_WIN32_GZIP_DATA:
413 case STREAM_MACOS_FORK_DATA:
414 case STREAM_HFSPLUS_ATTRIBUTES:
415 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
420 case STREAM_GZIP_DATA:
421 case STREAM_SPARSE_GZIP_DATA:
422 case STREAM_WIN32_GZIP_DATA:
424 case STREAM_WIN32_DATA:
425 case STREAM_UNIX_ATTRIBUTES:
426 case STREAM_FILE_DATA:
427 case STREAM_MD5_DIGEST:
428 case STREAM_UNIX_ATTRIBUTES_EX:
429 case STREAM_SPARSE_DATA:
430 case STREAM_PROGRAM_NAMES:
431 case STREAM_PROGRAM_DATA:
432 case STREAM_SHA1_DIGEST:
434 case STREAM_SHA256_DIGEST:
435 case STREAM_SHA512_DIGEST:
438 case STREAM_SIGNED_DIGEST:
439 case STREAM_ENCRYPTED_FILE_DATA:
440 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
441 case STREAM_ENCRYPTED_WIN32_DATA:
442 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
444 case 0: /* compatibility with old tapes */
450 HANDLE bget_handle(BFILE *bfd)
455 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
457 POOLMEM *win32_fname;
458 POOLMEM *win32_fname_wchar;
460 DWORD dwaccess, dwflags, dwshare;
462 /* Convert to Windows path format */
463 win32_fname = get_pool_memory(PM_FNAME);
464 win32_fname_wchar = get_pool_memory(PM_FNAME);
466 unix_name_to_win32(&win32_fname, (char *)fname);
468 if (bfd->cmd_plugin && plugin_bopen) {
470 Dmsg1(50, "call plugin_bopen fname=%s\n", fname);
471 rtnstat = plugin_bopen(bfd, fname, flags, mode);
472 Dmsg1(50, "return from plugin_bopen status=%d\n", rtnstat);
474 if (flags & O_CREAT || flags & O_WRONLY) { /* Open existing for write */
475 Dmsg1(50, "plugin_open for write OK file=%s.\n", fname);
476 bfd->mode = BF_WRITE;
478 Dmsg1(50, "plugin_open for read OK file=%s.\n", fname);
482 bfd->mode = BF_CLOSED;
483 Dmsg1(000, "==== plugin_bopen returned bad status=%d\n", rtnstat);
485 free_pool_memory(win32_fname_wchar);
486 free_pool_memory(win32_fname);
487 return bfd->mode == BF_CLOSED ? -1 : 1;
489 Dmsg0(50, "=== NO plugin\n");
491 if (!(p_CreateFileA || p_CreateFileW)) {
492 Dmsg0(50, "No CreateFileA and no CreateFileW!!!!!\n");
496 if (p_CreateFileW && p_MultiByteToWideChar) {
497 make_win32_path_UTF8_2_wchar(&win32_fname_wchar, fname);
500 if (flags & O_CREAT) { /* Create */
501 if (bfd->use_backup_api) {
502 dwaccess = GENERIC_WRITE|FILE_ALL_ACCESS|WRITE_OWNER|WRITE_DAC|ACCESS_SYSTEM_SECURITY;
503 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
505 dwaccess = GENERIC_WRITE;
509 if (p_CreateFileW && p_MultiByteToWideChar) {
510 // unicode open for create write
511 Dmsg1(100, "Create CreateFileW=%s\n", win32_fname);
512 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
513 dwaccess, /* Requested access */
515 NULL, /* SecurityAttributes */
516 CREATE_ALWAYS, /* CreationDisposition */
517 dwflags, /* Flags and attributes */
518 NULL); /* TemplateFile */
521 Dmsg1(100, "Create CreateFileA=%s\n", win32_fname);
522 bfd->fh = p_CreateFileA(win32_fname,
523 dwaccess, /* Requested access */
525 NULL, /* SecurityAttributes */
526 CREATE_ALWAYS, /* CreationDisposition */
527 dwflags, /* Flags and attributes */
528 NULL); /* TemplateFile */
531 bfd->mode = BF_WRITE;
533 } else if (flags & O_WRONLY) { /* Open existing for write */
534 if (bfd->use_backup_api) {
535 dwaccess = GENERIC_WRITE|WRITE_OWNER|WRITE_DAC;
536 dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT;
538 dwaccess = GENERIC_WRITE;
542 if (p_CreateFileW && p_MultiByteToWideChar) {
543 // unicode open for open existing write
544 Dmsg1(100, "Write only CreateFileW=%s\n", win32_fname);
545 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
546 dwaccess, /* Requested access */
548 NULL, /* SecurityAttributes */
549 OPEN_EXISTING, /* CreationDisposition */
550 dwflags, /* Flags and attributes */
551 NULL); /* TemplateFile */
554 Dmsg1(100, "Write only CreateFileA=%s\n", win32_fname);
555 bfd->fh = p_CreateFileA(win32_fname,
556 dwaccess, /* Requested access */
558 NULL, /* SecurityAttributes */
559 OPEN_EXISTING, /* CreationDisposition */
560 dwflags, /* Flags and attributes */
561 NULL); /* TemplateFile */
565 bfd->mode = BF_WRITE;
568 if (bfd->use_backup_api) {
569 dwaccess = GENERIC_READ|READ_CONTROL|ACCESS_SYSTEM_SECURITY;
570 dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_SEQUENTIAL_SCAN |
571 FILE_FLAG_OPEN_REPARSE_POINT;
572 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
574 dwaccess = GENERIC_READ;
576 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE;
579 if (p_CreateFileW && p_MultiByteToWideChar) {
580 // unicode open for open existing read
581 Dmsg1(100, "Read CreateFileW=%s\n", win32_fname);
582 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
583 dwaccess, /* Requested access */
584 dwshare, /* Share modes */
585 NULL, /* SecurityAttributes */
586 OPEN_EXISTING, /* CreationDisposition */
587 dwflags, /* Flags and attributes */
588 NULL); /* TemplateFile */
591 Dmsg1(100, "Read CreateFileA=%s\n", win32_fname);
592 bfd->fh = p_CreateFileA(win32_fname,
593 dwaccess, /* Requested access */
594 dwshare, /* Share modes */
595 NULL, /* SecurityAttributes */
596 OPEN_EXISTING, /* CreationDisposition */
597 dwflags, /* Flags and attributes */
598 NULL); /* TemplateFile */
604 if (bfd->fh == INVALID_HANDLE_VALUE) {
605 bfd->lerror = GetLastError();
606 bfd->berrno = b_errno_win32;
607 errno = b_errno_win32;
608 bfd->mode = BF_CLOSED;
611 bfd->lpContext = NULL;
612 bfd->win32DecompContext.bIsInData = false;
613 bfd->win32DecompContext.liNextHeader = 0;
614 free_pool_memory(win32_fname_wchar);
615 free_pool_memory(win32_fname);
616 return bfd->mode == BF_CLOSED ? -1 : 1;
620 * Returns 0 on success
623 int bclose(BFILE *bfd)
627 if (bfd->mode == BF_CLOSED) {
628 Dmsg0(50, "=== BFD already closed.\n");
632 if (bfd->cmd_plugin && plugin_bclose) {
633 stat = plugin_bclose(bfd);
634 Dmsg0(50, "==== BFD closed!!!\n");
639 * We need to tell the API to release the buffer it
640 * allocated in lpContext. We do so by calling the
641 * API one more time, but with the Abort bit set.
643 if (bfd->use_backup_api && bfd->mode == BF_READ) {
645 if (bfd->lpContext && !p_BackupRead(bfd->fh,
647 (DWORD)0, /* bytes to read */
648 &bfd->rw_bytes, /* bytes read */
650 1, /* ProcessSecurity */
651 &bfd->lpContext)) { /* Read context */
652 errno = b_errno_win32;
655 } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
657 if (bfd->lpContext && !p_BackupWrite(bfd->fh,
659 (DWORD)0, /* bytes to read */
660 &bfd->rw_bytes, /* bytes written */
662 1, /* ProcessSecurity */
663 &bfd->lpContext)) { /* Write context */
664 errno = b_errno_win32;
668 if (!CloseHandle(bfd->fh)) {
670 errno = b_errno_win32;
675 free_pool_memory(bfd->errmsg);
678 bfd->mode = BF_CLOSED;
679 bfd->lpContext = NULL;
680 bfd->cmd_plugin = false;
684 /* Returns: bytes read on success
688 ssize_t bread(BFILE *bfd, void *buf, size_t count)
692 if (bfd->cmd_plugin && plugin_bread) {
693 return plugin_bread(bfd, buf, count);
696 if (bfd->use_backup_api) {
697 if (!p_BackupRead(bfd->fh,
702 1, /* Process Security */
703 &bfd->lpContext)) { /* Context */
704 bfd->lerror = GetLastError();
705 bfd->berrno = b_errno_win32;
706 errno = b_errno_win32;
710 if (!ReadFile(bfd->fh,
715 bfd->lerror = GetLastError();
716 bfd->berrno = b_errno_win32;
717 errno = b_errno_win32;
722 return (ssize_t)bfd->rw_bytes;
725 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
729 if (bfd->cmd_plugin && plugin_bwrite) {
730 return plugin_bwrite(bfd, buf, count);
733 if (bfd->use_backup_api) {
734 if (!p_BackupWrite(bfd->fh,
739 1, /* Process Security */
740 &bfd->lpContext)) { /* Context */
741 bfd->lerror = GetLastError();
742 bfd->berrno = b_errno_win32;
743 errno = b_errno_win32;
747 if (!WriteFile(bfd->fh,
752 bfd->lerror = GetLastError();
753 bfd->berrno = b_errno_win32;
754 errno = b_errno_win32;
758 return (ssize_t)bfd->rw_bytes;
761 bool is_bopen(BFILE *bfd)
763 return bfd->mode != BF_CLOSED;
766 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
768 LONG offset_low = (LONG)offset;
769 LONG offset_high = (LONG)(offset >> 32);
772 if (bfd->cmd_plugin && plugin_blseek) {
773 return plugin_blseek(bfd, offset, whence);
776 dwResult = SetFilePointer(bfd->fh, offset_low, &offset_high, whence);
778 if (dwResult == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
779 return (boffset_t)-1;
782 return ((boffset_t)offset_high << 32) | dwResult;
785 #else /* Unix systems */
787 /* ===============================================================
791 * ===============================================================
793 void binit(BFILE *bfd)
795 memset(bfd, 0, sizeof(BFILE));
799 bool have_win32_api()
801 return false; /* no can do */
805 * Enables using the Backup API (win32_data).
806 * Returns true if function worked
807 * Returns false if failed (i.e. do not have Backup API on this machine)
809 bool set_win32_backup(BFILE *bfd)
811 return false; /* no can do */
815 bool set_portable_backup(BFILE *bfd)
817 return true; /* no problem */
821 * Return true if we are writing in portable format
822 * return false if not
824 bool is_portable_backup(BFILE *bfd)
826 return true; /* portable by definition */
829 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
834 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
836 bfd->cmd_plugin = true;
842 * This code is running on a non-Win32 machine
844 bool is_restore_stream_supported(int stream)
846 /* No Win32 backup on this machine */
849 case STREAM_GZIP_DATA:
850 case STREAM_SPARSE_GZIP_DATA:
851 case STREAM_WIN32_GZIP_DATA:
853 #ifndef HAVE_DARWIN_OS
854 case STREAM_MACOS_FORK_DATA:
855 case STREAM_HFSPLUS_ATTRIBUTES:
861 case STREAM_GZIP_DATA:
862 case STREAM_SPARSE_GZIP_DATA:
863 case STREAM_WIN32_GZIP_DATA:
865 case STREAM_WIN32_DATA:
866 case STREAM_UNIX_ATTRIBUTES:
867 case STREAM_FILE_DATA:
868 case STREAM_MD5_DIGEST:
869 case STREAM_UNIX_ATTRIBUTES_EX:
870 case STREAM_SPARSE_DATA:
871 case STREAM_PROGRAM_NAMES:
872 case STREAM_PROGRAM_DATA:
873 case STREAM_SHA1_DIGEST:
875 case STREAM_SHA256_DIGEST:
876 case STREAM_SHA512_DIGEST:
879 case STREAM_SIGNED_DIGEST:
880 case STREAM_ENCRYPTED_FILE_DATA:
881 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
882 case STREAM_ENCRYPTED_WIN32_DATA:
883 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
885 #ifdef HAVE_DARWIN_OS
886 case STREAM_MACOS_FORK_DATA:
887 case STREAM_HFSPLUS_ATTRIBUTES:
889 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
890 #endif /* HAVE_CRYPTO */
891 #endif /* HAVE_DARWIN_OS */
892 case 0: /* compatibility with old tapes */
899 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
901 if (bfd->cmd_plugin && plugin_bopen) {
902 Dmsg1(50, "call plugin_bopen fname=%s\n", fname);
903 bfd->fid = plugin_bopen(bfd, fname, flags, mode);
904 Dmsg1(50, "Plugin bopen stat=%d\n", bfd->fid);
908 /* Normal file open */
909 Dmsg1(dbglvl, "open file %s\n", fname);
911 /* We use fnctl to set O_NOATIME if requested to avoid open error */
912 bfd->fid = open(fname, flags & ~O_NOATIME, mode);
914 /* Set O_NOATIME if possible */
915 if (bfd->fid != -1 && flags & O_NOATIME) {
916 int oldflags = fcntl(bfd->fid, F_GETFL, 0);
917 if (oldflags == -1) {
922 int ret = fcntl(bfd->fid, F_SETFL, oldflags | O_NOATIME);
923 /* EPERM means setting O_NOATIME was not allowed */
924 if (ret == -1 && errno != EPERM) {
932 bfd->m_flags = flags;
933 Dmsg1(400, "Open file %d\n", bfd->fid);
936 bfd->win32DecompContext.bIsInData = false;
937 bfd->win32DecompContext.liNextHeader = 0;
939 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
940 if (bfd->fid != -1 && flags & O_RDONLY) {
941 int stat = posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_WILLNEED);
942 Dmsg2(400, "Did posix_fadvise on %s stat=%d\n", fname, stat);
949 #ifdef HAVE_DARWIN_OS
950 /* Open the resource fork of a file. */
951 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
955 rsrc_fname = get_pool_memory(PM_FNAME);
956 pm_strcpy(rsrc_fname, fname);
957 pm_strcat(rsrc_fname, _PATH_RSRCFORKSPEC);
958 bopen(bfd, rsrc_fname, flags, mode);
959 free_pool_memory(rsrc_fname);
963 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
970 int bclose(BFILE *bfd)
974 Dmsg1(400, "Close file %d\n", bfd->fid);
976 if (bfd->cmd_plugin && plugin_bclose) {
977 stat = plugin_bclose(bfd);
979 bfd->cmd_plugin = false;
982 if (bfd->fid == -1) {
985 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
986 if (bfd->m_flags & O_RDONLY) {
987 fdatasync(bfd->fid); /* sync the file */
988 /* Tell OS we don't need it any more */
989 posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_DONTNEED);
993 /* Close normal file */
994 stat = close(bfd->fid);
997 bfd->cmd_plugin = false;
1001 ssize_t bread(BFILE *bfd, void *buf, size_t count)
1005 if (bfd->cmd_plugin && plugin_bread) {
1006 return plugin_bread(bfd, buf, count);
1009 stat = read(bfd->fid, buf, count);
1010 bfd->berrno = errno;
1014 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
1018 if (bfd->cmd_plugin && plugin_bwrite) {
1019 return plugin_bwrite(bfd, buf, count);
1021 stat = write(bfd->fid, buf, count);
1022 bfd->berrno = errno;
1026 bool is_bopen(BFILE *bfd)
1028 return bfd->fid >= 0;
1031 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
1035 if (bfd->cmd_plugin && plugin_bwrite) {
1036 return plugin_blseek(bfd, offset, whence);
1038 pos = (boffset_t)lseek(bfd->fid, offset, whence);
1039 bfd->berrno = errno;