2 * Bacula low level File I/O routines. This routine simulates
3 * open(), read(), write(), and close(), but using native routines.
4 * I.e. on Windows, we use Windows APIs.
6 * Kern Sibbald, April MMIII
12 Bacula® - The Network Backup Solution
14 Copyright (C) 2003-2006 Free Software Foundation Europe e.V.
16 The main author of Bacula is Kern Sibbald, with contributions from
17 many others, a complete list can be found in the file AUTHORS.
18 This program is Free Software; you can redistribute it and/or
19 modify it under the terms of version two of the GNU General Public
20 License as published by the Free Software Foundation plus additions
21 that are listed in the file LICENSE.
23 This program is distributed in the hope that it will be useful, but
24 WITHOUT ANY WARRANTY; without even the implied warranty of
25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 General Public License for more details.
28 You should have received a copy of the GNU General Public License
29 along with this program; if not, write to the Free Software
30 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
33 Bacula® is a registered trademark of John Walker.
34 The licensor of Bacula is the Free Software Foundation Europe
35 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
36 Switzerland, email:ftf@fsfeurope.org.
42 bool (*python_set_prog)(JCR *jcr, const char *prog) = NULL;
43 int (*python_open)(BFILE *bfd, const char *fname, int flags, mode_t mode) = NULL;
44 int (*python_close)(BFILE *bfd) = NULL;
45 ssize_t (*python_read)(BFILE *bfd, void *buf, size_t count) = NULL;
46 ssize_t (*python_write)(BFILE *bfd, void *buf, size_t count) = NULL;
49 #include <sys/paths.h>
52 /* ===============================================================
54 * U N I X AND W I N D O W S
56 * ===============================================================
59 bool is_win32_stream(int stream)
62 case STREAM_WIN32_DATA:
63 case STREAM_WIN32_GZIP_DATA:
64 case STREAM_ENCRYPTED_WIN32_DATA:
65 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
71 const char *stream_to_ascii(int stream)
76 case STREAM_GZIP_DATA:
77 return _("GZIP data");
78 case STREAM_SPARSE_GZIP_DATA:
79 return _("GZIP sparse data");
80 case STREAM_WIN32_DATA:
81 return _("Win32 data");
82 case STREAM_WIN32_GZIP_DATA:
83 return _("Win32 GZIP data");
84 case STREAM_UNIX_ATTRIBUTES:
85 return _("File attributes");
86 case STREAM_FILE_DATA:
87 return _("File data");
88 case STREAM_MD5_DIGEST:
89 return _("MD5 digest");
90 case STREAM_UNIX_ATTRIBUTES_EX:
91 return _("Extended attributes");
92 case STREAM_SPARSE_DATA:
93 return _("Sparse data");
94 case STREAM_PROGRAM_NAMES:
95 return _("Program names");
96 case STREAM_PROGRAM_DATA:
97 return _("Program data");
98 case STREAM_SHA1_DIGEST:
99 return _("SHA1 digest");
100 case STREAM_MACOS_FORK_DATA:
101 return _("HFS+ resource fork");
102 case STREAM_HFSPLUS_ATTRIBUTES:
103 return _("HFS+ Finder Info");
104 case STREAM_SHA256_DIGEST:
105 return _("SHA256 digest");
106 case STREAM_SHA512_DIGEST:
107 return _("SHA512 digest");
108 case STREAM_SIGNED_DIGEST:
109 return _("Signed digest");
110 case STREAM_ENCRYPTED_FILE_DATA:
111 return _("Encrypted File data");
112 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
113 return _("Encrypted GZIP data");
114 case STREAM_ENCRYPTED_WIN32_DATA:
115 return _("Encrypted Win32 data");
116 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
117 return _("Encrypted Win32 GZIP data");
118 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
119 return _("Encrypted HFS+ resource fork");
121 sprintf(buf, "%d", stream);
122 return (const char *)buf;
127 void int64_LE2BE(int64_t* pBE, const int64_t v)
129 /* convert little endian to big endian */
130 if (htonl(1) != 1L) { /* no work if on little endian machine */
131 memcpy(pBE, &v, sizeof(int64_t));
134 uint8_t rv[sizeof(int64_t)];
135 uint8_t *pv = (uint8_t *) &v;
137 for (i = 0; i < 8; i++) {
140 memcpy(pBE, &rv, sizeof(int64_t));
145 void int32_LE2BE(int32_t* pBE, const int32_t v)
147 /* convert little endian to big endian */
148 if (htonl(1) != 1L) { /* no work if on little endian machine */
149 memcpy(pBE, &v, sizeof(int32_t));
152 uint8_t rv[sizeof(int32_t)];
153 uint8_t *pv = (uint8_t *) &v;
155 for (i = 0; i < 4; i++) {
158 memcpy(pBE, &rv, sizeof(int32_t));
163 bool processWin32BackupAPIBlock (BFILE *bfd, void *pBuffer, ssize_t dwSize)
165 /* pByte contains the buffer
166 dwSize the len to be processed. function assumes to be
167 called in successive incremental order over the complete
168 BackupRead stream beginning at pos 0 and ending at the end.
171 PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT* pContext = &(bfd->win32DecompContext);
172 bool bContinue = false;
173 int64_t dwDataOffset = 0;
176 /* Win32 Stream Header size without name of stream.
177 * = sizeof (WIN32_STREAM_ID)- sizeof(WCHAR*);
179 int32_t dwSizeHeader = 20;
182 if (pContext->liNextHeader >= dwSize) {
183 dwDataLen = dwSize-dwDataOffset;
184 bContinue = false; /* 1 iteration is enough */
186 dwDataLen = pContext->liNextHeader-dwDataOffset;
187 bContinue = true; /* multiple iterations may be necessary */
191 /* copy block of real DATA */
192 if (pContext->bIsInData) {
193 if (bwrite(bfd, ((char *)pBuffer)+dwDataOffset, dwDataLen) != (ssize_t)dwDataLen)
197 if (pContext->liNextHeader < dwSize) {/* is a header in this block ? */
198 int32_t dwOffsetTarget;
199 int32_t dwOffsetSource;
201 if (pContext->liNextHeader < 0) {
202 /* start of header was before this block, so we
203 * continue with the part in the current block
205 dwOffsetTarget = -pContext->liNextHeader;
208 /* start of header is inside of this block */
210 dwOffsetSource = pContext->liNextHeader;
213 int32_t dwHeaderPartLen = dwSizeHeader-dwOffsetTarget;
214 bool bHeaderIsComplete;
216 if (dwHeaderPartLen <= dwSize-dwOffsetSource) {
217 /* header (or rest of header) is completely available
220 bHeaderIsComplete = true;
222 /* header will continue in next block */
223 bHeaderIsComplete = false;
224 dwHeaderPartLen = dwSize-dwOffsetSource;
227 /* copy the available portion of header to persistent copy */
228 memcpy(((char *)&pContext->header_stream)+dwOffsetTarget, ((char *)pBuffer)+dwOffsetSource, dwHeaderPartLen);
230 /* recalculate position of next header */
231 if (bHeaderIsComplete) {
232 /* convert stream name size (32 bit little endian) to machine type */
234 int32_LE2BE (&dwNameSize, pContext->header_stream.dwStreamNameSize);
235 dwDataOffset = dwNameSize+pContext->liNextHeader+dwSizeHeader;
237 /* convert stream size (64 bit little endian) to machine type */
238 int64_LE2BE (&(pContext->liNextHeader), pContext->header_stream.Size);
239 pContext->liNextHeader += dwDataOffset;
241 pContext->bIsInData = pContext->header_stream.dwStreamId == WIN32_BACKUP_DATA;
242 if (dwDataOffset == dwSize)
245 /* stop and continue with next block */
247 pContext->bIsInData = false;
252 /* set "NextHeader" relative to the beginning of the next block */
253 pContext->liNextHeader-= dwSize;
260 /* ===============================================================
264 * ===============================================================
267 #if defined(HAVE_WIN32)
269 void unix_name_to_win32(POOLMEM **win32_name, char *name);
270 extern "C" HANDLE get_osfhandle(int fd);
273 void binit(BFILE *bfd)
275 memset(bfd, 0, sizeof(BFILE));
277 bfd->mode = BF_CLOSED;
278 bfd->use_backup_api = have_win32_api();
282 * Enables using the Backup API (win32_data).
283 * Returns 1 if function worked
284 * Returns 0 if failed (i.e. do not have Backup API on this machine)
286 bool set_win32_backup(BFILE *bfd)
288 /* We enable if possible here */
289 bfd->use_backup_api = have_win32_api();
290 return bfd->use_backup_api;
294 bool set_portable_backup(BFILE *bfd)
296 bfd->use_backup_api = false;
300 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
308 * Return 1 if we are NOT using Win32 BackupWrite()
311 bool is_portable_backup(BFILE *bfd)
313 return !bfd->use_backup_api;
316 bool have_win32_api()
318 return p_BackupRead && p_BackupWrite;
323 * Return true if we support the stream
324 * false if we do not support the stream
326 * This code is running under Win32, so we
327 * do not need #ifdef on MACOS ...
329 bool is_restore_stream_supported(int stream)
333 /* Streams known not to be supported */
335 case STREAM_GZIP_DATA:
336 case STREAM_SPARSE_GZIP_DATA:
337 case STREAM_WIN32_GZIP_DATA:
339 case STREAM_MACOS_FORK_DATA:
340 case STREAM_HFSPLUS_ATTRIBUTES:
341 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
346 case STREAM_GZIP_DATA:
347 case STREAM_SPARSE_GZIP_DATA:
348 case STREAM_WIN32_GZIP_DATA:
350 case STREAM_WIN32_DATA:
351 case STREAM_UNIX_ATTRIBUTES:
352 case STREAM_FILE_DATA:
353 case STREAM_MD5_DIGEST:
354 case STREAM_UNIX_ATTRIBUTES_EX:
355 case STREAM_SPARSE_DATA:
356 case STREAM_PROGRAM_NAMES:
357 case STREAM_PROGRAM_DATA:
358 case STREAM_SHA1_DIGEST:
360 case STREAM_SHA256_DIGEST:
361 case STREAM_SHA512_DIGEST:
364 case STREAM_SIGNED_DIGEST:
365 case STREAM_ENCRYPTED_FILE_DATA:
366 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
367 case STREAM_ENCRYPTED_WIN32_DATA:
368 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
370 case 0: /* compatibility with old tapes */
376 HANDLE bget_handle(BFILE *bfd)
381 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
383 POOLMEM *win32_fname;
384 POOLMEM *win32_fname_wchar;
386 DWORD dwaccess, dwflags, dwshare;
388 /* Convert to Windows path format */
389 win32_fname = get_pool_memory(PM_FNAME);
390 win32_fname_wchar = get_pool_memory(PM_FNAME);
392 unix_name_to_win32(&win32_fname, (char *)fname);
394 if (!(p_CreateFileA || p_CreateFileW))
397 if (p_CreateFileW && p_MultiByteToWideChar)
398 make_win32_path_UTF8_2_wchar(&win32_fname_wchar, fname);
400 if (flags & O_CREAT) { /* Create */
401 if (bfd->use_backup_api) {
402 dwaccess = GENERIC_WRITE|FILE_ALL_ACCESS|WRITE_OWNER|WRITE_DAC|ACCESS_SYSTEM_SECURITY;
403 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
405 dwaccess = GENERIC_WRITE;
409 // unicode or ansii open for create write
410 if (p_CreateFileW && p_MultiByteToWideChar) {
411 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
412 dwaccess, /* Requested access */
414 NULL, /* SecurityAttributes */
415 CREATE_ALWAYS, /* CreationDisposition */
416 dwflags, /* Flags and attributes */
417 NULL); /* TemplateFile */
419 bfd->fh = p_CreateFileA(win32_fname,
420 dwaccess, /* Requested access */
422 NULL, /* SecurityAttributes */
423 CREATE_ALWAYS, /* CreationDisposition */
424 dwflags, /* Flags and attributes */
425 NULL); /* TemplateFile */
428 bfd->mode = BF_WRITE;
430 } else if (flags & O_WRONLY) { /* Open existing for write */
431 if (bfd->use_backup_api) {
432 dwaccess = GENERIC_WRITE|WRITE_OWNER|WRITE_DAC;
433 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
435 dwaccess = GENERIC_WRITE;
439 // unicode or ansii open for open existing write
440 if (p_CreateFileW && p_MultiByteToWideChar) {
441 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
442 dwaccess, /* Requested access */
444 NULL, /* SecurityAttributes */
445 OPEN_EXISTING, /* CreationDisposition */
446 dwflags, /* Flags and attributes */
447 NULL); /* TemplateFile */
449 bfd->fh = p_CreateFileA(win32_fname,
450 dwaccess, /* Requested access */
452 NULL, /* SecurityAttributes */
453 OPEN_EXISTING, /* CreationDisposition */
454 dwflags, /* Flags and attributes */
455 NULL); /* TemplateFile */
459 bfd->mode = BF_WRITE;
462 if (bfd->use_backup_api) {
463 dwaccess = GENERIC_READ|READ_CONTROL|ACCESS_SYSTEM_SECURITY;
464 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
465 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
467 dwaccess = GENERIC_READ;
469 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE;
472 // unicode or ansii open for open existing read
473 if (p_CreateFileW && p_MultiByteToWideChar) {
474 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
475 dwaccess, /* Requested access */
476 dwshare, /* Share modes */
477 NULL, /* SecurityAttributes */
478 OPEN_EXISTING, /* CreationDisposition */
479 dwflags, /* Flags and attributes */
480 NULL); /* TemplateFile */
482 bfd->fh = p_CreateFileA(win32_fname,
483 dwaccess, /* Requested access */
484 dwshare, /* Share modes */
485 NULL, /* SecurityAttributes */
486 OPEN_EXISTING, /* CreationDisposition */
487 dwflags, /* Flags and attributes */
488 NULL); /* TemplateFile */
494 if (bfd->fh == INVALID_HANDLE_VALUE) {
495 bfd->lerror = GetLastError();
496 bfd->berrno = b_errno_win32;
497 errno = b_errno_win32;
498 bfd->mode = BF_CLOSED;
501 bfd->lpContext = NULL;
502 bfd->win32DecompContext.bIsInData = false;
503 bfd->win32DecompContext.liNextHeader = 0;
504 free_pool_memory(win32_fname_wchar);
505 free_pool_memory(win32_fname);
506 return bfd->mode == BF_CLOSED ? -1 : 1;
510 * Returns 0 on success
513 int bclose(BFILE *bfd)
518 free_pool_memory(bfd->errmsg);
521 if (bfd->mode == BF_CLOSED) {
524 if (bfd->use_backup_api && bfd->mode == BF_READ) {
526 if (!bfd->lpContext && !p_BackupRead(bfd->fh,
528 (DWORD)0, /* bytes to read */
529 &bfd->rw_bytes, /* bytes read */
531 1, /* ProcessSecurity */
532 &bfd->lpContext)) { /* Read context */
533 errno = b_errno_win32;
536 } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
538 if (!bfd->lpContext && !p_BackupWrite(bfd->fh,
540 (DWORD)0, /* bytes to read */
541 &bfd->rw_bytes, /* bytes written */
543 1, /* ProcessSecurity */
544 &bfd->lpContext)) { /* Write context */
545 errno = b_errno_win32;
549 if (!CloseHandle(bfd->fh)) {
551 errno = b_errno_win32;
553 bfd->mode = BF_CLOSED;
554 bfd->lpContext = NULL;
558 /* Returns: bytes read on success
562 ssize_t bread(BFILE *bfd, void *buf, size_t count)
566 if (bfd->use_backup_api) {
567 if (!p_BackupRead(bfd->fh,
572 1, /* Process Security */
573 &bfd->lpContext)) { /* Context */
574 bfd->lerror = GetLastError();
575 bfd->berrno = b_errno_win32;
576 errno = b_errno_win32;
580 if (!ReadFile(bfd->fh,
585 bfd->lerror = GetLastError();
586 bfd->berrno = b_errno_win32;
587 errno = b_errno_win32;
592 return (ssize_t)bfd->rw_bytes;
595 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
599 if (bfd->use_backup_api) {
600 if (!p_BackupWrite(bfd->fh,
605 1, /* Process Security */
606 &bfd->lpContext)) { /* Context */
607 bfd->lerror = GetLastError();
608 bfd->berrno = b_errno_win32;
609 errno = b_errno_win32;
613 if (!WriteFile(bfd->fh,
618 bfd->lerror = GetLastError();
619 bfd->berrno = b_errno_win32;
620 errno = b_errno_win32;
624 return (ssize_t)bfd->rw_bytes;
627 bool is_bopen(BFILE *bfd)
629 return bfd->mode != BF_CLOSED;
632 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
634 LONG offset_low = (LONG)offset;
635 LONG offset_high = (LONG)(offset >> 32);
638 dwResult = SetFilePointer(bfd->fh, offset_low, &offset_high, whence);
640 if (dwResult == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
641 return (boffset_t)-1;
644 return ((boffset_t)offset_high << 32) | dwResult;
647 #else /* Unix systems */
649 /* ===============================================================
653 * ===============================================================
655 void binit(BFILE *bfd)
657 memset(bfd, 0, sizeof(BFILE));
661 bool have_win32_api()
663 return false; /* no can do */
667 * Enables using the Backup API (win32_data).
668 * Returns true if function worked
669 * Returns false if failed (i.e. do not have Backup API on this machine)
671 bool set_win32_backup(BFILE *bfd)
673 return false; /* no can do */
677 bool set_portable_backup(BFILE *bfd)
679 return true; /* no problem */
683 * Return true if we are writing in portable format
684 * return false if not
686 bool is_portable_backup(BFILE *bfd)
688 return true; /* portable by definition */
691 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
694 if (bfd->prog && strcmp(prog, bfd->prog) == 0) {
695 return true; /* already setup */
698 if (python_set_prog(jcr, prog)) {
699 Dmsg1(000, "Set prog=%s\n", prog);
705 Dmsg0(000, "No prog set\n");
712 * This code is running on a non-Win32 machine
714 bool is_restore_stream_supported(int stream)
716 /* No Win32 backup on this machine */
719 case STREAM_GZIP_DATA:
720 case STREAM_SPARSE_GZIP_DATA:
721 case STREAM_WIN32_GZIP_DATA:
723 #ifndef HAVE_DARWIN_OS
724 case STREAM_MACOS_FORK_DATA:
725 case STREAM_HFSPLUS_ATTRIBUTES:
731 case STREAM_GZIP_DATA:
732 case STREAM_SPARSE_GZIP_DATA:
733 case STREAM_WIN32_GZIP_DATA:
735 case STREAM_WIN32_DATA:
736 case STREAM_UNIX_ATTRIBUTES:
737 case STREAM_FILE_DATA:
738 case STREAM_MD5_DIGEST:
739 case STREAM_UNIX_ATTRIBUTES_EX:
740 case STREAM_SPARSE_DATA:
741 case STREAM_PROGRAM_NAMES:
742 case STREAM_PROGRAM_DATA:
743 case STREAM_SHA1_DIGEST:
745 case STREAM_SHA256_DIGEST:
746 case STREAM_SHA512_DIGEST:
749 case STREAM_SIGNED_DIGEST:
750 case STREAM_ENCRYPTED_FILE_DATA:
751 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
752 case STREAM_ENCRYPTED_WIN32_DATA:
753 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
755 #ifdef HAVE_DARWIN_OS
756 case STREAM_MACOS_FORK_DATA:
757 case STREAM_HFSPLUS_ATTRIBUTES:
759 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
760 #endif /* HAVE_CRYPTO */
761 #endif /* HAVE_DARWIN_OS */
762 case 0: /* compatibility with old tapes */
769 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
771 /* Open reader/writer program */
773 Dmsg1(000, "Open file %d\n", bfd->fid);
774 return python_open(bfd, fname, flags, mode);
777 /* Normal file open */
778 Dmsg1(400, "open file %s\n", fname);
779 /* We use fnctl to set O_NOATIME if requested to avoid open error */
780 bfd->fid = open(fname, flags & ~O_NOATIME, mode);
781 /* Set O_NOATIME if possible */
782 if (bfd->fid != -1 && flags & O_NOATIME) {
783 int oldflags = fcntl(bfd->fid, F_GETFL, 0);
784 if (oldflags == -1) {
789 int ret = fcntl(bfd->fid, F_SETFL, oldflags | O_NOATIME);
790 /* EPERM means setting O_NOATIME was not allowed */
791 if (ret == -1 && errno != EPERM) {
799 Dmsg1(400, "Open file %d\n", bfd->fid);
802 bfd->win32DecompContext.bIsInData = false;
803 bfd->win32DecompContext.liNextHeader = 0;
808 #ifdef HAVE_DARWIN_OS
809 /* Open the resource fork of a file. */
810 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
814 rsrc_fname = get_pool_memory(PM_FNAME);
815 pm_strcpy(rsrc_fname, fname);
816 pm_strcat(rsrc_fname, _PATH_RSRCFORKSPEC);
817 bopen(bfd, rsrc_fname, flags, mode);
818 free_pool_memory(rsrc_fname);
824 int bclose(BFILE *bfd)
828 Dmsg1(400, "Close file %d\n", bfd->fid);
830 /* Close reader/writer program */
832 return python_close(bfd);
835 if (bfd->fid == -1) {
839 /* Close normal file */
840 stat = close(bfd->fid);
846 ssize_t bread(BFILE *bfd, void *buf, size_t count)
851 return python_read(bfd, buf, count);
853 stat = read(bfd->fid, buf, count);
858 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
863 return python_write(bfd, buf, count);
865 stat = write(bfd->fid, buf, count);
870 bool is_bopen(BFILE *bfd)
872 return bfd->fid >= 0;
875 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
878 pos = (boffset_t)lseek(bfd->fid, (off_t)offset, whence);