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) 2003-2004 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,
35 #include <sys/paths.h>
38 /* ===============================================================
40 * U N I X AND W I N D O W S
42 * ===============================================================
45 int is_win32_stream(int stream)
48 case STREAM_WIN32_DATA:
49 case STREAM_WIN32_GZIP_DATA:
55 const char *stream_to_ascii(int stream)
60 case STREAM_GZIP_DATA:
62 case STREAM_SPARSE_GZIP_DATA:
63 return "GZIP sparse data";
64 case STREAM_WIN32_DATA:
66 case STREAM_WIN32_GZIP_DATA:
67 return "Win32 GZIP data";
68 case STREAM_UNIX_ATTRIBUTES:
69 return "File attributes";
70 case STREAM_FILE_DATA:
72 case STREAM_MD5_SIGNATURE:
73 return "MD5 signature";
74 case STREAM_UNIX_ATTRIBUTES_EX:
75 return "Extended attributes";
76 case STREAM_SPARSE_DATA:
78 case STREAM_PROGRAM_NAMES:
79 return "Program names";
80 case STREAM_PROGRAM_DATA:
81 return "Program data";
82 case STREAM_SHA1_SIGNATURE:
83 return "SHA1 signature";
84 case STREAM_MACOS_FORK_DATA:
85 return "HFS+ resource fork";
86 case STREAM_HFSPLUS_ATTRIBUTES:
87 return "HFS+ Finder Info";
89 sprintf(buf, "%d", stream);
90 return (const char *)buf;
96 /* ===============================================================
100 * ===============================================================
103 #if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
105 void unix_name_to_win32(POOLMEM **win32_name, char *name);
106 extern "C" HANDLE get_osfhandle(int fd);
110 void binit(BFILE *bfd)
112 memset(bfd, 0, sizeof(BFILE));
114 bfd->mode = BF_CLOSED;
115 bfd->use_backup_api = have_win32_api();
119 * Enables using the Backup API (win32_data).
120 * Returns 1 if function worked
121 * Returns 0 if failed (i.e. do not have Backup API on this machine)
123 int set_win32_backup(BFILE *bfd)
125 /* We enable if possible here */
126 bfd->use_backup_api = have_win32_api();
127 return bfd->use_backup_api;
131 int set_portable_backup(BFILE *bfd)
133 bfd->use_backup_api = 0;
137 void set_prog(BFILE *bfd, char *prog, JCR *jcr)
144 * Return 1 if we are NOT using Win32 BackupWrite()
147 int is_portable_backup(BFILE *bfd)
149 return !bfd->use_backup_api;
154 return p_BackupRead && p_BackupWrite;
160 * Return 1 if we support the stream
161 * 0 if we do not support the stream
163 int is_stream_supported(int stream)
165 /* No Win32 backup on this machine */
168 case STREAM_GZIP_DATA:
169 case STREAM_SPARSE_GZIP_DATA:
172 case STREAM_WIN32_DATA:
173 case STREAM_WIN32_GZIP_DATA:
174 return have_win32_api();
178 case STREAM_GZIP_DATA:
179 case STREAM_SPARSE_GZIP_DATA:
181 case STREAM_UNIX_ATTRIBUTES:
182 case STREAM_FILE_DATA:
183 case STREAM_MD5_SIGNATURE:
184 case STREAM_UNIX_ATTRIBUTES_EX:
185 case STREAM_SPARSE_DATA:
186 case STREAM_PROGRAM_NAMES:
187 case STREAM_PROGRAM_DATA:
188 case STREAM_SHA1_SIGNATURE:
189 #ifdef HAVE_DARWIN_OS
190 case STREAM_MACOS_FORK_DATA:
191 case STREAM_HFSPLUS_ATTRIBUTES:
193 case 0: /* compatibility with old tapes */
199 HANDLE bget_handle(BFILE *bfd)
204 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
206 POOLMEM *win32_fname;
207 DWORD dwaccess, dwflags, dwshare;
209 /* Convert to Windows path format */
210 win32_fname = get_pool_memory(PM_FNAME);
211 unix_name_to_win32(&win32_fname, (char *)fname);
213 if (flags & O_CREAT) { /* Create */
214 if (bfd->use_backup_api) {
215 dwaccess = GENERIC_WRITE|FILE_ALL_ACCESS|WRITE_OWNER|WRITE_DAC|ACCESS_SYSTEM_SECURITY;
216 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
218 dwaccess = GENERIC_WRITE;
221 bfd->fh = CreateFile(win32_fname,
222 dwaccess, /* Requested access */
224 NULL, /* SecurityAttributes */
225 CREATE_ALWAYS, /* CreationDisposition */
226 dwflags, /* Flags and attributes */
227 NULL); /* TemplateFile */
228 bfd->mode = BF_WRITE;
230 } else if (flags & O_WRONLY) { /* Open existing for write */
231 if (bfd->use_backup_api) {
232 dwaccess = GENERIC_WRITE|WRITE_OWNER|WRITE_DAC;
233 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
235 dwaccess = GENERIC_WRITE;
238 bfd->fh = CreateFile(win32_fname,
239 dwaccess, /* Requested access */
241 NULL, /* SecurityAttributes */
242 OPEN_EXISTING, /* CreationDisposition */
243 dwflags, /* Flags and attributes */
244 NULL); /* TemplateFile */
245 bfd->mode = BF_WRITE;
248 if (bfd->use_backup_api) {
249 dwaccess = GENERIC_READ|READ_CONTROL|ACCESS_SYSTEM_SECURITY;
250 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
251 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
253 dwaccess = GENERIC_READ;
255 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE;
257 bfd->fh = CreateFile(win32_fname,
258 dwaccess, /* Requested access */
259 dwshare, /* Share modes */
260 NULL, /* SecurityAttributes */
261 OPEN_EXISTING, /* CreationDisposition */
262 dwflags, /* Flags and attributes */
263 NULL); /* TemplateFile */
267 if (bfd->fh == INVALID_HANDLE_VALUE) {
268 bfd->lerror = GetLastError();
269 bfd->berrno = b_errno_win32;
270 errno = b_errno_win32;
271 bfd->mode = BF_CLOSED;
274 bfd->lpContext = NULL;
275 free_pool_memory(win32_fname);
276 return bfd->mode == BF_CLOSED ? -1 : 1;
280 * Returns 0 on success
283 int bclose(BFILE *bfd)
288 free_pool_memory(bfd->errmsg);
291 if (bfd->mode == BF_CLOSED) {
294 if (bfd->use_backup_api && bfd->mode == BF_READ) {
296 if (!bfd->lpContext && !p_BackupRead(bfd->fh,
298 (DWORD)0, /* bytes to read */
299 &bfd->rw_bytes, /* bytes read */
301 1, /* ProcessSecurity */
302 &bfd->lpContext)) { /* Read context */
303 errno = b_errno_win32;
306 } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
308 if (!bfd->lpContext && !p_BackupWrite(bfd->fh,
310 (DWORD)0, /* bytes to read */
311 &bfd->rw_bytes, /* bytes written */
313 1, /* ProcessSecurity */
314 &bfd->lpContext)) { /* Write context */
315 errno = b_errno_win32;
319 if (!CloseHandle(bfd->fh)) {
321 errno = b_errno_win32;
323 bfd->mode = BF_CLOSED;
324 bfd->lpContext = NULL;
328 /* Returns: bytes read on success
332 ssize_t bread(BFILE *bfd, void *buf, size_t count)
336 if (bfd->use_backup_api) {
337 if (!p_BackupRead(bfd->fh,
342 1, /* Process Security */
343 &bfd->lpContext)) { /* Context */
344 bfd->lerror = GetLastError();
345 bfd->berrno = b_errno_win32;
346 errno = b_errno_win32;
350 if (!ReadFile(bfd->fh,
355 bfd->lerror = GetLastError();
356 bfd->berrno = b_errno_win32;
357 errno = b_errno_win32;
362 return (ssize_t)bfd->rw_bytes;
365 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
369 if (bfd->use_backup_api) {
370 if (!p_BackupWrite(bfd->fh,
375 1, /* Process Security */
376 &bfd->lpContext)) { /* Context */
377 bfd->lerror = GetLastError();
378 bfd->berrno = b_errno_win32;
379 errno = b_errno_win32;
383 if (!WriteFile(bfd->fh,
388 bfd->lerror = GetLastError();
389 bfd->berrno = b_errno_win32;
390 errno = b_errno_win32;
394 return (ssize_t)bfd->rw_bytes;
397 int is_bopen(BFILE *bfd)
399 return bfd->mode != BF_CLOSED;
402 off_t blseek(BFILE *bfd, off_t offset, int whence)
404 /* ****FIXME**** this must be implemented if we want to read Win32 Archives */
408 #else /* Unix systems */
410 /* ===============================================================
414 * ===============================================================
416 void binit(BFILE *bfd)
418 memset(bfd, 0, sizeof(BFILE));
424 return 0; /* no can do */
428 * Enables using the Backup API (win32_data).
429 * Returns 1 if function worked
430 * Returns 0 if failed (i.e. do not have Backup API on this machine)
432 int set_win32_backup(BFILE *bfd)
434 return 0; /* no can do */
438 int set_portable_backup(BFILE *bfd)
440 return 1; /* no problem */
444 * Return 1 if we are writing in portable format
447 int is_portable_backup(BFILE *bfd)
449 return 1; /* portable by definition */
452 void set_prog(BFILE *bfd, char *prog, JCR *jcr)
459 int is_stream_supported(int stream)
461 /* No Win32 backup on this machine */
464 case STREAM_GZIP_DATA:
465 case STREAM_SPARSE_GZIP_DATA:
467 case STREAM_WIN32_DATA:
468 case STREAM_WIN32_GZIP_DATA:
473 case STREAM_GZIP_DATA:
474 case STREAM_SPARSE_GZIP_DATA:
476 case STREAM_UNIX_ATTRIBUTES:
477 case STREAM_FILE_DATA:
478 case STREAM_MD5_SIGNATURE:
479 case STREAM_UNIX_ATTRIBUTES_EX:
480 case STREAM_SPARSE_DATA:
481 case STREAM_PROGRAM_NAMES:
482 case STREAM_PROGRAM_DATA:
483 case STREAM_SHA1_SIGNATURE:
484 #ifdef HAVE_DARWIN_OS
485 case STREAM_MACOS_FORK_DATA:
486 case STREAM_HFSPLUS_ATTRIBUTES:
488 case 0: /* compatibility with old tapes */
495 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
497 /* Open reader/writer program */
499 POOLMEM *ecmd = get_pool_memory(PM_FNAME);
500 ecmd = edit_job_codes(bfd->jcr, ecmd, bfd->prog, fname);
502 if (flags & O_RDONLY) {
507 bfd->bpipe = open_bpipe(ecmd, 0, pmode);
508 if (bfd->bpipe == NULL) {
511 free_pool_memory(ecmd);
514 free_pool_memory(ecmd);
515 if (flags & O_RDONLY) {
516 bfd->fid = fileno(bfd->bpipe->rfd);
518 bfd->fid = fileno(bfd->bpipe->wfd);
524 /* Normal file open */
525 bfd->fid = open(fname, flags, mode);
527 Dmsg1(400, "Open file %d\n", bfd->fid);
532 #ifdef HAVE_DARWIN_OS
533 /* Open the resource fork of a file. */
534 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
539 fname_len = strlen(fname);
540 rsrc_fname = get_pool_memory(PM_FNAME);
541 bstrncpy(rsrc_fname, fname, fname_len + 1);
542 bstrncpy(rsrc_fname + fname_len, _PATH_RSRCFORKSPEC,
543 strlen(_PATH_RSRCFORKSPEC) + 1);
544 bopen(bfd, rsrc_fname, flags, mode);
545 free_pool_memory(rsrc_fname);
550 int bclose(BFILE *bfd)
553 Dmsg1(400, "Close file %d\n", bfd->fid);
554 if (bfd->fid == -1) {
557 /* Close reader/writer program */
558 if (bfd->prog && bfd->bpipe) {
559 stat = close_bpipe(bfd->bpipe);
566 /* Close normal file */
567 stat = close(bfd->fid);
573 ssize_t bread(BFILE *bfd, void *buf, size_t count)
576 stat = read(bfd->fid, buf, count);
581 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
584 stat = write(bfd->fid, buf, count);
589 int is_bopen(BFILE *bfd)
591 return bfd->fid >= 0;
594 off_t blseek(BFILE *bfd, off_t offset, int whence)
597 pos = lseek(bfd->fid, offset, whence);
603 char *xberror(BFILE *bfd)
605 return strerror(bfd->berrno);