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