]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/findlib/bfile.c
Added support for TRU64 Extended Attributes interface.
[bacula/bacula] / bacula / src / findlib / bfile.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2003-2010 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version three of the GNU Affero General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU Affero General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of Kern Sibbald.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  *  Bacula low level File I/O routines.  This routine simulates
30  *    open(), read(), write(), and close(), but using native routines.
31  *    I.e. on Windows, we use Windows APIs.
32  *
33  *    Kern Sibbald, April MMIII
34  *
35  */
36
37 #include "bacula.h"
38 #include "find.h"
39
40 const int dbglvl = 200;
41
42 int       (*plugin_bopen)(BFILE *bfd, const char *fname, int flags, mode_t mode) = NULL;
43 int       (*plugin_bclose)(BFILE *bfd) = NULL;
44 ssize_t   (*plugin_bread)(BFILE *bfd, void *buf, size_t count) = NULL;
45 ssize_t   (*plugin_bwrite)(BFILE *bfd, void *buf, size_t count) = NULL;
46 boffset_t (*plugin_blseek)(BFILE *bfd, boffset_t offset, int whence) = NULL;
47
48
49 #ifdef HAVE_DARWIN_OS
50 #include <sys/paths.h>
51 #endif
52
53 #if !defined(HAVE_FDATASYNC)
54 #define fdatasync(fd)
55 #endif
56
57 #ifdef HAVE_WIN32
58 void pause_msg(const char *file, const char *func, int line, const char *msg)
59 {
60    char buf[1000];
61    if (msg) {
62       bsnprintf(buf, sizeof(buf), "%s:%s:%d %s", file, func, line, msg);
63    } else {
64       bsnprintf(buf, sizeof(buf), "%s:%s:%d", file, func, line);
65    }
66    MessageBox(NULL, buf, "Pause", MB_OK);
67 }
68 #endif
69
70 /* ===============================================================
71  *
72  *            U N I X   AND   W I N D O W S
73  *
74  * ===============================================================
75  */
76
77 bool is_win32_stream(int stream)
78 {
79    switch (stream) {
80    case STREAM_WIN32_DATA:
81    case STREAM_WIN32_GZIP_DATA:
82    case STREAM_ENCRYPTED_WIN32_DATA:
83    case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
84       return true;
85    }
86    return false;
87 }
88
89 const char *stream_to_ascii(int stream)
90 {
91    static char buf[20];
92
93    switch (stream) {
94    case STREAM_UNIX_ATTRIBUTES:
95       return _("Unix attributes");
96    case STREAM_FILE_DATA:
97       return _("File data");
98    case STREAM_MD5_DIGEST:
99       return _("MD5 digest");
100    case STREAM_GZIP_DATA:
101       return _("GZIP data");
102    case STREAM_UNIX_ATTRIBUTES_EX:
103       return _("Extended attributes");
104    case STREAM_SPARSE_DATA:
105       return _("Sparse data");
106    case STREAM_SPARSE_GZIP_DATA:
107       return _("GZIP sparse data");
108    case STREAM_PROGRAM_NAMES:
109       return _("Program names");
110    case STREAM_PROGRAM_DATA:
111       return _("Program data");
112    case STREAM_SHA1_DIGEST:
113       return _("SHA1 digest");
114    case STREAM_WIN32_DATA:
115       return _("Win32 data");
116    case STREAM_WIN32_GZIP_DATA:
117       return _("Win32 GZIP 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_WIN32_GZIP_DATA:
141       return _("Encrypted Win32 GZIP data");
142    case STREAM_ENCRYPTED_MACOS_FORK_DATA:
143       return _("Encrypted MacOS fork data");
144    case STREAM_ACL_AIX_TEXT:
145       return _("AIX Specific ACL attribs");
146    case STREAM_ACL_DARWIN_ACCESS_ACL:
147       return _("Darwin Specific ACL attribs");
148    case STREAM_ACL_FREEBSD_DEFAULT_ACL:
149       return _("FreeBSD Specific Default ACL attribs");
150    case STREAM_ACL_FREEBSD_ACCESS_ACL:
151       return _("FreeBSD Specific Access ACL attribs");
152    case STREAM_ACL_HPUX_ACL_ENTRY:
153       return _("HPUX Specific ACL attribs");
154    case STREAM_ACL_IRIX_DEFAULT_ACL:
155       return _("Irix Specific Default ACL attribs");
156    case STREAM_ACL_IRIX_ACCESS_ACL:
157       return _("Irix Specific Access ACL attribs");
158    case STREAM_ACL_LINUX_DEFAULT_ACL:
159       return _("Linux Specific Default ACL attribs");
160    case STREAM_ACL_LINUX_ACCESS_ACL:
161       return _("Linux Specific Access ACL attribs");
162    case STREAM_ACL_TRU64_DEFAULT_ACL:
163       return _("TRU64 Specific Default ACL attribs");
164    case STREAM_ACL_TRU64_ACCESS_ACL:
165       return _("TRU64 Specific Access ACL attribs");
166    case STREAM_ACL_SOLARIS_ACLENT:
167       return _("Solaris Specific ACL attribs");
168    case STREAM_ACL_SOLARIS_ACE:
169       return _("Solaris Specific ACL attribs");
170    case STREAM_ACL_AFS_TEXT:
171       return _("AFS Specific ACL attribs");
172    case STREAM_ACL_AIX_AIXC:
173       return _("AIX Specific ACL attribs");
174    case STREAM_ACL_AIX_NFS4:
175       return _("AIX Specific ACL attribs");
176    case STREAM_XATTR_TRU64:
177       return _("TRU64 Specific Extended attribs");
178    case STREAM_XATTR_AIX:
179       return _("AIX Specific Extended attribs");
180    case STREAM_XATTR_OPENBSD:
181       return _("OpenBSD Specific Extended attribs");
182    case STREAM_XATTR_SOLARIS_SYS:
183       return _("Solaris Specific Extensible attribs or System Extended attribs");
184    case STREAM_XATTR_SOLARIS:
185       return _("Solaris Specific Extended attribs");
186    case STREAM_XATTR_DARWIN:
187       return _("Darwin Specific Extended attribs");
188    case STREAM_XATTR_FREEBSD:
189       return _("FreeBSD Specific Extended attribs");
190    case STREAM_XATTR_LINUX:
191       return _("Linux Specific Extended attribs");
192    case STREAM_XATTR_NETBSD:
193       return _("NetBSD Specific Extended attribs");
194    default:
195       sprintf(buf, "%d", stream);
196       return (const char *)buf;
197    }
198 }
199
200 /**   
201  *  Convert a 64 bit little endian to a big endian
202  */
203 void int64_LE2BE(int64_t* pBE, const int64_t v)
204 {
205    /* convert little endian to big endian */
206    if (htonl(1) != 1L) { /* no work if on little endian machine */
207       memcpy(pBE, &v, sizeof(int64_t));
208    } else {
209       int i;
210       uint8_t rv[sizeof(int64_t)];
211       uint8_t *pv = (uint8_t *) &v;
212
213       for (i = 0; i < 8; i++) {
214          rv[i] = pv[7 - i];
215       }
216       memcpy(pBE, &rv, sizeof(int64_t));
217    }    
218 }
219
220 /**
221  *  Convert a 32 bit little endian to a big endian
222  */
223 void int32_LE2BE(int32_t* pBE, const int32_t v)
224 {
225    /* convert little endian to big endian */
226    if (htonl(1) != 1L) { /* no work if on little endian machine */
227       memcpy(pBE, &v, sizeof(int32_t));
228    } else {
229       int i;
230       uint8_t rv[sizeof(int32_t)];
231       uint8_t *pv = (uint8_t *) &v;
232
233       for (i = 0; i < 4; i++) {
234          rv[i] = pv[3 - i];
235       }
236       memcpy(pBE, &rv, sizeof(int32_t));
237    }    
238 }
239
240
241 /**
242  *  Read a BackupRead block and pull out the file data
243  */
244 bool processWin32BackupAPIBlock (BFILE *bfd, void *pBuffer, ssize_t dwSize)
245 {
246    /* pByte contains the buffer 
247       dwSize the len to be processed.  function assumes to be
248       called in successive incremental order over the complete
249       BackupRead stream beginning at pos 0 and ending at the end.
250     */
251
252    PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT* pContext = &(bfd->win32DecompContext);
253    bool bContinue = false;
254    int64_t dwDataOffset = 0;
255    int64_t dwDataLen;
256
257    /* Win32 Stream Header size without name of stream.
258     * = sizeof (WIN32_STREAM_ID)- sizeof(WCHAR*); 
259     */
260    int32_t dwSizeHeader = 20; 
261
262    do {
263       if (pContext->liNextHeader >= dwSize) {
264          dwDataLen = dwSize-dwDataOffset;
265          bContinue = false; /* 1 iteration is enough */
266       } else {
267          dwDataLen = pContext->liNextHeader-dwDataOffset;
268          bContinue = true; /* multiple iterations may be necessary */
269       }
270
271       /* flush */
272       /* copy block of real DATA */
273       if (pContext->bIsInData) {
274          if (bwrite(bfd, ((char *)pBuffer)+dwDataOffset, dwDataLen) != (ssize_t)dwDataLen)
275             return false;
276       }
277
278       if (pContext->liNextHeader < dwSize) {/* is a header in this block ? */
279          int32_t dwOffsetTarget;
280          int32_t dwOffsetSource;
281
282          if (pContext->liNextHeader < 0) {
283             /* start of header was before this block, so we
284              * continue with the part in the current block 
285              */
286             dwOffsetTarget = -pContext->liNextHeader;
287             dwOffsetSource = 0;
288          } else {
289             /* start of header is inside of this block */
290             dwOffsetTarget = 0;
291             dwOffsetSource = pContext->liNextHeader;
292          }
293
294          int32_t dwHeaderPartLen = dwSizeHeader-dwOffsetTarget;
295          bool bHeaderIsComplete;
296
297          if (dwHeaderPartLen <= dwSize-dwOffsetSource) {
298             /* header (or rest of header) is completely available
299                in current block 
300              */
301             bHeaderIsComplete = true;
302          } else {
303             /* header will continue in next block */
304             bHeaderIsComplete = false;
305             dwHeaderPartLen = dwSize-dwOffsetSource;
306          }
307
308          /* copy the available portion of header to persistent copy */
309          memcpy(((char *)&pContext->header_stream)+dwOffsetTarget, ((char *)pBuffer)+dwOffsetSource, dwHeaderPartLen);
310
311          /* recalculate position of next header */
312          if (bHeaderIsComplete) {
313             /* convert stream name size (32 bit little endian) to machine type */
314             int32_t dwNameSize; 
315             int32_LE2BE (&dwNameSize, pContext->header_stream.dwStreamNameSize);
316             dwDataOffset = dwNameSize+pContext->liNextHeader+dwSizeHeader;
317
318             /* convert stream size (64 bit little endian) to machine type */
319             int64_LE2BE (&(pContext->liNextHeader), pContext->header_stream.Size);
320             pContext->liNextHeader += dwDataOffset;
321
322             pContext->bIsInData = pContext->header_stream.dwStreamId == WIN32_BACKUP_DATA;
323             if (dwDataOffset == dwSize)
324                bContinue = false;
325          } else {
326             /* stop and continue with next block */
327             bContinue = false;
328             pContext->bIsInData = false;
329          }
330       }
331    } while (bContinue);
332
333    /* set "NextHeader" relative to the beginning of the next block */
334    pContext->liNextHeader-= dwSize;
335
336    return TRUE;
337 }
338
339
340
341 /* ===============================================================
342  *
343  *            W I N D O W S
344  *
345  * ===============================================================
346  */
347
348 #if defined(HAVE_WIN32)
349
350 void unix_name_to_win32(POOLMEM **win32_name, char *name);
351 extern "C" HANDLE get_osfhandle(int fd);
352
353
354 void binit(BFILE *bfd)
355 {
356    memset(bfd, 0, sizeof(BFILE));
357    bfd->fid = -1;
358    bfd->mode = BF_CLOSED;
359    bfd->use_backup_api = have_win32_api();
360    bfd->cmd_plugin = false;
361 }
362
363 /*
364  * Enables using the Backup API (win32_data).
365  *   Returns 1 if function worked
366  *   Returns 0 if failed (i.e. do not have Backup API on this machine)
367  */
368 bool set_win32_backup(BFILE *bfd)
369 {
370    /* We enable if possible here */
371    bfd->use_backup_api = have_win32_api();
372    return bfd->use_backup_api;
373 }
374
375
376 bool set_portable_backup(BFILE *bfd)
377 {
378    bfd->use_backup_api = false;
379    return true;
380 }
381
382 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
383 {
384    bfd->cmd_plugin = true;
385    bfd->jcr = jcr;
386    return true;
387 }
388
389 /*
390  * Return 1 if we are NOT using Win32 BackupWrite()
391  * return 0 if are
392  */
393 bool is_portable_backup(BFILE *bfd)
394 {
395    return !bfd->use_backup_api;
396 }
397
398 bool have_win32_api()
399 {
400    return p_BackupRead && p_BackupWrite;
401 }
402
403
404 /*
405  * Return true  if we support the stream
406  *        false if we do not support the stream
407  *
408  *  This code is running under Win32, so we
409  *    do not need #ifdef on MACOS ...
410  */
411 bool is_restore_stream_supported(int stream)
412 {
413    switch (stream) {
414
415 /* Streams known not to be supported */
416 #ifndef HAVE_LIBZ
417    case STREAM_GZIP_DATA:
418    case STREAM_SPARSE_GZIP_DATA:
419    case STREAM_WIN32_GZIP_DATA:
420 #endif
421    case STREAM_MACOS_FORK_DATA:
422    case STREAM_HFSPLUS_ATTRIBUTES:
423    case STREAM_ENCRYPTED_MACOS_FORK_DATA:
424       return false;
425
426    /* Known streams */
427 #ifdef HAVE_LIBZ
428    case STREAM_GZIP_DATA:
429    case STREAM_SPARSE_GZIP_DATA:
430    case STREAM_WIN32_GZIP_DATA:
431 #endif
432    case STREAM_WIN32_DATA:
433    case STREAM_UNIX_ATTRIBUTES:
434    case STREAM_FILE_DATA:
435    case STREAM_MD5_DIGEST:
436    case STREAM_UNIX_ATTRIBUTES_EX:
437    case STREAM_SPARSE_DATA:
438    case STREAM_PROGRAM_NAMES:
439    case STREAM_PROGRAM_DATA:
440    case STREAM_SHA1_DIGEST:
441 #ifdef HAVE_SHA2
442    case STREAM_SHA256_DIGEST:
443    case STREAM_SHA512_DIGEST:
444 #endif
445 #ifdef HAVE_CRYPTO
446    case STREAM_SIGNED_DIGEST:
447    case STREAM_ENCRYPTED_FILE_DATA:
448    case STREAM_ENCRYPTED_FILE_GZIP_DATA:
449    case STREAM_ENCRYPTED_WIN32_DATA:
450    case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
451 #endif
452    case 0:                            /* compatibility with old tapes */
453       return true;
454    }
455    return false;
456 }
457
458 HANDLE bget_handle(BFILE *bfd)
459 {
460    return bfd->fh;
461 }
462
463 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
464 {
465    POOLMEM *win32_fname;
466    POOLMEM *win32_fname_wchar;
467
468    DWORD dwaccess, dwflags, dwshare;
469
470    /* Convert to Windows path format */
471    win32_fname = get_pool_memory(PM_FNAME);
472    win32_fname_wchar = get_pool_memory(PM_FNAME);
473    
474    unix_name_to_win32(&win32_fname, (char *)fname);
475
476    if (bfd->cmd_plugin && plugin_bopen) {
477       int rtnstat;
478       Dmsg1(50, "call plugin_bopen fname=%s\n", fname);
479       rtnstat = plugin_bopen(bfd, fname, flags, mode);
480       Dmsg1(50, "return from plugin_bopen status=%d\n", rtnstat);
481       if (rtnstat >= 0) {
482          if (flags & O_CREAT || flags & O_WRONLY) {   /* Open existing for write */
483             Dmsg1(50, "plugin_open for write OK file=%s.\n", fname);
484             bfd->mode = BF_WRITE;
485          } else {
486             Dmsg1(50, "plugin_open for read OK file=%s.\n", fname);
487             bfd->mode = BF_READ;
488          }
489       } else {
490          bfd->mode = BF_CLOSED;
491          Dmsg1(000, "==== plugin_bopen returned bad status=%d\n", rtnstat);
492       }
493       free_pool_memory(win32_fname_wchar);
494       free_pool_memory(win32_fname);
495       return bfd->mode == BF_CLOSED ? -1 : 1;
496    }
497    Dmsg0(50, "=== NO plugin\n");
498
499    if (!(p_CreateFileA || p_CreateFileW)) {
500       Dmsg0(50, "No CreateFileA and no CreateFileW!!!!!\n");
501       return 0;
502    }
503
504    if (p_CreateFileW && p_MultiByteToWideChar) {
505       make_win32_path_UTF8_2_wchar(&win32_fname_wchar, fname);
506    }
507
508    if (flags & O_CREAT) {             /* Create */
509       if (bfd->use_backup_api) {
510          dwaccess = GENERIC_WRITE|FILE_ALL_ACCESS|WRITE_OWNER|WRITE_DAC|ACCESS_SYSTEM_SECURITY;
511          dwflags = FILE_FLAG_BACKUP_SEMANTICS;
512       } else {
513          dwaccess = GENERIC_WRITE;
514          dwflags = 0;
515       }
516
517       if (p_CreateFileW && p_MultiByteToWideChar) {   
518          // unicode open for create write
519          Dmsg1(100, "Create CreateFileW=%s\n", win32_fname);
520          bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
521                 dwaccess,                /* Requested access */
522                 0,                       /* Shared mode */
523                 NULL,                    /* SecurityAttributes */
524                 CREATE_ALWAYS,           /* CreationDisposition */
525                 dwflags,                 /* Flags and attributes */
526                 NULL);                   /* TemplateFile */
527       } else {
528          // ascii open
529          Dmsg1(100, "Create CreateFileA=%s\n", win32_fname);
530          bfd->fh = p_CreateFileA(win32_fname,
531                 dwaccess,                /* Requested access */
532                 0,                       /* Shared mode */
533                 NULL,                    /* SecurityAttributes */
534                 CREATE_ALWAYS,           /* CreationDisposition */
535                 dwflags,                 /* Flags and attributes */
536                 NULL);                   /* TemplateFile */
537       }
538
539       bfd->mode = BF_WRITE;
540
541    } else if (flags & O_WRONLY) {     /* Open existing for write */
542       if (bfd->use_backup_api) {
543          dwaccess = GENERIC_WRITE|WRITE_OWNER|WRITE_DAC;
544          dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT;
545       } else {
546          dwaccess = GENERIC_WRITE;
547          dwflags = 0;
548       }
549
550       if (p_CreateFileW && p_MultiByteToWideChar) {   
551          // unicode open for open existing write
552          Dmsg1(100, "Write only CreateFileW=%s\n", win32_fname);
553          bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
554                 dwaccess,                /* Requested access */
555                 0,                       /* Shared mode */
556                 NULL,                    /* SecurityAttributes */
557                 OPEN_EXISTING,           /* CreationDisposition */
558                 dwflags,                 /* Flags and attributes */
559                 NULL);                   /* TemplateFile */
560       } else {
561          // ascii open
562          Dmsg1(100, "Write only CreateFileA=%s\n", win32_fname);
563          bfd->fh = p_CreateFileA(win32_fname,
564                 dwaccess,                /* Requested access */
565                 0,                       /* Shared mode */
566                 NULL,                    /* SecurityAttributes */
567                 OPEN_EXISTING,           /* CreationDisposition */
568                 dwflags,                 /* Flags and attributes */
569                 NULL);                   /* TemplateFile */
570
571       }
572
573       bfd->mode = BF_WRITE;
574
575    } else {                           /* Read */
576       if (bfd->use_backup_api) {
577          dwaccess = GENERIC_READ|READ_CONTROL|ACCESS_SYSTEM_SECURITY;
578          dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_SEQUENTIAL_SCAN |
579                    FILE_FLAG_OPEN_REPARSE_POINT;
580          dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
581       } else {
582          dwaccess = GENERIC_READ;
583          dwflags = 0;
584          dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE;
585       }
586
587       if (p_CreateFileW && p_MultiByteToWideChar) {   
588          // unicode open for open existing read
589          Dmsg1(100, "Read CreateFileW=%s\n", win32_fname);
590          bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
591                 dwaccess,                /* Requested access */
592                 dwshare,                 /* Share modes */
593                 NULL,                    /* SecurityAttributes */
594                 OPEN_EXISTING,           /* CreationDisposition */
595                 dwflags,                 /* Flags and attributes */
596                 NULL);                   /* TemplateFile */
597       } else {
598          // ascii open 
599          Dmsg1(100, "Read CreateFileA=%s\n", win32_fname);
600          bfd->fh = p_CreateFileA(win32_fname,
601                 dwaccess,                /* Requested access */
602                 dwshare,                 /* Share modes */
603                 NULL,                    /* SecurityAttributes */
604                 OPEN_EXISTING,           /* CreationDisposition */
605                 dwflags,                 /* Flags and attributes */
606                 NULL);                   /* TemplateFile */
607       }
608
609       bfd->mode = BF_READ;
610    }
611
612    if (bfd->fh == INVALID_HANDLE_VALUE) {
613       bfd->lerror = GetLastError();
614       bfd->berrno = b_errno_win32;
615       errno = b_errno_win32;
616       bfd->mode = BF_CLOSED;
617    }
618    bfd->errmsg = NULL;
619    bfd->lpContext = NULL;
620    bfd->win32DecompContext.bIsInData = false;
621    bfd->win32DecompContext.liNextHeader = 0;
622    free_pool_memory(win32_fname_wchar);
623    free_pool_memory(win32_fname);
624    return bfd->mode == BF_CLOSED ? -1 : 1;
625 }
626
627 /*
628  * Returns  0 on success
629  *         -1 on error
630  */
631 int bclose(BFILE *bfd)
632 {
633    int stat = 0;
634
635    if (bfd->mode == BF_CLOSED) {
636       Dmsg0(50, "=== BFD already closed.\n");
637       return 0;
638    }
639
640    if (bfd->cmd_plugin && plugin_bclose) {
641       stat = plugin_bclose(bfd);
642       Dmsg0(50, "==== BFD closed!!!\n");
643       goto all_done;
644    }
645
646    /*
647     * We need to tell the API to release the buffer it
648     *  allocated in lpContext.  We do so by calling the
649     *  API one more time, but with the Abort bit set.
650     */
651    if (bfd->use_backup_api && bfd->mode == BF_READ) {
652       BYTE buf[10];
653       if (bfd->lpContext && !p_BackupRead(bfd->fh,
654               buf,                    /* buffer */
655               (DWORD)0,               /* bytes to read */
656               &bfd->rw_bytes,         /* bytes read */
657               1,                      /* Abort */
658               1,                      /* ProcessSecurity */
659               &bfd->lpContext)) {     /* Read context */
660          errno = b_errno_win32;
661          stat = -1;
662       }
663    } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
664       BYTE buf[10];
665       if (bfd->lpContext && !p_BackupWrite(bfd->fh,
666               buf,                    /* buffer */
667               (DWORD)0,               /* bytes to read */
668               &bfd->rw_bytes,         /* bytes written */
669               1,                      /* Abort */
670               1,                      /* ProcessSecurity */
671               &bfd->lpContext)) {     /* Write context */
672          errno = b_errno_win32;
673          stat = -1;
674       }
675    }
676    if (!CloseHandle(bfd->fh)) {
677       stat = -1;
678       errno = b_errno_win32;
679    }
680
681 all_done:
682    if (bfd->errmsg) {
683       free_pool_memory(bfd->errmsg);
684       bfd->errmsg = NULL;
685    }
686    bfd->mode = BF_CLOSED;
687    bfd->lpContext = NULL;
688    bfd->cmd_plugin = false;
689    return stat;
690 }
691
692 /* Returns: bytes read on success
693  *           0         on EOF
694  *          -1         on error
695  */
696 ssize_t bread(BFILE *bfd, void *buf, size_t count)
697 {
698    bfd->rw_bytes = 0;
699
700    if (bfd->cmd_plugin && plugin_bread) {
701       return plugin_bread(bfd, buf, count);
702    }
703
704    if (bfd->use_backup_api) {
705       if (!p_BackupRead(bfd->fh,
706            (BYTE *)buf,
707            count,
708            &bfd->rw_bytes,
709            0,                           /* no Abort */
710            1,                           /* Process Security */
711            &bfd->lpContext)) {          /* Context */
712          bfd->lerror = GetLastError();
713          bfd->berrno = b_errno_win32;
714          errno = b_errno_win32;
715          return -1;
716       }
717    } else {
718       if (!ReadFile(bfd->fh,
719            buf,
720            count,
721            &bfd->rw_bytes,
722            NULL)) {
723          bfd->lerror = GetLastError();
724          bfd->berrno = b_errno_win32;
725          errno = b_errno_win32;
726          return -1;
727       }
728    }
729
730    return (ssize_t)bfd->rw_bytes;
731 }
732
733 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
734 {
735    bfd->rw_bytes = 0;
736
737    if (bfd->cmd_plugin && plugin_bwrite) {
738       return plugin_bwrite(bfd, buf, count);
739    }
740
741    if (bfd->use_backup_api) {
742       if (!p_BackupWrite(bfd->fh,
743            (BYTE *)buf,
744            count,
745            &bfd->rw_bytes,
746            0,                           /* No abort */
747            1,                           /* Process Security */
748            &bfd->lpContext)) {          /* Context */
749          bfd->lerror = GetLastError();
750          bfd->berrno = b_errno_win32;
751          errno = b_errno_win32;
752          return -1;
753       }
754    } else {
755       if (!WriteFile(bfd->fh,
756            buf,
757            count,
758            &bfd->rw_bytes,
759            NULL)) {
760          bfd->lerror = GetLastError();
761          bfd->berrno = b_errno_win32;
762          errno = b_errno_win32;
763          return -1;
764       }
765    }
766    return (ssize_t)bfd->rw_bytes;
767 }
768
769 bool is_bopen(BFILE *bfd)
770 {
771    return bfd->mode != BF_CLOSED;
772 }
773
774 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
775 {
776    LONG  offset_low = (LONG)offset;
777    LONG  offset_high = (LONG)(offset >> 32);
778    DWORD dwResult;
779
780    if (bfd->cmd_plugin && plugin_blseek) {
781       return plugin_blseek(bfd, offset, whence);
782    }
783
784    dwResult = SetFilePointer(bfd->fh, offset_low, &offset_high, whence);
785
786    if (dwResult == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
787       return (boffset_t)-1;
788    }
789
790    return ((boffset_t)offset_high << 32) | dwResult;
791 }
792
793 #else  /* Unix systems */
794
795 /* ===============================================================
796  *
797  *            U N I X
798  *
799  * ===============================================================
800  */
801 void binit(BFILE *bfd)
802 {
803    memset(bfd, 0, sizeof(BFILE));
804    bfd->fid = -1;
805 }
806
807 bool have_win32_api()
808 {
809    return false;                       /* no can do */
810 }
811
812 /*
813  * Enables using the Backup API (win32_data).
814  *   Returns true  if function worked
815  *   Returns false if failed (i.e. do not have Backup API on this machine)
816  */
817 bool set_win32_backup(BFILE *bfd)
818 {
819    return false;                       /* no can do */
820 }
821
822
823 bool set_portable_backup(BFILE *bfd)
824 {
825    return true;                        /* no problem */
826 }
827
828 /*
829  * Return true  if we are writing in portable format
830  * return false if not
831  */
832 bool is_portable_backup(BFILE *bfd)
833 {
834    return true;                       /* portable by definition */
835 }
836
837 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
838 {
839    return false;
840 }
841
842 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
843 {
844    bfd->cmd_plugin = true;
845    bfd->jcr = jcr;
846    return true;
847 }
848
849 /* 
850  * This code is running on a non-Win32 machine 
851  */
852 bool is_restore_stream_supported(int stream)
853 {
854    /* No Win32 backup on this machine */
855      switch (stream) {
856 #ifndef HAVE_LIBZ
857    case STREAM_GZIP_DATA:
858    case STREAM_SPARSE_GZIP_DATA:
859    case STREAM_WIN32_GZIP_DATA:    
860 #endif
861 #ifndef HAVE_DARWIN_OS
862    case STREAM_MACOS_FORK_DATA:
863    case STREAM_HFSPLUS_ATTRIBUTES:
864 #endif
865       return false;
866
867    /* Known streams */
868 #ifdef HAVE_LIBZ
869    case STREAM_GZIP_DATA:
870    case STREAM_SPARSE_GZIP_DATA:
871    case STREAM_WIN32_GZIP_DATA:    
872 #endif
873    case STREAM_WIN32_DATA:
874    case STREAM_UNIX_ATTRIBUTES:
875    case STREAM_FILE_DATA:
876    case STREAM_MD5_DIGEST:
877    case STREAM_UNIX_ATTRIBUTES_EX:
878    case STREAM_SPARSE_DATA:
879    case STREAM_PROGRAM_NAMES:
880    case STREAM_PROGRAM_DATA:
881    case STREAM_SHA1_DIGEST:
882 #ifdef HAVE_SHA2
883    case STREAM_SHA256_DIGEST:
884    case STREAM_SHA512_DIGEST:
885 #endif
886 #ifdef HAVE_CRYPTO
887    case STREAM_SIGNED_DIGEST:
888    case STREAM_ENCRYPTED_FILE_DATA:
889    case STREAM_ENCRYPTED_FILE_GZIP_DATA:
890    case STREAM_ENCRYPTED_WIN32_DATA:
891    case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
892 #endif
893 #ifdef HAVE_DARWIN_OS
894    case STREAM_MACOS_FORK_DATA:
895    case STREAM_HFSPLUS_ATTRIBUTES:
896 #ifdef HAVE_CRYPTO
897    case STREAM_ENCRYPTED_MACOS_FORK_DATA:
898 #endif /* HAVE_CRYPTO */
899 #endif /* HAVE_DARWIN_OS */
900    case 0:   /* compatibility with old tapes */
901       return true;
902
903    }
904    return false;
905 }
906
907 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
908 {
909    if (bfd->cmd_plugin && plugin_bopen) {
910       Dmsg1(50, "call plugin_bopen fname=%s\n", fname);
911       bfd->fid = plugin_bopen(bfd, fname, flags, mode);
912       Dmsg1(50, "Plugin bopen stat=%d\n", bfd->fid);
913       return bfd->fid;
914    }
915
916    /* Normal file open */
917    Dmsg1(dbglvl, "open file %s\n", fname);
918
919    /* We use fnctl to set O_NOATIME if requested to avoid open error */
920    bfd->fid = open(fname, flags & ~O_NOATIME, mode);
921
922    /* Set O_NOATIME if possible */
923    if (bfd->fid != -1 && flags & O_NOATIME) {
924       int oldflags = fcntl(bfd->fid, F_GETFL, 0);
925       if (oldflags == -1) {
926          bfd->berrno = errno;
927          close(bfd->fid);
928          bfd->fid = -1;
929       } else {
930          int ret = fcntl(bfd->fid, F_SETFL, oldflags | O_NOATIME);
931         /* EPERM means setting O_NOATIME was not allowed  */
932          if (ret == -1 && errno != EPERM) {
933             bfd->berrno = errno;
934             close(bfd->fid);
935             bfd->fid = -1;
936          }
937       }
938    }
939    bfd->berrno = errno;
940    bfd->m_flags = flags;
941    Dmsg1(400, "Open file %d\n", bfd->fid);
942    errno = bfd->berrno;
943
944    bfd->win32DecompContext.bIsInData = false;
945    bfd->win32DecompContext.liNextHeader = 0;
946
947 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
948    if (bfd->fid != -1 && flags & O_RDONLY) {
949       int stat = posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_WILLNEED);
950       Dmsg2(400, "Did posix_fadvise on %s stat=%d\n", fname, stat);
951    }
952 #endif
953
954    return bfd->fid;
955 }
956
957 #ifdef HAVE_DARWIN_OS
958 /* Open the resource fork of a file. */
959 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
960 {
961    POOLMEM *rsrc_fname;
962
963    rsrc_fname = get_pool_memory(PM_FNAME);
964    pm_strcpy(rsrc_fname, fname);
965    pm_strcat(rsrc_fname, _PATH_RSRCFORKSPEC);
966    bopen(bfd, rsrc_fname, flags, mode);
967    free_pool_memory(rsrc_fname);
968    return bfd->fid;
969 }
970 #else
971 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
972 {
973    return -1;
974 }
975 #endif
976
977
978 int bclose(BFILE *bfd)
979 {
980    int stat;
981
982    Dmsg1(400, "Close file %d\n", bfd->fid);
983
984    if (bfd->cmd_plugin && plugin_bclose) {
985       stat = plugin_bclose(bfd);
986       bfd->fid = -1;
987       bfd->cmd_plugin = false;
988    }
989
990    if (bfd->fid == -1) {
991       return 0;
992    }
993 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
994    if (bfd->m_flags & O_RDONLY) {
995       fdatasync(bfd->fid);            /* sync the file */
996       /* Tell OS we don't need it any more */
997       posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_DONTNEED);
998    }
999 #endif
1000
1001    /* Close normal file */
1002    stat = close(bfd->fid);
1003    bfd->berrno = errno;
1004    bfd->fid = -1;
1005    bfd->cmd_plugin = false;
1006    return stat;
1007 }
1008
1009 ssize_t bread(BFILE *bfd, void *buf, size_t count)
1010 {
1011    ssize_t stat;
1012
1013    if (bfd->cmd_plugin && plugin_bread) {
1014       return plugin_bread(bfd, buf, count);
1015    }
1016
1017    stat = read(bfd->fid, buf, count);
1018    bfd->berrno = errno;
1019    return stat;
1020 }
1021
1022 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
1023 {
1024    ssize_t stat;
1025
1026    if (bfd->cmd_plugin && plugin_bwrite) {
1027       return plugin_bwrite(bfd, buf, count);
1028    }
1029    stat = write(bfd->fid, buf, count);
1030    bfd->berrno = errno;
1031    return stat;
1032 }
1033
1034 bool is_bopen(BFILE *bfd)
1035 {
1036    return bfd->fid >= 0;
1037 }
1038
1039 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
1040 {
1041    boffset_t pos;
1042
1043    if (bfd->cmd_plugin && plugin_bwrite) {
1044       return plugin_blseek(bfd, offset, whence);
1045    }
1046    pos = (boffset_t)lseek(bfd->fid, offset, whence);
1047    bfd->berrno = errno;
1048    return pos;
1049 }
1050
1051 #endif