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