]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/findlib/bfile.c
kes Implement Windows reparse points -- similar to directories, but
[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;                          
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    if (bfd->use_backup_api && bfd->mode == BF_READ) {
540       BYTE buf[10];
541       if (!bfd->lpContext && !p_BackupRead(bfd->fh,
542               buf,                    /* buffer */
543               (DWORD)0,               /* bytes to read */
544               &bfd->rw_bytes,         /* bytes read */
545               1,                      /* Abort */
546               1,                      /* ProcessSecurity */
547               &bfd->lpContext)) {     /* Read context */
548          errno = b_errno_win32;
549          stat = -1;
550       }
551    } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
552       BYTE buf[10];
553       if (!bfd->lpContext && !p_BackupWrite(bfd->fh,
554               buf,                    /* buffer */
555               (DWORD)0,               /* bytes to read */
556               &bfd->rw_bytes,         /* bytes written */
557               1,                      /* Abort */
558               1,                      /* ProcessSecurity */
559               &bfd->lpContext)) {     /* Write context */
560          errno = b_errno_win32;
561          stat = -1;
562       }
563    }
564    if (!CloseHandle(bfd->fh)) {
565       stat = -1;
566       errno = b_errno_win32;
567    }
568    bfd->mode = BF_CLOSED;
569    bfd->lpContext = NULL;
570    return stat;
571 }
572
573 /* Returns: bytes read on success
574  *           0         on EOF
575  *          -1         on error
576  */
577 ssize_t bread(BFILE *bfd, void *buf, size_t count)
578 {
579    bfd->rw_bytes = 0;
580
581    if (bfd->use_backup_api) {
582       if (!p_BackupRead(bfd->fh,
583            (BYTE *)buf,
584            count,
585            &bfd->rw_bytes,
586            0,                           /* no Abort */
587            1,                           /* Process Security */
588            &bfd->lpContext)) {          /* Context */
589          bfd->lerror = GetLastError();
590          bfd->berrno = b_errno_win32;
591          errno = b_errno_win32;
592          return -1;
593       }
594    } else {
595       if (!ReadFile(bfd->fh,
596            buf,
597            count,
598            &bfd->rw_bytes,
599            NULL)) {
600          bfd->lerror = GetLastError();
601          bfd->berrno = b_errno_win32;
602          errno = b_errno_win32;
603          return -1;
604       }
605    }
606
607    return (ssize_t)bfd->rw_bytes;
608 }
609
610 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
611 {
612    bfd->rw_bytes = 0;
613
614    if (bfd->use_backup_api) {
615       if (!p_BackupWrite(bfd->fh,
616            (BYTE *)buf,
617            count,
618            &bfd->rw_bytes,
619            0,                           /* No abort */
620            1,                           /* Process Security */
621            &bfd->lpContext)) {          /* Context */
622          bfd->lerror = GetLastError();
623          bfd->berrno = b_errno_win32;
624          errno = b_errno_win32;
625          return -1;
626       }
627    } else {
628       if (!WriteFile(bfd->fh,
629            buf,
630            count,
631            &bfd->rw_bytes,
632            NULL)) {
633          bfd->lerror = GetLastError();
634          bfd->berrno = b_errno_win32;
635          errno = b_errno_win32;
636          return -1;
637       }
638    }
639    return (ssize_t)bfd->rw_bytes;
640 }
641
642 bool is_bopen(BFILE *bfd)
643 {
644    return bfd->mode != BF_CLOSED;
645 }
646
647 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
648 {
649    LONG  offset_low = (LONG)offset;
650    LONG  offset_high = (LONG)(offset >> 32);
651    DWORD dwResult;
652
653    dwResult = SetFilePointer(bfd->fh, offset_low, &offset_high, whence);
654
655    if (dwResult == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
656       return (boffset_t)-1;
657    }
658
659    return ((boffset_t)offset_high << 32) | dwResult;
660 }
661
662 #else  /* Unix systems */
663
664 /* ===============================================================
665  *
666  *            U N I X
667  *
668  * ===============================================================
669  */
670 void binit(BFILE *bfd)
671 {
672    memset(bfd, 0, sizeof(BFILE));
673    bfd->fid = -1;
674 }
675
676 bool have_win32_api()
677 {
678    return false;                       /* no can do */
679 }
680
681 /*
682  * Enables using the Backup API (win32_data).
683  *   Returns true  if function worked
684  *   Returns false if failed (i.e. do not have Backup API on this machine)
685  */
686 bool set_win32_backup(BFILE *bfd)
687 {
688    return false;                       /* no can do */
689 }
690
691
692 bool set_portable_backup(BFILE *bfd)
693 {
694    return true;                        /* no problem */
695 }
696
697 /*
698  * Return true  if we are writing in portable format
699  * return false if not
700  */
701 bool is_portable_backup(BFILE *bfd)
702 {
703    return true;                       /* portable by definition */
704 }
705
706 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
707 {
708 #ifdef HAVE_PYTHON
709    if (bfd->prog && strcmp(prog, bfd->prog) == 0) {
710       return true;                    /* already setup */
711    }
712
713    if (python_set_prog(jcr, prog)) {
714       Dmsg1(000, "Set prog=%s\n", prog);
715       bfd->prog = prog;
716       bfd->jcr = jcr;
717       return true;
718    }
719 #endif
720    Dmsg0(000, "No prog set\n");
721    bfd->prog = NULL;
722    return false;
723
724 }
725
726 /* 
727  * This code is running on a non-Win32 machine 
728  */
729 bool is_restore_stream_supported(int stream)
730 {
731    /* No Win32 backup on this machine */
732      switch (stream) {
733 #ifndef HAVE_LIBZ
734    case STREAM_GZIP_DATA:
735    case STREAM_SPARSE_GZIP_DATA:
736    case STREAM_WIN32_GZIP_DATA:    
737 #endif
738 #ifndef HAVE_DARWIN_OS
739    case STREAM_MACOS_FORK_DATA:
740    case STREAM_HFSPLUS_ATTRIBUTES:
741 #endif
742       return false;
743
744    /* Known streams */
745 #ifdef HAVE_LIBZ
746    case STREAM_GZIP_DATA:
747    case STREAM_SPARSE_GZIP_DATA:
748    case STREAM_WIN32_GZIP_DATA:    
749 #endif
750    case STREAM_WIN32_DATA:
751    case STREAM_UNIX_ATTRIBUTES:
752    case STREAM_FILE_DATA:
753    case STREAM_MD5_DIGEST:
754    case STREAM_UNIX_ATTRIBUTES_EX:
755    case STREAM_SPARSE_DATA:
756    case STREAM_PROGRAM_NAMES:
757    case STREAM_PROGRAM_DATA:
758    case STREAM_SHA1_DIGEST:
759 #ifdef HAVE_SHA2
760    case STREAM_SHA256_DIGEST:
761    case STREAM_SHA512_DIGEST:
762 #endif
763 #ifdef HAVE_CRYPTO
764    case STREAM_SIGNED_DIGEST:
765    case STREAM_ENCRYPTED_FILE_DATA:
766    case STREAM_ENCRYPTED_FILE_GZIP_DATA:
767    case STREAM_ENCRYPTED_WIN32_DATA:
768    case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
769 #endif
770 #ifdef HAVE_DARWIN_OS
771    case STREAM_MACOS_FORK_DATA:
772    case STREAM_HFSPLUS_ATTRIBUTES:
773 #ifdef HAVE_CRYPTO
774    case STREAM_ENCRYPTED_MACOS_FORK_DATA:
775 #endif /* HAVE_CRYPTO */
776 #endif /* HAVE_DARWIN_OS */
777    case 0:   /* compatibility with old tapes */
778       return true;
779
780    }
781    return false;
782 }
783
784 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
785 {
786    /* Open reader/writer program */
787    if (bfd->prog) {
788       Dmsg1(000, "Open file %d\n", bfd->fid);
789       return python_open(bfd, fname, flags, mode);
790    }
791
792    /* Normal file open */
793    Dmsg1(400, "open file %s\n", fname);
794    /* We use fnctl to set O_NOATIME if requested to avoid open error */
795    bfd->fid = open(fname, flags & ~O_NOATIME, mode);
796    /* Set O_NOATIME if possible */
797    if (bfd->fid != -1 && flags & O_NOATIME) {
798       int oldflags = fcntl(bfd->fid, F_GETFL, 0);
799       if (oldflags == -1) {
800          bfd->berrno = errno;
801          close(bfd->fid);
802          bfd->fid = -1;
803       } else {
804          int ret = fcntl(bfd->fid, F_SETFL, oldflags | O_NOATIME);
805         /* EPERM means setting O_NOATIME was not allowed  */
806          if (ret == -1 && errno != EPERM) {
807             bfd->berrno = errno;
808             close(bfd->fid);
809             bfd->fid = -1;
810          }
811       }
812    }
813    bfd->berrno = errno;
814    bfd->m_flags = flags;
815    Dmsg1(400, "Open file %d\n", bfd->fid);
816    errno = bfd->berrno;
817
818    bfd->win32DecompContext.bIsInData = false;
819    bfd->win32DecompContext.liNextHeader = 0;
820
821 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
822    if (bfd->fid != -1 && flags & O_RDONLY) {
823       int stat = posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_WILLNEED);
824       Dmsg2(400, "Did posix_fadvise on %s stat=%d\n", fname, stat);
825    }
826 #endif
827
828    return bfd->fid;
829 }
830
831 #ifdef HAVE_DARWIN_OS
832 /* Open the resource fork of a file. */
833 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
834 {
835    POOLMEM *rsrc_fname;
836
837    rsrc_fname = get_pool_memory(PM_FNAME);
838    pm_strcpy(rsrc_fname, fname);
839    pm_strcat(rsrc_fname, _PATH_RSRCFORKSPEC);
840    bopen(bfd, rsrc_fname, flags, mode);
841    free_pool_memory(rsrc_fname);
842    return bfd->fid;
843 }
844 #endif
845
846
847 int bclose(BFILE *bfd)
848 {
849    int stat;
850
851    Dmsg1(400, "Close file %d\n", bfd->fid);
852
853    /* Close reader/writer program */
854    if (bfd->prog) {
855       return python_close(bfd);
856    }
857
858    if (bfd->fid == -1) {
859       return 0;
860    }
861 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
862    if (bfd->m_flags & O_RDONLY) {
863       fdatasync(bfd->fid);            /* sync the file */
864       /* Tell OS we don't need it any more */
865       posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_DONTNEED);
866    }
867 #endif
868
869    /* Close normal file */
870    stat = close(bfd->fid);
871    bfd->berrno = errno;
872    bfd->fid = -1;
873    return stat;
874 }
875
876 ssize_t bread(BFILE *bfd, void *buf, size_t count)
877 {
878    ssize_t stat;
879
880    if (bfd->prog) {
881       return python_read(bfd, buf, count);
882    }
883    stat = read(bfd->fid, buf, count);
884    bfd->berrno = errno;
885    return stat;
886 }
887
888 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
889 {
890    ssize_t stat;
891
892    if (bfd->prog) {
893       return python_write(bfd, buf, count);
894    }
895    stat = write(bfd->fid, buf, count);
896    bfd->berrno = errno;
897    return stat;
898 }
899
900 bool is_bopen(BFILE *bfd)
901 {
902    return bfd->fid >= 0;
903 }
904
905 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
906 {
907     boffset_t pos;
908     pos = (boffset_t)lseek(bfd->fid, (off_t)offset, whence);
909     bfd->berrno = errno;
910     return pos;
911 }
912
913 #endif