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