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