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