]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/findlib/bfile.c
- Applied a patch from Peter Eriksson that removes a dynamic stack
[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 }
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;
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 #ifdef HAVE_WIN32
221           dwaccess = GENERIC_WRITE|/*FILE_ALL_ACCESS|*/WRITE_OWNER|WRITE_DAC/*|ACCESS_SYSTEM_SECURITY*/;
222 #else
223           dwaccess = GENERIC_WRITE|FILE_ALL_ACCESS|WRITE_OWNER|WRITE_DAC|ACCESS_SYSTEM_SECURITY;
224 #endif
225          dwflags = FILE_FLAG_BACKUP_SEMANTICS;
226       } else {
227          dwaccess = GENERIC_WRITE;
228          dwflags = 0;
229       }
230       bfd->fh = CreateFile(win32_fname,
231              dwaccess,                /* Requested access */
232              0,                       /* Shared mode */
233              NULL,                    /* SecurityAttributes */
234              OPEN_EXISTING,           /* CreationDisposition */
235              dwflags,                 /* Flags and attributes */
236              NULL);                   /* TemplateFile */
237       bfd->mode = BF_WRITE;
238
239    } else {                           /* Read */
240       if (bfd->use_backup_api) {
241          dwaccess = GENERIC_READ|READ_CONTROL|ACCESS_SYSTEM_SECURITY;
242          dwflags = FILE_FLAG_BACKUP_SEMANTICS;
243       } else {
244          dwaccess = GENERIC_READ;
245          dwflags = 0;
246       }
247       bfd->fh = CreateFile(win32_fname,
248              dwaccess,                /* Requested access */
249              FILE_SHARE_READ,         /* Shared mode */
250              NULL,                    /* SecurityAttributes */
251              OPEN_EXISTING,           /* CreationDisposition */
252              dwflags,                 /* Flags and attributes */
253              NULL);                   /* TemplateFile */
254       bfd->mode = BF_READ;
255    }
256
257    if (bfd->fh == INVALID_HANDLE_VALUE) {
258       bfd->lerror = GetLastError();
259       bfd->berrno = b_errno_win32;
260       errno = b_errno_win32;
261       bfd->mode = BF_CLOSED;
262    }
263    bfd->errmsg = NULL;
264    bfd->lpContext = NULL;
265    free_pool_memory(win32_fname);
266    return bfd->mode == BF_CLOSED ? -1 : 1;
267 }
268
269 /* 
270  * Returns  0 on success
271  *         -1 on error
272  */
273 int bclose(BFILE *bfd)
274
275    int stat = 0;
276
277    if (bfd->errmsg) {
278       free_pool_memory(bfd->errmsg);
279       bfd->errmsg = NULL;
280    }
281    if (bfd->mode == BF_CLOSED) {
282       return 0;
283    }
284    if (bfd->use_backup_api && bfd->mode == BF_READ) {
285       BYTE buf[10];
286       if (!bfd->lpContext && !p_BackupRead(bfd->fh,   
287               buf,                    /* buffer */
288               (DWORD)0,               /* bytes to read */
289               &bfd->rw_bytes,         /* bytes read */
290               1,                      /* Abort */
291               1,                      /* ProcessSecurity */
292               &bfd->lpContext)) {     /* Read context */
293          errno = b_errno_win32;
294          stat = -1;
295       } 
296    } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
297       BYTE buf[10];
298       if (!bfd->lpContext && !p_BackupWrite(bfd->fh,   
299               buf,                    /* buffer */
300               (DWORD)0,               /* bytes to read */
301               &bfd->rw_bytes,         /* bytes written */
302               1,                      /* Abort */
303               1,                      /* ProcessSecurity */
304               &bfd->lpContext)) {     /* Write context */
305          errno = b_errno_win32;
306          stat = -1;
307       } 
308    }
309    if (!CloseHandle(bfd->fh)) {
310       stat = -1;
311       errno = b_errno_win32;
312    }
313    bfd->mode = BF_CLOSED;
314    bfd->lpContext = NULL;
315    return stat;
316 }
317
318 /*
319  * Generate error message 
320  */
321 /* DO NOT USE */
322 char *xberror(BFILE *bfd)
323 {
324    LPTSTR msg;
325
326    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
327                  FORMAT_MESSAGE_FROM_SYSTEM,
328                  NULL,
329                  bfd->lerror,
330                  0,
331                  (LPTSTR)&msg,
332                  0,
333                  NULL);
334    strip_trailing_junk(msg);
335    if (!bfd->errmsg) {
336       bfd->errmsg = get_pool_memory(PM_FNAME);
337    }
338    pm_strcpy(&bfd->errmsg, msg);
339    LocalFree(msg);
340    return bfd->errmsg;
341 }
342
343 /* Returns: bytes read on success
344  *           0         on EOF
345  *          -1         on error
346  */
347 ssize_t bread(BFILE *bfd, void *buf, size_t count)
348 {
349    bfd->rw_bytes = 0;
350
351    if (bfd->use_backup_api) {
352       if (!p_BackupRead(bfd->fh,
353            (BYTE *)buf,
354            count,
355            &bfd->rw_bytes,
356            0,                           /* no Abort */
357            1,                           /* Process Security */
358            &bfd->lpContext)) {          /* Context */
359          bfd->lerror = GetLastError();
360          bfd->berrno = b_errno_win32;
361          errno = b_errno_win32;
362          return -1;
363       }
364    } else {
365       if (!ReadFile(bfd->fh,
366            buf,
367            count,
368            &bfd->rw_bytes,
369            NULL)) {
370          bfd->lerror = GetLastError();
371          bfd->berrno = b_errno_win32;
372          errno = b_errno_win32;
373          return -1;
374       }
375    }
376
377    return (ssize_t)bfd->rw_bytes;
378 }
379
380 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
381 {
382    bfd->rw_bytes = 0;
383
384    if (bfd->use_backup_api) {
385       if (!p_BackupWrite(bfd->fh,
386            (BYTE *)buf,
387            count,
388            &bfd->rw_bytes,
389            0,                           /* No abort */
390            1,                           /* Process Security */
391            &bfd->lpContext)) {          /* Context */
392          bfd->lerror = GetLastError();
393          bfd->berrno = b_errno_win32;
394          errno = b_errno_win32;
395          return -1;
396       }
397    } else {
398       if (!WriteFile(bfd->fh,
399            buf,
400            count,
401            &bfd->rw_bytes,
402            NULL)) {
403          bfd->lerror = GetLastError();
404          bfd->berrno = b_errno_win32;
405          errno = b_errno_win32;
406          return -1;
407       }
408    }
409    return (ssize_t)bfd->rw_bytes;
410 }
411
412 int is_bopen(BFILE *bfd)
413 {
414    return bfd->mode != BF_CLOSED;
415 }
416
417 off_t blseek(BFILE *bfd, off_t offset, int whence)
418 {
419    /* ****FIXME**** this must be implemented if we want to read Win32 Archives */
420    return -1;
421 }
422
423 #else  /* Unix systems */
424
425 /* ===============================================================
426  * 
427  *            U N I X
428  *
429  * ===============================================================
430  */
431 void binit(BFILE *bfd)
432 {
433    memset(bfd, 0, sizeof(BFILE));
434    bfd->fid = -1;
435 }
436
437 int have_win32_api()
438
439    return 0;                          /* no can do */
440
441
442 /*
443  * Enables using the Backup API (win32_data).
444  *   Returns 1 if function worked
445  *   Returns 0 if failed (i.e. do not have Backup API on this machine)
446  */
447 int set_win32_backup(BFILE *bfd) 
448 {
449    return 0;                          /* no can do */
450 }
451
452
453 int set_portable_backup(BFILE *bfd)
454 {
455    return 1;                          /* no problem */
456 }
457
458 /*
459  * Return 1 if we are writing in portable format
460  * return 0 if not
461  */
462 int is_portable_backup(BFILE *bfd) 
463 {
464    return 1;                          /* portable by definition */
465 }
466
467 void set_prog(BFILE *bfd, char *prog, JCR *jcr)
468 {
469    bfd->prog = prog;
470    bfd->jcr = jcr;
471 }
472
473
474 int is_stream_supported(int stream)
475 {
476    /* No Win32 backup on this machine */
477    switch (stream) {
478 #ifndef HAVE_LIBZ
479    case STREAM_GZIP_DATA:
480    case STREAM_SPARSE_GZIP_DATA:
481 #endif
482    case STREAM_WIN32_DATA:
483    case STREAM_WIN32_GZIP_DATA:
484       return 0;
485
486    /* Known streams */
487 #ifdef HAVE_LIBZ
488    case STREAM_GZIP_DATA:
489    case STREAM_SPARSE_GZIP_DATA:
490 #endif
491    case STREAM_UNIX_ATTRIBUTES:
492    case STREAM_FILE_DATA:
493    case STREAM_MD5_SIGNATURE:
494    case STREAM_UNIX_ATTRIBUTES_EX:
495    case STREAM_SPARSE_DATA:
496    case STREAM_PROGRAM_NAMES:
497    case STREAM_PROGRAM_DATA:
498    case STREAM_SHA1_SIGNATURE:
499    case 0:                            /* compatibility with old tapes */
500       return 1;
501
502    }
503    return 0;
504 }
505
506 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
507 {
508    /* Open reader/writer program */
509    if (bfd->prog) {
510       POOLMEM *ecmd = get_pool_memory(PM_FNAME);
511       ecmd = edit_job_codes(bfd->jcr, ecmd, bfd->prog, fname);
512       const char *pmode;
513       if (flags & O_RDONLY) {
514          pmode = "r";
515       } else {
516          pmode = "w";
517       }
518       bfd->bpipe = open_bpipe(ecmd, 0, pmode);
519       if (bfd->bpipe == NULL) {
520          bfd->berrno = errno;
521          bfd->fid = -1;
522          free_pool_memory(ecmd);
523          return -1;
524       }
525       free_pool_memory(ecmd);
526       if (flags & O_RDONLY) {
527          bfd->fid = fileno(bfd->bpipe->rfd);
528       } else {
529          bfd->fid = fileno(bfd->bpipe->wfd);
530       }
531       errno = 0;
532       return bfd->fid;
533    }
534
535    /* Normal file open */
536    bfd->fid = open(fname, flags, mode);
537    bfd->berrno = errno;
538    Dmsg1(400, "Open file %d\n", bfd->fid);
539    errno = bfd->berrno;
540    return bfd->fid;
541 }
542
543 int bclose(BFILE *bfd)
544
545    int stat;  
546    Dmsg1(400, "Close file %d\n", bfd->fid);
547    if (bfd->fid == -1) {
548       return 0;
549    }
550    /* Close reader/writer program */
551    if (bfd->prog && bfd->bpipe) {
552       stat = close_bpipe(bfd->bpipe);
553       bfd->berrno = errno;
554       bfd->fid = -1;
555       bfd->bpipe = NULL;
556       return stat;
557    }
558    
559    /* Close normal file */
560    stat = close(bfd->fid);
561    bfd->berrno = errno;
562    bfd->fid = -1;
563    return stat;
564 }
565
566 ssize_t bread(BFILE *bfd, void *buf, size_t count)
567 {
568    ssize_t stat;
569    stat = read(bfd->fid, buf, count);
570    bfd->berrno = errno;
571    return stat;
572 }
573
574 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
575 {
576    ssize_t stat;
577    stat = write(bfd->fid, buf, count);
578    bfd->berrno = errno;
579    return stat;
580 }
581
582 int is_bopen(BFILE *bfd)
583 {
584    return bfd->fid >= 0;
585 }
586
587 off_t blseek(BFILE *bfd, off_t offset, int whence)
588 {
589     off_t pos;
590     pos = lseek(bfd->fid, offset, whence);
591     bfd->berrno = errno;
592     return pos;
593 }
594
595 /* DO NOT USE */
596 char *xberror(BFILE *bfd)
597 {
598     return strerror(bfd->berrno);
599 }
600
601 #endif