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