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