2 Bacula® - The Network Backup Solution
4 Copyright (C) 2003-2008 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
42 const int dbglvl = 200;
44 int (*plugin_bopen)(BFILE *bfd, const char *fname, int flags, mode_t mode) = NULL;
45 int (*plugin_bclose)(BFILE *bfd) = NULL;
46 ssize_t (*plugin_bread)(BFILE *bfd, void *buf, size_t count) = NULL;
47 ssize_t (*plugin_bwrite)(BFILE *bfd, void *buf, size_t count) = NULL;
48 boffset_t (*plugin_blseek)(BFILE *bfd, boffset_t offset, int whence) = NULL;
52 #include <sys/paths.h>
55 #if !defined(HAVE_FDATASYNC)
60 void pause_msg(const char *file, const char *func, int line, const char *msg)
64 bsnprintf(buf, sizeof(buf), "%s:%s:%d %s", file, func, line, msg);
66 bsnprintf(buf, sizeof(buf), "%s:%s:%d", file, func, line);
68 MessageBox(NULL, buf, "Pause", MB_OK);
72 /* ===============================================================
74 * U N I X AND W I N D O W S
76 * ===============================================================
79 bool is_win32_stream(int stream)
82 case STREAM_WIN32_DATA:
83 case STREAM_WIN32_GZIP_DATA:
84 case STREAM_ENCRYPTED_WIN32_DATA:
85 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
91 const char *stream_to_ascii(int stream)
96 case STREAM_UNIX_ATTRIBUTES:
97 return _("Unix attributes");
98 case STREAM_FILE_DATA:
99 return _("File data");
100 case STREAM_MD5_DIGEST:
101 return _("MD5 digest");
102 case STREAM_GZIP_DATA:
103 return _("GZIP data");
104 case STREAM_UNIX_ATTRIBUTES_EX:
105 return _("Extended attributes");
106 case STREAM_SPARSE_DATA:
107 return _("Sparse data");
108 case STREAM_SPARSE_GZIP_DATA:
109 return _("GZIP sparse data");
110 case STREAM_PROGRAM_NAMES:
111 return _("Program names");
112 case STREAM_PROGRAM_DATA:
113 return _("Program data");
114 case STREAM_SHA1_DIGEST:
115 return _("SHA1 digest");
116 case STREAM_WIN32_DATA:
117 return _("Win32 data");
118 case STREAM_WIN32_GZIP_DATA:
119 return _("Win32 GZIP data");
120 case STREAM_MACOS_FORK_DATA:
121 return _("MacOS Fork data");
122 case STREAM_HFSPLUS_ATTRIBUTES:
123 return _("HFS+ attribs");
124 case STREAM_UNIX_ACCESS_ACL:
125 return _("Standard Unix ACL attribs");
126 case STREAM_UNIX_DEFAULT_ACL:
127 return _("Default Unix ACL attribs");
128 case STREAM_SHA256_DIGEST:
129 return _("SHA256 digest");
130 case STREAM_SHA512_DIGEST:
131 return _("SHA512 digest");
132 case STREAM_SIGNED_DIGEST:
133 return _("Signed digest");
134 case STREAM_ENCRYPTED_FILE_DATA:
135 return _("Encrypted File data");
136 case STREAM_ENCRYPTED_WIN32_DATA:
137 return _("Encrypted Win32 data");
138 case STREAM_ENCRYPTED_SESSION_DATA:
139 return _("Encrypted session data");
140 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
141 return _("Encrypted GZIP data");
142 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
143 return _("Encrypted Win32 GZIP data");
144 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
145 return _("Encrypted MacOS fork data");
147 sprintf(buf, "%d", stream);
148 return (const char *)buf;
153 void int64_LE2BE(int64_t* pBE, const int64_t v)
155 /* convert little endian to big endian */
156 if (htonl(1) != 1L) { /* no work if on little endian machine */
157 memcpy(pBE, &v, sizeof(int64_t));
160 uint8_t rv[sizeof(int64_t)];
161 uint8_t *pv = (uint8_t *) &v;
163 for (i = 0; i < 8; i++) {
166 memcpy(pBE, &rv, sizeof(int64_t));
171 void int32_LE2BE(int32_t* pBE, const int32_t v)
173 /* convert little endian to big endian */
174 if (htonl(1) != 1L) { /* no work if on little endian machine */
175 memcpy(pBE, &v, sizeof(int32_t));
178 uint8_t rv[sizeof(int32_t)];
179 uint8_t *pv = (uint8_t *) &v;
181 for (i = 0; i < 4; i++) {
184 memcpy(pBE, &rv, sizeof(int32_t));
189 bool processWin32BackupAPIBlock (BFILE *bfd, void *pBuffer, ssize_t dwSize)
191 /* pByte contains the buffer
192 dwSize the len to be processed. function assumes to be
193 called in successive incremental order over the complete
194 BackupRead stream beginning at pos 0 and ending at the end.
197 PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT* pContext = &(bfd->win32DecompContext);
198 bool bContinue = false;
199 int64_t dwDataOffset = 0;
202 /* Win32 Stream Header size without name of stream.
203 * = sizeof (WIN32_STREAM_ID)- sizeof(WCHAR*);
205 int32_t dwSizeHeader = 20;
208 if (pContext->liNextHeader >= dwSize) {
209 dwDataLen = dwSize-dwDataOffset;
210 bContinue = false; /* 1 iteration is enough */
212 dwDataLen = pContext->liNextHeader-dwDataOffset;
213 bContinue = true; /* multiple iterations may be necessary */
217 /* copy block of real DATA */
218 if (pContext->bIsInData) {
219 if (bwrite(bfd, ((char *)pBuffer)+dwDataOffset, dwDataLen) != (ssize_t)dwDataLen)
223 if (pContext->liNextHeader < dwSize) {/* is a header in this block ? */
224 int32_t dwOffsetTarget;
225 int32_t dwOffsetSource;
227 if (pContext->liNextHeader < 0) {
228 /* start of header was before this block, so we
229 * continue with the part in the current block
231 dwOffsetTarget = -pContext->liNextHeader;
234 /* start of header is inside of this block */
236 dwOffsetSource = pContext->liNextHeader;
239 int32_t dwHeaderPartLen = dwSizeHeader-dwOffsetTarget;
240 bool bHeaderIsComplete;
242 if (dwHeaderPartLen <= dwSize-dwOffsetSource) {
243 /* header (or rest of header) is completely available
246 bHeaderIsComplete = true;
248 /* header will continue in next block */
249 bHeaderIsComplete = false;
250 dwHeaderPartLen = dwSize-dwOffsetSource;
253 /* copy the available portion of header to persistent copy */
254 memcpy(((char *)&pContext->header_stream)+dwOffsetTarget, ((char *)pBuffer)+dwOffsetSource, dwHeaderPartLen);
256 /* recalculate position of next header */
257 if (bHeaderIsComplete) {
258 /* convert stream name size (32 bit little endian) to machine type */
260 int32_LE2BE (&dwNameSize, pContext->header_stream.dwStreamNameSize);
261 dwDataOffset = dwNameSize+pContext->liNextHeader+dwSizeHeader;
263 /* convert stream size (64 bit little endian) to machine type */
264 int64_LE2BE (&(pContext->liNextHeader), pContext->header_stream.Size);
265 pContext->liNextHeader += dwDataOffset;
267 pContext->bIsInData = pContext->header_stream.dwStreamId == WIN32_BACKUP_DATA;
268 if (dwDataOffset == dwSize)
271 /* stop and continue with next block */
273 pContext->bIsInData = false;
278 /* set "NextHeader" relative to the beginning of the next block */
279 pContext->liNextHeader-= dwSize;
286 /* ===============================================================
290 * ===============================================================
293 #if defined(HAVE_WIN32)
295 void unix_name_to_win32(POOLMEM **win32_name, char *name);
296 extern "C" HANDLE get_osfhandle(int fd);
299 void binit(BFILE *bfd)
301 memset(bfd, 0, sizeof(BFILE));
303 bfd->mode = BF_CLOSED;
304 bfd->use_backup_api = have_win32_api();
305 bfd->cmd_plugin = false;
309 * Enables using the Backup API (win32_data).
310 * Returns 1 if function worked
311 * Returns 0 if failed (i.e. do not have Backup API on this machine)
313 bool set_win32_backup(BFILE *bfd)
315 /* We enable if possible here */
316 bfd->use_backup_api = have_win32_api();
317 return bfd->use_backup_api;
321 bool set_portable_backup(BFILE *bfd)
323 bfd->use_backup_api = false;
327 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
329 bfd->cmd_plugin = true;
335 * Return 1 if we are NOT using Win32 BackupWrite()
338 bool is_portable_backup(BFILE *bfd)
340 return !bfd->use_backup_api;
343 bool have_win32_api()
345 return p_BackupRead && p_BackupWrite;
350 * Return true if we support the stream
351 * false if we do not support the stream
353 * This code is running under Win32, so we
354 * do not need #ifdef on MACOS ...
356 bool is_restore_stream_supported(int stream)
360 /* Streams known not to be supported */
362 case STREAM_GZIP_DATA:
363 case STREAM_SPARSE_GZIP_DATA:
364 case STREAM_WIN32_GZIP_DATA:
366 case STREAM_MACOS_FORK_DATA:
367 case STREAM_HFSPLUS_ATTRIBUTES:
368 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
373 case STREAM_GZIP_DATA:
374 case STREAM_SPARSE_GZIP_DATA:
375 case STREAM_WIN32_GZIP_DATA:
377 case STREAM_WIN32_DATA:
378 case STREAM_UNIX_ATTRIBUTES:
379 case STREAM_FILE_DATA:
380 case STREAM_MD5_DIGEST:
381 case STREAM_UNIX_ATTRIBUTES_EX:
382 case STREAM_SPARSE_DATA:
383 case STREAM_PROGRAM_NAMES:
384 case STREAM_PROGRAM_DATA:
385 case STREAM_SHA1_DIGEST:
387 case STREAM_SHA256_DIGEST:
388 case STREAM_SHA512_DIGEST:
391 case STREAM_SIGNED_DIGEST:
392 case STREAM_ENCRYPTED_FILE_DATA:
393 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
394 case STREAM_ENCRYPTED_WIN32_DATA:
395 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
397 case 0: /* compatibility with old tapes */
403 HANDLE bget_handle(BFILE *bfd)
408 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
410 POOLMEM *win32_fname;
411 POOLMEM *win32_fname_wchar;
413 DWORD dwaccess, dwflags, dwshare;
415 /* Convert to Windows path format */
416 win32_fname = get_pool_memory(PM_FNAME);
417 win32_fname_wchar = get_pool_memory(PM_FNAME);
419 unix_name_to_win32(&win32_fname, (char *)fname);
421 if (bfd->cmd_plugin && plugin_bopen) {
423 Dmsg1(50, "call plugin_bopen fname=%s\n", fname);
424 rtnstat = plugin_bopen(bfd, fname, flags, mode);
425 Dmsg1(50, "return from plugin_bopen status=%d\n", rtnstat);
427 if (flags & O_CREAT || flags & O_WRONLY) { /* Open existing for write */
428 Dmsg1(50, "plugin_open for write OK file=%s.\n", fname);
429 bfd->mode = BF_WRITE;
431 Dmsg1(50, "plugin_open for read OK file=%s.\n", fname);
435 bfd->mode = BF_CLOSED;
436 Dmsg1(000, "==== plugin_bopen returned bad status=%d\n", rtnstat);
438 free_pool_memory(win32_fname_wchar);
439 free_pool_memory(win32_fname);
440 return bfd->mode == BF_CLOSED ? -1 : 1;
442 Dmsg0(50, "=== NOT plugin\n");
444 if (!(p_CreateFileA || p_CreateFileW))
447 if (p_CreateFileW && p_MultiByteToWideChar)
448 make_win32_path_UTF8_2_wchar(&win32_fname_wchar, fname);
450 if (flags & O_CREAT) { /* Create */
451 if (bfd->use_backup_api) {
452 dwaccess = GENERIC_WRITE|FILE_ALL_ACCESS|WRITE_OWNER|WRITE_DAC|ACCESS_SYSTEM_SECURITY;
453 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
455 dwaccess = GENERIC_WRITE;
459 if (p_CreateFileW && p_MultiByteToWideChar) {
460 // unicode open for create write
461 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
462 dwaccess, /* Requested access */
464 NULL, /* SecurityAttributes */
465 CREATE_ALWAYS, /* CreationDisposition */
466 dwflags, /* Flags and attributes */
467 NULL); /* TemplateFile */
470 bfd->fh = p_CreateFileA(win32_fname,
471 dwaccess, /* Requested access */
473 NULL, /* SecurityAttributes */
474 CREATE_ALWAYS, /* CreationDisposition */
475 dwflags, /* Flags and attributes */
476 NULL); /* TemplateFile */
479 bfd->mode = BF_WRITE;
481 } else if (flags & O_WRONLY) { /* Open existing for write */
482 if (bfd->use_backup_api) {
483 dwaccess = GENERIC_WRITE|WRITE_OWNER|WRITE_DAC;
484 dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT;
486 dwaccess = GENERIC_WRITE;
490 if (p_CreateFileW && p_MultiByteToWideChar) {
491 // unicode open for open existing write
492 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
493 dwaccess, /* Requested access */
495 NULL, /* SecurityAttributes */
496 OPEN_EXISTING, /* CreationDisposition */
497 dwflags, /* Flags and attributes */
498 NULL); /* TemplateFile */
501 bfd->fh = p_CreateFileA(win32_fname,
502 dwaccess, /* Requested access */
504 NULL, /* SecurityAttributes */
505 OPEN_EXISTING, /* CreationDisposition */
506 dwflags, /* Flags and attributes */
507 NULL); /* TemplateFile */
511 bfd->mode = BF_WRITE;
514 if (bfd->use_backup_api) {
515 dwaccess = GENERIC_READ|READ_CONTROL|ACCESS_SYSTEM_SECURITY;
516 dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_SEQUENTIAL_SCAN |
517 FILE_FLAG_OPEN_REPARSE_POINT;
518 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
520 dwaccess = GENERIC_READ;
522 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE;
525 if (p_CreateFileW && p_MultiByteToWideChar) {
526 // unicode open for open existing read
527 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
528 dwaccess, /* Requested access */
529 dwshare, /* Share modes */
530 NULL, /* SecurityAttributes */
531 OPEN_EXISTING, /* CreationDisposition */
532 dwflags, /* Flags and attributes */
533 NULL); /* TemplateFile */
536 bfd->fh = p_CreateFileA(win32_fname,
537 dwaccess, /* Requested access */
538 dwshare, /* Share modes */
539 NULL, /* SecurityAttributes */
540 OPEN_EXISTING, /* CreationDisposition */
541 dwflags, /* Flags and attributes */
542 NULL); /* TemplateFile */
548 if (bfd->fh == INVALID_HANDLE_VALUE) {
549 bfd->lerror = GetLastError();
550 bfd->berrno = b_errno_win32;
551 errno = b_errno_win32;
552 bfd->mode = BF_CLOSED;
555 bfd->lpContext = NULL;
556 bfd->win32DecompContext.bIsInData = false;
557 bfd->win32DecompContext.liNextHeader = 0;
558 free_pool_memory(win32_fname_wchar);
559 free_pool_memory(win32_fname);
560 return bfd->mode == BF_CLOSED ? -1 : 1;
564 * Returns 0 on success
567 int bclose(BFILE *bfd)
572 free_pool_memory(bfd->errmsg);
575 if (bfd->mode == BF_CLOSED) {
576 Dmsg0(50, "=== BFD already closed.\n");
580 if (bfd->cmd_plugin && plugin_bclose) {
581 stat = plugin_bclose(bfd);
582 Dmsg0(50, "==== BFD closed!!!\n");
587 * We need to tell the API to release the buffer it
588 * allocated in lpContext. We do so by calling the
589 * API one more time, but with the Abort bit set.
591 if (bfd->use_backup_api && bfd->mode == BF_READ) {
593 if (bfd->lpContext && !p_BackupRead(bfd->fh,
595 (DWORD)0, /* bytes to read */
596 &bfd->rw_bytes, /* bytes read */
598 1, /* ProcessSecurity */
599 &bfd->lpContext)) { /* Read context */
600 errno = b_errno_win32;
603 } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
605 if (bfd->lpContext && !p_BackupWrite(bfd->fh,
607 (DWORD)0, /* bytes to read */
608 &bfd->rw_bytes, /* bytes written */
610 1, /* ProcessSecurity */
611 &bfd->lpContext)) { /* Write context */
612 errno = b_errno_win32;
616 if (!CloseHandle(bfd->fh)) {
618 errno = b_errno_win32;
622 bfd->mode = BF_CLOSED;
623 bfd->lpContext = NULL;
624 bfd->cmd_plugin = false;
628 /* Returns: bytes read on success
632 ssize_t bread(BFILE *bfd, void *buf, size_t count)
636 if (bfd->cmd_plugin && plugin_bread) {
637 return plugin_bread(bfd, buf, count);
640 if (bfd->use_backup_api) {
641 if (!p_BackupRead(bfd->fh,
646 1, /* Process Security */
647 &bfd->lpContext)) { /* Context */
648 bfd->lerror = GetLastError();
649 bfd->berrno = b_errno_win32;
650 errno = b_errno_win32;
654 if (!ReadFile(bfd->fh,
659 bfd->lerror = GetLastError();
660 bfd->berrno = b_errno_win32;
661 errno = b_errno_win32;
666 return (ssize_t)bfd->rw_bytes;
669 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
673 if (bfd->cmd_plugin && plugin_bwrite) {
674 return plugin_bwrite(bfd, buf, count);
677 if (bfd->use_backup_api) {
678 if (!p_BackupWrite(bfd->fh,
683 1, /* Process Security */
684 &bfd->lpContext)) { /* Context */
685 bfd->lerror = GetLastError();
686 bfd->berrno = b_errno_win32;
687 errno = b_errno_win32;
691 if (!WriteFile(bfd->fh,
696 bfd->lerror = GetLastError();
697 bfd->berrno = b_errno_win32;
698 errno = b_errno_win32;
702 return (ssize_t)bfd->rw_bytes;
705 bool is_bopen(BFILE *bfd)
707 return bfd->mode != BF_CLOSED;
710 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
712 LONG offset_low = (LONG)offset;
713 LONG offset_high = (LONG)(offset >> 32);
716 if (bfd->cmd_plugin && plugin_blseek) {
717 return plugin_blseek(bfd, offset, whence);
720 dwResult = SetFilePointer(bfd->fh, offset_low, &offset_high, whence);
722 if (dwResult == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
723 return (boffset_t)-1;
726 return ((boffset_t)offset_high << 32) | dwResult;
729 #else /* Unix systems */
731 /* ===============================================================
735 * ===============================================================
737 void binit(BFILE *bfd)
739 memset(bfd, 0, sizeof(BFILE));
743 bool have_win32_api()
745 return false; /* no can do */
749 * Enables using the Backup API (win32_data).
750 * Returns true if function worked
751 * Returns false if failed (i.e. do not have Backup API on this machine)
753 bool set_win32_backup(BFILE *bfd)
755 return false; /* no can do */
759 bool set_portable_backup(BFILE *bfd)
761 return true; /* no problem */
765 * Return true if we are writing in portable format
766 * return false if not
768 bool is_portable_backup(BFILE *bfd)
770 return true; /* portable by definition */
773 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
778 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
780 bfd->cmd_plugin = true;
786 * This code is running on a non-Win32 machine
788 bool is_restore_stream_supported(int stream)
790 /* No Win32 backup on this machine */
793 case STREAM_GZIP_DATA:
794 case STREAM_SPARSE_GZIP_DATA:
795 case STREAM_WIN32_GZIP_DATA:
797 #ifndef HAVE_DARWIN_OS
798 case STREAM_MACOS_FORK_DATA:
799 case STREAM_HFSPLUS_ATTRIBUTES:
805 case STREAM_GZIP_DATA:
806 case STREAM_SPARSE_GZIP_DATA:
807 case STREAM_WIN32_GZIP_DATA:
809 case STREAM_WIN32_DATA:
810 case STREAM_UNIX_ATTRIBUTES:
811 case STREAM_FILE_DATA:
812 case STREAM_MD5_DIGEST:
813 case STREAM_UNIX_ATTRIBUTES_EX:
814 case STREAM_SPARSE_DATA:
815 case STREAM_PROGRAM_NAMES:
816 case STREAM_PROGRAM_DATA:
817 case STREAM_SHA1_DIGEST:
819 case STREAM_SHA256_DIGEST:
820 case STREAM_SHA512_DIGEST:
823 case STREAM_SIGNED_DIGEST:
824 case STREAM_ENCRYPTED_FILE_DATA:
825 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
826 case STREAM_ENCRYPTED_WIN32_DATA:
827 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
829 #ifdef HAVE_DARWIN_OS
830 case STREAM_MACOS_FORK_DATA:
831 case STREAM_HFSPLUS_ATTRIBUTES:
833 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
834 #endif /* HAVE_CRYPTO */
835 #endif /* HAVE_DARWIN_OS */
836 case 0: /* compatibility with old tapes */
843 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
845 if (bfd->cmd_plugin && plugin_bopen) {
846 Dmsg1(50, "call plugin_bopen fname=%s\n", fname);
847 bfd->fid = plugin_bopen(bfd, fname, flags, mode);
848 Dmsg1(50, "Plugin bopen stat=%d\n", bfd->fid);
852 /* Normal file open */
853 Dmsg1(dbglvl, "open file %s\n", fname);
855 /* We use fnctl to set O_NOATIME if requested to avoid open error */
856 bfd->fid = open(fname, flags & ~O_NOATIME, mode);
858 /* Set O_NOATIME if possible */
859 if (bfd->fid != -1 && flags & O_NOATIME) {
860 int oldflags = fcntl(bfd->fid, F_GETFL, 0);
861 if (oldflags == -1) {
866 int ret = fcntl(bfd->fid, F_SETFL, oldflags | O_NOATIME);
867 /* EPERM means setting O_NOATIME was not allowed */
868 if (ret == -1 && errno != EPERM) {
876 bfd->m_flags = flags;
877 Dmsg1(400, "Open file %d\n", bfd->fid);
880 bfd->win32DecompContext.bIsInData = false;
881 bfd->win32DecompContext.liNextHeader = 0;
883 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
884 if (bfd->fid != -1 && flags & O_RDONLY) {
885 int stat = posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_WILLNEED);
886 Dmsg2(400, "Did posix_fadvise on %s stat=%d\n", fname, stat);
893 #ifdef HAVE_DARWIN_OS
894 /* Open the resource fork of a file. */
895 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
899 rsrc_fname = get_pool_memory(PM_FNAME);
900 pm_strcpy(rsrc_fname, fname);
901 pm_strcat(rsrc_fname, _PATH_RSRCFORKSPEC);
902 bopen(bfd, rsrc_fname, flags, mode);
903 free_pool_memory(rsrc_fname);
909 int bclose(BFILE *bfd)
913 Dmsg1(400, "Close file %d\n", bfd->fid);
915 if (bfd->cmd_plugin && plugin_bclose) {
916 stat = plugin_bclose(bfd);
918 bfd->cmd_plugin = false;
921 if (bfd->fid == -1) {
924 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
925 if (bfd->m_flags & O_RDONLY) {
926 fdatasync(bfd->fid); /* sync the file */
927 /* Tell OS we don't need it any more */
928 posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_DONTNEED);
932 /* Close normal file */
933 stat = close(bfd->fid);
936 bfd->cmd_plugin = false;
940 ssize_t bread(BFILE *bfd, void *buf, size_t count)
944 if (bfd->cmd_plugin && plugin_bread) {
945 return plugin_bread(bfd, buf, count);
948 stat = read(bfd->fid, buf, count);
953 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
957 if (bfd->cmd_plugin && plugin_bwrite) {
958 return plugin_bwrite(bfd, buf, count);
960 stat = write(bfd->fid, buf, count);
965 bool is_bopen(BFILE *bfd)
967 return bfd->fid >= 0;
970 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
974 if (bfd->cmd_plugin && plugin_bwrite) {
975 return plugin_blseek(bfd, offset, whence);
977 pos = (boffset_t)lseek(bfd->fid, offset, whence);