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