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