2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2015 Kern Sibbald
5 Copyright (C) 2003-2014 Free Software Foundation Europe e.V.
7 The original author of Bacula is Kern Sibbald, with contributions
8 from many others, a complete list can be found in the file AUTHORS.
10 You may use this file and others of this release according to the
11 license defined in the LICENSE file, which includes the Affero General
12 Public License, v3.0 ("AGPLv3") and some additional permissions and
13 terms pursuant to its AGPLv3 Section 7.
15 This notice must be preserved when any source code is
16 conveyed and/or propagated.
18 Bacula(R) is a registered trademark of Kern Sibbald.
21 * Bacula low level File I/O routines. This routine simulates
22 * open(), read(), write(), and close(), but using native routines.
23 * I.e. on Windows, we use Windows APIs.
25 * Kern Sibbald, April MMIII
32 const int dbglvl = 200;
34 int (*plugin_bopen)(BFILE *bfd, const char *fname, uint64_t flags, mode_t mode) = NULL;
35 int (*plugin_bclose)(BFILE *bfd) = NULL;
36 ssize_t (*plugin_bread)(BFILE *bfd, void *buf, size_t count) = NULL;
37 ssize_t (*plugin_bwrite)(BFILE *bfd, void *buf, size_t count) = NULL;
38 boffset_t (*plugin_blseek)(BFILE *bfd, boffset_t offset, int whence) = NULL;
42 #include <sys/paths.h>
45 #if !defined(HAVE_FDATASYNC)
50 void pause_msg(const char *file, const char *func, int line, const char *msg)
54 bsnprintf(buf, sizeof(buf), "%s:%s:%d %s", file, func, line, msg);
56 bsnprintf(buf, sizeof(buf), "%s:%s:%d", file, func, line);
58 MessageBox(NULL, buf, "Pause", MB_OK);
62 /* ===============================================================
64 * U N I X AND W I N D O W S
66 * ===============================================================
69 bool is_win32_stream(int stream)
72 case STREAM_WIN32_DATA:
73 case STREAM_WIN32_GZIP_DATA:
74 case STREAM_WIN32_COMPRESSED_DATA:
75 case STREAM_ENCRYPTED_WIN32_DATA:
76 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
77 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
83 const char *stream_to_ascii(int stream)
87 switch (stream & STREAMMASK_TYPE) {
88 case STREAM_UNIX_ATTRIBUTES:
89 return _("Unix attributes");
90 case STREAM_FILE_DATA:
91 return _("File data");
92 case STREAM_MD5_DIGEST:
93 return _("MD5 digest");
94 case STREAM_GZIP_DATA:
95 return _("GZIP data");
96 case STREAM_COMPRESSED_DATA:
97 return _("Compressed data");
98 case STREAM_UNIX_ATTRIBUTES_EX:
99 return _("Extended attributes");
100 case STREAM_SPARSE_DATA:
101 return _("Sparse data");
102 case STREAM_SPARSE_GZIP_DATA:
103 return _("GZIP sparse data");
104 case STREAM_SPARSE_COMPRESSED_DATA:
105 return _("Compressed sparse data");
106 case STREAM_PROGRAM_NAMES:
107 return _("Program names");
108 case STREAM_PROGRAM_DATA:
109 return _("Program data");
110 case STREAM_SHA1_DIGEST:
111 return _("SHA1 digest");
112 case STREAM_WIN32_DATA:
113 return _("Win32 data");
114 case STREAM_WIN32_GZIP_DATA:
115 return _("Win32 GZIP data");
116 case STREAM_WIN32_COMPRESSED_DATA:
117 return _("Win32 compressed 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_FILE_COMPRESSED_DATA:
141 return _("Encrypted compressed data");
142 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
143 return _("Encrypted Win32 GZIP data");
144 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
145 return _("Encrypted Win32 Compressed data");
146 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
147 return _("Encrypted MacOS fork data");
148 case STREAM_PLUGIN_NAME:
149 return _("Plugin Name");
150 case STREAM_PLUGIN_DATA:
151 return _("Plugin Data");
152 case STREAM_RESTORE_OBJECT:
153 return _("Restore Object");
154 case STREAM_ACL_AIX_TEXT:
155 return _("AIX ACL attribs");
156 case STREAM_ACL_DARWIN_ACCESS:
157 return _("Darwin ACL attribs");
158 case STREAM_ACL_FREEBSD_DEFAULT:
159 return _("FreeBSD Default ACL attribs");
160 case STREAM_ACL_FREEBSD_ACCESS:
161 return _("FreeBSD Access ACL attribs");
162 case STREAM_ACL_HPUX_ACL_ENTRY:
163 return _("HPUX ACL attribs");
164 case STREAM_ACL_IRIX_DEFAULT:
165 return _("Irix Default ACL attribs");
166 case STREAM_ACL_IRIX_ACCESS:
167 return _("Irix Access ACL attribs");
168 case STREAM_ACL_LINUX_DEFAULT:
169 return _("Linux Default ACL attribs");
170 case STREAM_ACL_LINUX_ACCESS:
171 return _("Linux Access ACL attribs");
172 case STREAM_ACL_TRU64_DEFAULT:
173 return _("TRU64 Default ACL attribs");
174 case STREAM_ACL_TRU64_ACCESS:
175 return _("TRU64 Access ACL attribs");
176 case STREAM_ACL_SOLARIS_POSIX:
177 return _("Solaris POSIX ACL attribs");
178 case STREAM_ACL_SOLARIS_NFS4:
179 return _("Solaris NFSv4/ZFS ACL attribs");
180 case STREAM_ACL_AFS_TEXT:
181 return _("AFS ACL attribs");
182 case STREAM_ACL_AIX_AIXC:
183 return _("AIX POSIX ACL attribs");
184 case STREAM_ACL_AIX_NFS4:
185 return _("AIX NFSv4 ACL attribs");
186 case STREAM_ACL_FREEBSD_NFS4:
187 return _("FreeBSD NFSv4/ZFS ACL attribs");
188 case STREAM_ACL_HURD_DEFAULT:
189 return _("GNU Hurd Default ACL attribs");
190 case STREAM_ACL_HURD_ACCESS:
191 return _("GNU Hurd Access ACL attribs");
192 case STREAM_XATTR_HURD:
193 return _("GNU Hurd Extended attribs");
194 case STREAM_XATTR_IRIX:
195 return _("IRIX Extended attribs");
196 case STREAM_XATTR_TRU64:
197 return _("TRU64 Extended attribs");
198 case STREAM_XATTR_AIX:
199 return _("AIX Extended attribs");
200 case STREAM_XATTR_OPENBSD:
201 return _("OpenBSD Extended attribs");
202 case STREAM_XATTR_SOLARIS_SYS:
203 return _("Solaris Extensible attribs or System Extended attribs");
204 case STREAM_XATTR_SOLARIS:
205 return _("Solaris Extended attribs");
206 case STREAM_XATTR_DARWIN:
207 return _("Darwin Extended attribs");
208 case STREAM_XATTR_FREEBSD:
209 return _("FreeBSD Extended attribs");
210 case STREAM_XATTR_LINUX:
211 return _("Linux Extended attribs");
212 case STREAM_XATTR_NETBSD:
213 return _("NetBSD Extended attribs");
215 sprintf(buf, "%d", stream);
216 return (const char *)buf;
221 * Convert a 64 bit little endian to a big endian
223 void int64_LE2BE(int64_t* pBE, const int64_t v)
225 /* convert little endian to big endian */
226 if (htonl(1) != 1L) { /* no work if on little endian machine */
227 memcpy(pBE, &v, sizeof(int64_t));
230 uint8_t rv[sizeof(int64_t)];
231 uint8_t *pv = (uint8_t *) &v;
233 for (i = 0; i < 8; i++) {
236 memcpy(pBE, &rv, sizeof(int64_t));
241 * Convert a 32 bit little endian to a big endian
243 void int32_LE2BE(int32_t* pBE, const int32_t v)
245 /* convert little endian to big endian */
246 if (htonl(1) != 1L) { /* no work if on little endian machine */
247 memcpy(pBE, &v, sizeof(int32_t));
250 uint8_t rv[sizeof(int32_t)];
251 uint8_t *pv = (uint8_t *) &v;
253 for (i = 0; i < 4; i++) {
256 memcpy(pBE, &rv, sizeof(int32_t));
262 * Read a BackupRead block and pull out the file data
264 bool processWin32BackupAPIBlock (BFILE *bfd, void *pBuffer, ssize_t dwSize)
266 /* pByte contains the buffer
267 dwSize the len to be processed. function assumes to be
268 called in successive incremental order over the complete
269 BackupRead stream beginning at pos 0 and ending at the end.
272 PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT* pContext = &(bfd->win32DecompContext);
273 bool bContinue = false;
274 int64_t dwDataOffset = 0;
277 /* Win32 Stream Header size without name of stream.
278 * = sizeof (WIN32_STREAM_ID)- sizeof(WCHAR*);
280 int32_t dwSizeHeader = 20;
283 if (pContext->liNextHeader >= dwSize) {
284 dwDataLen = dwSize-dwDataOffset;
285 bContinue = false; /* 1 iteration is enough */
287 dwDataLen = pContext->liNextHeader-dwDataOffset;
288 bContinue = true; /* multiple iterations may be necessary */
292 /* copy block of real DATA */
293 if (pContext->bIsInData) {
294 if (bwrite(bfd, ((char *)pBuffer)+dwDataOffset, dwDataLen) != (ssize_t)dwDataLen)
298 if (pContext->liNextHeader < dwSize) {/* is a header in this block ? */
299 int32_t dwOffsetTarget;
300 int32_t dwOffsetSource;
302 if (pContext->liNextHeader < 0) {
303 /* start of header was before this block, so we
304 * continue with the part in the current block
306 dwOffsetTarget = -pContext->liNextHeader;
309 /* start of header is inside of this block */
311 dwOffsetSource = pContext->liNextHeader;
314 int32_t dwHeaderPartLen = dwSizeHeader-dwOffsetTarget;
315 bool bHeaderIsComplete;
317 if (dwHeaderPartLen <= dwSize-dwOffsetSource) {
318 /* header (or rest of header) is completely available
321 bHeaderIsComplete = true;
323 /* header will continue in next block */
324 bHeaderIsComplete = false;
325 dwHeaderPartLen = dwSize-dwOffsetSource;
328 /* copy the available portion of header to persistent copy */
329 memcpy(((char *)&pContext->header_stream)+dwOffsetTarget, ((char *)pBuffer)+dwOffsetSource, dwHeaderPartLen);
331 /* recalculate position of next header */
332 if (bHeaderIsComplete) {
333 /* convert stream name size (32 bit little endian) to machine type */
335 int32_LE2BE (&dwNameSize, pContext->header_stream.dwStreamNameSize);
336 dwDataOffset = dwNameSize+pContext->liNextHeader+dwSizeHeader;
338 /* convert stream size (64 bit little endian) to machine type */
339 int64_LE2BE (&(pContext->liNextHeader), pContext->header_stream.Size);
340 pContext->liNextHeader += dwDataOffset;
342 pContext->bIsInData = pContext->header_stream.dwStreamId == WIN32_BACKUP_DATA;
343 if (dwDataOffset == dwSize)
346 /* stop and continue with next block */
348 pContext->bIsInData = false;
353 /* set "NextHeader" relative to the beginning of the next block */
354 pContext->liNextHeader-= dwSize;
362 /* ===============================================================
366 * ===============================================================
369 void binit(BFILE *bfd)
371 memset(bfd, 0, sizeof(BFILE));
376 bool have_win32_api()
378 return false; /* no can do */
382 * Enables using the Backup API (win32_data).
383 * Returns true if function worked
384 * Returns false if failed (i.e. do not have Backup API on this machine)
387 bool set_win32_backup(BFILE *bfd)
389 return false; /* no can do */
394 bool set_portable_backup(BFILE *bfd)
396 return true; /* no problem */
400 * Return true if we are writing in portable format
401 * return false if not
404 bool is_portable_backup(BFILE *bfd)
406 return true; /* portable by definition */
410 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
416 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
418 bfd->cmd_plugin = true;
424 * This code is running on a non-Win32 machine
427 bool is_restore_stream_supported(int stream)
429 /* No Win32 backup on this machine */
432 case STREAM_GZIP_DATA:
433 case STREAM_SPARSE_GZIP_DATA:
434 case STREAM_WIN32_GZIP_DATA:
437 case STREAM_COMPRESSED_DATA:
438 case STREAM_SPARSE_COMPRESSED_DATA:
439 case STREAM_WIN32_COMPRESSED_DATA:
440 case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
441 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
443 #ifndef HAVE_DARWIN_OS
444 case STREAM_MACOS_FORK_DATA:
445 case STREAM_HFSPLUS_ATTRIBUTES:
451 case STREAM_GZIP_DATA:
452 case STREAM_SPARSE_GZIP_DATA:
453 case STREAM_WIN32_GZIP_DATA:
456 case STREAM_COMPRESSED_DATA:
457 case STREAM_SPARSE_COMPRESSED_DATA:
458 case STREAM_WIN32_COMPRESSED_DATA:
459 case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
460 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
462 case STREAM_WIN32_DATA:
463 case STREAM_UNIX_ATTRIBUTES:
464 case STREAM_FILE_DATA:
465 case STREAM_MD5_DIGEST:
466 case STREAM_UNIX_ATTRIBUTES_EX:
467 case STREAM_SPARSE_DATA:
468 case STREAM_PROGRAM_NAMES:
469 case STREAM_PROGRAM_DATA:
470 case STREAM_SHA1_DIGEST:
472 case STREAM_SHA256_DIGEST:
473 case STREAM_SHA512_DIGEST:
476 case STREAM_SIGNED_DIGEST:
477 case STREAM_ENCRYPTED_FILE_DATA:
478 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
479 case STREAM_ENCRYPTED_WIN32_DATA:
480 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
482 #ifdef HAVE_DARWIN_OS
483 case STREAM_MACOS_FORK_DATA:
484 case STREAM_HFSPLUS_ATTRIBUTES:
486 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
487 #endif /* HAVE_CRYPTO */
488 #endif /* HAVE_DARWIN_OS */
489 case 0: /* compatibility with old tapes */
497 int bopen(BFILE *bfd, const char *fname, uint64_t flags, mode_t mode)
499 if (bfd->cmd_plugin && plugin_bopen) {
500 Dmsg1(400, "call plugin_bopen fname=%s\n", fname);
501 bfd->fid = plugin_bopen(bfd, fname, flags, mode);
502 Dmsg2(400, "Plugin bopen fid=%d file=%s\n", bfd->fid, fname);
506 /* Normal file open */
507 Dmsg1(dbglvl, "open file %s\n", fname);
509 /* We use fnctl to set O_NOATIME if requested to avoid open error */
510 bfd->fid = open(fname, flags & ~O_NOATIME, mode);
512 /* Set O_NOATIME if possible */
513 if (bfd->fid != -1 && flags & O_NOATIME) {
514 int oldflags = fcntl(bfd->fid, F_GETFL, 0);
515 if (oldflags == -1) {
520 int ret = fcntl(bfd->fid, F_SETFL, oldflags | O_NOATIME);
521 /* EPERM means setting O_NOATIME was not allowed */
522 if (ret == -1 && errno != EPERM) {
530 bfd->m_flags = flags;
532 bfd->total_bytes = 0;
533 Dmsg1(400, "Open file %d\n", bfd->fid);
536 bfd->win32DecompContext.bIsInData = false;
537 bfd->win32DecompContext.liNextHeader = 0;
539 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
540 if (bfd->fid != -1 && flags & O_RDONLY) {
541 int stat = posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_WILLNEED);
542 Dmsg2(400, "Did posix_fadvise on %s stat=%d\n", fname, 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;
587 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
588 if (bfd->m_flags & O_RDONLY) {
589 fdatasync(bfd->fid); /* sync the file */
590 /* Tell OS we don't need it any more */
591 posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_DONTNEED);
595 /* Close normal file */
596 stat = close(bfd->fid);
599 bfd->cmd_plugin = false;
604 ssize_t bread(BFILE *bfd, void *buf, size_t count)
608 if (bfd->cmd_plugin && plugin_bread) {
609 return plugin_bread(bfd, buf, count);
612 stat = read(bfd->fid, buf, count);
616 bfd->total_bytes += stat;
622 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
626 if (bfd->cmd_plugin && plugin_bwrite) {
627 return plugin_bwrite(bfd, buf, count);
629 stat = write(bfd->fid, buf, count);
633 bfd->total_bytes += stat;
639 bool is_bopen(BFILE *bfd)
641 return bfd->fid >= 0;
645 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
649 if (bfd->cmd_plugin && plugin_bwrite) {
650 return plugin_blseek(bfd, offset, whence);
652 pos = (boffset_t)lseek(bfd->fid, offset, whence);