1 /*
2 Bacula(R) - The Network Backup Solution
3
4 Copyright (C) 2000-2020 Kern Sibbald
5
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.
8
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.
13
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
16
17 Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
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.
23 *
24 * Kern Sibbald, April MMIII
25 *
26 */
27
28 #include "bacula.h"
29 #include "find.h"
30
31 const int dbglvl = 200;
32
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;
38
39
40 #ifdef HAVE_DARWIN_OS
41 #include <sys/paths.h>
42 #endif
43
44 #if !defined(HAVE_FDATASYNC)
45 #define fdatasync(fd)
46 #endif
47
48 #ifdef HAVE_WIN32
pause_msg(const char * file,const char * func,int line,const char * msg)49 void pause_msg(const char *file, const char *func, int line, const char *msg)
50 {
51 char buf[1000];
52 if (msg) {
53 bsnprintf(buf, sizeof(buf), "%s:%s:%d %s", file, func, line, msg);
54 } else {
55 bsnprintf(buf, sizeof(buf), "%s:%s:%d", file, func, line);
56 }
57 MessageBox(NULL, buf, "Pause", MB_OK);
58 }
59 #endif
60
61 /* ===============================================================
62 *
63 * U N I X AND W I N D O W S
64 *
65 * ===============================================================
66 */
67
is_win32_stream(int stream)68 bool is_win32_stream(int stream)
69 {
70 switch (stream & STREAMMASK_TYPE) {
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:
77 return true;
78 }
79 return false;
80 }
81
stream_to_ascii(int stream)82 const char *stream_to_ascii(int stream)
83 {
84 static char buf[20];
85
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");
213 default:
214 sprintf(buf, "%d", stream);
215 return (const char *)buf;
216 }
217 }
218
219 /**
220 * Convert a 64 bit little endian to a big endian
221 */
int64_LE2BE(int64_t * pBE,const int64_t v)222 void int64_LE2BE(int64_t* pBE, const int64_t v)
223 {
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));
227 } else {
228 int i;
229 uint8_t rv[sizeof(int64_t)];
230 uint8_t *pv = (uint8_t *) &v;
231
232 for (i = 0; i < 8; i++) {
233 rv[i] = pv[7 - i];
234 }
235 memcpy(pBE, &rv, sizeof(int64_t));
236 }
237 }
238
239 /**
240 * Convert a 32 bit little endian to a big endian
241 */
int32_LE2BE(int32_t * pBE,const int32_t v)242 void int32_LE2BE(int32_t* pBE, const int32_t v)
243 {
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));
247 } else {
248 int i;
249 uint8_t rv[sizeof(int32_t)];
250 uint8_t *pv = (uint8_t *) &v;
251
252 for (i = 0; i < 4; i++) {
253 rv[i] = pv[3 - i];
254 }
255 memcpy(pBE, &rv, sizeof(int32_t));
256 }
257 }
258
259
260 /**
261 * Read a BackupRead block and pull out the file data
262 */
processWin32BackupAPIBlock(BFILE * bfd,void * pBuffer,ssize_t dwSize)263 bool processWin32BackupAPIBlock (BFILE *bfd, void *pBuffer, ssize_t dwSize)
264 {
265 int64_t len = dwSize;
266 char *dat=(char *)pBuffer;
267 int64_t use_len;
268
269 while (len>0 && bfd->win32filter.have_data(&dat, &len, &use_len)) {
270 if (bwrite(bfd, dat, use_len) != (ssize_t)use_len) {
271 return false;
272 }
273 dat+=use_len;
274 }
275 return true;
276 }
277
278 /* ===============================================================
279 *
280 * W I N D O W S
281 *
282 * ===============================================================
283 */
284
285 #if defined(HAVE_WIN32)
286
287 void unix_name_to_win32(POOLMEM **win32_name, const char *name);
288 extern "C" HANDLE get_osfhandle(int fd);
289
290
binit(BFILE * bfd)291 void binit(BFILE *bfd)
292 {
293 memset((void *)bfd, 0, sizeof(BFILE));
294 bfd->fid = -1;
295 bfd->mode = BF_CLOSED;
296 bfd->use_backup_api = have_win32_api();
297 bfd->cmd_plugin = false;
298 }
299
300 /*
301 * Enables using the Backup API (win32_data).
302 * Returns 1 if function worked
303 * Returns 0 if failed (i.e. do not have Backup API on this machine)
304 */
set_win32_backup(BFILE * bfd)305 bool set_win32_backup(BFILE *bfd)
306 {
307 /* We enable if possible here */
308 bfd->use_backup_api = have_win32_api();
309 return bfd->use_backup_api;
310 }
311
set_fattrs(BFILE * bfd,struct stat * statp)312 void set_fattrs(BFILE *bfd, struct stat *statp)
313 {
314 bfd->fattrs = statp->st_fattrs;
315 Dmsg1(200, "set_fattrs 0x%x\n", bfd->fattrs);
316 }
317
set_portable_backup(BFILE * bfd)318 bool set_portable_backup(BFILE *bfd)
319 {
320 bfd->use_backup_api = false;
321 return true;
322 }
323
set_cmd_plugin(BFILE * bfd,JCR * jcr)324 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
325 {
326 bfd->cmd_plugin = true;
327 bfd->jcr = jcr;
328 return true;
329 }
330
331 /*
332 * Return 1 if we are NOT using Win32 BackupWrite()
333 * return 0 if are
334 */
is_portable_backup(BFILE * bfd)335 bool is_portable_backup(BFILE *bfd)
336 {
337 return !bfd->use_backup_api;
338 }
339
is_plugin_data(BFILE * bfd)340 bool is_plugin_data(BFILE *bfd)
341 {
342 return bfd->cmd_plugin;
343 }
344
have_win32_api()345 bool have_win32_api()
346 {
347 return p_BackupRead && p_BackupWrite;
348 }
349
350
351 /*
352 * Return true if we support the stream
353 * false if we do not support the stream
354 *
355 * This code is running under Win32, so we
356 * do not need #ifdef on MACOS ...
357 */
is_restore_stream_supported(int stream)358 bool is_restore_stream_supported(int stream)
359 {
360 switch (stream) {
361
362 /* Streams known not to be supported */
363 #ifndef HAVE_LIBZ
364 case STREAM_GZIP_DATA:
365 case STREAM_SPARSE_GZIP_DATA:
366 case STREAM_WIN32_GZIP_DATA:
367 #endif
368 #ifndef HAVE_LZO
369 case STREAM_COMPRESSED_DATA:
370 case STREAM_SPARSE_COMPRESSED_DATA:
371 case STREAM_WIN32_COMPRESSED_DATA:
372 case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
373 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
374 #endif
375 case STREAM_MACOS_FORK_DATA:
376 case STREAM_HFSPLUS_ATTRIBUTES:
377 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
378 return false;
379
380 /* Known streams */
381 #ifdef HAVE_LIBZ
382 case STREAM_GZIP_DATA:
383 case STREAM_SPARSE_GZIP_DATA:
384 case STREAM_WIN32_GZIP_DATA:
385 #endif
386 #ifdef HAVE_LZO
387 case STREAM_COMPRESSED_DATA:
388 case STREAM_SPARSE_COMPRESSED_DATA:
389 case STREAM_WIN32_COMPRESSED_DATA:
390 #endif
391 case STREAM_WIN32_DATA:
392 case STREAM_UNIX_ATTRIBUTES:
393 case STREAM_FILE_DATA:
394 case STREAM_MD5_DIGEST:
395 case STREAM_UNIX_ATTRIBUTES_EX:
396 case STREAM_SPARSE_DATA:
397 case STREAM_PROGRAM_NAMES:
398 case STREAM_PROGRAM_DATA:
399 case STREAM_SHA1_DIGEST:
400 #ifdef HAVE_SHA2
401 case STREAM_SHA256_DIGEST:
402 case STREAM_SHA512_DIGEST:
403 #endif
404 #ifdef HAVE_CRYPTO
405 case STREAM_SIGNED_DIGEST:
406 case STREAM_ENCRYPTED_FILE_DATA:
407 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
408 case STREAM_ENCRYPTED_WIN32_DATA:
409 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
410 #ifdef HAVE_LZO
411 case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
412 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
413 #endif
414 #endif /* !HAVE_CRYPTO */
415 case 0: /* compatibility with old tapes */
416 return true;
417 }
418 return false;
419 }
420
bget_handle(BFILE * bfd)421 HANDLE bget_handle(BFILE *bfd)
422 {
423 return bfd->fh;
424 }
425
426 /*
427 * The following code was contributed by Graham Keeling from his
428 * burp project. August 2014
429 */
encrypt_bopen(BFILE * bfd,const char * fname,uint64_t flags,mode_t mode)430 static int encrypt_bopen(BFILE *bfd, const char *fname, uint64_t flags, mode_t mode)
431 {
432 ULONG ulFlags = 0;
433 POOLMEM *win32_fname;
434 POOLMEM *win32_fname_wchar;
435
436 bfd->mode = BF_CLOSED;
437 bfd->fid = -1;
438
439 if (!(p_OpenEncryptedFileRawA || p_OpenEncryptedFileRawW)) {
440 Dmsg0(50, "No OpenEncryptedFileRawA and no OpenEncryptedFileRawW APIs!!!\n");
441 return -1;
442 }
443
444 /* Convert to Windows path format */
445 win32_fname = get_pool_memory(PM_FNAME);
446 win32_fname_wchar = get_pool_memory(PM_FNAME);
447
448 unix_name_to_win32(&win32_fname, (char *)fname);
449
450 if (p_CreateFileW && p_MultiByteToWideChar) {
451 make_win32_path_UTF8_2_wchar(&win32_fname_wchar, fname);
452 }
453
454 if ((flags & O_CREAT) || (flags & O_WRONLY)) {
455 ulFlags = CREATE_FOR_IMPORT | OVERWRITE_HIDDEN;
456 if (bfd->fattrs & FILE_ATTRIBUTE_DIRECTORY) {
457 mkdir(fname, 0777);
458 ulFlags |= CREATE_FOR_DIR;
459 }
460 bfd->mode = BF_WRITE;
461 Dmsg0(200, "encrypt_bopen for write.\n");
462 } else {
463 /* Open existing for read */
464 ulFlags = CREATE_FOR_EXPORT;
465 bfd->mode = BF_READ;
466 Dmsg0(200, "encrypt_bopen for read.\n");
467 }
468
469 if (p_OpenEncryptedFileRawW && p_MultiByteToWideChar) {
470 /* unicode open */
471 if (p_OpenEncryptedFileRawW((LPCWSTR)win32_fname_wchar,
472 ulFlags, &(bfd->pvContext))) {
473 bfd->mode = BF_CLOSED;
474 errno = b_errno_win32;
475 bfd->berrno = b_errno_win32;
476 }
477 } else {
478 /* ascii open */
479 if (p_OpenEncryptedFileRawA(win32_fname, ulFlags, &(bfd->pvContext))) {
480 bfd->mode = BF_CLOSED;
481 errno = b_errno_win32;
482 bfd->berrno = b_errno_win32;
483 }
484 }
485 free_pool_memory(win32_fname_wchar);
486 free_pool_memory(win32_fname);
487 bfd->fid = (bfd->mode == BF_CLOSED) ? -1 : 0;
488 return bfd->mode==BF_CLOSED ? -1: 1;
489 }
490
encrypt_bclose(BFILE * bfd)491 static int encrypt_bclose(BFILE *bfd)
492 {
493 Dmsg0(200, "encrypt_bclose\n");
494 if (p_CloseEncryptedFileRaw) {
495 p_CloseEncryptedFileRaw(bfd->pvContext);
496 }
497 bfd->pvContext = NULL;
498 bfd->mode = BF_CLOSED;
499 bfd->fattrs = 0;
500 bfd->fid = -1;
501 return 0;
502 }
503
504 /* Windows */
bopen(BFILE * bfd,const char * fname,uint64_t flags,mode_t mode)505 int bopen(BFILE *bfd, const char *fname, uint64_t flags, mode_t mode)
506 {
507 POOLMEM *win32_fname_wchar;
508
509 DWORD dwaccess, dwflags, dwshare;
510
511 if (bfd->fattrs & FILE_ATTRIBUTE_ENCRYPTED) {
512 return encrypt_bopen(bfd, fname, flags, mode);
513 }
514
515 /* Convert to Windows path format */
516 win32_fname_wchar = get_pool_memory(PM_FNAME);
517
518 if (bfd->cmd_plugin && plugin_bopen) {
519 int rtnstat;
520 Dmsg1(50, "call plugin_bopen fname=%s\n", fname);
521 rtnstat = plugin_bopen(bfd, fname, flags, mode);
522 Dmsg1(50, "return from plugin_bopen status=%d\n", rtnstat);
523 if (rtnstat >= 0) {
524 if (flags & O_CREAT || flags & O_WRONLY) { /* Open existing for write */
525 Dmsg1(50, "plugin_open for write OK file=%s.\n", fname);
526 bfd->mode = BF_WRITE;
527 } else {
528 Dmsg1(50, "plugin_open for read OK file=%s.\n", fname);
529 bfd->mode = BF_READ;
530 }
531 bfd->fid = -1; /* The file descriptor is invalid */
532 } else {
533 bfd->mode = BF_CLOSED;
534 bfd->fid = -1;
535 Dmsg1(10, "==== plugin_bopen returned bad status=%d\n", rtnstat);
536 }
537 free_pool_memory(win32_fname_wchar);
538 return bfd->mode == BF_CLOSED ? -1 : 1;
539 }
540 Dmsg0(100, "=== NO plugin\n");
541
542 if (!(p_CreateFileA || p_CreateFileW)) {
543 Dmsg0(50, "No CreateFileA and no CreateFileW!!!!!\n");
544 return 0;
545 }
546
547 if (p_CreateFileW && p_MultiByteToWideChar) {
548 make_win32_path_UTF8_2_wchar(&win32_fname_wchar, fname);
549 }
550
551 if (flags & O_CREAT) { /* Create */
552 if (bfd->use_backup_api) {
553 dwaccess = GENERIC_WRITE|FILE_ALL_ACCESS|WRITE_OWNER|WRITE_DAC|ACCESS_SYSTEM_SECURITY;
554 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
555 } else {
556 dwaccess = GENERIC_WRITE;
557 dwflags = 0;
558 }
559
560 // unicode open for create write
561 Dmsg1(100, "Create CreateFileW=%ls\n", win32_fname_wchar);
562 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
563 dwaccess, /* Requested access */
564 0, /* Shared mode */
565 NULL, /* SecurityAttributes */
566 CREATE_ALWAYS, /* CreationDisposition */
567 dwflags, /* Flags and attributes */
568 NULL); /* TemplateFile */
569
570 bfd->mode = BF_WRITE;
571
572 } else if (flags & O_WRONLY) { /* Open existing for write */
573 if (bfd->use_backup_api) {
574 dwaccess = GENERIC_READ|GENERIC_WRITE|WRITE_OWNER|WRITE_DAC;
575
576 if (bfd->fattrs & FILE_ATTRIBUTE_DIRECTORY) {
577 /* Avoid issues with directories
578 * ERR=The process cannot access the file because it is being used by another
579 */
580 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
581 } else {
582 dwshare = 0;
583 }
584 /* If deduped, we do not want to open the reparse point */
585 if (bfd->fattrs & FILE_ATTRIBUTE_DEDUP) { /* Maybe check for bfd->reparse_point */
586 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
587 } else {
588 dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT;
589 }
590 } else {
591 dwaccess = GENERIC_READ|GENERIC_WRITE;
592 dwflags = 0;
593 dwshare = 0;
594 }
595
596 // unicode open for open existing write
597 Dmsg1(100, "Write only CreateFileW=%ls\n", win32_fname_wchar);
598 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
599 dwaccess, /* Requested access */
600 dwshare, /* Shared mode */
601 NULL, /* SecurityAttributes */
602 OPEN_EXISTING, /* CreationDisposition */
603 dwflags, /* Flags and attributes */
604 NULL); /* TemplateFile */
605
606 bfd->mode = BF_WRITE;
607
608 } else { /* Read */
609 if (bfd->use_backup_api) {
610 dwaccess = GENERIC_READ|READ_CONTROL|ACCESS_SYSTEM_SECURITY;
611 dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_SEQUENTIAL_SCAN |
612 FILE_FLAG_OPEN_REPARSE_POINT;
613 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
614 } else {
615 dwaccess = GENERIC_READ;
616 dwflags = 0;
617 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE;
618 }
619
620 // unicode open for open existing read
621 Dmsg1(100, "Read CreateFileW=%ls\n", win32_fname_wchar);
622 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
623 dwaccess, /* Requested access */
624 dwshare, /* Share modes */
625 NULL, /* SecurityAttributes */
626 OPEN_EXISTING, /* CreationDisposition */
627 dwflags, /* Flags and attributes */
628 NULL); /* TemplateFile */
629
630 bfd->mode = BF_READ;
631 }
632
633 if (bfd->fh == INVALID_HANDLE_VALUE) {
634 berrno be;
635 bfd->lerror = GetLastError();
636 bfd->berrno = b_errno_win32;
637 errno = b_errno_win32;
638 bfd->mode = BF_CLOSED;
639 Dmsg1(100, "Open failed: %s\n", be.bstrerror());
640 }
641 bfd->block = 0;
642 bfd->total_bytes = 0;
643 bfd->errmsg = NULL;
644 bfd->lpContext = NULL;
645 bfd->win32filter.init();
646 free_pool_memory(win32_fname_wchar);
647 bfd->fid = (bfd->mode == BF_CLOSED) ? -1 : 0;
648 return bfd->mode == BF_CLOSED ? -1 : 1;
649 }
650
651 /*
652 * Returns 0 on success
653 * -1 on error
654 */
655 /* Windows */
bclose(BFILE * bfd)656 int bclose(BFILE *bfd)
657 {
658 int stat = 0;
659
660 if (bfd->mode == BF_CLOSED) {
661 Dmsg0(50, "=== BFD already closed.\n");
662 return 0;
663 }
664
665 if (bfd->cmd_plugin && plugin_bclose) {
666 stat = plugin_bclose(bfd);
667 Dmsg0(50, "==== BFD closed!!!\n");
668 goto all_done;
669 }
670
671 if (bfd->fattrs & FILE_ATTRIBUTE_ENCRYPTED) {
672 return encrypt_bclose(bfd);
673 }
674
675 /*
676 * We need to tell the API to release the buffer it
677 * allocated in lpContext. We do so by calling the
678 * API one more time, but with the Abort bit set.
679 */
680 if (bfd->use_backup_api && bfd->mode == BF_READ) {
681 BYTE buf[10];
682 if (bfd->lpContext && !p_BackupRead(bfd->fh,
683 buf, /* buffer */
684 (DWORD)0, /* bytes to read */
685 &bfd->rw_bytes, /* bytes read */
686 1, /* Abort */
687 1, /* ProcessSecurity */
688 &bfd->lpContext)) { /* Read context */
689 errno = b_errno_win32;
690 stat = -1;
691 }
692 } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
693 BYTE buf[10];
694 if (bfd->lpContext && !p_BackupWrite(bfd->fh,
695 buf, /* buffer */
696 (DWORD)0, /* bytes to read */
697 &bfd->rw_bytes, /* bytes written */
698 1, /* Abort */
699 1, /* ProcessSecurity */
700 &bfd->lpContext)) { /* Write context */
701 errno = b_errno_win32;
702 stat = -1;
703 }
704 }
705 if (!CloseHandle(bfd->fh)) {
706 stat = -1;
707 errno = b_errno_win32;
708 }
709
710 all_done:
711 if (bfd->errmsg) {
712 free_pool_memory(bfd->errmsg);
713 bfd->errmsg = NULL;
714 }
715 bfd->mode = BF_CLOSED;
716 bfd->fattrs = 0;
717 bfd->fid = -1;
718 bfd->lpContext = NULL;
719 bfd->cmd_plugin = false;
720 return stat;
721 }
722
723 /* Returns: bytes read on success
724 * 0 on EOF
725 * -1 on error
726 */
727 /* Windows */
bread(BFILE * bfd,void * buf,size_t count)728 ssize_t bread(BFILE *bfd, void *buf, size_t count)
729 {
730 bfd->rw_bytes = 0;
731
732 if (bfd->cmd_plugin && plugin_bread) {
733 return plugin_bread(bfd, buf, count);
734 }
735
736 if (bfd->use_backup_api) {
737 if (!p_BackupRead(bfd->fh,
738 (BYTE *)buf,
739 count,
740 &bfd->rw_bytes,
741 0, /* no Abort */
742 1, /* Process Security */
743 &bfd->lpContext)) { /* Context */
744 berrno be;
745 bfd->lerror = GetLastError();
746 bfd->berrno = b_errno_win32;
747 errno = b_errno_win32;
748 Dmsg1(100, "Read failed: %s\n", be.bstrerror());
749 return -1;
750 }
751 } else {
752 if (!ReadFile(bfd->fh,
753 buf,
754 count,
755 &bfd->rw_bytes,
756 NULL)) {
757 bfd->lerror = GetLastError();
758 bfd->berrno = b_errno_win32;
759 errno = b_errno_win32;
760 return -1;
761 }
762 }
763 bfd->block++;
764 if (bfd->rw_bytes > 0) {
765 bfd->total_bytes += bfd->rw_bytes;
766 }
767 return (ssize_t)bfd->rw_bytes;
768 }
769
770 /* Windows */
bwrite(BFILE * bfd,void * buf,size_t count)771 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
772 {
773 bfd->rw_bytes = 0;
774
775 if (bfd->cmd_plugin && plugin_bwrite) {
776 return plugin_bwrite(bfd, buf, count);
777 }
778
779 if (bfd->use_backup_api) {
780 if (!p_BackupWrite(bfd->fh,
781 (BYTE *)buf,
782 count,
783 &bfd->rw_bytes,
784 0, /* No abort */
785 1, /* Process Security */
786 &bfd->lpContext)) { /* Context */
787 berrno be;
788 bfd->lerror = GetLastError();
789 bfd->berrno = b_errno_win32;
790 errno = b_errno_win32;
791 Dmsg1(100, "Write failed: %s\n", be.bstrerror());
792 return -1;
793 }
794 } else {
795 if (!WriteFile(bfd->fh,
796 buf,
797 count,
798 &bfd->rw_bytes,
799 NULL)) {
800 bfd->lerror = GetLastError();
801 bfd->berrno = b_errno_win32;
802 errno = b_errno_win32;
803 return -1;
804 }
805 }
806 bfd->block++;
807 if (bfd->rw_bytes > 0) {
808 bfd->total_bytes += bfd->rw_bytes;
809 }
810 return (ssize_t)bfd->rw_bytes;
811 }
812
813 /* Windows */
is_bopen(BFILE * bfd)814 bool is_bopen(BFILE *bfd)
815 {
816 return bfd->mode != BF_CLOSED;
817 }
818
819 /* Windows */
blseek(BFILE * bfd,boffset_t offset,int whence)820 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
821 {
822 LONG offset_low = (LONG)offset;
823 LONG offset_high = (LONG)(offset >> 32);
824 DWORD dwResult;
825
826 if (bfd->cmd_plugin && plugin_blseek) {
827 return plugin_blseek(bfd, offset, whence);
828 }
829
830 dwResult = SetFilePointer(bfd->fh, offset_low, &offset_high, whence);
831
832 if (dwResult == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
833 return (boffset_t)-1;
834 }
835
836 return ((boffset_t)offset_high << 32) | dwResult;
837 }
838
839 #else /* Unix systems */
840
841 /* ===============================================================
842 *
843 * U N I X
844 *
845 * ===============================================================
846 */
847 /* Unix */
binit(BFILE * bfd)848 void binit(BFILE *bfd)
849 {
850 bmemset(bfd, 0, sizeof(BFILE));
851 bfd->fid = -1;
852 }
853
854 /* Unix */
have_win32_api()855 bool have_win32_api()
856 {
857 return false; /* no can do */
858 }
859
860 /*
861 * Enables using the Backup API (win32_data).
862 * Returns true if function worked
863 * Returns false if failed (i.e. do not have Backup API on this machine)
864 */
865 /* Unix */
set_win32_backup(BFILE * bfd)866 bool set_win32_backup(BFILE *bfd)
867 {
868 return false; /* no can do */
869 }
870
871
872 /* Unix */
set_portable_backup(BFILE * bfd)873 bool set_portable_backup(BFILE *bfd)
874 {
875 return true; /* no problem */
876 }
877
is_plugin_data(BFILE * bfd)878 bool is_plugin_data(BFILE *bfd)
879 {
880 return bfd->cmd_plugin;
881 }
882
883 /*
884 * Return true if we are writing in portable format
885 * return false if not
886 */
887 /* Unix */
is_portable_backup(BFILE * bfd)888 bool is_portable_backup(BFILE *bfd)
889 {
890 return true; /* portable by definition */
891 }
892
893 /* Unix */
set_prog(BFILE * bfd,char * prog,JCR * jcr)894 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
895 {
896 return false;
897 }
898
899 /* Unix */
set_cmd_plugin(BFILE * bfd,JCR * jcr)900 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
901 {
902 bfd->cmd_plugin = true;
903 bfd->jcr = jcr;
904 return true;
905 }
906
907 /*
908 * This code is running on a non-Win32 machine
909 */
910 /* Unix */
is_restore_stream_supported(int stream)911 bool is_restore_stream_supported(int stream)
912 {
913 /* No Win32 backup on this machine */
914 switch (stream) {
915 #ifndef HAVE_LIBZ
916 case STREAM_GZIP_DATA:
917 case STREAM_SPARSE_GZIP_DATA:
918 case STREAM_WIN32_GZIP_DATA:
919 #endif
920 #ifndef HAVE_LZO
921 case STREAM_COMPRESSED_DATA:
922 case STREAM_SPARSE_COMPRESSED_DATA:
923 case STREAM_WIN32_COMPRESSED_DATA:
924 case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
925 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
926 #endif
927 #ifndef HAVE_DARWIN_OS
928 case STREAM_MACOS_FORK_DATA:
929 case STREAM_HFSPLUS_ATTRIBUTES:
930 #endif
931 return false;
932
933 /* Known streams */
934 #ifdef HAVE_LIBZ
935 case STREAM_GZIP_DATA:
936 case STREAM_SPARSE_GZIP_DATA:
937 case STREAM_WIN32_GZIP_DATA:
938 #endif
939 #ifdef HAVE_LZO
940 case STREAM_COMPRESSED_DATA:
941 case STREAM_SPARSE_COMPRESSED_DATA:
942 case STREAM_WIN32_COMPRESSED_DATA:
943 case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
944 case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
945 #endif
946 case STREAM_WIN32_DATA:
947 case STREAM_UNIX_ATTRIBUTES:
948 case STREAM_FILE_DATA:
949 case STREAM_MD5_DIGEST:
950 case STREAM_UNIX_ATTRIBUTES_EX:
951 case STREAM_SPARSE_DATA:
952 case STREAM_PROGRAM_NAMES:
953 case STREAM_PROGRAM_DATA:
954 case STREAM_SHA1_DIGEST:
955 #ifdef HAVE_SHA2
956 case STREAM_SHA256_DIGEST:
957 case STREAM_SHA512_DIGEST:
958 #endif
959 #ifdef HAVE_CRYPTO
960 case STREAM_SIGNED_DIGEST:
961 case STREAM_ENCRYPTED_FILE_DATA:
962 case STREAM_ENCRYPTED_FILE_GZIP_DATA:
963 case STREAM_ENCRYPTED_WIN32_DATA:
964 case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
965 #endif
966 #ifdef HAVE_DARWIN_OS
967 case STREAM_MACOS_FORK_DATA:
968 case STREAM_HFSPLUS_ATTRIBUTES:
969 #ifdef HAVE_CRYPTO
970 case STREAM_ENCRYPTED_MACOS_FORK_DATA:
971 #endif /* HAVE_CRYPTO */
972 #endif /* HAVE_DARWIN_OS */
973 case 0: /* compatibility with old tapes */
974 return true;
975
976 }
977 return false;
978 }
979
980 /* Unix */
bopen(BFILE * bfd,const char * fname,uint64_t flags,mode_t mode)981 int bopen(BFILE *bfd, const char *fname, uint64_t flags, mode_t mode)
982 {
983 if (bfd->cmd_plugin && plugin_bopen) {
984 Dmsg1(400, "call plugin_bopen fname=%s\n", fname);
985 bfd->fid = plugin_bopen(bfd, fname, flags, mode);
986 Dmsg2(400, "Plugin bopen fid=%d file=%s\n", bfd->fid, fname);
987 return bfd->fid;
988 }
989
990 /* Normal file open */
991 Dmsg1(dbglvl, "open file %s\n", fname);
992
993 /* We use fnctl to set O_NOATIME if requested to avoid open error */
994 bfd->fid = open(fname, (flags | O_CLOEXEC) & ~O_NOATIME, mode);
995
996 /* Set O_NOATIME if possible */
997 if (bfd->fid != -1 && flags & O_NOATIME) {
998 int oldflags = fcntl(bfd->fid, F_GETFL, 0);
999 if (oldflags == -1) {
1000 bfd->berrno = errno;
1001 close(bfd->fid);
1002 bfd->fid = -1;
1003 } else {
1004 int ret = fcntl(bfd->fid, F_SETFL, oldflags | O_NOATIME);
1005 /* EPERM means setting O_NOATIME was not allowed */
1006 if (ret == -1 && errno != EPERM) {
1007 bfd->berrno = errno;
1008 close(bfd->fid);
1009 bfd->fid = -1;
1010 }
1011 }
1012 }
1013 bfd->berrno = errno;
1014 bfd->m_flags = flags;
1015 bfd->block = 0;
1016 bfd->total_bytes = 0;
1017 Dmsg1(400, "Open file %d\n", bfd->fid);
1018 errno = bfd->berrno;
1019
1020 bfd->win32filter.init();
1021
1022 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
1023 /* If not RDWR or WRONLY must be Read Only */
1024 if (bfd->fid != -1 && !(flags & (O_RDWR|O_WRONLY))) {
1025 int stat = posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_WILLNEED);
1026 Dmsg3(400, "Did posix_fadvise WILLNEED on %s fid=%d stat=%d\n", fname, bfd->fid, stat);
1027 }
1028 #endif
1029
1030 return bfd->fid;
1031 }
1032
1033 #ifdef HAVE_DARWIN_OS
1034 /* Open the resource fork of a file. */
bopen_rsrc(BFILE * bfd,const char * fname,uint64_t flags,mode_t mode)1035 int bopen_rsrc(BFILE *bfd, const char *fname, uint64_t flags, mode_t mode)
1036 {
1037 POOLMEM *rsrc_fname;
1038
1039 rsrc_fname = get_pool_memory(PM_FNAME);
1040 pm_strcpy(rsrc_fname, fname);
1041 pm_strcat(rsrc_fname, _PATH_RSRCFORKSPEC);
1042 bopen(bfd, rsrc_fname, flags, mode);
1043 free_pool_memory(rsrc_fname);
1044 return bfd->fid;
1045 }
1046 #else /* Unix */
1047
1048 /* Unix */
bopen_rsrc(BFILE * bfd,const char * fname,uint64_t flags,mode_t mode)1049 int bopen_rsrc(BFILE *bfd, const char *fname, uint64_t flags, mode_t mode)
1050 { return -1; }
1051
1052 #endif
1053
1054
1055 /* Unix */
bclose(BFILE * bfd)1056 int bclose(BFILE *bfd)
1057 {
1058 int stat;
1059
1060 Dmsg2(400, "Close bfd=%p file %d\n", bfd, bfd->fid);
1061
1062 if (bfd->fid == -1) {
1063 return 0;
1064 }
1065 if (bfd->cmd_plugin && plugin_bclose) {
1066 stat = plugin_bclose(bfd);
1067 bfd->fid = -1;
1068 bfd->cmd_plugin = false;
1069 }
1070
1071 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
1072 /* If not RDWR or WRONLY must be Read Only */
1073 if (!(bfd->m_flags & (O_RDWR|O_WRONLY))) {
1074 fdatasync(bfd->fid); /* sync the file */
1075 /* Tell OS we don't need it any more */
1076 posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_DONTNEED);
1077 Dmsg1(400, "Did posix_fadvise DONTNEED on fid=%d\n", bfd->fid);
1078 }
1079 #endif
1080
1081 /* Close normal file */
1082 stat = close(bfd->fid);
1083 bfd->berrno = errno;
1084 bfd->fid = -1;
1085 bfd->cmd_plugin = false;
1086 return stat;
1087 }
1088
1089 /* Unix */
bread(BFILE * bfd,void * buf,size_t count)1090 ssize_t bread(BFILE *bfd, void *buf, size_t count)
1091 {
1092 ssize_t stat;
1093
1094 if (bfd->cmd_plugin && plugin_bread) {
1095 return plugin_bread(bfd, buf, count);
1096 }
1097
1098 stat = read(bfd->fid, buf, count);
1099 bfd->berrno = errno;
1100 bfd->block++;
1101 if (stat > 0) {
1102 bfd->total_bytes += stat;
1103 }
1104 return stat;
1105 }
1106
1107 /* Unix */
bwrite(BFILE * bfd,void * buf,size_t count)1108 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
1109 {
1110 ssize_t stat;
1111
1112 if (bfd->cmd_plugin && plugin_bwrite) {
1113 return plugin_bwrite(bfd, buf, count);
1114 }
1115 stat = write(bfd->fid, buf, count);
1116 bfd->berrno = errno;
1117 bfd->block++;
1118 if (stat > 0) {
1119 bfd->total_bytes += stat;
1120 }
1121 return stat;
1122 }
1123
1124 /* Unix */
is_bopen(BFILE * bfd)1125 bool is_bopen(BFILE *bfd)
1126 {
1127 return bfd->fid >= 0;
1128 }
1129
1130 /* Unix */
blseek(BFILE * bfd,boffset_t offset,int whence)1131 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
1132 {
1133 boffset_t pos;
1134
1135 if (bfd->cmd_plugin && plugin_bwrite) {
1136 return plugin_blseek(bfd, offset, whence);
1137 }
1138 pos = (boffset_t)lseek(bfd->fid, offset, whence);
1139 bfd->berrno = errno;
1140 return pos;
1141 }
1142
1143 #endif
1144