]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/findlib/bfile.c
Baculize encrypt_bopen/close
[bacula/bacula] / bacula / src / findlib / bfile.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2003-2014 Free Software Foundation Europe e.V.
5
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.
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    Bacula® is a registered trademark of Kern Sibbald.
15 */
16 /*
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.
20  *
21  *    Kern Sibbald, April MMIII
22  *
23  */
24
25 #include "bacula.h"
26 #include "find.h"
27
28 const int dbglvl = 200;
29
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;
35
36
37 #ifdef HAVE_DARWIN_OS
38 #include <sys/paths.h>
39 #endif
40
41 #if !defined(HAVE_FDATASYNC)
42 #define fdatasync(fd)
43 #endif
44
45 #ifdef HAVE_WIN32
46 void pause_msg(const char *file, const char *func, int line, const char *msg)
47 {
48    char buf[1000];
49    if (msg) {
50       bsnprintf(buf, sizeof(buf), "%s:%s:%d %s", file, func, line, msg);
51    } else {
52       bsnprintf(buf, sizeof(buf), "%s:%s:%d", file, func, line);
53    }
54    MessageBox(NULL, buf, "Pause", MB_OK);
55 }
56
57 /*
58  * The following code was contributed by Graham Keeling from his
59  *  burp project.  August 2014
60  */
61 static int encrypt_bopen(BFILE *bfd, const char *fname, uint64_t flags, mode_t mode)
62 {
63    ULONG ulFlags = 0;
64    POOLMEM *win32_fname;
65    POOLMEM *win32_fname_wchar;
66
67    bfd->mode = BF_CLOSED;
68    bfd->fid = -1;
69
70    if (!(p_OpenEncryptedFileRawA || p_OpenEncryptedFileRawW)) {
71       Dmsg0(50, "No OpenEncryptedFileRawA and no OpenEncryptedFileRawW APIs!!!\n");
72       return -1;
73    }
74
75    /* Convert to Windows path format */
76    win32_fname = get_pool_memory(PM_FNAME);
77    win32_fname_wchar = get_pool_memory(PM_FNAME);
78
79    unix_name_to_win32(&win32_fname, (char *)fname);
80
81    if (p_CreateFileW && p_MultiByteToWideChar) {
82       make_win32_path_UTF8_2_wchar(&win32_fname_wchar, fname);
83    }
84
85    if ((flags & O_CREAT) || (flags & O_WRONLY)) {
86       ulFlags = CREATE_FOR_IMPORT | OVERWRITE_HIDDEN;
87       if (bfd->fattrs & FILE_ATTRIBUTE_DIRECTORY) {
88          mkdir(fname, 0777);
89          ulFlags |= CREATE_FOR_DIR;
90       }
91       bfd->mode = BF_WRITE;
92    } else {
93       /* Open existing for read */
94       ulFlags = CREATE_FOR_EXPORT;
95       bfd->mode = BF_READ;
96    }
97
98    if (p_OpenEncryptedFileRawW && p_MultiByteToWideChar) {
99       /* unicode open */
100       if (p_OpenEncryptedFileRawW((LPCWSTR)win32_fname_wchar,
101                    ulFlags, &(bfd->pvContext))) {
102          bfd->mode = BF_CLOSED;
103       }
104    } else {
105       /* ascii open */
106       if (p_OpenEncryptedFileRawA(win32_fname, ulFlags, &(bfd->pvContext))) {
107          bfd->mode = BF_CLOSED;
108       }
109    }
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;
114 }
115
116 static int encrypt_bclose(BFILE *bfd)
117 {
118    if (p_CloseEncryptedFileRaw) {
119       p_CloseEncryptedFileRaw(bfd->pvContext);
120    }
121    bfd->pvContext = NULL;
122    bfd->mode = BF_CLOSED;
123    bfd->fattrs = 0;
124    bfd->fid = -1;
125    return 0;
126 }
127
128 #endif
129
130 /* ===============================================================
131  *
132  *            U N I X   AND   W I N D O W S
133  *
134  * ===============================================================
135  */
136
137 bool is_win32_stream(int stream)
138 {
139    switch (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:
146       return true;
147    }
148    return false;
149 }
150
151 const char *stream_to_ascii(int stream)
152 {
153    static char buf[20];
154
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");
282    default:
283       sprintf(buf, "%d", stream);
284       return (const char *)buf;
285    }
286 }
287
288 /**
289  *  Convert a 64 bit little endian to a big endian
290  */
291 void int64_LE2BE(int64_t* pBE, const int64_t v)
292 {
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));
296    } else {
297       int i;
298       uint8_t rv[sizeof(int64_t)];
299       uint8_t *pv = (uint8_t *) &v;
300
301       for (i = 0; i < 8; i++) {
302          rv[i] = pv[7 - i];
303       }
304       memcpy(pBE, &rv, sizeof(int64_t));
305    }
306 }
307
308 /**
309  *  Convert a 32 bit little endian to a big endian
310  */
311 void int32_LE2BE(int32_t* pBE, const int32_t v)
312 {
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));
316    } else {
317       int i;
318       uint8_t rv[sizeof(int32_t)];
319       uint8_t *pv = (uint8_t *) &v;
320
321       for (i = 0; i < 4; i++) {
322          rv[i] = pv[3 - i];
323       }
324       memcpy(pBE, &rv, sizeof(int32_t));
325    }
326 }
327
328
329 /*
330  *  Read a BackupRead block and pull out the file data
331  */
332 bool processWin32BackupAPIBlock (BFILE *bfd, void *pBuffer, ssize_t dwSize)
333 {
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.
338     */
339
340    PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT* pContext = &(bfd->win32DecompContext);
341    bool bContinue = false;
342    int64_t dwDataOffset = 0;
343    int64_t dwDataLen;
344
345    /* Win32 Stream Header size without name of stream.
346     * = sizeof (WIN32_STREAM_ID)- sizeof(WCHAR*);
347     */
348    int32_t dwSizeHeader = 20;
349
350    do {
351       if (pContext->liNextHeader >= dwSize) {
352          dwDataLen = dwSize-dwDataOffset;
353          bContinue = false; /* 1 iteration is enough */
354       } else {
355          dwDataLen = pContext->liNextHeader-dwDataOffset;
356          bContinue = true; /* multiple iterations may be necessary */
357       }
358
359       /* flush */
360       /* copy block of real DATA */
361       if (pContext->bIsInData) {
362          if (bwrite(bfd, ((char *)pBuffer)+dwDataOffset, dwDataLen) != (ssize_t)dwDataLen)
363             return false;
364       }
365
366       if (pContext->liNextHeader < dwSize) {/* is a header in this block ? */
367          int32_t dwOffsetTarget;
368          int32_t dwOffsetSource;
369
370          if (pContext->liNextHeader < 0) {
371             /* start of header was before this block, so we
372              * continue with the part in the current block
373              */
374             dwOffsetTarget = -pContext->liNextHeader;
375             dwOffsetSource = 0;
376          } else {
377             /* start of header is inside of this block */
378             dwOffsetTarget = 0;
379             dwOffsetSource = pContext->liNextHeader;
380          }
381
382          int32_t dwHeaderPartLen = dwSizeHeader-dwOffsetTarget;
383          bool bHeaderIsComplete;
384
385          if (dwHeaderPartLen <= dwSize-dwOffsetSource) {
386             /* header (or rest of header) is completely available
387                in current block
388              */
389             bHeaderIsComplete = true;
390          } else {
391             /* header will continue in next block */
392             bHeaderIsComplete = false;
393             dwHeaderPartLen = dwSize-dwOffsetSource;
394          }
395
396          /* copy the available portion of header to persistent copy */
397          memcpy(((char *)&pContext->header_stream)+dwOffsetTarget, ((char *)pBuffer)+dwOffsetSource, dwHeaderPartLen);
398
399          /* recalculate position of next header */
400          if (bHeaderIsComplete) {
401             /* convert stream name size (32 bit little endian) to machine type */
402             int32_t dwNameSize;
403             int32_LE2BE (&dwNameSize, pContext->header_stream.dwStreamNameSize);
404             dwDataOffset = dwNameSize+pContext->liNextHeader+dwSizeHeader;
405
406             /* convert stream size (64 bit little endian) to machine type */
407             int64_LE2BE (&(pContext->liNextHeader), pContext->header_stream.Size);
408             pContext->liNextHeader += dwDataOffset;
409
410             pContext->bIsInData = pContext->header_stream.dwStreamId == WIN32_BACKUP_DATA;
411             if (dwDataOffset == dwSize)
412                bContinue = false;
413          } else {
414             /* stop and continue with next block */
415             bContinue = false;
416             pContext->bIsInData = false;
417          }
418       }
419    } while (bContinue);
420
421    /* set "NextHeader" relative to the beginning of the next block */
422    pContext->liNextHeader-= dwSize;
423
424    return TRUE;
425 }
426
427
428
429
430 /* ===============================================================
431  *
432  *            U N I X
433  *
434  * ===============================================================
435  */
436 /* Unix */
437 void binit(BFILE *bfd)
438 {
439    memset(bfd, 0, sizeof(BFILE));
440    bfd->fid = -1;
441 }
442
443 /* Unix */
444 bool have_win32_api()
445 {
446    return false;                       /* no can do */
447 }
448
449 /*
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)
453  */
454 /* Unix */
455 bool set_win32_backup(BFILE *bfd)
456 {
457    return false;                       /* no can do */
458 }
459
460
461 /* Unix */
462 bool set_portable_backup(BFILE *bfd)
463 {
464    return true;                        /* no problem */
465 }
466
467 /*
468  * Return true  if we are writing in portable format
469  * return false if not
470  */
471 /* Unix */
472 bool is_portable_backup(BFILE *bfd)
473 {
474    return true;                       /* portable by definition */
475 }
476
477 /* Unix */
478 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
479 {
480    return false;
481 }
482
483 /* Unix */
484 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
485 {
486    bfd->cmd_plugin = true;
487    bfd->jcr = jcr;
488    return true;
489 }
490
491 /*
492  * This code is running on a non-Win32 machine
493  */
494 /* Unix */
495 bool is_restore_stream_supported(int stream)
496 {
497    /* No Win32 backup on this machine */
498      switch (stream) {
499 #ifndef HAVE_LIBZ
500    case STREAM_GZIP_DATA:
501    case STREAM_SPARSE_GZIP_DATA:
502    case STREAM_WIN32_GZIP_DATA:
503 #endif
504 #ifndef HAVE_LZO
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:
510 #endif
511 #ifndef HAVE_DARWIN_OS
512    case STREAM_MACOS_FORK_DATA:
513    case STREAM_HFSPLUS_ATTRIBUTES:
514 #endif
515       return false;
516
517    /* Known streams */
518 #ifdef HAVE_LIBZ
519    case STREAM_GZIP_DATA:
520    case STREAM_SPARSE_GZIP_DATA:
521    case STREAM_WIN32_GZIP_DATA:
522 #endif
523 #ifdef HAVE_LZO
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:
529 #endif
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:
539 #ifdef HAVE_SHA2
540    case STREAM_SHA256_DIGEST:
541    case STREAM_SHA512_DIGEST:
542 #endif
543 #ifdef HAVE_CRYPTO
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:
549 #endif
550 #ifdef HAVE_DARWIN_OS
551    case STREAM_MACOS_FORK_DATA:
552    case STREAM_HFSPLUS_ATTRIBUTES:
553 #ifdef HAVE_CRYPTO
554    case STREAM_ENCRYPTED_MACOS_FORK_DATA:
555 #endif /* HAVE_CRYPTO */
556 #endif /* HAVE_DARWIN_OS */
557    case 0:   /* compatibility with old tapes */
558       return true;
559
560    }
561    return false;
562 }
563
564 /* Unix */
565 int bopen(BFILE *bfd, const char *fname, uint64_t flags, mode_t mode)
566 {
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);
571       return bfd->fid;
572    }
573
574    /* Normal file open */
575    Dmsg1(dbglvl, "open file %s\n", fname);
576
577    /* We use fnctl to set O_NOATIME if requested to avoid open error */
578    bfd->fid = open(fname, flags & ~O_NOATIME, mode);
579
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) {
584          bfd->berrno = errno;
585          close(bfd->fid);
586          bfd->fid = -1;
587       } else {
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) {
591             bfd->berrno = errno;
592             close(bfd->fid);
593             bfd->fid = -1;
594          }
595       }
596    }
597    bfd->berrno = errno;
598    bfd->m_flags = flags;
599    bfd->block = 0;
600    bfd->total_bytes = 0;
601    Dmsg1(400, "Open file %d\n", bfd->fid);
602    errno = bfd->berrno;
603
604    bfd->win32DecompContext.bIsInData = false;
605    bfd->win32DecompContext.liNextHeader = 0;
606
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);
611    }
612 #endif
613
614    return bfd->fid;
615 }
616
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)
620 {
621    POOLMEM *rsrc_fname;
622
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);
628    return bfd->fid;
629 }
630 #else
631 /* Unix */
632 int bopen_rsrc(BFILE *bfd, const char *fname, uint64_t flags, mode_t mode)
633 {
634    return -1;
635 }
636 #endif
637
638
639 /* Unix */
640 int bclose(BFILE *bfd)
641 {
642    int stat;
643
644    Dmsg1(400, "Close file %d\n", bfd->fid);
645
646    if (bfd->fid == -1) {
647       return 0;
648    }
649    if (bfd->cmd_plugin && plugin_bclose) {
650       stat = plugin_bclose(bfd);
651       bfd->fid = -1;
652       bfd->cmd_plugin = false;
653    }
654
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);
660    }
661 #endif
662
663    /* Close normal file */
664    stat = close(bfd->fid);
665    bfd->berrno = errno;
666    bfd->fid = -1;
667    bfd->cmd_plugin = false;
668    return stat;
669 }
670
671 /* Unix */
672 ssize_t bread(BFILE *bfd, void *buf, size_t count)
673 {
674    ssize_t stat;
675
676    if (bfd->cmd_plugin && plugin_bread) {
677       return plugin_bread(bfd, buf, count);
678    }
679
680    stat = read(bfd->fid, buf, count);
681    bfd->berrno = errno;
682    bfd->block++;
683    if (stat > 0) {
684       bfd->total_bytes += stat;
685    }
686    return stat;
687 }
688
689 /* Unix */
690 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
691 {
692    ssize_t stat;
693
694    if (bfd->cmd_plugin && plugin_bwrite) {
695       return plugin_bwrite(bfd, buf, count);
696    }
697    stat = write(bfd->fid, buf, count);
698    bfd->berrno = errno;
699    bfd->block++;
700    if (stat > 0) {
701       bfd->total_bytes += stat;
702    }
703    return stat;
704 }
705
706 /* Unix */
707 bool is_bopen(BFILE *bfd)
708 {
709    return bfd->fid >= 0;
710 }
711
712 /* Unix */
713 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
714 {
715    boffset_t pos;
716
717    if (bfd->cmd_plugin && plugin_bwrite) {
718       return plugin_blseek(bfd, offset, whence);
719    }
720    pos = (boffset_t)lseek(bfd->fid, offset, whence);
721    bfd->berrno = errno;
722    return pos;
723 }