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