2 Bacula® - The Network Backup Solution
4 Copyright (C) 2003-2014 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from many
7 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 Bacula® is a registered trademark of Kern Sibbald.
17 * Bacula low level File I/O routines. This routine simulates
18 * open(), read(), write(), and close(), but using native routines.
19 * I.e. on Windows, we use Windows APIs.
21 * Kern Sibbald, April MMIII
28 const int dbglvl = 200;
30 int (*plugin_bopen)(BFILE *bfd, const char *fname, uint64_t flags, mode_t mode) = NULL;
31 int (*plugin_bclose)(BFILE *bfd) = NULL;
32 ssize_t (*plugin_bread)(BFILE *bfd, void *buf, size_t count) = NULL;
33 ssize_t (*plugin_bwrite)(BFILE *bfd, void *buf, size_t count) = NULL;
34 boffset_t (*plugin_blseek)(BFILE *bfd, boffset_t offset, int whence) = NULL;
38 #include <sys/paths.h>
41 #if !defined(HAVE_FDATASYNC)
46 void pause_msg(const char *file, const char *func, int line, const char *msg)
50 bsnprintf(buf, sizeof(buf), "%s:%s:%d %s", file, func, line, msg);
52 bsnprintf(buf, sizeof(buf), "%s:%s:%d", file, func, line);
54 MessageBox(NULL, buf, "Pause", MB_OK);
58 * The following code was contributed by Graham Keeling from his
59 * burp project. August 2014
61 static int encrypt_bopen(BFILE *bfd, const char *fname, uint64_t flags, mode_t mode)
65 POOLMEM *win32_fname_wchar;
67 bfd->mode = BF_CLOSED;
70 if (!(p_OpenEncryptedFileRawA || p_OpenEncryptedFileRawW)) {
71 Dmsg0(50, "No OpenEncryptedFileRawA and no OpenEncryptedFileRawW APIs!!!\n");
75 /* Convert to Windows path format */
76 win32_fname = get_pool_memory(PM_FNAME);
77 win32_fname_wchar = get_pool_memory(PM_FNAME);
79 unix_name_to_win32(&win32_fname, (char *)fname);
81 if (p_CreateFileW && p_MultiByteToWideChar) {
82 make_win32_path_UTF8_2_wchar(&win32_fname_wchar, fname);
85 if ((flags & O_CREAT) || (flags & O_WRONLY)) {
86 ulFlags = CREATE_FOR_IMPORT | OVERWRITE_HIDDEN;
87 if (bfd->fattrs & FILE_ATTRIBUTE_DIRECTORY) {
89 ulFlags |= CREATE_FOR_DIR;
93 /* Open existing for read */
94 ulFlags = CREATE_FOR_EXPORT;
98 if (p_OpenEncryptedFileRawW && p_MultiByteToWideChar) {
100 if (p_OpenEncryptedFileRawW((LPCWSTR)win32_fname_wchar,
101 ulFlags, &(bfd->pvContext))) {
102 bfd->mode = BF_CLOSED;
106 if (p_OpenEncryptedFileRawA(win32_fname, ulFlags, &(bfd->pvContext))) {
107 bfd->mode = BF_CLOSED;
110 free_pool_memory(win32_fname_wchar);
111 free_pool_memory(win32_fname);
112 bfd->fid = (bfd->mode == BF_CLOSED) ? -1 : 0;
113 return bfd->mode==BF_CLOSED ? -1: 1;
116 static int encrypt_bclose(BFILE *bfd)
118 if (p_CloseEncryptedFileRaw) {
119 p_CloseEncryptedFileRaw(bfd->pvContext);
121 bfd->pvContext = NULL;
122 bfd->mode = BF_CLOSED;
130 /* ===============================================================
132 * U N I X AND W I N D O W S
134 * ===============================================================
137 bool is_win32_stream(int stream)
140 case STREAM_WIN32_DATA:
141 case STREAM_WIN32_GZIP_DATA:
142 case STREAM_WIN32_COMPRESSED_DATA:
143 case STREAM_ENCRYPTED_WIN32_DATA:
144 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
145 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
151 const char *stream_to_ascii(int stream)
155 switch (stream & STREAMMASK_TYPE) {
156 case STREAM_UNIX_ATTRIBUTES:
157 return _("Unix attributes");
158 case STREAM_FILE_DATA:
159 return _("File data");
160 case STREAM_MD5_DIGEST:
161 return _("MD5 digest");
162 case STREAM_GZIP_DATA:
163 return _("GZIP data");
164 case STREAM_COMPRESSED_DATA:
165 return _("Compressed data");
166 case STREAM_UNIX_ATTRIBUTES_EX:
167 return _("Extended attributes");
168 case STREAM_SPARSE_DATA:
169 return _("Sparse data");
170 case STREAM_SPARSE_GZIP_DATA:
171 return _("GZIP sparse data");
172 case STREAM_SPARSE_COMPRESSED_DATA:
173 return _("Compressed sparse data");
174 case STREAM_PROGRAM_NAMES:
175 return _("Program names");
176 case STREAM_PROGRAM_DATA:
177 return _("Program data");
178 case STREAM_SHA1_DIGEST:
179 return _("SHA1 digest");
180 case STREAM_WIN32_DATA:
181 return _("Win32 data");
182 case STREAM_WIN32_GZIP_DATA:
183 return _("Win32 GZIP data");
184 case STREAM_WIN32_COMPRESSED_DATA:
185 return _("Win32 compressed data");
186 case STREAM_MACOS_FORK_DATA:
187 return _("MacOS Fork data");
188 case STREAM_HFSPLUS_ATTRIBUTES:
189 return _("HFS+ attribs");
190 case STREAM_UNIX_ACCESS_ACL:
191 return _("Standard Unix ACL attribs");
192 case STREAM_UNIX_DEFAULT_ACL:
193 return _("Default Unix ACL attribs");
194 case STREAM_SHA256_DIGEST:
195 return _("SHA256 digest");
196 case STREAM_SHA512_DIGEST:
197 return _("SHA512 digest");
198 case STREAM_SIGNED_DIGEST:
199 return _("Signed digest");
200 case STREAM_ENCRYPTED_FILE_DATA:
201 return _("Encrypted File data");
202 case STREAM_ENCRYPTED_WIN32_DATA:
203 return _("Encrypted Win32 data");
204 case STREAM_ENCRYPTED_SESSION_DATA:
205 return _("Encrypted session data");
206 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
207 return _("Encrypted GZIP data");
208 case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
209 return _("Encrypted compressed data");
210 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
211 return _("Encrypted Win32 GZIP data");
212 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
213 return _("Encrypted Win32 Compressed data");
214 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
215 return _("Encrypted MacOS fork data");
216 case STREAM_PLUGIN_NAME:
217 return _("Plugin Name");
218 case STREAM_PLUGIN_DATA:
219 return _("Plugin Data");
220 case STREAM_RESTORE_OBJECT:
221 return _("Restore Object");
222 case STREAM_ACL_AIX_TEXT:
223 return _("AIX Specific ACL attribs");
224 case STREAM_ACL_DARWIN_ACCESS_ACL:
225 return _("Darwin Specific ACL attribs");
226 case STREAM_ACL_FREEBSD_DEFAULT_ACL:
227 return _("FreeBSD Specific Default ACL attribs");
228 case STREAM_ACL_FREEBSD_ACCESS_ACL:
229 return _("FreeBSD Specific Access ACL attribs");
230 case STREAM_ACL_HPUX_ACL_ENTRY:
231 return _("HPUX Specific ACL attribs");
232 case STREAM_ACL_IRIX_DEFAULT_ACL:
233 return _("Irix Specific Default ACL attribs");
234 case STREAM_ACL_IRIX_ACCESS_ACL:
235 return _("Irix Specific Access ACL attribs");
236 case STREAM_ACL_LINUX_DEFAULT_ACL:
237 return _("Linux Specific Default ACL attribs");
238 case STREAM_ACL_LINUX_ACCESS_ACL:
239 return _("Linux Specific Access ACL attribs");
240 case STREAM_ACL_TRU64_DEFAULT_ACL:
241 return _("TRU64 Specific Default ACL attribs");
242 case STREAM_ACL_TRU64_ACCESS_ACL:
243 return _("TRU64 Specific Access ACL attribs");
244 case STREAM_ACL_SOLARIS_ACLENT:
245 return _("Solaris Specific POSIX ACL attribs");
246 case STREAM_ACL_SOLARIS_ACE:
247 return _("Solaris Specific NFSv4/ZFS ACL attribs");
248 case STREAM_ACL_AFS_TEXT:
249 return _("AFS Specific ACL attribs");
250 case STREAM_ACL_AIX_AIXC:
251 return _("AIX Specific POSIX ACL attribs");
252 case STREAM_ACL_AIX_NFS4:
253 return _("AIX Specific NFSv4 ACL attribs");
254 case STREAM_ACL_FREEBSD_NFS4_ACL:
255 return _("FreeBSD Specific NFSv4/ZFS ACL attribs");
256 case STREAM_ACL_HURD_DEFAULT_ACL:
257 return _("GNU Hurd Specific Default ACL attribs");
258 case STREAM_ACL_HURD_ACCESS_ACL:
259 return _("GNU Hurd Specific Access ACL attribs");
260 case STREAM_XATTR_HURD:
261 return _("GNU Hurd Specific Extended attribs");
262 case STREAM_XATTR_IRIX:
263 return _("IRIX Specific Extended attribs");
264 case STREAM_XATTR_TRU64:
265 return _("TRU64 Specific Extended attribs");
266 case STREAM_XATTR_AIX:
267 return _("AIX Specific Extended attribs");
268 case STREAM_XATTR_OPENBSD:
269 return _("OpenBSD Specific Extended attribs");
270 case STREAM_XATTR_SOLARIS_SYS:
271 return _("Solaris Specific Extensible attribs or System Extended attribs");
272 case STREAM_XATTR_SOLARIS:
273 return _("Solaris Specific Extended attribs");
274 case STREAM_XATTR_DARWIN:
275 return _("Darwin Specific Extended attribs");
276 case STREAM_XATTR_FREEBSD:
277 return _("FreeBSD Specific Extended attribs");
278 case STREAM_XATTR_LINUX:
279 return _("Linux Specific Extended attribs");
280 case STREAM_XATTR_NETBSD:
281 return _("NetBSD Specific Extended attribs");
283 sprintf(buf, "%d", stream);
284 return (const char *)buf;
289 * Convert a 64 bit little endian to a big endian
291 void int64_LE2BE(int64_t* pBE, const int64_t v)
293 /* convert little endian to big endian */
294 if (htonl(1) != 1L) { /* no work if on little endian machine */
295 memcpy(pBE, &v, sizeof(int64_t));
298 uint8_t rv[sizeof(int64_t)];
299 uint8_t *pv = (uint8_t *) &v;
301 for (i = 0; i < 8; i++) {
304 memcpy(pBE, &rv, sizeof(int64_t));
309 * Convert a 32 bit little endian to a big endian
311 void int32_LE2BE(int32_t* pBE, const int32_t v)
313 /* convert little endian to big endian */
314 if (htonl(1) != 1L) { /* no work if on little endian machine */
315 memcpy(pBE, &v, sizeof(int32_t));
318 uint8_t rv[sizeof(int32_t)];
319 uint8_t *pv = (uint8_t *) &v;
321 for (i = 0; i < 4; i++) {
324 memcpy(pBE, &rv, sizeof(int32_t));
330 * Read a BackupRead block and pull out the file data
332 bool processWin32BackupAPIBlock (BFILE *bfd, void *pBuffer, ssize_t dwSize)
334 /* pByte contains the buffer
335 dwSize the len to be processed. function assumes to be
336 called in successive incremental order over the complete
337 BackupRead stream beginning at pos 0 and ending at the end.
340 PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT* pContext = &(bfd->win32DecompContext);
341 bool bContinue = false;
342 int64_t dwDataOffset = 0;
345 /* Win32 Stream Header size without name of stream.
346 * = sizeof (WIN32_STREAM_ID)- sizeof(WCHAR*);
348 int32_t dwSizeHeader = 20;
351 if (pContext->liNextHeader >= dwSize) {
352 dwDataLen = dwSize-dwDataOffset;
353 bContinue = false; /* 1 iteration is enough */
355 dwDataLen = pContext->liNextHeader-dwDataOffset;
356 bContinue = true; /* multiple iterations may be necessary */
360 /* copy block of real DATA */
361 if (pContext->bIsInData) {
362 if (bwrite(bfd, ((char *)pBuffer)+dwDataOffset, dwDataLen) != (ssize_t)dwDataLen)
366 if (pContext->liNextHeader < dwSize) {/* is a header in this block ? */
367 int32_t dwOffsetTarget;
368 int32_t dwOffsetSource;
370 if (pContext->liNextHeader < 0) {
371 /* start of header was before this block, so we
372 * continue with the part in the current block
374 dwOffsetTarget = -pContext->liNextHeader;
377 /* start of header is inside of this block */
379 dwOffsetSource = pContext->liNextHeader;
382 int32_t dwHeaderPartLen = dwSizeHeader-dwOffsetTarget;
383 bool bHeaderIsComplete;
385 if (dwHeaderPartLen <= dwSize-dwOffsetSource) {
386 /* header (or rest of header) is completely available
389 bHeaderIsComplete = true;
391 /* header will continue in next block */
392 bHeaderIsComplete = false;
393 dwHeaderPartLen = dwSize-dwOffsetSource;
396 /* copy the available portion of header to persistent copy */
397 memcpy(((char *)&pContext->header_stream)+dwOffsetTarget, ((char *)pBuffer)+dwOffsetSource, dwHeaderPartLen);
399 /* recalculate position of next header */
400 if (bHeaderIsComplete) {
401 /* convert stream name size (32 bit little endian) to machine type */
403 int32_LE2BE (&dwNameSize, pContext->header_stream.dwStreamNameSize);
404 dwDataOffset = dwNameSize+pContext->liNextHeader+dwSizeHeader;
406 /* convert stream size (64 bit little endian) to machine type */
407 int64_LE2BE (&(pContext->liNextHeader), pContext->header_stream.Size);
408 pContext->liNextHeader += dwDataOffset;
410 pContext->bIsInData = pContext->header_stream.dwStreamId == WIN32_BACKUP_DATA;
411 if (dwDataOffset == dwSize)
414 /* stop and continue with next block */
416 pContext->bIsInData = false;
421 /* set "NextHeader" relative to the beginning of the next block */
422 pContext->liNextHeader-= dwSize;
430 /* ===============================================================
434 * ===============================================================
437 void binit(BFILE *bfd)
439 memset(bfd, 0, sizeof(BFILE));
444 bool have_win32_api()
446 return false; /* no can do */
450 * Enables using the Backup API (win32_data).
451 * Returns true if function worked
452 * Returns false if failed (i.e. do not have Backup API on this machine)
455 bool set_win32_backup(BFILE *bfd)
457 return false; /* no can do */
462 bool set_portable_backup(BFILE *bfd)
464 return true; /* no problem */
468 * Return true if we are writing in portable format
469 * return false if not
472 bool is_portable_backup(BFILE *bfd)
474 return true; /* portable by definition */
478 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
484 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
486 bfd->cmd_plugin = true;
492 * This code is running on a non-Win32 machine
495 bool is_restore_stream_supported(int stream)
497 /* No Win32 backup on this machine */
500 case STREAM_GZIP_DATA:
501 case STREAM_SPARSE_GZIP_DATA:
502 case STREAM_WIN32_GZIP_DATA:
505 case STREAM_COMPRESSED_DATA:
506 case STREAM_SPARSE_COMPRESSED_DATA:
507 case STREAM_WIN32_COMPRESSED_DATA:
508 case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
509 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
511 #ifndef HAVE_DARWIN_OS
512 case STREAM_MACOS_FORK_DATA:
513 case STREAM_HFSPLUS_ATTRIBUTES:
519 case STREAM_GZIP_DATA:
520 case STREAM_SPARSE_GZIP_DATA:
521 case STREAM_WIN32_GZIP_DATA:
524 case STREAM_COMPRESSED_DATA:
525 case STREAM_SPARSE_COMPRESSED_DATA:
526 case STREAM_WIN32_COMPRESSED_DATA:
527 case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
528 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
530 case STREAM_WIN32_DATA:
531 case STREAM_UNIX_ATTRIBUTES:
532 case STREAM_FILE_DATA:
533 case STREAM_MD5_DIGEST:
534 case STREAM_UNIX_ATTRIBUTES_EX:
535 case STREAM_SPARSE_DATA:
536 case STREAM_PROGRAM_NAMES:
537 case STREAM_PROGRAM_DATA:
538 case STREAM_SHA1_DIGEST:
540 case STREAM_SHA256_DIGEST:
541 case STREAM_SHA512_DIGEST:
544 case STREAM_SIGNED_DIGEST:
545 case STREAM_ENCRYPTED_FILE_DATA:
546 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
547 case STREAM_ENCRYPTED_WIN32_DATA:
548 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
550 #ifdef HAVE_DARWIN_OS
551 case STREAM_MACOS_FORK_DATA:
552 case STREAM_HFSPLUS_ATTRIBUTES:
554 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
555 #endif /* HAVE_CRYPTO */
556 #endif /* HAVE_DARWIN_OS */
557 case 0: /* compatibility with old tapes */
565 int bopen(BFILE *bfd, const char *fname, uint64_t flags, mode_t mode)
567 if (bfd->cmd_plugin && plugin_bopen) {
568 Dmsg1(400, "call plugin_bopen fname=%s\n", fname);
569 bfd->fid = plugin_bopen(bfd, fname, flags, mode);
570 Dmsg2(400, "Plugin bopen fid=%d file=%s\n", bfd->fid, fname);
574 /* Normal file open */
575 Dmsg1(dbglvl, "open file %s\n", fname);
577 /* We use fnctl to set O_NOATIME if requested to avoid open error */
578 bfd->fid = open(fname, flags & ~O_NOATIME, mode);
580 /* Set O_NOATIME if possible */
581 if (bfd->fid != -1 && flags & O_NOATIME) {
582 int oldflags = fcntl(bfd->fid, F_GETFL, 0);
583 if (oldflags == -1) {
588 int ret = fcntl(bfd->fid, F_SETFL, oldflags | O_NOATIME);
589 /* EPERM means setting O_NOATIME was not allowed */
590 if (ret == -1 && errno != EPERM) {
598 bfd->m_flags = flags;
600 bfd->total_bytes = 0;
601 Dmsg1(400, "Open file %d\n", bfd->fid);
604 bfd->win32DecompContext.bIsInData = false;
605 bfd->win32DecompContext.liNextHeader = 0;
607 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
608 if (bfd->fid != -1 && flags & O_RDONLY) {
609 int stat = posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_WILLNEED);
610 Dmsg2(400, "Did posix_fadvise on %s stat=%d\n", fname, stat);
617 #ifdef HAVE_DARWIN_OS
618 /* Open the resource fork of a file. */
619 int bopen_rsrc(BFILE *bfd, const char *fname, uint64_t flags, mode_t mode)
623 rsrc_fname = get_pool_memory(PM_FNAME);
624 pm_strcpy(rsrc_fname, fname);
625 pm_strcat(rsrc_fname, _PATH_RSRCFORKSPEC);
626 bopen(bfd, rsrc_fname, flags, mode);
627 free_pool_memory(rsrc_fname);
632 int bopen_rsrc(BFILE *bfd, const char *fname, uint64_t flags, mode_t mode)
640 int bclose(BFILE *bfd)
644 Dmsg1(400, "Close file %d\n", bfd->fid);
646 if (bfd->fid == -1) {
649 if (bfd->cmd_plugin && plugin_bclose) {
650 stat = plugin_bclose(bfd);
652 bfd->cmd_plugin = false;
655 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
656 if (bfd->m_flags & O_RDONLY) {
657 fdatasync(bfd->fid); /* sync the file */
658 /* Tell OS we don't need it any more */
659 posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_DONTNEED);
663 /* Close normal file */
664 stat = close(bfd->fid);
667 bfd->cmd_plugin = false;
672 ssize_t bread(BFILE *bfd, void *buf, size_t count)
676 if (bfd->cmd_plugin && plugin_bread) {
677 return plugin_bread(bfd, buf, count);
680 stat = read(bfd->fid, buf, count);
684 bfd->total_bytes += stat;
690 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
694 if (bfd->cmd_plugin && plugin_bwrite) {
695 return plugin_bwrite(bfd, buf, count);
697 stat = write(bfd->fid, buf, count);
701 bfd->total_bytes += stat;
707 bool is_bopen(BFILE *bfd)
709 return bfd->fid >= 0;
713 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
717 if (bfd->cmd_plugin && plugin_bwrite) {
718 return plugin_blseek(bfd, offset, whence);
720 pos = (boffset_t)lseek(bfd->fid, offset, whence);