]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/findlib/bfile.c
Fix new FileSet exclusion
[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) 2000-2003 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    bfd->errmsg = NULL;
109    bfd->lpContext = NULL;
110    bfd->lerror = 0;
111    bfd->berrno = 0;
112 }
113
114 /*
115  * Enables using the Backup API (win32_data).
116  *   Returns 1 if function worked
117  *   Returns 0 if failed (i.e. do not have Backup API on this machine)
118  */
119 int set_win32_backup(BFILE *bfd) 
120 {
121    /* We enable if possible here */
122    bfd->use_backup_api = have_win32_api();
123    return bfd->use_backup_api;
124 }
125
126
127 int set_portable_backup(BFILE *bfd)
128 {
129    bfd->use_backup_api = 0;
130    return 1;
131 }
132
133 /*
134  * Return 1 if we are NOT using Win32 BackupWrite() 
135  * return 0 if are
136  */
137 int is_portable_backup(BFILE *bfd) 
138 {
139    return !bfd->use_backup_api;
140 }
141
142 int have_win32_api()
143 {
144    return p_BackupRead && p_BackupWrite;
145 }
146
147
148
149 /*
150  * Return 1 if we support the stream
151  *        0 if we do not support the stream
152  */
153 int is_stream_supported(int stream)
154 {
155    /* No Win32 backup on this machine */
156    switch (stream) {
157 #ifndef HAVE_LIBZ
158    case STREAM_GZIP_DATA:
159    case STREAM_SPARSE_GZIP_DATA:
160       return 0;
161 #endif
162    case STREAM_WIN32_DATA:
163    case STREAM_WIN32_GZIP_DATA:
164       return have_win32_api();
165
166    /* Known streams */
167 #ifdef HAVE_LIBZ
168    case STREAM_GZIP_DATA:
169    case STREAM_SPARSE_GZIP_DATA:
170 #endif
171    case STREAM_UNIX_ATTRIBUTES:
172    case STREAM_FILE_DATA:
173    case STREAM_MD5_SIGNATURE:
174    case STREAM_UNIX_ATTRIBUTES_EX:
175    case STREAM_SPARSE_DATA:
176    case STREAM_PROGRAM_NAMES:
177    case STREAM_PROGRAM_DATA:
178    case STREAM_SHA1_SIGNATURE:
179    case 0:                            /* compatibility with old tapes */
180       return 1;
181    }
182    return 0;
183 }
184
185 HANDLE bget_handle(BFILE *bfd)
186 {
187    return bfd->fh;
188 }
189
190 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
191 {
192    POOLMEM *win32_fname;
193    DWORD dwaccess, dwflags;
194
195    /* Convert to Windows path format */
196    win32_fname = get_pool_memory(PM_FNAME);
197    unix_name_to_win32(&win32_fname, (char *)fname);
198
199    if (flags & O_CREAT) {             /* Create */
200       if (bfd->use_backup_api) {
201          dwaccess = GENERIC_WRITE|FILE_ALL_ACCESS|WRITE_OWNER|WRITE_DAC|ACCESS_SYSTEM_SECURITY;                
202          dwflags = FILE_FLAG_BACKUP_SEMANTICS;
203       } else {
204          dwaccess = GENERIC_WRITE;
205          dwflags = 0;
206       }
207       bfd->fh = CreateFile(win32_fname,
208              dwaccess,                /* Requested access */
209              0,                       /* Shared mode */
210              NULL,                    /* SecurityAttributes */
211              CREATE_ALWAYS,           /* CreationDisposition */
212              dwflags,                 /* Flags and attributes */
213              NULL);                   /* TemplateFile */
214       bfd->mode = BF_WRITE;
215
216    } else if (flags & O_WRONLY) {     /* Open existing for write */
217       if (bfd->use_backup_api) {
218 #ifdef HAVE_WIN32
219           dwaccess = GENERIC_WRITE|/*FILE_ALL_ACCESS|*/WRITE_OWNER|WRITE_DAC/*|ACCESS_SYSTEM_SECURITY*/;
220 #else
221           dwaccess = GENERIC_WRITE|FILE_ALL_ACCESS|WRITE_OWNER|WRITE_DAC|ACCESS_SYSTEM_SECURITY;
222 #endif
223          dwflags = FILE_FLAG_BACKUP_SEMANTICS;
224       } else {
225          dwaccess = GENERIC_WRITE;
226          dwflags = 0;
227       }
228       bfd->fh = CreateFile(win32_fname,
229              dwaccess,                /* Requested access */
230              0,                       /* Shared mode */
231              NULL,                    /* SecurityAttributes */
232              OPEN_EXISTING,           /* CreationDisposition */
233              dwflags,                 /* Flags and attributes */
234              NULL);                   /* TemplateFile */
235       bfd->mode = BF_WRITE;
236
237    } else {                           /* Read */
238       if (bfd->use_backup_api) {
239          dwaccess = GENERIC_READ|READ_CONTROL|ACCESS_SYSTEM_SECURITY;
240          dwflags = FILE_FLAG_BACKUP_SEMANTICS;
241       } else {
242          dwaccess = GENERIC_READ;
243          dwflags = 0;
244       }
245       bfd->fh = CreateFile(win32_fname,
246              dwaccess,                /* Requested access */
247              FILE_SHARE_READ,         /* Shared mode */
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 /*
317  * Generate error message 
318  */
319 /* DO NOT USE */
320 char *xberror(BFILE *bfd)
321 {
322    LPTSTR msg;
323
324    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
325                  FORMAT_MESSAGE_FROM_SYSTEM,
326                  NULL,
327                  bfd->lerror,
328                  0,
329                  (LPTSTR)&msg,
330                  0,
331                  NULL);
332    strip_trailing_junk(msg);
333    if (!bfd->errmsg) {
334       bfd->errmsg = get_pool_memory(PM_FNAME);
335    }
336    pm_strcpy(&bfd->errmsg, msg);
337    LocalFree(msg);
338    return bfd->errmsg;
339 }
340
341 /* Returns: bytes read on success
342  *           0         on EOF
343  *          -1         on error
344  */
345 ssize_t bread(BFILE *bfd, void *buf, size_t count)
346 {
347    bfd->rw_bytes = 0;
348
349    if (bfd->use_backup_api) {
350       if (!p_BackupRead(bfd->fh,
351            (BYTE *)buf,
352            count,
353            &bfd->rw_bytes,
354            0,                           /* no Abort */
355            1,                           /* Process Security */
356            &bfd->lpContext)) {          /* Context */
357          bfd->lerror = GetLastError();
358          bfd->berrno = b_errno_win32;
359          errno = b_errno_win32;
360          return -1;
361       }
362    } else {
363       if (!ReadFile(bfd->fh,
364            buf,
365            count,
366            &bfd->rw_bytes,
367            NULL)) {
368          bfd->lerror = GetLastError();
369          bfd->berrno = b_errno_win32;
370          errno = b_errno_win32;
371          return -1;
372       }
373    }
374
375    return (ssize_t)bfd->rw_bytes;
376 }
377
378 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
379 {
380    bfd->rw_bytes = 0;
381
382    if (bfd->use_backup_api) {
383       if (!p_BackupWrite(bfd->fh,
384            (BYTE *)buf,
385            count,
386            &bfd->rw_bytes,
387            0,                           /* No abort */
388            1,                           /* Process Security */
389            &bfd->lpContext)) {          /* Context */
390          bfd->lerror = GetLastError();
391          bfd->berrno = b_errno_win32;
392          errno = b_errno_win32;
393          return -1;
394       }
395    } else {
396       if (!WriteFile(bfd->fh,
397            buf,
398            count,
399            &bfd->rw_bytes,
400            NULL)) {
401          bfd->lerror = GetLastError();
402          bfd->berrno = b_errno_win32;
403          errno = b_errno_win32;
404          return -1;
405       }
406    }
407    return (ssize_t)bfd->rw_bytes;
408 }
409
410 int is_bopen(BFILE *bfd)
411 {
412    return bfd->mode != BF_CLOSED;
413 }
414
415 off_t blseek(BFILE *bfd, off_t offset, int whence)
416 {
417    /* ****FIXME**** this must be implemented if we want to read Win32 Archives */
418    return -1;
419 }
420
421 #else  /* Unix systems */
422
423 /* ===============================================================
424  * 
425  *            U N I X
426  *
427  * ===============================================================
428  */
429 void binit(BFILE *bfd)
430 {
431    memset(bfd, 0, sizeof(BFILE));
432    bfd->fid = -1;
433 }
434
435 int have_win32_api()
436
437    return 0;                          /* no can do */
438
439
440 /*
441  * Enables using the Backup API (win32_data).
442  *   Returns 1 if function worked
443  *   Returns 0 if failed (i.e. do not have Backup API on this machine)
444  */
445 int set_win32_backup(BFILE *bfd) 
446 {
447    return 0;                          /* no can do */
448 }
449
450
451 int set_portable_backup(BFILE *bfd)
452 {
453    return 1;                          /* no problem */
454 }
455
456 /*
457  * Return 1 if we are writing in portable format
458  * return 0 if not
459  */
460 int is_portable_backup(BFILE *bfd) 
461 {
462    return 1;                          /* portable by definition */
463 }
464
465 int is_stream_supported(int stream)
466 {
467    /* No Win32 backup on this machine */
468    switch (stream) {
469 #ifndef HAVE_LIBZ
470    case STREAM_GZIP_DATA:
471    case STREAM_SPARSE_GZIP_DATA:
472 #endif
473    case STREAM_WIN32_DATA:
474    case STREAM_WIN32_GZIP_DATA:
475       return 0;
476
477    /* Known streams */
478 #ifdef HAVE_LIBZ
479    case STREAM_GZIP_DATA:
480    case STREAM_SPARSE_GZIP_DATA:
481 #endif
482    case STREAM_UNIX_ATTRIBUTES:
483    case STREAM_FILE_DATA:
484    case STREAM_MD5_SIGNATURE:
485    case STREAM_UNIX_ATTRIBUTES_EX:
486    case STREAM_SPARSE_DATA:
487    case STREAM_PROGRAM_NAMES:
488    case STREAM_PROGRAM_DATA:
489    case STREAM_SHA1_SIGNATURE:
490    case 0:                            /* compatibility with old tapes */
491       return 1;
492
493    }
494    return 0;
495 }
496
497 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
498 {
499    bfd->fid = open(fname, flags, mode);
500    bfd->berrno = errno;
501    Dmsg1(400, "Open file %d\n", bfd->fid);
502    errno = bfd->berrno;
503    return bfd->fid;
504 }
505
506 int bclose(BFILE *bfd)
507
508    int stat;  
509    Dmsg1(400, "Close file %d\n", bfd->fid);
510    if (bfd->fid == -1) {
511       return 0;
512    }
513    stat = close(bfd->fid);
514    bfd->berrno = errno;
515    bfd->fid = -1;
516
517    return stat;
518 }
519
520 ssize_t bread(BFILE *bfd, void *buf, size_t count)
521 {
522    ssize_t stat;
523    stat = read(bfd->fid, buf, count);
524    bfd->berrno = errno;
525    return stat;
526 }
527
528 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
529 {
530    ssize_t stat;
531    stat = write(bfd->fid, buf, count);
532    bfd->berrno = errno;
533    return stat;
534 }
535
536 int is_bopen(BFILE *bfd)
537 {
538    return bfd->fid >= 0;
539 }
540
541 off_t blseek(BFILE *bfd, off_t offset, int whence)
542 {
543     off_t pos;
544     pos = lseek(bfd->fid, offset, whence);
545     bfd->berrno = errno;
546     return pos;
547 }
548
549 /* DO NOT USE */
550 char *xberror(BFILE *bfd)
551 {
552     return strerror(bfd->berrno);
553 }
554
555 #endif