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