]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/findlib/bfile.c
26May06
[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-2006 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       make_win32_path_UTF8_2_wchar(&win32_fname_wchar, 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       } else {
410          bfd->fh = p_CreateFileA(win32_fname,
411                 dwaccess,                /* Requested access */
412                 0,                       /* Shared mode */
413                 NULL,                    /* SecurityAttributes */
414                 CREATE_ALWAYS,           /* CreationDisposition */
415                 dwflags,                 /* Flags and attributes */
416                 NULL);                   /* TemplateFile */
417       }
418
419       bfd->mode = BF_WRITE;
420
421    } else if (flags & O_WRONLY) {     /* Open existing for write */
422       if (bfd->use_backup_api) {
423          dwaccess = GENERIC_WRITE|WRITE_OWNER|WRITE_DAC;
424          dwflags = FILE_FLAG_BACKUP_SEMANTICS;
425       } else {
426          dwaccess = GENERIC_WRITE;
427          dwflags = 0;
428       }
429
430       // unicode or ansii open for open existing write
431       if (p_CreateFileW && p_MultiByteToWideChar) {   
432          bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
433                 dwaccess,                /* Requested access */
434                 0,                       /* Shared mode */
435                 NULL,                    /* SecurityAttributes */
436                 OPEN_EXISTING,           /* CreationDisposition */
437                 dwflags,                 /* Flags and attributes */
438                 NULL);                   /* TemplateFile */
439       } else {
440          bfd->fh = p_CreateFileA(win32_fname,
441                 dwaccess,                /* Requested access */
442                 0,                       /* Shared mode */
443                 NULL,                    /* SecurityAttributes */
444                 OPEN_EXISTING,           /* CreationDisposition */
445                 dwflags,                 /* Flags and attributes */
446                 NULL);                   /* TemplateFile */
447
448       }
449
450       bfd->mode = BF_WRITE;
451
452    } else {                           /* Read */
453       if (bfd->use_backup_api) {
454          dwaccess = GENERIC_READ|READ_CONTROL|ACCESS_SYSTEM_SECURITY;
455          dwflags = FILE_FLAG_BACKUP_SEMANTICS;
456          dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
457       } else {
458          dwaccess = GENERIC_READ;
459          dwflags = 0;
460          dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE;
461       }
462
463       // unicode or ansii open for open existing read
464       if (p_CreateFileW && p_MultiByteToWideChar) {   
465          bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
466                 dwaccess,                /* Requested access */
467                 dwshare,                 /* Share modes */
468                 NULL,                    /* SecurityAttributes */
469                 OPEN_EXISTING,           /* CreationDisposition */
470                 dwflags,                 /* Flags and attributes */
471                 NULL);                   /* TemplateFile */
472       } else {
473          bfd->fh = p_CreateFileA(win32_fname,
474                 dwaccess,                /* Requested access */
475                 dwshare,                 /* Share modes */
476                 NULL,                    /* SecurityAttributes */
477                 OPEN_EXISTING,           /* CreationDisposition */
478                 dwflags,                 /* Flags and attributes */
479                 NULL);                   /* TemplateFile */
480       }
481
482       bfd->mode = BF_READ;
483    }
484
485    if (bfd->fh == INVALID_HANDLE_VALUE) {
486       bfd->lerror = GetLastError();
487       bfd->berrno = b_errno_win32;
488       errno = b_errno_win32;
489       bfd->mode = BF_CLOSED;
490    }
491    bfd->errmsg = NULL;
492    bfd->lpContext = NULL;
493    bfd->win32DecompContext.bIsInData = false;
494    bfd->win32DecompContext.liNextHeader = 0;
495    free_pool_memory(win32_fname_wchar);
496    free_pool_memory(win32_fname);
497    return bfd->mode == BF_CLOSED ? -1 : 1;
498 }
499
500 /*
501  * Returns  0 on success
502  *         -1 on error
503  */
504 int bclose(BFILE *bfd)
505 {
506    int stat = 0;
507
508    if (bfd->errmsg) {
509       free_pool_memory(bfd->errmsg);
510       bfd->errmsg = NULL;
511    }
512    if (bfd->mode == BF_CLOSED) {
513       return 0;
514    }
515    if (bfd->use_backup_api && bfd->mode == BF_READ) {
516       BYTE buf[10];
517       if (!bfd->lpContext && !p_BackupRead(bfd->fh,
518               buf,                    /* buffer */
519               (DWORD)0,               /* bytes to read */
520               &bfd->rw_bytes,         /* bytes read */
521               1,                      /* Abort */
522               1,                      /* ProcessSecurity */
523               &bfd->lpContext)) {     /* Read context */
524          errno = b_errno_win32;
525          stat = -1;
526       }
527    } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
528       BYTE buf[10];
529       if (!bfd->lpContext && !p_BackupWrite(bfd->fh,
530               buf,                    /* buffer */
531               (DWORD)0,               /* bytes to read */
532               &bfd->rw_bytes,         /* bytes written */
533               1,                      /* Abort */
534               1,                      /* ProcessSecurity */
535               &bfd->lpContext)) {     /* Write context */
536          errno = b_errno_win32;
537          stat = -1;
538       }
539    }
540    if (!CloseHandle(bfd->fh)) {
541       stat = -1;
542       errno = b_errno_win32;
543    }
544    bfd->mode = BF_CLOSED;
545    bfd->lpContext = NULL;
546    return stat;
547 }
548
549 /* Returns: bytes read on success
550  *           0         on EOF
551  *          -1         on error
552  */
553 ssize_t bread(BFILE *bfd, void *buf, size_t count)
554 {
555    bfd->rw_bytes = 0;
556
557    if (bfd->use_backup_api) {
558       if (!p_BackupRead(bfd->fh,
559            (BYTE *)buf,
560            count,
561            &bfd->rw_bytes,
562            0,                           /* no Abort */
563            1,                           /* Process Security */
564            &bfd->lpContext)) {          /* Context */
565          bfd->lerror = GetLastError();
566          bfd->berrno = b_errno_win32;
567          errno = b_errno_win32;
568          return -1;
569       }
570    } else {
571       if (!ReadFile(bfd->fh,
572            buf,
573            count,
574            &bfd->rw_bytes,
575            NULL)) {
576          bfd->lerror = GetLastError();
577          bfd->berrno = b_errno_win32;
578          errno = b_errno_win32;
579          return -1;
580       }
581    }
582
583    return (ssize_t)bfd->rw_bytes;
584 }
585
586 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
587 {
588    bfd->rw_bytes = 0;
589
590    if (bfd->use_backup_api) {
591       if (!p_BackupWrite(bfd->fh,
592            (BYTE *)buf,
593            count,
594            &bfd->rw_bytes,
595            0,                           /* No abort */
596            1,                           /* Process Security */
597            &bfd->lpContext)) {          /* Context */
598          bfd->lerror = GetLastError();
599          bfd->berrno = b_errno_win32;
600          errno = b_errno_win32;
601          return -1;
602       }
603    } else {
604       if (!WriteFile(bfd->fh,
605            buf,
606            count,
607            &bfd->rw_bytes,
608            NULL)) {
609          bfd->lerror = GetLastError();
610          bfd->berrno = b_errno_win32;
611          errno = b_errno_win32;
612          return -1;
613       }
614    }
615    return (ssize_t)bfd->rw_bytes;
616 }
617
618 bool is_bopen(BFILE *bfd)
619 {
620    return bfd->mode != BF_CLOSED;
621 }
622
623 off_t blseek(BFILE *bfd, off_t offset, int whence)
624 {
625    /* ****FIXME**** this must be implemented if we want to read Win32 Archives */
626    return -1;
627 }
628
629 #else  /* Unix systems */
630
631 /* ===============================================================
632  *
633  *            U N I X
634  *
635  * ===============================================================
636  */
637 void binit(BFILE *bfd)
638 {
639    memset(bfd, 0, sizeof(BFILE));
640    bfd->fid = -1;
641 }
642
643 bool have_win32_api()
644 {
645    return false;                       /* no can do */
646 }
647
648 /*
649  * Enables using the Backup API (win32_data).
650  *   Returns true  if function worked
651  *   Returns false if failed (i.e. do not have Backup API on this machine)
652  */
653 bool set_win32_backup(BFILE *bfd)
654 {
655    return false;                       /* no can do */
656 }
657
658
659 bool set_portable_backup(BFILE *bfd)
660 {
661    return true;                        /* no problem */
662 }
663
664 /*
665  * Return true  if we are writing in portable format
666  * return false if not
667  */
668 bool is_portable_backup(BFILE *bfd)
669 {
670    return true;                       /* portable by definition */
671 }
672
673 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
674 {
675 #ifdef HAVE_PYTHON
676    if (bfd->prog && strcmp(prog, bfd->prog) == 0) {
677       return true;                    /* already setup */
678    }
679
680    if (python_set_prog(jcr, prog)) {
681       Dmsg1(000, "Set prog=%s\n", prog);
682       bfd->prog = prog;
683       bfd->jcr = jcr;
684       return true;
685    }
686 #endif
687    Dmsg0(000, "No prog set\n");
688    bfd->prog = NULL;
689    return false;
690
691 }
692
693 /* 
694  * This code is running on a non-Win32 machine 
695  */
696 bool is_restore_stream_supported(int stream)
697 {
698    /* No Win32 backup on this machine */
699      switch (stream) {
700 #ifndef HAVE_LIBZ
701    case STREAM_GZIP_DATA:
702    case STREAM_SPARSE_GZIP_DATA:
703    case STREAM_WIN32_GZIP_DATA:    
704 #endif
705 #ifndef HAVE_DARWIN_OS
706    case STREAM_MACOS_FORK_DATA:
707    case STREAM_HFSPLUS_ATTRIBUTES:
708 #endif
709       return false;
710
711    /* Known streams */
712 #ifdef HAVE_LIBZ
713    case STREAM_GZIP_DATA:
714    case STREAM_SPARSE_GZIP_DATA:
715    case STREAM_WIN32_GZIP_DATA:    
716 #endif
717    case STREAM_WIN32_DATA:
718    case STREAM_UNIX_ATTRIBUTES:
719    case STREAM_FILE_DATA:
720    case STREAM_MD5_DIGEST:
721    case STREAM_UNIX_ATTRIBUTES_EX:
722    case STREAM_SPARSE_DATA:
723    case STREAM_PROGRAM_NAMES:
724    case STREAM_PROGRAM_DATA:
725    case STREAM_SHA1_DIGEST:
726 #ifdef HAVE_SHA2
727    case STREAM_SHA256_DIGEST:
728    case STREAM_SHA512_DIGEST:
729 #endif
730 #ifdef HAVE_CRYPTO
731    case STREAM_SIGNED_DIGEST:
732    case STREAM_ENCRYPTED_FILE_DATA:
733    case STREAM_ENCRYPTED_FILE_GZIP_DATA:
734    case STREAM_ENCRYPTED_WIN32_DATA:
735    case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
736 #endif
737 #ifdef HAVE_DARWIN_OS
738    case STREAM_MACOS_FORK_DATA:
739    case STREAM_HFSPLUS_ATTRIBUTES:
740 #ifdef HAVE_CRYPTO
741    case STREAM_ENCRYPTED_MACOS_FORK_DATA:
742 #endif /* HAVE_CRYPTO */
743 #endif /* HAVE_DARWIN_OS */
744    case 0:   /* compatibility with old tapes */
745       return true;
746
747    }
748    return false;
749 }
750
751 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
752 {
753    /* Open reader/writer program */
754    if (bfd->prog) {
755       Dmsg1(000, "Open file %d\n", bfd->fid);
756       return python_open(bfd, fname, flags, mode);
757    }
758
759    /* Normal file open */
760    Dmsg1(400, "open file %s\n", fname);
761    /* We use fnctl to set O_NOATIME if requested to avoid open error */
762    bfd->fid = open(fname, flags & ~O_NOATIME, mode);
763    /* Set O_NOATIME if possible */
764    if (bfd->fid != -1 && flags & O_NOATIME) {
765       int oldflags = fcntl(bfd->fid, F_GETFL, 0);
766       if (oldflags == -1) {
767          bfd->berrno = errno;
768          close(bfd->fid);
769          bfd->fid = -1;
770       } else {
771          int ret = fcntl(bfd->fid, F_SETFL, oldflags | O_NOATIME);
772         /* EPERM means setting O_NOATIME was not allowed  */
773          if (ret == -1 && errno != EPERM) {
774             bfd->berrno = errno;
775             close(bfd->fid);
776             bfd->fid = -1;
777          }
778       }
779    }
780    bfd->berrno = errno;
781    Dmsg1(400, "Open file %d\n", bfd->fid);
782    errno = bfd->berrno;
783
784    bfd->win32DecompContext.bIsInData = false;
785    bfd->win32DecompContext.liNextHeader = 0;
786
787    return bfd->fid;
788 }
789
790 #ifdef HAVE_DARWIN_OS
791 /* Open the resource fork of a file. */
792 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
793 {
794    POOLMEM *rsrc_fname;
795
796    rsrc_fname = get_pool_memory(PM_FNAME);
797    pm_strcpy(rsrc_fname, fname);
798    pm_strcat(rsrc_fname, _PATH_RSRCFORKSPEC);
799    bopen(bfd, rsrc_fname, flags, mode);
800    free_pool_memory(rsrc_fname);
801    return bfd->fid;
802 }
803 #endif
804
805
806 int bclose(BFILE *bfd)
807 {
808    int stat;
809
810    Dmsg1(400, "Close file %d\n", bfd->fid);
811
812    /* Close reader/writer program */
813    if (bfd->prog) {
814       return python_close(bfd);
815    }
816
817    if (bfd->fid == -1) {
818       return 0;
819    }
820
821    /* Close normal file */
822    stat = close(bfd->fid);
823    bfd->berrno = errno;
824    bfd->fid = -1;
825    return stat;
826 }
827
828 ssize_t bread(BFILE *bfd, void *buf, size_t count)
829 {
830    ssize_t stat;
831
832    if (bfd->prog) {
833       return python_read(bfd, buf, count);
834    }
835    stat = read(bfd->fid, buf, count);
836    bfd->berrno = errno;
837    return stat;
838 }
839
840 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
841 {
842    ssize_t stat;
843
844    if (bfd->prog) {
845       return python_write(bfd, buf, count);
846    }
847    stat = write(bfd->fid, buf, count);
848    bfd->berrno = errno;
849    return stat;
850 }
851
852 bool is_bopen(BFILE *bfd)
853 {
854    return bfd->fid >= 0;
855 }
856
857 off_t blseek(BFILE *bfd, off_t offset, int whence)
858 {
859     off_t pos;
860     pos = lseek(bfd->fid, offset, whence);
861     bfd->berrno = errno;
862     return pos;
863 }
864
865 #endif