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