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