]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/findlib/bfile.c
Make Bacula build without Python
[bacula/bacula] / bacula / src / findlib / bfile.c
1 /*
2  *  Bacula low level File I/O routines.  This routine simulates
3  *    open(), read(), write(), and close(), but using native routines.
4  *    I.e. on Windows, we use Windows APIs.
5  *
6  *    Kern Sibbald, April MMIII
7  *
8  *   Version $Id$
9  *
10  */
11 /*
12    Copyright (C) 2003-2004 Kern Sibbald and John Walker
13
14    This program is free software; you can redistribute it and/or
15    modify it under the terms of the GNU General Public License as
16    published by the Free Software Foundation; either version 2 of
17    the License, or (at your option) any later version.
18
19    This program is distributed in the hope that it will be useful,
20    but WITHOUT ANY WARRANTY; without even the implied warranty of
21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22    General Public License for more details.
23
24    You should have received a copy of the GNU General Public
25    License along with this program; if not, write to the Free
26    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
27    MA 02111-1307, USA.
28
29  */
30
31 #include "bacula.h"
32 #include "find.h"
33
34 extern int generate_job_event(JCR *jcr, const char *event);
35
36 #ifdef HAVE_DARWIN_OS
37 #include <sys/paths.h>
38 #endif
39
40 /* ===============================================================
41  *
42  *            U N I X   AND   W I N D O W S
43  *
44  * ===============================================================
45  */
46
47 bool is_win32_stream(int stream)
48 {
49    switch (stream) {
50    case STREAM_WIN32_DATA:
51    case STREAM_WIN32_GZIP_DATA:
52       return true;
53    }
54    return false;
55 }
56
57 const char *stream_to_ascii(int stream)
58 {
59    static char buf[20];
60
61    switch (stream) {
62    case STREAM_GZIP_DATA:
63       return "GZIP data";
64    case STREAM_SPARSE_GZIP_DATA:
65       return "GZIP sparse data";
66    case STREAM_WIN32_DATA:
67       return "Win32 data";
68    case STREAM_WIN32_GZIP_DATA:
69       return "Win32 GZIP data";
70    case STREAM_UNIX_ATTRIBUTES:
71       return "File attributes";
72    case STREAM_FILE_DATA:
73       return "File data";
74    case STREAM_MD5_SIGNATURE:
75       return "MD5 signature";
76    case STREAM_UNIX_ATTRIBUTES_EX:
77       return "Extended attributes";
78    case STREAM_SPARSE_DATA:
79       return "Sparse data";
80    case STREAM_PROGRAM_NAMES:
81       return "Program names";
82    case STREAM_PROGRAM_DATA:
83       return "Program data";
84    case STREAM_SHA1_SIGNATURE:
85       return "SHA1 signature";
86    case STREAM_MACOS_FORK_DATA:
87       return "HFS+ resource fork";
88    case STREAM_HFSPLUS_ATTRIBUTES:
89       return "HFS+ Finder Info";
90    default:
91       sprintf(buf, "%d", stream);
92       return (const char *)buf;
93    }
94 }
95
96
97
98 /* ===============================================================
99  *
100  *            W I N D O W S
101  *
102  * ===============================================================
103  */
104
105 #if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
106
107 void unix_name_to_win32(POOLMEM **win32_name, char *name);
108 extern "C" HANDLE get_osfhandle(int fd);
109
110
111
112 void binit(BFILE *bfd)
113 {
114    memset(bfd, 0, sizeof(BFILE));
115    bfd->fid = -1;
116    bfd->mode = BF_CLOSED;
117    bfd->use_backup_api = have_win32_api();
118 }
119
120 /*
121  * Enables using the Backup API (win32_data).
122  *   Returns 1 if function worked
123  *   Returns 0 if failed (i.e. do not have Backup API on this machine)
124  */
125 bool set_win32_backup(BFILE *bfd)
126 {
127    /* We enable if possible here */
128    bfd->use_backup_api = have_win32_api();
129    return bfd->use_backup_api;
130 }
131
132
133 bool set_portable_backup(BFILE *bfd)
134 {
135    bfd->use_backup_api = false;
136    return true;
137 }
138
139 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
140 {
141    bfd->prog = prog;
142    bfd->jcr = jcr;
143    return false;
144 }
145
146 /*
147  * Return 1 if we are NOT using Win32 BackupWrite()
148  * return 0 if are
149  */
150 bool is_portable_backup(BFILE *bfd)
151 {
152    return !bfd->use_backup_api;
153 }
154
155 bool have_win32_api()
156 {
157    return p_BackupRead && p_BackupWrite;
158 }
159
160
161
162 /*
163  * Return 1 if we support the stream
164  *        0 if we do not support the stream
165  */
166 bool is_stream_supported(int stream)
167 {
168    /* No Win32 backup on this machine */
169    switch (stream) {
170 #ifndef HAVE_LIBZ
171    case STREAM_GZIP_DATA:
172    case STREAM_SPARSE_GZIP_DATA:
173       return 0;
174 #endif
175    case STREAM_WIN32_DATA:
176    case STREAM_WIN32_GZIP_DATA:
177       return have_win32_api();
178
179    case STREAM_MACOS_FORK_DATA:
180    case STREAM_HFSPLUS_ATTRIBUTES:
181       return false;
182
183    /* Known streams */
184 #ifdef HAVE_LIBZ
185    case STREAM_GZIP_DATA:
186    case STREAM_SPARSE_GZIP_DATA:
187 #endif
188    case STREAM_UNIX_ATTRIBUTES:
189    case STREAM_FILE_DATA:
190    case STREAM_MD5_SIGNATURE:
191    case STREAM_UNIX_ATTRIBUTES_EX:
192    case STREAM_SPARSE_DATA:
193    case STREAM_PROGRAM_NAMES:
194    case STREAM_PROGRAM_DATA:
195    case STREAM_SHA1_SIGNATURE:
196    case 0:                            /* compatibility with old tapes */
197       return true;
198    }
199    return false;
200 }
201
202 HANDLE bget_handle(BFILE *bfd)
203 {
204    return bfd->fh;
205 }
206
207 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
208 {
209    POOLMEM *win32_fname;
210    DWORD dwaccess, dwflags, dwshare;
211
212    /* Convert to Windows path format */
213    win32_fname = get_pool_memory(PM_FNAME);
214    unix_name_to_win32(&win32_fname, (char *)fname);
215
216    if (flags & O_CREAT) {             /* Create */
217       if (bfd->use_backup_api) {
218          dwaccess = GENERIC_WRITE|FILE_ALL_ACCESS|WRITE_OWNER|WRITE_DAC|ACCESS_SYSTEM_SECURITY;
219          dwflags = FILE_FLAG_BACKUP_SEMANTICS;
220       } else {
221          dwaccess = GENERIC_WRITE;
222          dwflags = 0;
223       }
224       bfd->fh = CreateFile(win32_fname,
225              dwaccess,                /* Requested access */
226              0,                       /* Shared mode */
227              NULL,                    /* SecurityAttributes */
228              CREATE_ALWAYS,           /* CreationDisposition */
229              dwflags,                 /* Flags and attributes */
230              NULL);                   /* TemplateFile */
231       bfd->mode = BF_WRITE;
232
233    } else if (flags & O_WRONLY) {     /* Open existing for write */
234       if (bfd->use_backup_api) {
235          dwaccess = GENERIC_WRITE|WRITE_OWNER|WRITE_DAC;
236          dwflags = FILE_FLAG_BACKUP_SEMANTICS;
237       } else {
238          dwaccess = GENERIC_WRITE;
239          dwflags = 0;
240       }
241       bfd->fh = CreateFile(win32_fname,
242              dwaccess,                /* Requested access */
243              0,                       /* Shared mode */
244              NULL,                    /* SecurityAttributes */
245              OPEN_EXISTING,           /* CreationDisposition */
246              dwflags,                 /* Flags and attributes */
247              NULL);                   /* TemplateFile */
248       bfd->mode = BF_WRITE;
249
250    } else {                           /* Read */
251       if (bfd->use_backup_api) {
252          dwaccess = GENERIC_READ|READ_CONTROL|ACCESS_SYSTEM_SECURITY;
253          dwflags = FILE_FLAG_BACKUP_SEMANTICS;
254          dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
255       } else {
256          dwaccess = GENERIC_READ;
257          dwflags = 0;
258          dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE;
259       }
260       bfd->fh = CreateFile(win32_fname,
261              dwaccess,                /* Requested access */
262              dwshare,                 /* Share modes */
263              NULL,                    /* SecurityAttributes */
264              OPEN_EXISTING,           /* CreationDisposition */
265              dwflags,                 /* Flags and attributes */
266              NULL);                   /* TemplateFile */
267       bfd->mode = BF_READ;
268    }
269
270    if (bfd->fh == INVALID_HANDLE_VALUE) {
271       bfd->lerror = GetLastError();
272       bfd->berrno = b_errno_win32;
273       errno = b_errno_win32;
274       bfd->mode = BF_CLOSED;
275    }
276    bfd->errmsg = NULL;
277    bfd->lpContext = NULL;
278    free_pool_memory(win32_fname);
279    return bfd->mode == BF_CLOSED ? -1 : 1;
280 }
281
282 /*
283  * Returns  0 on success
284  *         -1 on error
285  */
286 int bclose(BFILE *bfd)
287 {
288    int stat = 0;
289
290    if (bfd->errmsg) {
291       free_pool_memory(bfd->errmsg);
292       bfd->errmsg = NULL;
293    }
294    if (bfd->mode == BF_CLOSED) {
295       return 0;
296    }
297    if (bfd->use_backup_api && bfd->mode == BF_READ) {
298       BYTE buf[10];
299       if (!bfd->lpContext && !p_BackupRead(bfd->fh,
300               buf,                    /* buffer */
301               (DWORD)0,               /* bytes to read */
302               &bfd->rw_bytes,         /* bytes read */
303               1,                      /* Abort */
304               1,                      /* ProcessSecurity */
305               &bfd->lpContext)) {     /* Read context */
306          errno = b_errno_win32;
307          stat = -1;
308       }
309    } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
310       BYTE buf[10];
311       if (!bfd->lpContext && !p_BackupWrite(bfd->fh,
312               buf,                    /* buffer */
313               (DWORD)0,               /* bytes to read */
314               &bfd->rw_bytes,         /* bytes written */
315               1,                      /* Abort */
316               1,                      /* ProcessSecurity */
317               &bfd->lpContext)) {     /* Write context */
318          errno = b_errno_win32;
319          stat = -1;
320       }
321    }
322    if (!CloseHandle(bfd->fh)) {
323       stat = -1;
324       errno = b_errno_win32;
325    }
326    bfd->mode = BF_CLOSED;
327    bfd->lpContext = NULL;
328    return stat;
329 }
330
331 /* Returns: bytes read on success
332  *           0         on EOF
333  *          -1         on error
334  */
335 ssize_t bread(BFILE *bfd, void *buf, size_t count)
336 {
337    bfd->rw_bytes = 0;
338
339    if (bfd->use_backup_api) {
340       if (!p_BackupRead(bfd->fh,
341            (BYTE *)buf,
342            count,
343            &bfd->rw_bytes,
344            0,                           /* no Abort */
345            1,                           /* Process Security */
346            &bfd->lpContext)) {          /* Context */
347          bfd->lerror = GetLastError();
348          bfd->berrno = b_errno_win32;
349          errno = b_errno_win32;
350          return -1;
351       }
352    } else {
353       if (!ReadFile(bfd->fh,
354            buf,
355            count,
356            &bfd->rw_bytes,
357            NULL)) {
358          bfd->lerror = GetLastError();
359          bfd->berrno = b_errno_win32;
360          errno = b_errno_win32;
361          return -1;
362       }
363    }
364
365    return (ssize_t)bfd->rw_bytes;
366 }
367
368 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
369 {
370    bfd->rw_bytes = 0;
371
372    if (bfd->use_backup_api) {
373       if (!p_BackupWrite(bfd->fh,
374            (BYTE *)buf,
375            count,
376            &bfd->rw_bytes,
377            0,                           /* No abort */
378            1,                           /* Process Security */
379            &bfd->lpContext)) {          /* Context */
380          bfd->lerror = GetLastError();
381          bfd->berrno = b_errno_win32;
382          errno = b_errno_win32;
383          return -1;
384       }
385    } else {
386       if (!WriteFile(bfd->fh,
387            buf,
388            count,
389            &bfd->rw_bytes,
390            NULL)) {
391          bfd->lerror = GetLastError();
392          bfd->berrno = b_errno_win32;
393          errno = b_errno_win32;
394          return -1;
395       }
396    }
397    return (ssize_t)bfd->rw_bytes;
398 }
399
400 bool is_bopen(BFILE *bfd)
401 {
402    return bfd->mode != BF_CLOSED;
403 }
404
405 off_t blseek(BFILE *bfd, off_t offset, int whence)
406 {
407    /* ****FIXME**** this must be implemented if we want to read Win32 Archives */
408    return -1;
409 }
410
411 #else  /* Unix systems */
412
413 /* ===============================================================
414  *
415  *            U N I X
416  *
417  * ===============================================================
418  */
419 void binit(BFILE *bfd)
420 {
421    memset(bfd, 0, sizeof(BFILE));
422    bfd->fid = -1;
423 }
424
425 bool have_win32_api()
426 {
427    return false;                       /* no can do */
428 }
429
430 /*
431  * Enables using the Backup API (win32_data).
432  *   Returns true  if function worked
433  *   Returns false if failed (i.e. do not have Backup API on this machine)
434  */
435 bool set_win32_backup(BFILE *bfd)
436 {
437    return false;                       /* no can do */
438 }
439
440
441 bool set_portable_backup(BFILE *bfd)
442 {
443    return true;                        /* no problem */
444 }
445
446 /*
447  * Return true  if we are writing in portable format
448  * return false if not
449  */
450 bool is_portable_backup(BFILE *bfd)
451 {
452    return true;                       /* portable by definition */
453 }
454
455 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
456 {
457 #ifdef HAVE_PYTHON
458    if (bfd->prog && strcmp(prog, bfd->prog) == 0) {
459       return true;                    /* already setup */
460    }
461
462    int stat = generate_job_event(jcr, "Reader");
463    if (stat == 1 && bfd->pio.fo && bfd->pio.fr && bfd->pio.fc) {
464       bfd->prog = prog;
465       bfd->jcr = jcr;
466       return true;
467    }
468 #endif
469    bfd->prog = NULL;
470    return false;
471
472 }
473
474
475 bool is_stream_supported(int stream)
476 {
477    /* No Win32 backup on this machine */
478    switch (stream) {
479 #ifndef HAVE_LIBZ
480    case STREAM_GZIP_DATA:
481    case STREAM_SPARSE_GZIP_DATA:
482 #endif
483    case STREAM_WIN32_DATA:
484    case STREAM_WIN32_GZIP_DATA:
485 #ifndef HAVE_DARWIN_OS
486    case STREAM_MACOS_FORK_DATA:
487    case STREAM_HFSPLUS_ATTRIBUTES:
488 #endif
489       return false;
490
491    /* Known streams */
492 #ifdef HAVE_LIBZ
493    case STREAM_GZIP_DATA:
494    case STREAM_SPARSE_GZIP_DATA:
495 #endif
496    case STREAM_UNIX_ATTRIBUTES:
497    case STREAM_FILE_DATA:
498    case STREAM_MD5_SIGNATURE:
499    case STREAM_UNIX_ATTRIBUTES_EX:
500    case STREAM_SPARSE_DATA:
501    case STREAM_PROGRAM_NAMES:
502    case STREAM_PROGRAM_DATA:
503    case STREAM_SHA1_SIGNATURE:
504 #ifdef HAVE_DARWIN_OS
505    case STREAM_MACOS_FORK_DATA:
506    case STREAM_HFSPLUS_ATTRIBUTES:
507 #endif
508    case 0:                            /* compatibility with old tapes */
509       return true;
510
511    }
512    return 0;
513 }
514
515 /* Old file reader code */
516 #ifdef xxx
517    if (bfd->prog) {
518       POOLMEM *ecmd = get_pool_memory(PM_FNAME);
519       ecmd = edit_job_codes(bfd->jcr, ecmd, bfd->prog, fname);
520       const char *pmode;
521       if (flags & O_RDONLY) {
522          pmode = "r";
523       } else {
524          pmode = "w";
525       }
526       bfd->bpipe = open_bpipe(ecmd, 0, pmode);
527       if (bfd->bpipe == NULL) {
528          bfd->berrno = errno;
529          bfd->fid = -1;
530          free_pool_memory(ecmd);
531          return -1;
532       }
533       free_pool_memory(ecmd);
534       if (flags & O_RDONLY) {
535          bfd->fid = fileno(bfd->bpipe->rfd);
536       } else {
537          bfd->fid = fileno(bfd->bpipe->wfd);
538       }
539       errno = 0;
540       return bfd->fid;
541    }
542 #endif
543
544
545 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
546 {
547    /* Open reader/writer program */
548    if (bfd->prog) {
549       errno = 0;
550       return 1;
551    }
552
553    /* Normal file open */
554    bfd->fid = open(fname, flags, mode);
555    bfd->berrno = errno;
556    Dmsg1(400, "Open file %d\n", bfd->fid);
557    errno = bfd->berrno;
558    return bfd->fid;
559 }
560
561 #ifdef HAVE_DARWIN_OS
562 /* Open the resource fork of a file. */
563 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
564 {
565    POOLMEM *rsrc_fname;
566    size_t fname_len;
567
568    fname_len = strlen(fname);
569    rsrc_fname = get_pool_memory(PM_FNAME);
570    bstrncpy(rsrc_fname, fname, fname_len + 1);
571    bstrncpy(rsrc_fname + fname_len, _PATH_RSRCFORKSPEC,
572       strlen(_PATH_RSRCFORKSPEC) + 1);
573    bopen(bfd, rsrc_fname, flags, mode);
574    free_pool_memory(rsrc_fname);
575    return bfd->fid;
576 }
577 #endif
578
579 /* Old prog close code */
580 #ifdef xxx
581    if (bfd->prog && bfd->bpipe) {
582       stat = close_bpipe(bfd->bpipe);
583       bfd->berrno = errno;
584       bfd->fid = -1;
585       bfd->bpipe = NULL;
586       return stat;
587    }
588 #endif
589
590
591 int bclose(BFILE *bfd)
592 {
593    int stat;
594    Dmsg1(400, "Close file %d\n", bfd->fid);
595    if (bfd->fid == -1) {
596       return 0;
597    }
598    /* Close reader/writer program */
599    if (bfd->prog) {
600       return 0;
601    }
602
603    /* Close normal file */
604    stat = close(bfd->fid);
605    bfd->berrno = errno;
606    bfd->fid = -1;
607    return stat;
608 }
609
610 ssize_t bread(BFILE *bfd, void *buf, size_t count)
611 {
612    ssize_t stat;
613    stat = read(bfd->fid, buf, count);
614    bfd->berrno = errno;
615    return stat;
616 }
617
618 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
619 {
620    ssize_t stat;
621    stat = write(bfd->fid, buf, count);
622    bfd->berrno = errno;
623    return stat;
624 }
625
626 bool is_bopen(BFILE *bfd)
627 {
628    return bfd->fid >= 0;
629 }
630
631 off_t blseek(BFILE *bfd, off_t offset, int whence)
632 {
633     off_t pos;
634     pos = lseek(bfd->fid, offset, whence);
635     bfd->berrno = errno;
636     return pos;
637 }
638
639 #endif