]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/findlib/bfile.c
Backport from Bacula Enterprise
[bacula/bacula] / bacula / src / findlib / bfile.c
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2015 Kern Sibbald
5    Copyright (C) 2003-2014 Free Software Foundation Europe e.V.
6
7    The original author of Bacula is Kern Sibbald, with contributions
8    from many others, a complete list can be found in the file AUTHORS.
9
10    You may use this file and others of this release according to the
11    license defined in the LICENSE file, which includes the Affero General
12    Public License, v3.0 ("AGPLv3") and some additional permissions and
13    terms pursuant to its AGPLv3 Section 7.
14
15    This notice must be preserved when any source code is 
16    conveyed and/or propagated.
17
18    Bacula(R) is a registered trademark of Kern Sibbald.
19 */
20 /*
21  *  Bacula low level File I/O routines.  This routine simulates
22  *    open(), read(), write(), and close(), but using native routines.
23  *    I.e. on Windows, we use Windows APIs.
24  *
25  *    Kern Sibbald, April MMIII
26  *
27  */
28
29 #include "bacula.h"
30 #include "find.h"
31
32 const int dbglvl = 200;
33
34 int       (*plugin_bopen)(BFILE *bfd, const char *fname, uint64_t flags, mode_t mode) = NULL;
35 int       (*plugin_bclose)(BFILE *bfd) = NULL;
36 ssize_t   (*plugin_bread)(BFILE *bfd, void *buf, size_t count) = NULL;
37 ssize_t   (*plugin_bwrite)(BFILE *bfd, void *buf, size_t count) = NULL;
38 boffset_t (*plugin_blseek)(BFILE *bfd, boffset_t offset, int whence) = NULL;
39
40
41 #ifdef HAVE_DARWIN_OS
42 #include <sys/paths.h>
43 #endif
44
45 #if !defined(HAVE_FDATASYNC)
46 #define fdatasync(fd)
47 #endif
48
49 #ifdef HAVE_WIN32
50 void pause_msg(const char *file, const char *func, int line, const char *msg)
51 {
52    char buf[1000];
53    if (msg) {
54       bsnprintf(buf, sizeof(buf), "%s:%s:%d %s", file, func, line, msg);
55    } else {
56       bsnprintf(buf, sizeof(buf), "%s:%s:%d", file, func, line);
57    }
58    MessageBox(NULL, buf, "Pause", MB_OK);
59 }
60 #endif
61
62 /* ===============================================================
63  *
64  *            U N I X   AND   W I N D O W S
65  *
66  * ===============================================================
67  */
68
69 bool is_win32_stream(int stream)
70 {
71    switch (stream) {
72    case STREAM_WIN32_DATA:
73    case STREAM_WIN32_GZIP_DATA:
74    case STREAM_WIN32_COMPRESSED_DATA:
75    case STREAM_ENCRYPTED_WIN32_DATA:
76    case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
77    case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
78       return true;
79    }
80    return false;
81 }
82
83 const char *stream_to_ascii(int stream)
84 {
85    static char buf[20];
86
87    switch (stream & STREAMMASK_TYPE) {
88       case STREAM_UNIX_ATTRIBUTES:
89          return _("Unix attributes");
90       case STREAM_FILE_DATA:
91          return _("File data");
92       case STREAM_MD5_DIGEST:
93          return _("MD5 digest");
94       case STREAM_GZIP_DATA:
95          return _("GZIP data");
96       case STREAM_COMPRESSED_DATA:
97          return _("Compressed data");
98       case STREAM_UNIX_ATTRIBUTES_EX:
99          return _("Extended attributes");
100       case STREAM_SPARSE_DATA:
101          return _("Sparse data");
102       case STREAM_SPARSE_GZIP_DATA:
103          return _("GZIP sparse data");
104       case STREAM_SPARSE_COMPRESSED_DATA:
105          return _("Compressed sparse data");
106       case STREAM_PROGRAM_NAMES:
107          return _("Program names");
108       case STREAM_PROGRAM_DATA:
109          return _("Program data");
110       case STREAM_SHA1_DIGEST:
111          return _("SHA1 digest");
112       case STREAM_WIN32_DATA:
113          return _("Win32 data");
114       case STREAM_WIN32_GZIP_DATA:
115          return _("Win32 GZIP data");
116       case STREAM_WIN32_COMPRESSED_DATA:
117          return _("Win32 compressed data");
118       case STREAM_MACOS_FORK_DATA:
119          return _("MacOS Fork data");
120       case STREAM_HFSPLUS_ATTRIBUTES:
121          return _("HFS+ attribs");
122       case STREAM_UNIX_ACCESS_ACL:
123          return _("Standard Unix ACL attribs");
124       case STREAM_UNIX_DEFAULT_ACL:
125          return _("Default Unix ACL attribs");
126       case STREAM_SHA256_DIGEST:
127          return _("SHA256 digest");
128       case STREAM_SHA512_DIGEST:
129          return _("SHA512 digest");
130       case STREAM_SIGNED_DIGEST:
131          return _("Signed digest");
132       case STREAM_ENCRYPTED_FILE_DATA:
133          return _("Encrypted File data");
134       case STREAM_ENCRYPTED_WIN32_DATA:
135          return _("Encrypted Win32 data");
136       case STREAM_ENCRYPTED_SESSION_DATA:
137          return _("Encrypted session data");
138       case STREAM_ENCRYPTED_FILE_GZIP_DATA:
139          return _("Encrypted GZIP data");
140       case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
141          return _("Encrypted compressed data");
142       case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
143          return _("Encrypted Win32 GZIP data");
144       case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
145          return _("Encrypted Win32 Compressed data");
146       case STREAM_ENCRYPTED_MACOS_FORK_DATA:
147          return _("Encrypted MacOS fork data");
148       case STREAM_PLUGIN_NAME:
149          return _("Plugin Name");
150       case STREAM_PLUGIN_DATA:
151          return _("Plugin Data");
152       case STREAM_RESTORE_OBJECT:
153          return _("Restore Object");
154       case STREAM_ACL_AIX_TEXT:
155          return _("AIX ACL attribs");
156       case STREAM_ACL_DARWIN_ACCESS:
157          return _("Darwin ACL attribs");
158       case STREAM_ACL_FREEBSD_DEFAULT:
159          return _("FreeBSD Default ACL attribs");
160       case STREAM_ACL_FREEBSD_ACCESS:
161          return _("FreeBSD Access ACL attribs");
162       case STREAM_ACL_HPUX_ACL_ENTRY:
163          return _("HPUX ACL attribs");
164       case STREAM_ACL_IRIX_DEFAULT:
165          return _("Irix Default ACL attribs");
166       case STREAM_ACL_IRIX_ACCESS:
167          return _("Irix Access ACL attribs");
168       case STREAM_ACL_LINUX_DEFAULT:
169          return _("Linux Default ACL attribs");
170       case STREAM_ACL_LINUX_ACCESS:
171          return _("Linux Access ACL attribs");
172       case STREAM_ACL_TRU64_DEFAULT:
173          return _("TRU64 Default ACL attribs");
174       case STREAM_ACL_TRU64_ACCESS:
175          return _("TRU64 Access ACL attribs");
176       case STREAM_ACL_SOLARIS_POSIX:
177          return _("Solaris POSIX ACL attribs");
178       case STREAM_ACL_SOLARIS_NFS4:
179          return _("Solaris NFSv4/ZFS ACL attribs");
180       case STREAM_ACL_AFS_TEXT:
181          return _("AFS ACL attribs");
182       case STREAM_ACL_AIX_AIXC:
183          return _("AIX POSIX ACL attribs");
184       case STREAM_ACL_AIX_NFS4:
185          return _("AIX NFSv4 ACL attribs");
186       case STREAM_ACL_FREEBSD_NFS4:
187          return _("FreeBSD NFSv4/ZFS ACL attribs");
188       case STREAM_ACL_HURD_DEFAULT:
189          return _("GNU Hurd Default ACL attribs");
190       case STREAM_ACL_HURD_ACCESS:
191          return _("GNU Hurd Access ACL attribs");
192       case STREAM_XATTR_HURD:
193          return _("GNU Hurd Extended attribs");
194       case STREAM_XATTR_IRIX:
195          return _("IRIX Extended attribs");
196       case STREAM_XATTR_TRU64:
197          return _("TRU64 Extended attribs");
198       case STREAM_XATTR_AIX:
199          return _("AIX Extended attribs");
200       case STREAM_XATTR_OPENBSD:
201          return _("OpenBSD Extended attribs");
202       case STREAM_XATTR_SOLARIS_SYS:
203          return _("Solaris Extensible attribs or System Extended attribs");
204       case STREAM_XATTR_SOLARIS:
205          return _("Solaris Extended attribs");
206       case STREAM_XATTR_DARWIN:
207          return _("Darwin Extended attribs");
208       case STREAM_XATTR_FREEBSD:
209          return _("FreeBSD Extended attribs");
210       case STREAM_XATTR_LINUX:
211          return _("Linux Extended attribs");
212       case STREAM_XATTR_NETBSD:
213          return _("NetBSD Extended attribs");
214       default:
215          sprintf(buf, "%d", stream);
216          return (const char *)buf;
217       }
218 }
219
220 /**
221  *  Convert a 64 bit little endian to a big endian
222  */
223 void int64_LE2BE(int64_t* pBE, const int64_t v)
224 {
225    /* convert little endian to big endian */
226    if (htonl(1) != 1L) { /* no work if on little endian machine */
227       memcpy(pBE, &v, sizeof(int64_t));
228    } else {
229       int i;
230       uint8_t rv[sizeof(int64_t)];
231       uint8_t *pv = (uint8_t *) &v;
232
233       for (i = 0; i < 8; i++) {
234          rv[i] = pv[7 - i];
235       }
236       memcpy(pBE, &rv, sizeof(int64_t));
237    }
238 }
239
240 /**
241  *  Convert a 32 bit little endian to a big endian
242  */
243 void int32_LE2BE(int32_t* pBE, const int32_t v)
244 {
245    /* convert little endian to big endian */
246    if (htonl(1) != 1L) { /* no work if on little endian machine */
247       memcpy(pBE, &v, sizeof(int32_t));
248    } else {
249       int i;
250       uint8_t rv[sizeof(int32_t)];
251       uint8_t *pv = (uint8_t *) &v;
252
253       for (i = 0; i < 4; i++) {
254          rv[i] = pv[3 - i];
255       }
256       memcpy(pBE, &rv, sizeof(int32_t));
257    }
258 }
259
260
261 /**
262  *  Read a BackupRead block and pull out the file data
263  */
264 bool processWin32BackupAPIBlock (BFILE *bfd, void *pBuffer, ssize_t dwSize)
265 {
266    /* pByte contains the buffer
267       dwSize the len to be processed.  function assumes to be
268       called in successive incremental order over the complete
269       BackupRead stream beginning at pos 0 and ending at the end.
270     */
271
272    PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT* pContext = &(bfd->win32DecompContext);
273    bool bContinue = false;
274    int64_t dwDataOffset = 0;
275    int64_t dwDataLen;
276
277    /* Win32 Stream Header size without name of stream.
278     * = sizeof (WIN32_STREAM_ID)- sizeof(WCHAR*);
279     */
280    int32_t dwSizeHeader = 20;
281
282    do {
283       if (pContext->liNextHeader >= dwSize) {
284          dwDataLen = dwSize-dwDataOffset;
285          bContinue = false; /* 1 iteration is enough */
286       } else {
287          dwDataLen = pContext->liNextHeader-dwDataOffset;
288          bContinue = true; /* multiple iterations may be necessary */
289       }
290
291       /* flush */
292       /* copy block of real DATA */
293       if (pContext->bIsInData) {
294          if (bwrite(bfd, ((char *)pBuffer)+dwDataOffset, dwDataLen) != (ssize_t)dwDataLen)
295             return false;
296       }
297
298       if (pContext->liNextHeader < dwSize) {/* is a header in this block ? */
299          int32_t dwOffsetTarget;
300          int32_t dwOffsetSource;
301
302          if (pContext->liNextHeader < 0) {
303             /* start of header was before this block, so we
304              * continue with the part in the current block
305              */
306             dwOffsetTarget = -pContext->liNextHeader;
307             dwOffsetSource = 0;
308          } else {
309             /* start of header is inside of this block */
310             dwOffsetTarget = 0;
311             dwOffsetSource = pContext->liNextHeader;
312          }
313
314          int32_t dwHeaderPartLen = dwSizeHeader-dwOffsetTarget;
315          bool bHeaderIsComplete;
316
317          if (dwHeaderPartLen <= dwSize-dwOffsetSource) {
318             /* header (or rest of header) is completely available
319                in current block
320              */
321             bHeaderIsComplete = true;
322          } else {
323             /* header will continue in next block */
324             bHeaderIsComplete = false;
325             dwHeaderPartLen = dwSize-dwOffsetSource;
326          }
327
328          /* copy the available portion of header to persistent copy */
329          memcpy(((char *)&pContext->header_stream)+dwOffsetTarget, ((char *)pBuffer)+dwOffsetSource, dwHeaderPartLen);
330
331          /* recalculate position of next header */
332          if (bHeaderIsComplete) {
333             /* convert stream name size (32 bit little endian) to machine type */
334             int32_t dwNameSize;
335             int32_LE2BE (&dwNameSize, pContext->header_stream.dwStreamNameSize);
336             dwDataOffset = dwNameSize+pContext->liNextHeader+dwSizeHeader;
337
338             /* convert stream size (64 bit little endian) to machine type */
339             int64_LE2BE (&(pContext->liNextHeader), pContext->header_stream.Size);
340             pContext->liNextHeader += dwDataOffset;
341
342             pContext->bIsInData = pContext->header_stream.dwStreamId == WIN32_BACKUP_DATA;
343             if (dwDataOffset == dwSize)
344                bContinue = false;
345          } else {
346             /* stop and continue with next block */
347             bContinue = false;
348             pContext->bIsInData = false;
349          }
350       }
351    } while (bContinue);
352
353    /* set "NextHeader" relative to the beginning of the next block */
354    pContext->liNextHeader-= dwSize;
355
356    return TRUE;
357 }
358
359
360
361
362 /* ===============================================================
363  *
364  *            U N I X
365  *
366  * ===============================================================
367  */
368 /* Unix */
369 void binit(BFILE *bfd)
370 {
371    memset(bfd, 0, sizeof(BFILE));
372    bfd->fid = -1;
373 }
374
375 /* Unix */
376 bool have_win32_api()
377 {
378    return false;                       /* no can do */
379 }
380
381 /*
382  * Enables using the Backup API (win32_data).
383  *   Returns true  if function worked
384  *   Returns false if failed (i.e. do not have Backup API on this machine)
385  */
386 /* Unix */
387 bool set_win32_backup(BFILE *bfd)
388 {
389    return false;                       /* no can do */
390 }
391
392
393 /* Unix */
394 bool set_portable_backup(BFILE *bfd)
395 {
396    return true;                        /* no problem */
397 }
398
399 /*
400  * Return true  if we are writing in portable format
401  * return false if not
402  */
403 /* Unix */
404 bool is_portable_backup(BFILE *bfd)
405 {
406    return true;                       /* portable by definition */
407 }
408
409 /* Unix */
410 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
411 {
412    return false;
413 }
414
415 /* Unix */
416 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
417 {
418    bfd->cmd_plugin = true;
419    bfd->jcr = jcr;
420    return true;
421 }
422
423 /*
424  * This code is running on a non-Win32 machine
425  */
426 /* Unix */
427 bool is_restore_stream_supported(int stream)
428 {
429    /* No Win32 backup on this machine */
430      switch (stream) {
431 #ifndef HAVE_LIBZ
432    case STREAM_GZIP_DATA:
433    case STREAM_SPARSE_GZIP_DATA:
434    case STREAM_WIN32_GZIP_DATA:
435 #endif
436 #ifndef HAVE_LZO
437    case STREAM_COMPRESSED_DATA:
438    case STREAM_SPARSE_COMPRESSED_DATA:
439    case STREAM_WIN32_COMPRESSED_DATA:
440    case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
441    case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
442 #endif
443 #ifndef HAVE_DARWIN_OS
444    case STREAM_MACOS_FORK_DATA:
445    case STREAM_HFSPLUS_ATTRIBUTES:
446 #endif
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    case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
460    case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
461 #endif
462    case STREAM_WIN32_DATA:
463    case STREAM_UNIX_ATTRIBUTES:
464    case STREAM_FILE_DATA:
465    case STREAM_MD5_DIGEST:
466    case STREAM_UNIX_ATTRIBUTES_EX:
467    case STREAM_SPARSE_DATA:
468    case STREAM_PROGRAM_NAMES:
469    case STREAM_PROGRAM_DATA:
470    case STREAM_SHA1_DIGEST:
471 #ifdef HAVE_SHA2
472    case STREAM_SHA256_DIGEST:
473    case STREAM_SHA512_DIGEST:
474 #endif
475 #ifdef HAVE_CRYPTO
476    case STREAM_SIGNED_DIGEST:
477    case STREAM_ENCRYPTED_FILE_DATA:
478    case STREAM_ENCRYPTED_FILE_GZIP_DATA:
479    case STREAM_ENCRYPTED_WIN32_DATA:
480    case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
481 #endif
482 #ifdef HAVE_DARWIN_OS
483    case STREAM_MACOS_FORK_DATA:
484    case STREAM_HFSPLUS_ATTRIBUTES:
485 #ifdef HAVE_CRYPTO
486    case STREAM_ENCRYPTED_MACOS_FORK_DATA:
487 #endif /* HAVE_CRYPTO */
488 #endif /* HAVE_DARWIN_OS */
489    case 0:   /* compatibility with old tapes */
490       return true;
491
492    }
493    return false;
494 }
495
496 /* Unix */
497 int bopen(BFILE *bfd, const char *fname, uint64_t flags, mode_t mode)
498 {
499    if (bfd->cmd_plugin && plugin_bopen) {
500       Dmsg1(400, "call plugin_bopen fname=%s\n", fname);
501       bfd->fid = plugin_bopen(bfd, fname, flags, mode);
502       Dmsg2(400, "Plugin bopen fid=%d file=%s\n", bfd->fid, fname);
503       return bfd->fid;
504    }
505
506    /* Normal file open */
507    Dmsg1(dbglvl, "open file %s\n", fname);
508
509    /* We use fnctl to set O_NOATIME if requested to avoid open error */
510    bfd->fid = open(fname, flags & ~O_NOATIME, mode);
511
512    /* Set O_NOATIME if possible */
513    if (bfd->fid != -1 && flags & O_NOATIME) {
514       int oldflags = fcntl(bfd->fid, F_GETFL, 0);
515       if (oldflags == -1) {
516          bfd->berrno = errno;
517          close(bfd->fid);
518          bfd->fid = -1;
519       } else {
520          int ret = fcntl(bfd->fid, F_SETFL, oldflags | O_NOATIME);
521         /* EPERM means setting O_NOATIME was not allowed  */
522          if (ret == -1 && errno != EPERM) {
523             bfd->berrno = errno;
524             close(bfd->fid);
525             bfd->fid = -1;
526          }
527       }
528    }
529    bfd->berrno = errno;
530    bfd->m_flags = flags;
531    bfd->block = 0;
532    bfd->total_bytes = 0;
533    Dmsg1(400, "Open file %d\n", bfd->fid);
534    errno = bfd->berrno;
535
536    bfd->win32DecompContext.bIsInData = false;
537    bfd->win32DecompContext.liNextHeader = 0;
538
539 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
540    if (bfd->fid != -1 && flags & O_RDONLY) {
541       int stat = posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_WILLNEED);
542       Dmsg2(400, "Did posix_fadvise on %s stat=%d\n", fname, stat);
543    }
544 #endif
545
546    return bfd->fid;
547 }
548
549 #ifdef HAVE_DARWIN_OS
550 /* Open the resource fork of a file. */
551 int bopen_rsrc(BFILE *bfd, const char *fname, uint64_t flags, mode_t mode)
552 {
553    POOLMEM *rsrc_fname;
554
555    rsrc_fname = get_pool_memory(PM_FNAME);
556    pm_strcpy(rsrc_fname, fname);
557    pm_strcat(rsrc_fname, _PATH_RSRCFORKSPEC);
558    bopen(bfd, rsrc_fname, flags, mode);
559    free_pool_memory(rsrc_fname);
560    return bfd->fid;
561 }
562 #else /* Unix */
563
564 /* Unix */
565 int bopen_rsrc(BFILE *bfd, const char *fname, uint64_t flags, mode_t mode)
566     { return -1; }
567
568 #endif
569
570
571 /* Unix */
572 int bclose(BFILE *bfd)
573 {
574    int stat;
575
576    Dmsg2(400, "Close bfd=%p file %d\n", bfd, bfd->fid);
577
578    if (bfd->fid == -1) {
579       return 0;
580    }
581    if (bfd->cmd_plugin && plugin_bclose) {
582       stat = plugin_bclose(bfd);
583       bfd->fid = -1;
584       bfd->cmd_plugin = false;
585    }
586
587 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
588    if (bfd->m_flags & O_RDONLY) {
589       fdatasync(bfd->fid);            /* sync the file */
590       /* Tell OS we don't need it any more */
591       posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_DONTNEED);
592    }
593 #endif
594
595    /* Close normal file */
596    stat = close(bfd->fid);
597    bfd->berrno = errno;
598    bfd->fid = -1;
599    bfd->cmd_plugin = false;
600    return stat;
601 }
602
603 /* Unix */
604 ssize_t bread(BFILE *bfd, void *buf, size_t count)
605 {
606    ssize_t stat;
607
608    if (bfd->cmd_plugin && plugin_bread) {
609       return plugin_bread(bfd, buf, count);
610    }
611
612    stat = read(bfd->fid, buf, count);
613    bfd->berrno = errno;
614    bfd->block++;
615    if (stat > 0) {
616       bfd->total_bytes += stat;
617    }
618    return stat;
619 }
620
621 /* Unix */
622 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
623 {
624    ssize_t stat;
625
626    if (bfd->cmd_plugin && plugin_bwrite) {
627       return plugin_bwrite(bfd, buf, count);
628    }
629    stat = write(bfd->fid, buf, count);
630    bfd->berrno = errno;
631    bfd->block++;
632    if (stat > 0) {
633       bfd->total_bytes += stat;
634    }
635    return stat;
636 }
637
638 /* Unix */
639 bool is_bopen(BFILE *bfd)
640 {
641    return bfd->fid >= 0;
642 }
643
644 /* Unix */
645 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
646 {
647    boffset_t pos;
648
649    if (bfd->cmd_plugin && plugin_bwrite) {
650       return plugin_blseek(bfd, offset, whence);
651    }
652    pos = (boffset_t)lseek(bfd->fid, offset, whence);
653    bfd->berrno = errno;
654    return pos;
655 }
656