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.
6 * Kern Sibbald, April MMIII
12 Copyright (C) 2000-2003 Kern Sibbald and John Walker
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.
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.
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,
34 /* ===============================================================
36 * U N I X AND W I N D O W S
38 * ===============================================================
40 char *stream_to_ascii(int stream)
45 case STREAM_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:
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:
59 case STREAM_MD5_SIGNATURE:
60 return "MD5 signature";
61 case STREAM_UNIX_ATTRIBUTES_EX:
62 return "Extended attributes";
63 case STREAM_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";
72 sprintf(buf, "%d", stream);
79 /* ===============================================================
83 * ===============================================================
88 void unix_name_to_win32(POOLMEM **win32_name, char *name);
89 extern "C" HANDLE get_osfhandle(int fd);
92 void binit(BFILE *bfd)
95 bfd->mode = BF_CLOSED;
96 bfd->use_backup_api = p_BackupRead && p_BackupWrite;
98 bfd->lpContext = NULL;
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)
107 int set_win32_backup(BFILE *bfd, int enable)
110 bfd->use_backup_api = 0;
113 /* We enable if possible here */
114 bfd->use_backup_api = p_BackupRead && p_BackupWrite;
115 return bfd->use_backup_api;
119 * Return 1 if we can do Win32 backup
122 int is_win32_backup(void)
124 return p_BackupRead && p_BackupWrite;
128 * Return 1 if we support the stream
129 * 0 if we do not support the stream
131 int is_stream_supported(int stream)
133 /* No Win32 backup on this machine */
136 case STREAM_GZIP_DATA:
137 case STREAM_SPARSE_GZIP_DATA:
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 */
147 case STREAM_GZIP_DATA:
148 case STREAM_SPARSE_GZIP_DATA:
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 */
164 HANDLE bget_handle(BFILE *bfd)
169 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
171 POOLMEM *win32_fname;
172 DWORD dwaccess, dwflags;
174 /* Convert to Windows path format */
175 win32_fname = get_pool_memory(PM_FNAME);
176 unix_name_to_win32(&win32_fname, (char *)fname);
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;
183 dwaccess = GENERIC_WRITE;
186 bfd->fh = CreateFile(win32_fname,
187 dwaccess, /* Requested access */
189 NULL, /* SecurityAttributes */
190 CREATE_ALWAYS, /* CreationDisposition */
191 dwflags, /* Flags and attributes */
192 NULL); /* TemplateFile */
193 bfd->mode = BF_WRITE;
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;
200 dwaccess = GENERIC_WRITE;
203 bfd->fh = CreateFile(win32_fname,
204 dwaccess, /* Requested access */
206 NULL, /* SecurityAttributes */
207 OPEN_EXISTING, /* CreationDisposition */
208 dwflags, /* Flags and attributes */
209 NULL); /* TemplateFile */
210 bfd->mode = BF_WRITE;
213 if (bfd->use_backup_api) {
214 dwaccess = GENERIC_READ|READ_CONTROL|ACCESS_SYSTEM_SECURITY;
215 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
217 dwaccess = GENERIC_READ;
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 */
230 if (bfd->fh == INVALID_HANDLE_VALUE) {
231 bfd->lerror = GetLastError();
232 bfd->mode = BF_CLOSED;
235 bfd->lpContext = NULL;
236 return bfd->mode == BF_CLOSED ? -1 : 1;
240 * Returns 0 on success
243 int bclose(BFILE *bfd)
248 free_pool_memory(bfd->errmsg);
251 if (bfd->mode == BF_CLOSED) {
254 if (bfd->use_backup_api && bfd->mode == BF_READ) {
256 if (!bfd->lpContext && !p_BackupRead(bfd->fh,
258 (DWORD)0, /* bytes to read */
259 &bfd->rw_bytes, /* bytes read */
261 1, /* ProcessSecurity */
262 &bfd->lpContext)) { /* Read context */
265 } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
267 if (!bfd->lpContext && !p_BackupWrite(bfd->fh,
269 (DWORD)0, /* bytes to read */
270 &bfd->rw_bytes, /* bytes written */
272 1, /* ProcessSecurity */
273 &bfd->lpContext)) { /* Write context */
277 if (!CloseHandle(bfd->fh)) {
280 bfd->mode = BF_CLOSED;
281 bfd->lpContext = NULL;
286 * Generate error message
288 char *berror(BFILE *bfd)
292 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
293 FORMAT_MESSAGE_FROM_SYSTEM,
300 strip_trailing_junk(msg);
302 bfd->errmsg = get_pool_memory(PM_FNAME);
304 pm_strcpy(&bfd->errmsg, msg);
309 /* Returns: bytes read on success
313 ssize_t bread(BFILE *bfd, void *buf, size_t count)
317 if (bfd->use_backup_api) {
318 if (!p_BackupRead(bfd->fh,
323 1, /* Process Security */
324 &bfd->lpContext)) { /* Context */
325 bfd->lerror = GetLastError();
329 if (!ReadFile(bfd->fh,
334 bfd->lerror = GetLastError();
339 return (ssize_t)bfd->rw_bytes;
342 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
346 if (bfd->use_backup_api) {
347 if (!p_BackupWrite(bfd->fh,
352 1, /* Process Security */
353 &bfd->lpContext)) { /* Context */
354 bfd->lerror = GetLastError();
358 if (!WriteFile(bfd->fh,
363 bfd->lerror = GetLastError();
367 return (ssize_t)bfd->rw_bytes;
370 int is_bopen(BFILE *bfd)
372 return bfd->mode != BF_CLOSED;
375 off_t blseek(BFILE *bfd, off_t offset, int whence)
377 /* ****FIXME**** this is needed if we want to read Win32 Archives */
381 #else /* Unix systems */
383 /* ===============================================================
387 * ===============================================================
389 void binit(BFILE *bfd)
394 int set_win32_backup(BFILE *bfd, int enable)
399 int is_win32_backup(void)
404 int is_stream_supported(int stream)
406 /* No Win32 backup on this machine */
409 case STREAM_GZIP_DATA:
410 case STREAM_SPARSE_GZIP_DATA:
412 case STREAM_WIN32_ATTRIBUTES:
413 case STREAM_WIN32_DATA:
414 case STREAM_WIN32_GZIP_DATA:
419 case STREAM_GZIP_DATA:
420 case STREAM_SPARSE_GZIP_DATA:
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 */
437 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
439 bfd->fid = open(fname, flags, mode);
444 int bclose(BFILE *bfd)
446 int stat = close(bfd->fid);
452 ssize_t bread(BFILE *bfd, void *buf, size_t count)
455 stat = read(bfd->fid, buf, count);
460 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
463 stat = write(bfd->fid, buf, count);
468 int is_bopen(BFILE *bfd)
470 return bfd->fid >= 0;
473 off_t blseek(BFILE *bfd, off_t offset, int whence)
476 pos = lseek(bfd->fid, offset, whence);
481 char *berror(BFILE *bfd)
483 return strerror(bfd->berrno);