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