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