]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/findlib/bfile.c
First cut berrno unified Unix/Win32 errno handling
[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       bfd->mode = BF_CLOSED;
259    }
260    bfd->errmsg = NULL;
261    bfd->lpContext = NULL;
262    free_pool_memory(win32_fname);
263    return bfd->mode == BF_CLOSED ? -1 : 1;
264 }
265
266 /* 
267  * Returns  0 on success
268  *         -1 on error
269  */
270 int bclose(BFILE *bfd)
271
272    int stat = 0;
273
274    if (bfd->errmsg) {
275       free_pool_memory(bfd->errmsg);
276       bfd->errmsg = NULL;
277    }
278    if (bfd->mode == BF_CLOSED) {
279       return 0;
280    }
281    if (bfd->use_backup_api && bfd->mode == BF_READ) {
282       BYTE buf[10];
283       if (!bfd->lpContext && !p_BackupRead(bfd->fh,   
284               buf,                    /* buffer */
285               (DWORD)0,               /* bytes to read */
286               &bfd->rw_bytes,         /* bytes read */
287               1,                      /* Abort */
288               1,                      /* ProcessSecurity */
289               &bfd->lpContext)) {     /* Read context */
290          stat = -1;
291       } 
292    } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
293       BYTE buf[10];
294       if (!bfd->lpContext && !p_BackupWrite(bfd->fh,   
295               buf,                    /* buffer */
296               (DWORD)0,               /* bytes to read */
297               &bfd->rw_bytes,         /* bytes written */
298               1,                      /* Abort */
299               1,                      /* ProcessSecurity */
300               &bfd->lpContext)) {     /* Write context */
301          stat = -1;
302       } 
303    }
304    if (!CloseHandle(bfd->fh)) {
305       stat = -1;
306    }
307    bfd->mode = BF_CLOSED;
308    bfd->lpContext = NULL;
309    return stat;
310 }
311
312 /*
313  * Generate error message 
314  */
315 char *berror(BFILE *bfd)
316 {
317    LPTSTR msg;
318
319    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
320                  FORMAT_MESSAGE_FROM_SYSTEM,
321                  NULL,
322                  bfd->lerror,
323                  0,
324                  (LPTSTR)&msg,
325                  0,
326                  NULL);
327    strip_trailing_junk(msg);
328    if (!bfd->errmsg) {
329       bfd->errmsg = get_pool_memory(PM_FNAME);
330    }
331    pm_strcpy(&bfd->errmsg, msg);
332    LocalFree(msg);
333    return bfd->errmsg;
334 }
335
336 /* Returns: bytes read on success
337  *           0         on EOF
338  *          -1         on error
339  */
340 ssize_t bread(BFILE *bfd, void *buf, size_t count)
341 {
342    bfd->rw_bytes = 0;
343
344    if (bfd->use_backup_api) {
345       if (!p_BackupRead(bfd->fh,
346            (BYTE *)buf,
347            count,
348            &bfd->rw_bytes,
349            0,                           /* no Abort */
350            1,                           /* Process Security */
351            &bfd->lpContext)) {          /* Context */
352          bfd->lerror = GetLastError();
353          bfd->berrno = b_errno_win32;
354          return -1;
355       }
356    } else {
357       if (!ReadFile(bfd->fh,
358            buf,
359            count,
360            &bfd->rw_bytes,
361            NULL)) {
362          bfd->lerror = GetLastError();
363          bfd->berrno = b_errno_win32;
364          return -1;
365       }
366    }
367
368    return (ssize_t)bfd->rw_bytes;
369 }
370
371 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
372 {
373    bfd->rw_bytes = 0;
374
375    if (bfd->use_backup_api) {
376       if (!p_BackupWrite(bfd->fh,
377            (BYTE *)buf,
378            count,
379            &bfd->rw_bytes,
380            0,                           /* No abort */
381            1,                           /* Process Security */
382            &bfd->lpContext)) {          /* Context */
383          bfd->lerror = GetLastError();
384          bfd->berrno = b_errno_win32;
385          return -1;
386       }
387    } else {
388       if (!WriteFile(bfd->fh,
389            buf,
390            count,
391            &bfd->rw_bytes,
392            NULL)) {
393          bfd->lerror = GetLastError();
394          bfd->berrno = b_errno_win32;
395          return -1;
396       }
397    }
398    return (ssize_t)bfd->rw_bytes;
399 }
400
401 int is_bopen(BFILE *bfd)
402 {
403    return bfd->mode != BF_CLOSED;
404 }
405
406 off_t blseek(BFILE *bfd, off_t offset, int whence)
407 {
408    /* ****FIXME**** this is needed if we want to read Win32 Archives */
409    return -1;
410 }
411
412 #else  /* Unix systems */
413
414 /* ===============================================================
415  * 
416  *            U N I X
417  *
418  * ===============================================================
419  */
420 void binit(BFILE *bfd)
421 {
422    memset(bfd, 0, sizeof(BFILE));
423    bfd->fid = -1;
424 }
425
426 int have_win32_api()
427
428    return 0;                          /* no can do */
429
430
431 /*
432  * Enables using the Backup API (win32_data).
433  *   Returns 1 if function worked
434  *   Returns 0 if failed (i.e. do not have Backup API on this machine)
435  */
436 int set_win32_backup(BFILE *bfd) 
437 {
438    return 0;                          /* no can do */
439 }
440
441
442 int set_portable_backup(BFILE *bfd)
443 {
444    return 1;                          /* no problem */
445 }
446
447 /*
448  * Return 1 if we are writing in portable format
449  * return 0 if not
450  */
451 int is_portable_backup(BFILE *bfd) 
452 {
453    return 1;                          /* portable by definition */
454 }
455
456 int is_stream_supported(int stream)
457 {
458    /* No Win32 backup on this machine */
459    switch (stream) {
460 #ifndef HAVE_LIBZ
461    case STREAM_GZIP_DATA:
462    case STREAM_SPARSE_GZIP_DATA:
463 #endif
464    case STREAM_WIN32_DATA:
465    case STREAM_WIN32_GZIP_DATA:
466       return 0;
467
468    /* Known streams */
469 #ifdef HAVE_LIBZ
470    case STREAM_GZIP_DATA:
471    case STREAM_SPARSE_GZIP_DATA:
472 #endif
473    case STREAM_UNIX_ATTRIBUTES:
474    case STREAM_FILE_DATA:
475    case STREAM_MD5_SIGNATURE:
476    case STREAM_UNIX_ATTRIBUTES_EX:
477    case STREAM_SPARSE_DATA:
478    case STREAM_PROGRAM_NAMES:
479    case STREAM_PROGRAM_DATA:
480    case STREAM_SHA1_SIGNATURE:
481    case 0:                            /* compatibility with old tapes */
482       return 1;
483
484    }
485    return 0;
486 }
487
488 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
489 {
490    bfd->fid = open(fname, flags, mode);
491    bfd->berrno = errno;
492    Dmsg1(400, "Open file %d\n", bfd->fid);
493    return bfd->fid;
494 }
495
496 int bclose(BFILE *bfd)
497
498    int stat;  
499    Dmsg1(400, "Close file %d\n", bfd->fid);
500    if (bfd->fid == -1) {
501       return 0;
502    }
503    stat = close(bfd->fid);
504    bfd->berrno = errno;
505    bfd->fid = -1;
506
507    return stat;
508 }
509
510 ssize_t bread(BFILE *bfd, void *buf, size_t count)
511 {
512    ssize_t stat;
513    stat = read(bfd->fid, buf, count);
514    bfd->berrno = errno;
515    return stat;
516 }
517
518 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
519 {
520    ssize_t stat;
521    stat = write(bfd->fid, buf, count);
522    bfd->berrno = errno;
523    return stat;
524 }
525
526 int is_bopen(BFILE *bfd)
527 {
528    return bfd->fid >= 0;
529 }
530
531 off_t blseek(BFILE *bfd, off_t offset, int whence)
532 {
533     off_t pos;
534     pos = lseek(bfd->fid, offset, whence);
535     bfd->berrno = errno;
536     return pos;
537 }
538
539 char *berror(BFILE *bfd)
540 {
541     return strerror(bfd->berrno);
542 }
543
544 #endif