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