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