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