]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/findlib/bfile.c
This commit was manufactured by cvs2svn to create tag
[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_restore_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    POOLMEM *win32_fname_wchar;
215
216    DWORD dwaccess, dwflags, dwshare;
217    
218    /* Convert to Windows path format */
219    win32_fname = get_pool_memory(PM_FNAME);
220    win32_fname_wchar = get_pool_memory(PM_FNAME);
221    
222    unix_name_to_win32(&win32_fname, (char *)fname);
223
224    if (!(p_CreateFileA || p_CreateFileW))
225       return 0;
226
227    if (p_CreateFileW && p_MultiByteToWideChar)               
228       UTF8_2_wchar(&win32_fname_wchar, win32_fname);
229
230    if (flags & O_CREAT) {             /* Create */
231       if (bfd->use_backup_api) {
232          dwaccess = GENERIC_WRITE|FILE_ALL_ACCESS|WRITE_OWNER|WRITE_DAC|ACCESS_SYSTEM_SECURITY;
233          dwflags = FILE_FLAG_BACKUP_SEMANTICS;
234       } else {
235          dwaccess = GENERIC_WRITE;
236          dwflags = 0;
237       }
238
239    // unicode or ansii open for create write
240    if (p_CreateFileW && p_MultiByteToWideChar) {   
241       bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
242              dwaccess,                /* Requested access */
243              0,                       /* Shared mode */
244              NULL,                    /* SecurityAttributes */
245              CREATE_ALWAYS,           /* CreationDisposition */
246              dwflags,                 /* Flags and attributes */
247              NULL);                   /* TemplateFile */
248    }
249    else {
250       bfd->fh = p_CreateFileA(win32_fname,
251              dwaccess,                /* Requested access */
252              0,                       /* Shared mode */
253              NULL,                    /* SecurityAttributes */
254              CREATE_ALWAYS,           /* CreationDisposition */
255              dwflags,                 /* Flags and attributes */
256              NULL);                   /* TemplateFile */
257    }
258
259
260       bfd->mode = BF_WRITE;
261
262    } else if (flags & O_WRONLY) {     /* Open existing for write */
263       if (bfd->use_backup_api) {
264          dwaccess = GENERIC_WRITE|WRITE_OWNER|WRITE_DAC;
265          dwflags = FILE_FLAG_BACKUP_SEMANTICS;
266       } else {
267          dwaccess = GENERIC_WRITE;
268          dwflags = 0;
269       }
270
271    // unicode or ansii open for open existing write
272    if (p_CreateFileW && p_MultiByteToWideChar) {   
273       bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
274              dwaccess,                /* Requested access */
275              0,                       /* Shared mode */
276              NULL,                    /* SecurityAttributes */
277              OPEN_EXISTING,           /* CreationDisposition */
278              dwflags,                 /* Flags and attributes */
279              NULL);                   /* TemplateFile */
280    }
281    else {
282       bfd->fh = p_CreateFileA(win32_fname,
283              dwaccess,                /* Requested access */
284              0,                       /* Shared mode */
285              NULL,                    /* SecurityAttributes */
286              OPEN_EXISTING,           /* CreationDisposition */
287              dwflags,                 /* Flags and attributes */
288              NULL);                   /* TemplateFile */
289
290    }
291
292       bfd->mode = BF_WRITE;
293
294    } else {                           /* Read */
295       if (bfd->use_backup_api) {
296          dwaccess = GENERIC_READ|READ_CONTROL|ACCESS_SYSTEM_SECURITY;
297          dwflags = FILE_FLAG_BACKUP_SEMANTICS;
298          dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
299       } else {
300          dwaccess = GENERIC_READ;
301          dwflags = 0;
302          dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE;
303       }
304
305       // unicode or ansii open for open existing read
306    if (p_CreateFileW && p_MultiByteToWideChar) {   
307       bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
308              dwaccess,                /* Requested access */
309              dwshare,                 /* Share modes */
310              NULL,                    /* SecurityAttributes */
311              OPEN_EXISTING,           /* CreationDisposition */
312              dwflags,                 /* Flags and attributes */
313              NULL);                   /* TemplateFile */
314    }
315    else {
316       bfd->fh = p_CreateFileA(win32_fname,
317              dwaccess,                /* Requested access */
318              dwshare,                 /* Share modes */
319              NULL,                    /* SecurityAttributes */
320              OPEN_EXISTING,           /* CreationDisposition */
321              dwflags,                 /* Flags and attributes */
322              NULL);                   /* TemplateFile */
323    }
324
325       bfd->mode = BF_READ;
326    }
327
328    if (bfd->fh == INVALID_HANDLE_VALUE) {
329       bfd->lerror = GetLastError();
330       bfd->berrno = b_errno_win32;
331       errno = b_errno_win32;
332       bfd->mode = BF_CLOSED;
333    }
334    bfd->errmsg = NULL;
335    bfd->lpContext = NULL;
336    free_pool_memory(win32_fname_wchar);
337    free_pool_memory(win32_fname);
338    return bfd->mode == BF_CLOSED ? -1 : 1;
339 }
340
341 /*
342  * Returns  0 on success
343  *         -1 on error
344  */
345 int bclose(BFILE *bfd)
346 {
347    int stat = 0;
348
349    if (bfd->errmsg) {
350       free_pool_memory(bfd->errmsg);
351       bfd->errmsg = NULL;
352    }
353    if (bfd->mode == BF_CLOSED) {
354       return 0;
355    }
356    if (bfd->use_backup_api && bfd->mode == BF_READ) {
357       BYTE buf[10];
358       if (!bfd->lpContext && !p_BackupRead(bfd->fh,
359               buf,                    /* buffer */
360               (DWORD)0,               /* bytes to read */
361               &bfd->rw_bytes,         /* bytes read */
362               1,                      /* Abort */
363               1,                      /* ProcessSecurity */
364               &bfd->lpContext)) {     /* Read context */
365          errno = b_errno_win32;
366          stat = -1;
367       }
368    } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
369       BYTE buf[10];
370       if (!bfd->lpContext && !p_BackupWrite(bfd->fh,
371               buf,                    /* buffer */
372               (DWORD)0,               /* bytes to read */
373               &bfd->rw_bytes,         /* bytes written */
374               1,                      /* Abort */
375               1,                      /* ProcessSecurity */
376               &bfd->lpContext)) {     /* Write context */
377          errno = b_errno_win32;
378          stat = -1;
379       }
380    }
381    if (!CloseHandle(bfd->fh)) {
382       stat = -1;
383       errno = b_errno_win32;
384    }
385    bfd->mode = BF_CLOSED;
386    bfd->lpContext = NULL;
387    return stat;
388 }
389
390 /* Returns: bytes read on success
391  *           0         on EOF
392  *          -1         on error
393  */
394 ssize_t bread(BFILE *bfd, void *buf, size_t count)
395 {
396    bfd->rw_bytes = 0;
397
398    if (bfd->use_backup_api) {
399       if (!p_BackupRead(bfd->fh,
400            (BYTE *)buf,
401            count,
402            &bfd->rw_bytes,
403            0,                           /* no Abort */
404            1,                           /* Process Security */
405            &bfd->lpContext)) {          /* Context */
406          bfd->lerror = GetLastError();
407          bfd->berrno = b_errno_win32;
408          errno = b_errno_win32;
409          return -1;
410       }
411    } else {
412       if (!ReadFile(bfd->fh,
413            buf,
414            count,
415            &bfd->rw_bytes,
416            NULL)) {
417          bfd->lerror = GetLastError();
418          bfd->berrno = b_errno_win32;
419          errno = b_errno_win32;
420          return -1;
421       }
422    }
423
424    return (ssize_t)bfd->rw_bytes;
425 }
426
427 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
428 {
429    bfd->rw_bytes = 0;
430
431    if (bfd->use_backup_api) {
432       if (!p_BackupWrite(bfd->fh,
433            (BYTE *)buf,
434            count,
435            &bfd->rw_bytes,
436            0,                           /* No abort */
437            1,                           /* Process Security */
438            &bfd->lpContext)) {          /* Context */
439          bfd->lerror = GetLastError();
440          bfd->berrno = b_errno_win32;
441          errno = b_errno_win32;
442          return -1;
443       }
444    } else {
445       if (!WriteFile(bfd->fh,
446            buf,
447            count,
448            &bfd->rw_bytes,
449            NULL)) {
450          bfd->lerror = GetLastError();
451          bfd->berrno = b_errno_win32;
452          errno = b_errno_win32;
453          return -1;
454       }
455    }
456    return (ssize_t)bfd->rw_bytes;
457 }
458
459 bool is_bopen(BFILE *bfd)
460 {
461    return bfd->mode != BF_CLOSED;
462 }
463
464 off_t blseek(BFILE *bfd, off_t offset, int whence)
465 {
466    /* ****FIXME**** this must be implemented if we want to read Win32 Archives */
467    return -1;
468 }
469
470 #else  /* Unix systems */
471
472 /* ===============================================================
473  *
474  *            U N I X
475  *
476  * ===============================================================
477  */
478 void binit(BFILE *bfd)
479 {
480    memset(bfd, 0, sizeof(BFILE));
481    bfd->fid = -1;
482 }
483
484 bool have_win32_api()
485 {
486    return false;                       /* no can do */
487 }
488
489 /*
490  * Enables using the Backup API (win32_data).
491  *   Returns true  if function worked
492  *   Returns false if failed (i.e. do not have Backup API on this machine)
493  */
494 bool set_win32_backup(BFILE *bfd)
495 {
496    return false;                       /* no can do */
497 }
498
499
500 bool set_portable_backup(BFILE *bfd)
501 {
502    return true;                        /* no problem */
503 }
504
505 /*
506  * Return true  if we are writing in portable format
507  * return false if not
508  */
509 bool is_portable_backup(BFILE *bfd)
510 {
511    return true;                       /* portable by definition */
512 }
513
514 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
515 {
516 #ifdef HAVE_PYTHON
517    if (bfd->prog && strcmp(prog, bfd->prog) == 0) {
518       return true;                    /* already setup */
519    }
520
521    if (python_set_prog(jcr, prog)) {
522       Dmsg1(000, "Set prog=%s\n", prog);
523       bfd->prog = prog;
524       bfd->jcr = jcr;
525       return true;
526    }
527 #endif
528    Dmsg0(000, "No prog set\n");
529    bfd->prog = NULL;
530    return false;
531
532 }
533
534
535 bool is_restore_stream_supported(int stream)
536 {
537    /* No Win32 backup on this machine */
538    switch (stream) {
539 #ifndef HAVE_LIBZ
540    case STREAM_GZIP_DATA:
541    case STREAM_SPARSE_GZIP_DATA:
542 #endif
543    case STREAM_WIN32_DATA:
544    case STREAM_WIN32_GZIP_DATA:
545 #ifndef HAVE_DARWIN_OS
546    case STREAM_MACOS_FORK_DATA:
547    case STREAM_HFSPLUS_ATTRIBUTES:
548 #endif
549       return false;
550
551    /* Known streams */
552 #ifdef HAVE_LIBZ
553    case STREAM_GZIP_DATA:
554    case STREAM_SPARSE_GZIP_DATA:
555 #endif
556    case STREAM_UNIX_ATTRIBUTES:
557    case STREAM_FILE_DATA:
558    case STREAM_MD5_SIGNATURE:
559    case STREAM_UNIX_ATTRIBUTES_EX:
560    case STREAM_SPARSE_DATA:
561    case STREAM_PROGRAM_NAMES:
562    case STREAM_PROGRAM_DATA:
563    case STREAM_SHA1_SIGNATURE:
564 #ifdef HAVE_DARWIN_OS
565    case STREAM_MACOS_FORK_DATA:
566    case STREAM_HFSPLUS_ATTRIBUTES:
567 #endif
568    case 0:                            /* compatibility with old tapes */
569       return true;
570
571    }
572    return 0;
573 }
574
575 /* Old file reader code */
576 #ifdef xxx
577    if (bfd->prog) {
578       POOLMEM *ecmd = get_pool_memory(PM_FNAME);
579       ecmd = edit_job_codes(bfd->jcr, ecmd, bfd->prog, fname);
580       const char *pmode;
581       if (flags & O_RDONLY) {
582          pmode = "r";
583       } else {
584          pmode = "w";
585       }
586       bfd->bpipe = open_bpipe(ecmd, 0, pmode);
587       if (bfd->bpipe == NULL) {
588          bfd->berrno = errno;
589          bfd->fid = -1;
590          free_pool_memory(ecmd);
591          return -1;
592       }
593       free_pool_memory(ecmd);
594       if (flags & O_RDONLY) {
595          bfd->fid = fileno(bfd->bpipe->rfd);
596       } else {
597          bfd->fid = fileno(bfd->bpipe->wfd);
598       }
599       errno = 0;
600       return bfd->fid;
601    }
602 #endif
603
604
605 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
606 {
607    /* Open reader/writer program */
608    if (bfd->prog) {
609       Dmsg1(000, "Open file %d\n", bfd->fid);
610       return python_open(bfd, fname, flags, mode);
611    }
612
613    /* Normal file open */
614    bfd->fid = open(fname, flags, mode);
615    bfd->berrno = errno;
616    Dmsg1(400, "Open file %d\n", bfd->fid);
617    errno = bfd->berrno;
618    return bfd->fid;
619 }
620
621 #ifdef HAVE_DARWIN_OS
622 /* Open the resource fork of a file. */
623 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
624 {
625    POOLMEM *rsrc_fname;
626
627    rsrc_fname = get_pool_memory(PM_FNAME);
628    pm_strcpy(rsrc_fname, fname);
629    pm_strcat(rsrc_fname, _PATH_RSRCFORKSPEC);
630    bopen(bfd, rsrc_fname, flags, mode);
631    free_pool_memory(rsrc_fname);
632    return bfd->fid;
633 }
634 #endif
635
636
637 int bclose(BFILE *bfd)
638 {
639    int stat;
640
641    Dmsg1(400, "Close file %d\n", bfd->fid);
642
643    /* Close reader/writer program */
644    if (bfd->prog) {
645       return python_close(bfd);
646    }
647
648    if (bfd->fid == -1) {
649       return 0;
650    }
651
652    /* Close normal file */
653    stat = close(bfd->fid);
654    bfd->berrno = errno;
655    bfd->fid = -1;
656    return stat;
657 }
658
659 ssize_t bread(BFILE *bfd, void *buf, size_t count)
660 {
661    ssize_t stat;
662
663    if (bfd->prog) {
664       return python_read(bfd, buf, count);
665    }
666    stat = read(bfd->fid, buf, count);
667    bfd->berrno = errno;
668    return stat;
669 }
670
671 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
672 {
673    ssize_t stat;
674
675    if (bfd->prog) {
676       return python_write(bfd, buf, count);
677    }
678    stat = write(bfd->fid, buf, count);
679    bfd->berrno = errno;
680    return stat;
681 }
682
683 bool is_bopen(BFILE *bfd)
684 {
685    return bfd->fid >= 0;
686 }
687
688 off_t blseek(BFILE *bfd, off_t offset, int whence)
689 {
690     off_t pos;
691     pos = lseek(bfd->fid, offset, whence);
692     bfd->berrno = errno;
693     return pos;
694 }
695
696 #endif