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