2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2015 Kern Sibbald
6 The original author of Bacula is Kern Sibbald, with contributions
7 from many others, a complete list can be found in the file AUTHORS.
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
17 Bacula(R) is a registered trademark of Kern Sibbald.
20 * Bacula low level File I/O routines. This routine simulates
21 * open(), read(), write(), and close(), but using native routines.
22 * I.e. on Windows, we use Windows APIs.
24 * Kern Sibbald, April MMIII
31 const int dbglvl = 200;
33 int (*plugin_bopen)(BFILE *bfd, const char *fname, uint64_t flags, mode_t mode) = NULL;
34 int (*plugin_bclose)(BFILE *bfd) = NULL;
35 ssize_t (*plugin_bread)(BFILE *bfd, void *buf, size_t count) = NULL;
36 ssize_t (*plugin_bwrite)(BFILE *bfd, void *buf, size_t count) = NULL;
37 boffset_t (*plugin_blseek)(BFILE *bfd, boffset_t offset, int whence) = NULL;
41 #include <sys/paths.h>
44 #if !defined(HAVE_FDATASYNC)
49 void pause_msg(const char *file, const char *func, int line, const char *msg)
53 bsnprintf(buf, sizeof(buf), "%s:%s:%d %s", file, func, line, msg);
55 bsnprintf(buf, sizeof(buf), "%s:%s:%d", file, func, line);
57 MessageBox(NULL, buf, "Pause", MB_OK);
61 /* ===============================================================
63 * U N I X AND W I N D O W S
65 * ===============================================================
68 bool is_win32_stream(int stream)
71 case STREAM_WIN32_DATA:
72 case STREAM_WIN32_GZIP_DATA:
73 case STREAM_WIN32_COMPRESSED_DATA:
74 case STREAM_ENCRYPTED_WIN32_DATA:
75 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
76 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
82 const char *stream_to_ascii(int stream)
86 switch (stream & STREAMMASK_TYPE) {
87 case STREAM_UNIX_ATTRIBUTES:
88 return _("Unix attributes");
89 case STREAM_FILE_DATA:
90 return _("File data");
91 case STREAM_MD5_DIGEST:
92 return _("MD5 digest");
93 case STREAM_GZIP_DATA:
94 return _("GZIP data");
95 case STREAM_COMPRESSED_DATA:
96 return _("Compressed data");
97 case STREAM_UNIX_ATTRIBUTES_EX:
98 return _("Extended attributes");
99 case STREAM_SPARSE_DATA:
100 return _("Sparse data");
101 case STREAM_SPARSE_GZIP_DATA:
102 return _("GZIP sparse data");
103 case STREAM_SPARSE_COMPRESSED_DATA:
104 return _("Compressed sparse data");
105 case STREAM_PROGRAM_NAMES:
106 return _("Program names");
107 case STREAM_PROGRAM_DATA:
108 return _("Program data");
109 case STREAM_SHA1_DIGEST:
110 return _("SHA1 digest");
111 case STREAM_WIN32_DATA:
112 return _("Win32 data");
113 case STREAM_WIN32_GZIP_DATA:
114 return _("Win32 GZIP data");
115 case STREAM_WIN32_COMPRESSED_DATA:
116 return _("Win32 compressed data");
117 case STREAM_MACOS_FORK_DATA:
118 return _("MacOS Fork data");
119 case STREAM_HFSPLUS_ATTRIBUTES:
120 return _("HFS+ attribs");
121 case STREAM_UNIX_ACCESS_ACL:
122 return _("Standard Unix ACL attribs");
123 case STREAM_UNIX_DEFAULT_ACL:
124 return _("Default Unix ACL attribs");
125 case STREAM_SHA256_DIGEST:
126 return _("SHA256 digest");
127 case STREAM_SHA512_DIGEST:
128 return _("SHA512 digest");
129 case STREAM_SIGNED_DIGEST:
130 return _("Signed digest");
131 case STREAM_ENCRYPTED_FILE_DATA:
132 return _("Encrypted File data");
133 case STREAM_ENCRYPTED_WIN32_DATA:
134 return _("Encrypted Win32 data");
135 case STREAM_ENCRYPTED_SESSION_DATA:
136 return _("Encrypted session data");
137 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
138 return _("Encrypted GZIP data");
139 case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
140 return _("Encrypted compressed data");
141 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
142 return _("Encrypted Win32 GZIP data");
143 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
144 return _("Encrypted Win32 Compressed data");
145 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
146 return _("Encrypted MacOS fork data");
147 case STREAM_PLUGIN_NAME:
148 return _("Plugin Name");
149 case STREAM_PLUGIN_DATA:
150 return _("Plugin Data");
151 case STREAM_RESTORE_OBJECT:
152 return _("Restore Object");
153 case STREAM_XACL_AIX_TEXT:
154 return _("AIX ACL attribs");
155 case STREAM_XACL_DARWIN_ACCESS:
156 return _("Darwin ACL attribs");
157 case STREAM_XACL_FREEBSD_DEFAULT:
158 return _("FreeBSD Default ACL attribs");
159 case STREAM_XACL_FREEBSD_ACCESS:
160 return _("FreeBSD Access ACL attribs");
161 case STREAM_XACL_HPUX_ACL_ENTRY:
162 return _("HPUX ACL attribs");
163 case STREAM_XACL_IRIX_DEFAULT:
164 return _("Irix Default ACL attribs");
165 case STREAM_XACL_IRIX_ACCESS:
166 return _("Irix Access ACL attribs");
167 case STREAM_XACL_LINUX_DEFAULT:
168 return _("Linux Default ACL attribs");
169 case STREAM_XACL_LINUX_ACCESS:
170 return _("Linux Access ACL attribs");
171 case STREAM_XACL_TRU64_DEFAULT:
172 return _("TRU64 Default ACL attribs");
173 case STREAM_XACL_TRU64_ACCESS:
174 return _("TRU64 Access ACL attribs");
175 case STREAM_XACL_SOLARIS_POSIX:
176 return _("Solaris POSIX ACL attribs");
177 case STREAM_XACL_SOLARIS_NFS4:
178 return _("Solaris NFSv4/ZFS ACL attribs");
179 case STREAM_XACL_AFS_TEXT:
180 return _("AFS ACL attribs");
181 case STREAM_XACL_AIX_AIXC:
182 return _("AIX POSIX ACL attribs");
183 case STREAM_XACL_AIX_NFS4:
184 return _("AIX NFSv4 ACL attribs");
185 case STREAM_XACL_FREEBSD_NFS4:
186 return _("FreeBSD NFSv4/ZFS ACL attribs");
187 case STREAM_XACL_HURD_DEFAULT:
188 return _("GNU Hurd Default ACL attribs");
189 case STREAM_XACL_HURD_ACCESS:
190 return _("GNU Hurd Access ACL attribs");
191 case STREAM_XACL_HURD_XATTR:
192 return _("GNU Hurd Extended attribs");
193 case STREAM_XACL_IRIX_XATTR:
194 return _("IRIX Extended attribs");
195 case STREAM_XACL_TRU64_XATTR:
196 return _("TRU64 Extended attribs");
197 case STREAM_XACL_AIX_XATTR:
198 return _("AIX Extended attribs");
199 case STREAM_XACL_OPENBSD_XATTR:
200 return _("OpenBSD Extended attribs");
201 case STREAM_XACL_SOLARIS_SYS_XATTR:
202 return _("Solaris Extensible attribs or System Extended attribs");
203 case STREAM_XACL_SOLARIS_XATTR:
204 return _("Solaris Extended attribs");
205 case STREAM_XACL_DARWIN_XATTR:
206 return _("Darwin Extended attribs");
207 case STREAM_XACL_FREEBSD_XATTR:
208 return _("FreeBSD Extended attribs");
209 case STREAM_XACL_LINUX_XATTR:
210 return _("Linux Extended attribs");
211 case STREAM_XACL_NETBSD_XATTR:
212 return _("NetBSD Extended attribs");
214 sprintf(buf, "%d", stream);
215 return (const char *)buf;
220 * Convert a 64 bit little endian to a big endian
222 void int64_LE2BE(int64_t* pBE, const int64_t v)
224 /* convert little endian to big endian */
225 if (htonl(1) != 1L) { /* no work if on little endian machine */
226 memcpy(pBE, &v, sizeof(int64_t));
229 uint8_t rv[sizeof(int64_t)];
230 uint8_t *pv = (uint8_t *) &v;
232 for (i = 0; i < 8; i++) {
235 memcpy(pBE, &rv, sizeof(int64_t));
240 * Convert a 32 bit little endian to a big endian
242 void int32_LE2BE(int32_t* pBE, const int32_t v)
244 /* convert little endian to big endian */
245 if (htonl(1) != 1L) { /* no work if on little endian machine */
246 memcpy(pBE, &v, sizeof(int32_t));
249 uint8_t rv[sizeof(int32_t)];
250 uint8_t *pv = (uint8_t *) &v;
252 for (i = 0; i < 4; i++) {
255 memcpy(pBE, &rv, sizeof(int32_t));
261 * Read a BackupRead block and pull out the file data
263 bool processWin32BackupAPIBlock (BFILE *bfd, void *pBuffer, ssize_t dwSize)
265 /* pByte contains the buffer
266 dwSize the len to be processed. function assumes to be
267 called in successive incremental order over the complete
268 BackupRead stream beginning at pos 0 and ending at the end.
271 PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT* pContext = &(bfd->win32DecompContext);
272 bool bContinue = false;
273 int64_t dwDataOffset = 0;
276 /* Win32 Stream Header size without name of stream.
277 * = sizeof (WIN32_STREAM_ID)- sizeof(WCHAR*);
279 int32_t dwSizeHeader = 20;
282 if (pContext->liNextHeader >= dwSize) {
283 dwDataLen = dwSize-dwDataOffset;
284 bContinue = false; /* 1 iteration is enough */
286 dwDataLen = pContext->liNextHeader-dwDataOffset;
287 bContinue = true; /* multiple iterations may be necessary */
291 /* copy block of real DATA */
292 if (pContext->bIsInData) {
293 if (bwrite(bfd, ((char *)pBuffer)+dwDataOffset, dwDataLen) != (ssize_t)dwDataLen)
297 if (pContext->liNextHeader < dwSize) {/* is a header in this block ? */
298 int32_t dwOffsetTarget;
299 int32_t dwOffsetSource;
301 if (pContext->liNextHeader < 0) {
302 /* start of header was before this block, so we
303 * continue with the part in the current block
305 dwOffsetTarget = -pContext->liNextHeader;
308 /* start of header is inside of this block */
310 dwOffsetSource = pContext->liNextHeader;
313 int32_t dwHeaderPartLen = dwSizeHeader-dwOffsetTarget;
314 bool bHeaderIsComplete;
316 if (dwHeaderPartLen <= dwSize-dwOffsetSource) {
317 /* header (or rest of header) is completely available
320 bHeaderIsComplete = true;
322 /* header will continue in next block */
323 bHeaderIsComplete = false;
324 dwHeaderPartLen = dwSize-dwOffsetSource;
327 /* copy the available portion of header to persistent copy */
328 memcpy(((char *)&pContext->header_stream)+dwOffsetTarget, ((char *)pBuffer)+dwOffsetSource, dwHeaderPartLen);
330 /* recalculate position of next header */
331 if (bHeaderIsComplete) {
332 /* convert stream name size (32 bit little endian) to machine type */
334 int32_LE2BE (&dwNameSize, pContext->header_stream.dwStreamNameSize);
335 dwDataOffset = dwNameSize+pContext->liNextHeader+dwSizeHeader;
337 /* convert stream size (64 bit little endian) to machine type */
338 int64_LE2BE (&(pContext->liNextHeader), pContext->header_stream.Size);
339 pContext->liNextHeader += dwDataOffset;
341 pContext->bIsInData = pContext->header_stream.dwStreamId == WIN32_BACKUP_DATA;
342 if (dwDataOffset == dwSize)
345 /* stop and continue with next block */
347 pContext->bIsInData = false;
352 /* set "NextHeader" relative to the beginning of the next block */
353 pContext->liNextHeader-= dwSize;
361 /* ===============================================================
365 * ===============================================================
368 void binit(BFILE *bfd)
370 memset(bfd, 0, sizeof(BFILE));
375 bool have_win32_api()
377 return false; /* no can do */
381 * Enables using the Backup API (win32_data).
382 * Returns true if function worked
383 * Returns false if failed (i.e. do not have Backup API on this machine)
386 bool set_win32_backup(BFILE *bfd)
388 return false; /* no can do */
393 bool set_portable_backup(BFILE *bfd)
395 return true; /* no problem */
399 * Return true if we are writing in portable format
400 * return false if not
403 bool is_portable_backup(BFILE *bfd)
405 return true; /* portable by definition */
409 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
415 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
417 bfd->cmd_plugin = true;
423 * This code is running on a non-Win32 machine
426 bool is_restore_stream_supported(int stream)
428 /* No Win32 backup on this machine */
431 case STREAM_GZIP_DATA:
432 case STREAM_SPARSE_GZIP_DATA:
433 case STREAM_WIN32_GZIP_DATA:
436 case STREAM_COMPRESSED_DATA:
437 case STREAM_SPARSE_COMPRESSED_DATA:
438 case STREAM_WIN32_COMPRESSED_DATA:
439 case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
440 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
442 #ifndef HAVE_DARWIN_OS
443 case STREAM_MACOS_FORK_DATA:
444 case STREAM_HFSPLUS_ATTRIBUTES:
450 case STREAM_GZIP_DATA:
451 case STREAM_SPARSE_GZIP_DATA:
452 case STREAM_WIN32_GZIP_DATA:
455 case STREAM_COMPRESSED_DATA:
456 case STREAM_SPARSE_COMPRESSED_DATA:
457 case STREAM_WIN32_COMPRESSED_DATA:
458 case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
459 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
461 case STREAM_WIN32_DATA:
462 case STREAM_UNIX_ATTRIBUTES:
463 case STREAM_FILE_DATA:
464 case STREAM_MD5_DIGEST:
465 case STREAM_UNIX_ATTRIBUTES_EX:
466 case STREAM_SPARSE_DATA:
467 case STREAM_PROGRAM_NAMES:
468 case STREAM_PROGRAM_DATA:
469 case STREAM_SHA1_DIGEST:
471 case STREAM_SHA256_DIGEST:
472 case STREAM_SHA512_DIGEST:
475 case STREAM_SIGNED_DIGEST:
476 case STREAM_ENCRYPTED_FILE_DATA:
477 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
478 case STREAM_ENCRYPTED_WIN32_DATA:
479 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
481 #ifdef HAVE_DARWIN_OS
482 case STREAM_MACOS_FORK_DATA:
483 case STREAM_HFSPLUS_ATTRIBUTES:
485 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
486 #endif /* HAVE_CRYPTO */
487 #endif /* HAVE_DARWIN_OS */
488 case 0: /* compatibility with old tapes */
496 int bopen(BFILE *bfd, const char *fname, uint64_t flags, mode_t mode)
498 if (bfd->cmd_plugin && plugin_bopen) {
499 Dmsg1(400, "call plugin_bopen fname=%s\n", fname);
500 bfd->fid = plugin_bopen(bfd, fname, flags, mode);
501 Dmsg2(400, "Plugin bopen fid=%d file=%s\n", bfd->fid, fname);
505 /* Normal file open */
506 Dmsg1(dbglvl, "open file %s\n", fname);
508 /* We use fnctl to set O_NOATIME if requested to avoid open error */
509 bfd->fid = open(fname, (flags | O_CLOEXEC) & ~O_NOATIME, mode);
511 /* Set O_NOATIME if possible */
512 if (bfd->fid != -1 && flags & O_NOATIME) {
513 int oldflags = fcntl(bfd->fid, F_GETFL, 0);
514 if (oldflags == -1) {
519 int ret = fcntl(bfd->fid, F_SETFL, oldflags | O_NOATIME);
520 /* EPERM means setting O_NOATIME was not allowed */
521 if (ret == -1 && errno != EPERM) {
529 bfd->m_flags = flags;
531 bfd->total_bytes = 0;
532 Dmsg1(400, "Open file %d\n", bfd->fid);
535 bfd->win32DecompContext.bIsInData = false;
536 bfd->win32DecompContext.liNextHeader = 0;
538 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
539 /* If not RDWR or WRONLY must be Read Only */
540 if (bfd->fid != -1 && !(flags & (O_RDWR|O_WRONLY))) {
541 int stat = posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_WILLNEED);
542 Dmsg3(400, "Did posix_fadvise WILLNEED on %s fid=%d stat=%d\n", fname, bfd->fid, stat);
549 #ifdef HAVE_DARWIN_OS
550 /* Open the resource fork of a file. */
551 int bopen_rsrc(BFILE *bfd, const char *fname, uint64_t flags, mode_t mode)
555 rsrc_fname = get_pool_memory(PM_FNAME);
556 pm_strcpy(rsrc_fname, fname);
557 pm_strcat(rsrc_fname, _PATH_RSRCFORKSPEC);
558 bopen(bfd, rsrc_fname, flags, mode);
559 free_pool_memory(rsrc_fname);
565 int bopen_rsrc(BFILE *bfd, const char *fname, uint64_t flags, mode_t mode)
572 int bclose(BFILE *bfd)
576 Dmsg2(400, "Close bfd=%p file %d\n", bfd, bfd->fid);
578 if (bfd->fid == -1) {
581 if (bfd->cmd_plugin && plugin_bclose) {
582 stat = plugin_bclose(bfd);
584 bfd->cmd_plugin = false;
588 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
589 /* If not RDWR or WRONLY must be Read Only */
590 if (!(bfd->m_flags & (O_RDWR|O_WRONLY))) {
591 fdatasync(bfd->fid); /* sync the file */
592 /* Tell OS we don't need it any more */
593 posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_DONTNEED);
594 Dmsg1(400, "Did posix_fadvise DONTNEED on fid=%d\n", bfd->fid);
598 /* Close normal file */
599 stat = close(bfd->fid);
602 bfd->cmd_plugin = false;
607 ssize_t bread(BFILE *bfd, void *buf, size_t count)
611 if (bfd->cmd_plugin && plugin_bread) {
612 return plugin_bread(bfd, buf, count);
615 stat = read(bfd->fid, buf, count);
619 bfd->total_bytes += stat;
625 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
629 if (bfd->cmd_plugin && plugin_bwrite) {
630 stat = plugin_bwrite(bfd, buf, count);
633 stat = write(bfd->fid, buf, count);
639 bfd->total_bytes += stat;
645 bool is_bopen(BFILE *bfd)
647 return bfd->fid >= 0;
651 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
655 if (bfd->cmd_plugin && plugin_bwrite) {
656 return plugin_blseek(bfd, offset, whence);
658 pos = (boffset_t)lseek(bfd->fid, offset, whence);