]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/findlib/bfile.c
- Use different share mode when opening files on WinMe/98/95 since
[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) 2003-2004 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 }
109
110 /*
111  * Enables using the Backup API (win32_data).
112  *   Returns 1 if function worked
113  *   Returns 0 if failed (i.e. do not have Backup API on this machine)
114  */
115 int set_win32_backup(BFILE *bfd) 
116 {
117    /* We enable if possible here */
118    bfd->use_backup_api = have_win32_api();
119    return bfd->use_backup_api;
120 }
121
122
123 int set_portable_backup(BFILE *bfd)
124 {
125    bfd->use_backup_api = 0;
126    return 1;
127 }
128
129 void set_prog(BFILE *bfd, char *prog, JCR *jcr)
130 {
131    bfd->prog = prog;
132    bfd->jcr = jcr;
133 }
134
135 /*
136  * Return 1 if we are NOT using Win32 BackupWrite() 
137  * return 0 if are
138  */
139 int is_portable_backup(BFILE *bfd) 
140 {
141    return !bfd->use_backup_api;
142 }
143
144 int have_win32_api()
145 {
146    return p_BackupRead && p_BackupWrite;
147 }
148
149
150
151 /*
152  * Return 1 if we support the stream
153  *        0 if we do not support the stream
154  */
155 int is_stream_supported(int stream)
156 {
157    /* No Win32 backup on this machine */
158    switch (stream) {
159 #ifndef HAVE_LIBZ
160    case STREAM_GZIP_DATA:
161    case STREAM_SPARSE_GZIP_DATA:
162       return 0;
163 #endif
164    case STREAM_WIN32_DATA:
165    case STREAM_WIN32_GZIP_DATA:
166       return have_win32_api();
167
168    /* Known streams */
169 #ifdef HAVE_LIBZ
170    case STREAM_GZIP_DATA:
171    case STREAM_SPARSE_GZIP_DATA:
172 #endif
173    case STREAM_UNIX_ATTRIBUTES:
174    case STREAM_FILE_DATA:
175    case STREAM_MD5_SIGNATURE:
176    case STREAM_UNIX_ATTRIBUTES_EX:
177    case STREAM_SPARSE_DATA:
178    case STREAM_PROGRAM_NAMES:
179    case STREAM_PROGRAM_DATA:
180    case STREAM_SHA1_SIGNATURE:
181    case 0:                            /* compatibility with old tapes */
182       return 1;
183    }
184    return 0;
185 }
186
187 HANDLE bget_handle(BFILE *bfd)
188 {
189    return bfd->fh;
190 }
191
192 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
193 {
194    POOLMEM *win32_fname;
195    DWORD dwaccess, dwflags, dwshare;
196
197    /* Convert to Windows path format */
198    win32_fname = get_pool_memory(PM_FNAME);
199    unix_name_to_win32(&win32_fname, (char *)fname);
200
201    if (flags & O_CREAT) {             /* Create */
202       if (bfd->use_backup_api) {
203          dwaccess = GENERIC_WRITE|FILE_ALL_ACCESS|WRITE_OWNER|WRITE_DAC|ACCESS_SYSTEM_SECURITY;                
204          dwflags = FILE_FLAG_BACKUP_SEMANTICS;
205       } else {
206          dwaccess = GENERIC_WRITE;
207          dwflags = 0;
208       }
209       bfd->fh = CreateFile(win32_fname,
210              dwaccess,                /* Requested access */
211              0,                       /* Shared mode */
212              NULL,                    /* SecurityAttributes */
213              CREATE_ALWAYS,           /* CreationDisposition */
214              dwflags,                 /* Flags and attributes */
215              NULL);                   /* TemplateFile */
216       bfd->mode = BF_WRITE;
217
218    } else if (flags & O_WRONLY) {     /* Open existing for write */
219       if (bfd->use_backup_api) {
220          dwaccess = GENERIC_WRITE|WRITE_OWNER|WRITE_DAC;
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          dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
240       } else {
241          dwaccess = GENERIC_READ;
242          dwflags = 0;
243          dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE;
244       }
245       bfd->fh = CreateFile(win32_fname,
246              dwaccess,                /* Requested access */
247              dwshare,                 /* Share modes */
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       errno = b_errno_win32;
259       bfd->mode = BF_CLOSED;
260    }
261    bfd->errmsg = NULL;
262    bfd->lpContext = NULL;
263    free_pool_memory(win32_fname);
264    return bfd->mode == BF_CLOSED ? -1 : 1;
265 }
266
267 /* 
268  * Returns  0 on success
269  *         -1 on error
270  */
271 int bclose(BFILE *bfd)
272
273    int stat = 0;
274
275    if (bfd->errmsg) {
276       free_pool_memory(bfd->errmsg);
277       bfd->errmsg = NULL;
278    }
279    if (bfd->mode == BF_CLOSED) {
280       return 0;
281    }
282    if (bfd->use_backup_api && bfd->mode == BF_READ) {
283       BYTE buf[10];
284       if (!bfd->lpContext && !p_BackupRead(bfd->fh,   
285               buf,                    /* buffer */
286               (DWORD)0,               /* bytes to read */
287               &bfd->rw_bytes,         /* bytes read */
288               1,                      /* Abort */
289               1,                      /* ProcessSecurity */
290               &bfd->lpContext)) {     /* Read context */
291          errno = b_errno_win32;
292          stat = -1;
293       } 
294    } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
295       BYTE buf[10];
296       if (!bfd->lpContext && !p_BackupWrite(bfd->fh,   
297               buf,                    /* buffer */
298               (DWORD)0,               /* bytes to read */
299               &bfd->rw_bytes,         /* bytes written */
300               1,                      /* Abort */
301               1,                      /* ProcessSecurity */
302               &bfd->lpContext)) {     /* Write context */
303          errno = b_errno_win32;
304          stat = -1;
305       } 
306    }
307    if (!CloseHandle(bfd->fh)) {
308       stat = -1;
309       errno = b_errno_win32;
310    }
311    bfd->mode = BF_CLOSED;
312    bfd->lpContext = NULL;
313    return stat;
314 }
315
316 /*
317  * Generate error message 
318  */
319 /* DO NOT USE */
320 char *xberror(BFILE *bfd)
321 {
322    LPTSTR msg;
323
324    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
325                  FORMAT_MESSAGE_FROM_SYSTEM,
326                  NULL,
327                  bfd->lerror,
328                  0,
329                  (LPTSTR)&msg,
330                  0,
331                  NULL);
332    strip_trailing_junk(msg);
333    if (!bfd->errmsg) {
334       bfd->errmsg = get_pool_memory(PM_FNAME);
335    }
336    pm_strcpy(bfd->errmsg, msg);
337    LocalFree(msg);
338    return bfd->errmsg;
339 }
340
341 /* Returns: bytes read on success
342  *           0         on EOF
343  *          -1         on error
344  */
345 ssize_t bread(BFILE *bfd, void *buf, size_t count)
346 {
347    bfd->rw_bytes = 0;
348
349    if (bfd->use_backup_api) {
350       if (!p_BackupRead(bfd->fh,
351            (BYTE *)buf,
352            count,
353            &bfd->rw_bytes,
354            0,                           /* no Abort */
355            1,                           /* Process Security */
356            &bfd->lpContext)) {          /* Context */
357          bfd->lerror = GetLastError();
358          bfd->berrno = b_errno_win32;
359          errno = b_errno_win32;
360          return -1;
361       }
362    } else {
363       if (!ReadFile(bfd->fh,
364            buf,
365            count,
366            &bfd->rw_bytes,
367            NULL)) {
368          bfd->lerror = GetLastError();
369          bfd->berrno = b_errno_win32;
370          errno = b_errno_win32;
371          return -1;
372       }
373    }
374
375    return (ssize_t)bfd->rw_bytes;
376 }
377
378 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
379 {
380    bfd->rw_bytes = 0;
381
382    if (bfd->use_backup_api) {
383       if (!p_BackupWrite(bfd->fh,
384            (BYTE *)buf,
385            count,
386            &bfd->rw_bytes,
387            0,                           /* No abort */
388            1,                           /* Process Security */
389            &bfd->lpContext)) {          /* Context */
390          bfd->lerror = GetLastError();
391          bfd->berrno = b_errno_win32;
392          errno = b_errno_win32;
393          return -1;
394       }
395    } else {
396       if (!WriteFile(bfd->fh,
397            buf,
398            count,
399            &bfd->rw_bytes,
400            NULL)) {
401          bfd->lerror = GetLastError();
402          bfd->berrno = b_errno_win32;
403          errno = b_errno_win32;
404          return -1;
405       }
406    }
407    return (ssize_t)bfd->rw_bytes;
408 }
409
410 int is_bopen(BFILE *bfd)
411 {
412    return bfd->mode != BF_CLOSED;
413 }
414
415 off_t blseek(BFILE *bfd, off_t offset, int whence)
416 {
417    /* ****FIXME**** this must be implemented if we want to read Win32 Archives */
418    return -1;
419 }
420
421 #else  /* Unix systems */
422
423 /* ===============================================================
424  * 
425  *            U N I X
426  *
427  * ===============================================================
428  */
429 void binit(BFILE *bfd)
430 {
431    memset(bfd, 0, sizeof(BFILE));
432    bfd->fid = -1;
433 }
434
435 int have_win32_api()
436
437    return 0;                          /* no can do */
438
439
440 /*
441  * Enables using the Backup API (win32_data).
442  *   Returns 1 if function worked
443  *   Returns 0 if failed (i.e. do not have Backup API on this machine)
444  */
445 int set_win32_backup(BFILE *bfd) 
446 {
447    return 0;                          /* no can do */
448 }
449
450
451 int set_portable_backup(BFILE *bfd)
452 {
453    return 1;                          /* no problem */
454 }
455
456 /*
457  * Return 1 if we are writing in portable format
458  * return 0 if not
459  */
460 int is_portable_backup(BFILE *bfd) 
461 {
462    return 1;                          /* portable by definition */
463 }
464
465 void set_prog(BFILE *bfd, char *prog, JCR *jcr)
466 {
467    bfd->prog = prog;
468    bfd->jcr = jcr;
469 }
470
471
472 int is_stream_supported(int stream)
473 {
474    /* No Win32 backup on this machine */
475    switch (stream) {
476 #ifndef HAVE_LIBZ
477    case STREAM_GZIP_DATA:
478    case STREAM_SPARSE_GZIP_DATA:
479 #endif
480    case STREAM_WIN32_DATA:
481    case STREAM_WIN32_GZIP_DATA:
482       return 0;
483
484    /* Known streams */
485 #ifdef HAVE_LIBZ
486    case STREAM_GZIP_DATA:
487    case STREAM_SPARSE_GZIP_DATA:
488 #endif
489    case STREAM_UNIX_ATTRIBUTES:
490    case STREAM_FILE_DATA:
491    case STREAM_MD5_SIGNATURE:
492    case STREAM_UNIX_ATTRIBUTES_EX:
493    case STREAM_SPARSE_DATA:
494    case STREAM_PROGRAM_NAMES:
495    case STREAM_PROGRAM_DATA:
496    case STREAM_SHA1_SIGNATURE:
497    case 0:                            /* compatibility with old tapes */
498       return 1;
499
500    }
501    return 0;
502 }
503
504 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
505 {
506    /* Open reader/writer program */
507    if (bfd->prog) {
508       POOLMEM *ecmd = get_pool_memory(PM_FNAME);
509       ecmd = edit_job_codes(bfd->jcr, ecmd, bfd->prog, fname);
510       const char *pmode;
511       if (flags & O_RDONLY) {
512          pmode = "r";
513       } else {
514          pmode = "w";
515       }
516       bfd->bpipe = open_bpipe(ecmd, 0, pmode);
517       if (bfd->bpipe == NULL) {
518          bfd->berrno = errno;
519          bfd->fid = -1;
520          free_pool_memory(ecmd);
521          return -1;
522       }
523       free_pool_memory(ecmd);
524       if (flags & O_RDONLY) {
525          bfd->fid = fileno(bfd->bpipe->rfd);
526       } else {
527          bfd->fid = fileno(bfd->bpipe->wfd);
528       }
529       errno = 0;
530       return bfd->fid;
531    }
532
533    /* Normal file open */
534    bfd->fid = open(fname, flags, mode);
535    bfd->berrno = errno;
536    Dmsg1(400, "Open file %d\n", bfd->fid);
537    errno = bfd->berrno;
538    return bfd->fid;
539 }
540
541 int bclose(BFILE *bfd)
542
543    int stat;  
544    Dmsg1(400, "Close file %d\n", bfd->fid);
545    if (bfd->fid == -1) {
546       return 0;
547    }
548    /* Close reader/writer program */
549    if (bfd->prog && bfd->bpipe) {
550       stat = close_bpipe(bfd->bpipe);
551       bfd->berrno = errno;
552       bfd->fid = -1;
553       bfd->bpipe = NULL;
554       return stat;
555    }
556    
557    /* Close normal file */
558    stat = close(bfd->fid);
559    bfd->berrno = errno;
560    bfd->fid = -1;
561    return stat;
562 }
563
564 ssize_t bread(BFILE *bfd, void *buf, size_t count)
565 {
566    ssize_t stat;
567    stat = read(bfd->fid, buf, count);
568    bfd->berrno = errno;
569    return stat;
570 }
571
572 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
573 {
574    ssize_t stat;
575    stat = write(bfd->fid, buf, count);
576    bfd->berrno = errno;
577    return stat;
578 }
579
580 int is_bopen(BFILE *bfd)
581 {
582    return bfd->fid >= 0;
583 }
584
585 off_t blseek(BFILE *bfd, off_t offset, int whence)
586 {
587     off_t pos;
588     pos = lseek(bfd->fid, offset, whence);
589     bfd->berrno = errno;
590     return pos;
591 }
592
593 /* DO NOT USE */
594 char *xberror(BFILE *bfd)
595 {
596     return strerror(bfd->berrno);
597 }
598
599 #endif