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 * ===============================================================
41 int is_win32_stream(int stream)
44 case STREAM_WIN32_DATA:
45 case STREAM_WIN32_GZIP_DATA:
51 const char *stream_to_ascii(int stream)
56 case STREAM_GZIP_DATA:
58 case STREAM_SPARSE_GZIP_DATA:
59 return "GZIP sparse data";
60 case STREAM_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:
68 case STREAM_MD5_SIGNATURE:
69 return "MD5 signature";
70 case STREAM_UNIX_ATTRIBUTES_EX:
71 return "Extended attributes";
72 case STREAM_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";
81 sprintf(buf, "%d", stream);
82 return (const char *)buf;
88 /* ===============================================================
92 * ===============================================================
95 #if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
97 void unix_name_to_win32(POOLMEM **win32_name, char *name);
98 extern "C" HANDLE get_osfhandle(int fd);
102 void binit(BFILE *bfd)
104 memset(bfd, 0, sizeof(BFILE));
106 bfd->mode = BF_CLOSED;
107 bfd->use_backup_api = have_win32_api();
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)
115 int set_win32_backup(BFILE *bfd)
117 /* We enable if possible here */
118 bfd->use_backup_api = have_win32_api();
119 return bfd->use_backup_api;
123 int set_portable_backup(BFILE *bfd)
125 bfd->use_backup_api = 0;
129 void set_prog(BFILE *bfd, char *prog, JCR *jcr)
136 * Return 1 if we are NOT using Win32 BackupWrite()
139 int is_portable_backup(BFILE *bfd)
141 return !bfd->use_backup_api;
146 return p_BackupRead && p_BackupWrite;
152 * Return 1 if we support the stream
153 * 0 if we do not support the stream
155 int is_stream_supported(int stream)
157 /* No Win32 backup on this machine */
160 case STREAM_GZIP_DATA:
161 case STREAM_SPARSE_GZIP_DATA:
164 case STREAM_WIN32_DATA:
165 case STREAM_WIN32_GZIP_DATA:
166 return have_win32_api();
170 case STREAM_GZIP_DATA:
171 case STREAM_SPARSE_GZIP_DATA:
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 */
187 HANDLE bget_handle(BFILE *bfd)
192 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
194 POOLMEM *win32_fname;
195 DWORD dwaccess, dwflags;
197 /* Convert to Windows path format */
198 win32_fname = get_pool_memory(PM_FNAME);
199 unix_name_to_win32(&win32_fname, (char *)fname);
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;
206 dwaccess = GENERIC_WRITE;
209 bfd->fh = CreateFile(win32_fname,
210 dwaccess, /* Requested access */
212 NULL, /* SecurityAttributes */
213 CREATE_ALWAYS, /* CreationDisposition */
214 dwflags, /* Flags and attributes */
215 NULL); /* TemplateFile */
216 bfd->mode = BF_WRITE;
218 } else if (flags & O_WRONLY) { /* Open existing for write */
219 if (bfd->use_backup_api) {
221 dwaccess = GENERIC_WRITE|/*FILE_ALL_ACCESS|*/WRITE_OWNER|WRITE_DAC/*|ACCESS_SYSTEM_SECURITY*/;
223 dwaccess = GENERIC_WRITE|FILE_ALL_ACCESS|WRITE_OWNER|WRITE_DAC|ACCESS_SYSTEM_SECURITY;
225 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
227 dwaccess = GENERIC_WRITE;
230 bfd->fh = CreateFile(win32_fname,
231 dwaccess, /* Requested access */
233 NULL, /* SecurityAttributes */
234 OPEN_EXISTING, /* CreationDisposition */
235 dwflags, /* Flags and attributes */
236 NULL); /* TemplateFile */
237 bfd->mode = BF_WRITE;
240 if (bfd->use_backup_api) {
241 dwaccess = GENERIC_READ|READ_CONTROL|ACCESS_SYSTEM_SECURITY;
242 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
244 dwaccess = GENERIC_READ;
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 */
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;
264 bfd->lpContext = NULL;
265 free_pool_memory(win32_fname);
266 return bfd->mode == BF_CLOSED ? -1 : 1;
270 * Returns 0 on success
273 int bclose(BFILE *bfd)
278 free_pool_memory(bfd->errmsg);
281 if (bfd->mode == BF_CLOSED) {
284 if (bfd->use_backup_api && bfd->mode == BF_READ) {
286 if (!bfd->lpContext && !p_BackupRead(bfd->fh,
288 (DWORD)0, /* bytes to read */
289 &bfd->rw_bytes, /* bytes read */
291 1, /* ProcessSecurity */
292 &bfd->lpContext)) { /* Read context */
293 errno = b_errno_win32;
296 } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
298 if (!bfd->lpContext && !p_BackupWrite(bfd->fh,
300 (DWORD)0, /* bytes to read */
301 &bfd->rw_bytes, /* bytes written */
303 1, /* ProcessSecurity */
304 &bfd->lpContext)) { /* Write context */
305 errno = b_errno_win32;
309 if (!CloseHandle(bfd->fh)) {
311 errno = b_errno_win32;
313 bfd->mode = BF_CLOSED;
314 bfd->lpContext = NULL;
319 * Generate error message
322 char *xberror(BFILE *bfd)
326 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
327 FORMAT_MESSAGE_FROM_SYSTEM,
334 strip_trailing_junk(msg);
336 bfd->errmsg = get_pool_memory(PM_FNAME);
338 pm_strcpy(&bfd->errmsg, msg);
343 /* Returns: bytes read on success
347 ssize_t bread(BFILE *bfd, void *buf, size_t count)
351 if (bfd->use_backup_api) {
352 if (!p_BackupRead(bfd->fh,
357 1, /* Process Security */
358 &bfd->lpContext)) { /* Context */
359 bfd->lerror = GetLastError();
360 bfd->berrno = b_errno_win32;
361 errno = b_errno_win32;
365 if (!ReadFile(bfd->fh,
370 bfd->lerror = GetLastError();
371 bfd->berrno = b_errno_win32;
372 errno = b_errno_win32;
377 return (ssize_t)bfd->rw_bytes;
380 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
384 if (bfd->use_backup_api) {
385 if (!p_BackupWrite(bfd->fh,
390 1, /* Process Security */
391 &bfd->lpContext)) { /* Context */
392 bfd->lerror = GetLastError();
393 bfd->berrno = b_errno_win32;
394 errno = b_errno_win32;
398 if (!WriteFile(bfd->fh,
403 bfd->lerror = GetLastError();
404 bfd->berrno = b_errno_win32;
405 errno = b_errno_win32;
409 return (ssize_t)bfd->rw_bytes;
412 int is_bopen(BFILE *bfd)
414 return bfd->mode != BF_CLOSED;
417 off_t blseek(BFILE *bfd, off_t offset, int whence)
419 /* ****FIXME**** this must be implemented if we want to read Win32 Archives */
423 #else /* Unix systems */
425 /* ===============================================================
429 * ===============================================================
431 void binit(BFILE *bfd)
433 memset(bfd, 0, sizeof(BFILE));
439 return 0; /* no can do */
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)
447 int set_win32_backup(BFILE *bfd)
449 return 0; /* no can do */
453 int set_portable_backup(BFILE *bfd)
455 return 1; /* no problem */
459 * Return 1 if we are writing in portable format
462 int is_portable_backup(BFILE *bfd)
464 return 1; /* portable by definition */
467 void set_prog(BFILE *bfd, char *prog, JCR *jcr)
474 int is_stream_supported(int stream)
476 /* No Win32 backup on this machine */
479 case STREAM_GZIP_DATA:
480 case STREAM_SPARSE_GZIP_DATA:
482 case STREAM_WIN32_DATA:
483 case STREAM_WIN32_GZIP_DATA:
488 case STREAM_GZIP_DATA:
489 case STREAM_SPARSE_GZIP_DATA:
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 */
506 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
508 /* Open reader/writer program */
510 POOLMEM *ecmd = get_pool_memory(PM_FNAME);
511 ecmd = edit_job_codes(bfd->jcr, ecmd, bfd->prog, fname);
513 if (flags & O_RDONLY) {
518 bfd->bpipe = open_bpipe(ecmd, 0, pmode);
519 if (bfd->bpipe == NULL) {
522 free_pool_memory(ecmd);
525 free_pool_memory(ecmd);
526 if (flags & O_RDONLY) {
527 bfd->fid = fileno(bfd->bpipe->rfd);
529 bfd->fid = fileno(bfd->bpipe->wfd);
535 /* Normal file open */
536 bfd->fid = open(fname, flags, mode);
538 Dmsg1(400, "Open file %d\n", bfd->fid);
543 int bclose(BFILE *bfd)
546 Dmsg1(400, "Close file %d\n", bfd->fid);
547 if (bfd->fid == -1) {
550 /* Close reader/writer program */
551 if (bfd->prog && bfd->bpipe) {
552 stat = close_bpipe(bfd->bpipe);
559 /* Close normal file */
560 stat = close(bfd->fid);
566 ssize_t bread(BFILE *bfd, void *buf, size_t count)
569 stat = read(bfd->fid, buf, count);
574 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
577 stat = write(bfd->fid, buf, count);
582 int is_bopen(BFILE *bfd)
584 return bfd->fid >= 0;
587 off_t blseek(BFILE *bfd, off_t offset, int whence)
590 pos = lseek(bfd->fid, offset, whence);
596 char *xberror(BFILE *bfd)
598 return strerror(bfd->berrno);