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