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