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