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