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