]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/findlib/bfile.c
Backport from BEE
[bacula/bacula] / bacula / src / findlib / bfile.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2003-2014 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from many
7    others, a complete list can be found in the file AUTHORS.
8
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13
14    Bacula® is a registered trademark of Kern Sibbald.
15 */
16 /*
17  *  Bacula low level File I/O routines.  This routine simulates
18  *    open(), read(), write(), and close(), but using native routines.
19  *    I.e. on Windows, we use Windows APIs.
20  *
21  *    Kern Sibbald, April MMIII
22  *
23  */
24
25 #include "bacula.h"
26 #include "find.h"
27
28 const int dbglvl = 200;
29
30 int       (*plugin_bopen)(BFILE *bfd, const char *fname, uint64_t flags, mode_t mode) = NULL;
31 int       (*plugin_bclose)(BFILE *bfd) = NULL;
32 ssize_t   (*plugin_bread)(BFILE *bfd, void *buf, size_t count) = NULL;
33 ssize_t   (*plugin_bwrite)(BFILE *bfd, void *buf, size_t count) = NULL;
34 boffset_t (*plugin_blseek)(BFILE *bfd, boffset_t offset, int whence) = NULL;
35
36
37 #ifdef HAVE_DARWIN_OS
38 #include <sys/paths.h>
39 #endif
40
41 #if !defined(HAVE_FDATASYNC)
42 #define fdatasync(fd)
43 #endif
44
45 #ifdef HAVE_WIN32
46 void pause_msg(const char *file, const char *func, int line, const char *msg)
47 {
48    char buf[1000];
49    if (msg) {
50       bsnprintf(buf, sizeof(buf), "%s:%s:%d %s", file, func, line, msg);
51    } else {
52       bsnprintf(buf, sizeof(buf), "%s:%s:%d", file, func, line);
53    }
54    MessageBox(NULL, buf, "Pause", MB_OK);
55 }
56 #endif
57
58 /* ===============================================================
59  *
60  *            U N I X   AND   W I N D O W S
61  *
62  * ===============================================================
63  */
64
65 bool is_win32_stream(int stream)
66 {
67    switch (stream) {
68    case STREAM_WIN32_DATA:
69    case STREAM_WIN32_GZIP_DATA:
70    case STREAM_WIN32_COMPRESSED_DATA:
71    case STREAM_ENCRYPTED_WIN32_DATA:
72    case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
73    case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
74       return true;
75    }
76    return false;
77 }
78
79 const char *stream_to_ascii(int stream)
80 {
81    static char buf[20];
82
83    switch (stream & STREAMMASK_TYPE) {
84    case STREAM_UNIX_ATTRIBUTES:
85       return _("Unix attributes");
86    case STREAM_FILE_DATA:
87       return _("File data");
88    case STREAM_MD5_DIGEST:
89       return _("MD5 digest");
90    case STREAM_GZIP_DATA:
91       return _("GZIP data");
92    case STREAM_COMPRESSED_DATA:
93       return _("Compressed data");
94    case STREAM_UNIX_ATTRIBUTES_EX:
95       return _("Extended attributes");
96    case STREAM_SPARSE_DATA:
97       return _("Sparse data");
98    case STREAM_SPARSE_GZIP_DATA:
99       return _("GZIP sparse data");
100    case STREAM_SPARSE_COMPRESSED_DATA:
101       return _("Compressed sparse data");
102    case STREAM_PROGRAM_NAMES:
103       return _("Program names");
104    case STREAM_PROGRAM_DATA:
105       return _("Program data");
106    case STREAM_SHA1_DIGEST:
107       return _("SHA1 digest");
108    case STREAM_WIN32_DATA:
109       return _("Win32 data");
110    case STREAM_WIN32_GZIP_DATA:
111       return _("Win32 GZIP data");
112    case STREAM_WIN32_COMPRESSED_DATA:
113       return _("Win32 compressed data");
114    case STREAM_MACOS_FORK_DATA:
115       return _("MacOS Fork data");
116    case STREAM_HFSPLUS_ATTRIBUTES:
117       return _("HFS+ attribs");
118    case STREAM_UNIX_ACCESS_ACL:
119       return _("Standard Unix ACL attribs");
120    case STREAM_UNIX_DEFAULT_ACL:
121       return _("Default Unix ACL attribs");
122    case STREAM_SHA256_DIGEST:
123       return _("SHA256 digest");
124    case STREAM_SHA512_DIGEST:
125       return _("SHA512 digest");
126    case STREAM_SIGNED_DIGEST:
127       return _("Signed digest");
128    case STREAM_ENCRYPTED_FILE_DATA:
129       return _("Encrypted File data");
130    case STREAM_ENCRYPTED_WIN32_DATA:
131       return _("Encrypted Win32 data");
132    case STREAM_ENCRYPTED_SESSION_DATA:
133       return _("Encrypted session data");
134    case STREAM_ENCRYPTED_FILE_GZIP_DATA:
135       return _("Encrypted GZIP data");
136    case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
137       return _("Encrypted compressed data");
138    case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
139       return _("Encrypted Win32 GZIP data");
140    case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
141       return _("Encrypted Win32 Compressed data");
142    case STREAM_ENCRYPTED_MACOS_FORK_DATA:
143       return _("Encrypted MacOS fork data");
144    case STREAM_PLUGIN_NAME:
145       return _("Plugin Name");
146    case STREAM_PLUGIN_DATA:
147       return _("Plugin Data");
148    case STREAM_RESTORE_OBJECT:
149       return _("Restore Object");
150    case STREAM_ACL_AIX_TEXT:
151       return _("AIX Specific ACL attribs");
152    case STREAM_ACL_DARWIN_ACCESS_ACL:
153       return _("Darwin Specific ACL attribs");
154    case STREAM_ACL_FREEBSD_DEFAULT_ACL:
155       return _("FreeBSD Specific Default ACL attribs");
156    case STREAM_ACL_FREEBSD_ACCESS_ACL:
157       return _("FreeBSD Specific Access ACL attribs");
158    case STREAM_ACL_HPUX_ACL_ENTRY:
159       return _("HPUX Specific ACL attribs");
160    case STREAM_ACL_IRIX_DEFAULT_ACL:
161       return _("Irix Specific Default ACL attribs");
162    case STREAM_ACL_IRIX_ACCESS_ACL:
163       return _("Irix Specific Access ACL attribs");
164    case STREAM_ACL_LINUX_DEFAULT_ACL:
165       return _("Linux Specific Default ACL attribs");
166    case STREAM_ACL_LINUX_ACCESS_ACL:
167       return _("Linux Specific Access ACL attribs");
168    case STREAM_ACL_TRU64_DEFAULT_ACL:
169       return _("TRU64 Specific Default ACL attribs");
170    case STREAM_ACL_TRU64_ACCESS_ACL:
171       return _("TRU64 Specific Access ACL attribs");
172    case STREAM_ACL_SOLARIS_ACLENT:
173       return _("Solaris Specific POSIX ACL attribs");
174    case STREAM_ACL_SOLARIS_ACE:
175       return _("Solaris Specific NFSv4/ZFS ACL attribs");
176    case STREAM_ACL_AFS_TEXT:
177       return _("AFS Specific ACL attribs");
178    case STREAM_ACL_AIX_AIXC:
179       return _("AIX Specific POSIX ACL attribs");
180    case STREAM_ACL_AIX_NFS4:
181       return _("AIX Specific NFSv4 ACL attribs");
182    case STREAM_ACL_FREEBSD_NFS4_ACL:
183       return _("FreeBSD Specific NFSv4/ZFS ACL attribs");
184    case STREAM_ACL_HURD_DEFAULT_ACL:
185       return _("GNU Hurd Specific Default ACL attribs");
186    case STREAM_ACL_HURD_ACCESS_ACL:
187       return _("GNU Hurd Specific Access ACL attribs");
188    case STREAM_XATTR_HURD:
189       return _("GNU Hurd Specific Extended 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  *
360  *            U N I X
361  *
362  * ===============================================================
363  */
364 /* Unix */
365 void binit(BFILE *bfd)
366 {
367    memset(bfd, 0, sizeof(BFILE));
368    bfd->fid = -1;
369 }
370
371 /* Unix */
372 bool have_win32_api()
373 {
374    return false;                       /* no can do */
375 }
376
377 /*
378  * Enables using the Backup API (win32_data).
379  *   Returns true  if function worked
380  *   Returns false if failed (i.e. do not have Backup API on this machine)
381  */
382 /* Unix */
383 bool set_win32_backup(BFILE *bfd)
384 {
385    return false;                       /* no can do */
386 }
387
388
389 /* Unix */
390 bool set_portable_backup(BFILE *bfd)
391 {
392    return true;                        /* no problem */
393 }
394
395 /*
396  * Return true  if we are writing in portable format
397  * return false if not
398  */
399 /* Unix */
400 bool is_portable_backup(BFILE *bfd)
401 {
402    return true;                       /* portable by definition */
403 }
404
405 /* Unix */
406 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
407 {
408    return false;
409 }
410
411 /* Unix */
412 bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
413 {
414    bfd->cmd_plugin = true;
415    bfd->jcr = jcr;
416    return true;
417 }
418
419 /*
420  * This code is running on a non-Win32 machine
421  */
422 /* Unix */
423 bool is_restore_stream_supported(int stream)
424 {
425    /* No Win32 backup on this machine */
426      switch (stream) {
427 #ifndef HAVE_LIBZ
428    case STREAM_GZIP_DATA:
429    case STREAM_SPARSE_GZIP_DATA:
430    case STREAM_WIN32_GZIP_DATA:
431 #endif
432 #ifndef HAVE_LZO
433    case STREAM_COMPRESSED_DATA:
434    case STREAM_SPARSE_COMPRESSED_DATA:
435    case STREAM_WIN32_COMPRESSED_DATA:
436    case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
437    case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
438 #endif
439 #ifndef HAVE_DARWIN_OS
440    case STREAM_MACOS_FORK_DATA:
441    case STREAM_HFSPLUS_ATTRIBUTES:
442 #endif
443       return false;
444
445    /* Known streams */
446 #ifdef HAVE_LIBZ
447    case STREAM_GZIP_DATA:
448    case STREAM_SPARSE_GZIP_DATA:
449    case STREAM_WIN32_GZIP_DATA:
450 #endif
451 #ifdef HAVE_LZO
452    case STREAM_COMPRESSED_DATA:
453    case STREAM_SPARSE_COMPRESSED_DATA:
454    case STREAM_WIN32_COMPRESSED_DATA:
455    case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
456    case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
457 #endif
458    case STREAM_WIN32_DATA:
459    case STREAM_UNIX_ATTRIBUTES:
460    case STREAM_FILE_DATA:
461    case STREAM_MD5_DIGEST:
462    case STREAM_UNIX_ATTRIBUTES_EX:
463    case STREAM_SPARSE_DATA:
464    case STREAM_PROGRAM_NAMES:
465    case STREAM_PROGRAM_DATA:
466    case STREAM_SHA1_DIGEST:
467 #ifdef HAVE_SHA2
468    case STREAM_SHA256_DIGEST:
469    case STREAM_SHA512_DIGEST:
470 #endif
471 #ifdef HAVE_CRYPTO
472    case STREAM_SIGNED_DIGEST:
473    case STREAM_ENCRYPTED_FILE_DATA:
474    case STREAM_ENCRYPTED_FILE_GZIP_DATA:
475    case STREAM_ENCRYPTED_WIN32_DATA:
476    case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
477 #endif
478 #ifdef HAVE_DARWIN_OS
479    case STREAM_MACOS_FORK_DATA:
480    case STREAM_HFSPLUS_ATTRIBUTES:
481 #ifdef HAVE_CRYPTO
482    case STREAM_ENCRYPTED_MACOS_FORK_DATA:
483 #endif /* HAVE_CRYPTO */
484 #endif /* HAVE_DARWIN_OS */
485    case 0:   /* compatibility with old tapes */
486       return true;
487
488    }
489    return false;
490 }
491
492 /* Unix */
493 int bopen(BFILE *bfd, const char *fname, uint64_t flags, mode_t mode)
494 {
495    if (bfd->cmd_plugin && plugin_bopen) {
496       Dmsg1(400, "call plugin_bopen fname=%s\n", fname);
497       bfd->fid = plugin_bopen(bfd, fname, flags, mode);
498       Dmsg2(400, "Plugin bopen fid=%d file=%s\n", bfd->fid, fname);
499       return bfd->fid;
500    }
501
502    /* Normal file open */
503    Dmsg1(dbglvl, "open file %s\n", fname);
504
505    /* We use fnctl to set O_NOATIME if requested to avoid open error */
506    bfd->fid = open(fname, flags & ~O_NOATIME, mode);
507
508    /* Set O_NOATIME if possible */
509    if (bfd->fid != -1 && flags & O_NOATIME) {
510       int oldflags = fcntl(bfd->fid, F_GETFL, 0);
511       if (oldflags == -1) {
512          bfd->berrno = errno;
513          close(bfd->fid);
514          bfd->fid = -1;
515       } else {
516          int ret = fcntl(bfd->fid, F_SETFL, oldflags | O_NOATIME);
517         /* EPERM means setting O_NOATIME was not allowed  */
518          if (ret == -1 && errno != EPERM) {
519             bfd->berrno = errno;
520             close(bfd->fid);
521             bfd->fid = -1;
522          }
523       }
524    }
525    bfd->berrno = errno;
526    bfd->m_flags = flags;
527    bfd->block = 0;
528    bfd->total_bytes = 0;
529    Dmsg1(400, "Open file %d\n", bfd->fid);
530    errno = bfd->berrno;
531
532    bfd->win32DecompContext.bIsInData = false;
533    bfd->win32DecompContext.liNextHeader = 0;
534
535 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
536    if (bfd->fid != -1 && flags & O_RDONLY) {
537       int stat = posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_WILLNEED);
538       Dmsg2(400, "Did posix_fadvise on %s stat=%d\n", fname, stat);
539    }
540 #endif
541
542    return bfd->fid;
543 }
544
545 #ifdef HAVE_DARWIN_OS
546 /* Open the resource fork of a file. */
547 int bopen_rsrc(BFILE *bfd, const char *fname, uint64_t flags, mode_t mode)
548 {
549    POOLMEM *rsrc_fname;
550
551    rsrc_fname = get_pool_memory(PM_FNAME);
552    pm_strcpy(rsrc_fname, fname);
553    pm_strcat(rsrc_fname, _PATH_RSRCFORKSPEC);
554    bopen(bfd, rsrc_fname, flags, mode);
555    free_pool_memory(rsrc_fname);
556    return bfd->fid;
557 }
558 #else
559 /* Unix */
560 int bopen_rsrc(BFILE *bfd, const char *fname, uint64_t flags, mode_t mode)
561 {
562    return -1;
563 }
564 #endif
565
566
567 /* Unix */
568 int bclose(BFILE *bfd)
569 {
570    int stat;
571
572    Dmsg1(400, "Close file %d\n", bfd->fid);
573
574    if (bfd->fid == -1) {
575       return 0;
576    }
577    if (bfd->cmd_plugin && plugin_bclose) {
578       stat = plugin_bclose(bfd);
579       bfd->fid = -1;
580       bfd->cmd_plugin = false;
581    }
582
583 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
584    if (bfd->m_flags & O_RDONLY) {
585       fdatasync(bfd->fid);            /* sync the file */
586       /* Tell OS we don't need it any more */
587       posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_DONTNEED);
588    }
589 #endif
590
591    /* Close normal file */
592    stat = close(bfd->fid);
593    bfd->berrno = errno;
594    bfd->fid = -1;
595    bfd->cmd_plugin = false;
596    return stat;
597 }
598
599 /* Unix */
600 ssize_t bread(BFILE *bfd, void *buf, size_t count)
601 {
602    ssize_t stat;
603
604    if (bfd->cmd_plugin && plugin_bread) {
605       return plugin_bread(bfd, buf, count);
606    }
607
608    stat = read(bfd->fid, buf, count);
609    bfd->berrno = errno;
610    bfd->block++;
611    if (stat > 0) {
612       bfd->total_bytes += stat;
613    }
614    return stat;
615 }
616
617 /* Unix */
618 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
619 {
620    ssize_t stat;
621
622    if (bfd->cmd_plugin && plugin_bwrite) {
623       return plugin_bwrite(bfd, buf, count);
624    }
625    stat = write(bfd->fid, buf, count);
626    bfd->berrno = errno;
627    bfd->block++;
628    if (stat > 0) {
629       bfd->total_bytes += stat;
630    }
631    return stat;
632 }
633
634 /* Unix */
635 bool is_bopen(BFILE *bfd)
636 {
637    return bfd->fid >= 0;
638 }
639
640 /* Unix */
641 boffset_t blseek(BFILE *bfd, boffset_t offset, int whence)
642 {
643    boffset_t pos;
644
645    if (bfd->cmd_plugin && plugin_bwrite) {
646       return plugin_blseek(bfd, offset, whence);
647    }
648    pos = (boffset_t)lseek(bfd->fid, offset, whence);
649    bfd->berrno = errno;
650    return pos;
651 }