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