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