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-2005 Kern Sibbald
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 bool (*python_set_prog)(JCR *jcr, const char *prog) = NULL;
35 int (*python_open)(BFILE *bfd, const char *fname, int flags, mode_t mode) = NULL;
36 int (*python_close)(BFILE *bfd) = NULL;
37 ssize_t (*python_read)(BFILE *bfd, void *buf, size_t count) = NULL;
38 ssize_t (*python_write)(BFILE *bfd, void *buf, size_t count) = NULL;
41 #include <sys/paths.h>
44 /* ===============================================================
46 * U N I X AND W I N D O W S
48 * ===============================================================
51 bool is_win32_stream(int stream)
54 case STREAM_WIN32_DATA:
55 case STREAM_WIN32_GZIP_DATA:
61 const char *stream_to_ascii(int stream)
66 case STREAM_GZIP_DATA:
68 case STREAM_SPARSE_GZIP_DATA:
69 return "GZIP sparse data";
70 case STREAM_WIN32_DATA:
72 case STREAM_WIN32_GZIP_DATA:
73 return "Win32 GZIP data";
74 case STREAM_UNIX_ATTRIBUTES:
75 return "File attributes";
76 case STREAM_FILE_DATA:
78 case STREAM_MD5_SIGNATURE:
79 return "MD5 signature";
80 case STREAM_UNIX_ATTRIBUTES_EX:
81 return "Extended attributes";
82 case STREAM_SPARSE_DATA:
84 case STREAM_PROGRAM_NAMES:
85 return "Program names";
86 case STREAM_PROGRAM_DATA:
87 return "Program data";
88 case STREAM_SHA1_SIGNATURE:
89 return "SHA1 signature";
90 case STREAM_MACOS_FORK_DATA:
91 return "HFS+ resource fork";
92 case STREAM_HFSPLUS_ATTRIBUTES:
93 return "HFS+ Finder Info";
95 sprintf(buf, "%d", stream);
96 return (const char *)buf;
102 /* ===============================================================
106 * ===============================================================
109 #if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
111 void unix_name_to_win32(POOLMEM **win32_name, char *name);
112 extern "C" HANDLE get_osfhandle(int fd);
116 void binit(BFILE *bfd)
118 memset(bfd, 0, sizeof(BFILE));
120 bfd->mode = BF_CLOSED;
121 bfd->use_backup_api = have_win32_api();
125 * Enables using the Backup API (win32_data).
126 * Returns 1 if function worked
127 * Returns 0 if failed (i.e. do not have Backup API on this machine)
129 bool set_win32_backup(BFILE *bfd)
131 /* We enable if possible here */
132 bfd->use_backup_api = have_win32_api();
133 return bfd->use_backup_api;
137 bool set_portable_backup(BFILE *bfd)
139 bfd->use_backup_api = false;
143 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
151 * Return 1 if we are NOT using Win32 BackupWrite()
154 bool is_portable_backup(BFILE *bfd)
156 return !bfd->use_backup_api;
159 bool have_win32_api()
161 return p_BackupRead && p_BackupWrite;
167 * Return 1 if we support the stream
168 * 0 if we do not support the stream
170 bool is_stream_supported(int stream)
172 /* No Win32 backup on this machine */
175 case STREAM_GZIP_DATA:
176 case STREAM_SPARSE_GZIP_DATA:
179 case STREAM_WIN32_DATA:
180 case STREAM_WIN32_GZIP_DATA:
181 return have_win32_api();
183 case STREAM_MACOS_FORK_DATA:
184 case STREAM_HFSPLUS_ATTRIBUTES:
189 case STREAM_GZIP_DATA:
190 case STREAM_SPARSE_GZIP_DATA:
192 case STREAM_UNIX_ATTRIBUTES:
193 case STREAM_FILE_DATA:
194 case STREAM_MD5_SIGNATURE:
195 case STREAM_UNIX_ATTRIBUTES_EX:
196 case STREAM_SPARSE_DATA:
197 case STREAM_PROGRAM_NAMES:
198 case STREAM_PROGRAM_DATA:
199 case STREAM_SHA1_SIGNATURE:
200 case 0: /* compatibility with old tapes */
206 HANDLE bget_handle(BFILE *bfd)
211 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
213 POOLMEM *win32_fname;
214 DWORD dwaccess, dwflags, dwshare;
215 WCHAR win32_fname_wchar[MAX_PATH_UNICODE];
217 /* Convert to Windows path format */
218 win32_fname = get_pool_memory(PM_FNAME);
219 unix_name_to_win32(&win32_fname, (char *)fname);
221 if (!(p_CreateFileA || p_CreateFileW))
225 UTF8_2_wchar(win32_fname_wchar, win32_fname, MAX_PATH_UNICODE);
228 if (flags & O_CREAT) { /* Create */
229 if (bfd->use_backup_api) {
230 dwaccess = GENERIC_WRITE|FILE_ALL_ACCESS|WRITE_OWNER|WRITE_DAC|ACCESS_SYSTEM_SECURITY;
231 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
233 dwaccess = GENERIC_WRITE;
237 // unicode or ansii open for create write
239 bfd->fh = p_CreateFileW(win32_fname_wchar,
240 dwaccess, /* Requested access */
242 NULL, /* SecurityAttributes */
243 CREATE_ALWAYS, /* CreationDisposition */
244 dwflags, /* Flags and attributes */
245 NULL); /* TemplateFile */
248 bfd->fh = p_CreateFileA(win32_fname,
249 dwaccess, /* Requested access */
251 NULL, /* SecurityAttributes */
252 CREATE_ALWAYS, /* CreationDisposition */
253 dwflags, /* Flags and attributes */
254 NULL); /* TemplateFile */
258 bfd->mode = BF_WRITE;
260 } else if (flags & O_WRONLY) { /* Open existing for write */
261 if (bfd->use_backup_api) {
262 dwaccess = GENERIC_WRITE|WRITE_OWNER|WRITE_DAC;
263 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
265 dwaccess = GENERIC_WRITE;
269 // unicode or ansii open for open existing write
271 bfd->fh = p_CreateFileW(win32_fname_wchar,
272 dwaccess, /* Requested access */
274 NULL, /* SecurityAttributes */
275 OPEN_EXISTING, /* CreationDisposition */
276 dwflags, /* Flags and attributes */
277 NULL); /* TemplateFile */
280 bfd->fh = p_CreateFileA(win32_fname,
281 dwaccess, /* Requested access */
283 NULL, /* SecurityAttributes */
284 OPEN_EXISTING, /* CreationDisposition */
285 dwflags, /* Flags and attributes */
286 NULL); /* TemplateFile */
290 bfd->mode = BF_WRITE;
293 if (bfd->use_backup_api) {
294 dwaccess = GENERIC_READ|READ_CONTROL|ACCESS_SYSTEM_SECURITY;
295 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
296 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
298 dwaccess = GENERIC_READ;
300 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE;
303 // unicode or ansii open for open existing read
305 bfd->fh = p_CreateFileW(win32_fname_wchar,
306 dwaccess, /* Requested access */
307 dwshare, /* Share modes */
308 NULL, /* SecurityAttributes */
309 OPEN_EXISTING, /* CreationDisposition */
310 dwflags, /* Flags and attributes */
311 NULL); /* TemplateFile */
314 bfd->fh = p_CreateFileA(win32_fname,
315 dwaccess, /* Requested access */
316 dwshare, /* Share modes */
317 NULL, /* SecurityAttributes */
318 OPEN_EXISTING, /* CreationDisposition */
319 dwflags, /* Flags and attributes */
320 NULL); /* TemplateFile */
326 if (bfd->fh == INVALID_HANDLE_VALUE) {
327 bfd->lerror = GetLastError();
328 bfd->berrno = b_errno_win32;
329 errno = b_errno_win32;
330 bfd->mode = BF_CLOSED;
333 bfd->lpContext = NULL;
334 free_pool_memory(win32_fname);
335 return bfd->mode == BF_CLOSED ? -1 : 1;
339 * Returns 0 on success
342 int bclose(BFILE *bfd)
347 free_pool_memory(bfd->errmsg);
350 if (bfd->mode == BF_CLOSED) {
353 if (bfd->use_backup_api && bfd->mode == BF_READ) {
355 if (!bfd->lpContext && !p_BackupRead(bfd->fh,
357 (DWORD)0, /* bytes to read */
358 &bfd->rw_bytes, /* bytes read */
360 1, /* ProcessSecurity */
361 &bfd->lpContext)) { /* Read context */
362 errno = b_errno_win32;
365 } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
367 if (!bfd->lpContext && !p_BackupWrite(bfd->fh,
369 (DWORD)0, /* bytes to read */
370 &bfd->rw_bytes, /* bytes written */
372 1, /* ProcessSecurity */
373 &bfd->lpContext)) { /* Write context */
374 errno = b_errno_win32;
378 if (!CloseHandle(bfd->fh)) {
380 errno = b_errno_win32;
382 bfd->mode = BF_CLOSED;
383 bfd->lpContext = NULL;
387 /* Returns: bytes read on success
391 ssize_t bread(BFILE *bfd, void *buf, size_t count)
395 if (bfd->use_backup_api) {
396 if (!p_BackupRead(bfd->fh,
401 1, /* Process Security */
402 &bfd->lpContext)) { /* Context */
403 bfd->lerror = GetLastError();
404 bfd->berrno = b_errno_win32;
405 errno = b_errno_win32;
409 if (!ReadFile(bfd->fh,
414 bfd->lerror = GetLastError();
415 bfd->berrno = b_errno_win32;
416 errno = b_errno_win32;
421 return (ssize_t)bfd->rw_bytes;
424 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
428 if (bfd->use_backup_api) {
429 if (!p_BackupWrite(bfd->fh,
434 1, /* Process Security */
435 &bfd->lpContext)) { /* Context */
436 bfd->lerror = GetLastError();
437 bfd->berrno = b_errno_win32;
438 errno = b_errno_win32;
442 if (!WriteFile(bfd->fh,
447 bfd->lerror = GetLastError();
448 bfd->berrno = b_errno_win32;
449 errno = b_errno_win32;
453 return (ssize_t)bfd->rw_bytes;
456 bool is_bopen(BFILE *bfd)
458 return bfd->mode != BF_CLOSED;
461 off_t blseek(BFILE *bfd, off_t offset, int whence)
463 /* ****FIXME**** this must be implemented if we want to read Win32 Archives */
467 #else /* Unix systems */
469 /* ===============================================================
473 * ===============================================================
475 void binit(BFILE *bfd)
477 memset(bfd, 0, sizeof(BFILE));
481 bool have_win32_api()
483 return false; /* no can do */
487 * Enables using the Backup API (win32_data).
488 * Returns true if function worked
489 * Returns false if failed (i.e. do not have Backup API on this machine)
491 bool set_win32_backup(BFILE *bfd)
493 return false; /* no can do */
497 bool set_portable_backup(BFILE *bfd)
499 return true; /* no problem */
503 * Return true if we are writing in portable format
504 * return false if not
506 bool is_portable_backup(BFILE *bfd)
508 return true; /* portable by definition */
511 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
514 if (bfd->prog && strcmp(prog, bfd->prog) == 0) {
515 return true; /* already setup */
518 if (python_set_prog(jcr, prog)) {
519 Dmsg1(000, "Set prog=%s\n", prog);
525 Dmsg0(000, "No prog set\n");
532 bool is_stream_supported(int stream)
534 /* No Win32 backup on this machine */
537 case STREAM_GZIP_DATA:
538 case STREAM_SPARSE_GZIP_DATA:
540 case STREAM_WIN32_DATA:
541 case STREAM_WIN32_GZIP_DATA:
542 #ifndef HAVE_DARWIN_OS
543 case STREAM_MACOS_FORK_DATA:
544 case STREAM_HFSPLUS_ATTRIBUTES:
550 case STREAM_GZIP_DATA:
551 case STREAM_SPARSE_GZIP_DATA:
553 case STREAM_UNIX_ATTRIBUTES:
554 case STREAM_FILE_DATA:
555 case STREAM_MD5_SIGNATURE:
556 case STREAM_UNIX_ATTRIBUTES_EX:
557 case STREAM_SPARSE_DATA:
558 case STREAM_PROGRAM_NAMES:
559 case STREAM_PROGRAM_DATA:
560 case STREAM_SHA1_SIGNATURE:
561 #ifdef HAVE_DARWIN_OS
562 case STREAM_MACOS_FORK_DATA:
563 case STREAM_HFSPLUS_ATTRIBUTES:
565 case 0: /* compatibility with old tapes */
572 /* Old file reader code */
575 POOLMEM *ecmd = get_pool_memory(PM_FNAME);
576 ecmd = edit_job_codes(bfd->jcr, ecmd, bfd->prog, fname);
578 if (flags & O_RDONLY) {
583 bfd->bpipe = open_bpipe(ecmd, 0, pmode);
584 if (bfd->bpipe == NULL) {
587 free_pool_memory(ecmd);
590 free_pool_memory(ecmd);
591 if (flags & O_RDONLY) {
592 bfd->fid = fileno(bfd->bpipe->rfd);
594 bfd->fid = fileno(bfd->bpipe->wfd);
602 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
604 /* Open reader/writer program */
606 Dmsg1(000, "Open file %d\n", bfd->fid);
607 return python_open(bfd, fname, flags, mode);
610 /* Normal file open */
611 bfd->fid = open(fname, flags, mode);
613 Dmsg1(400, "Open file %d\n", bfd->fid);
618 #ifdef HAVE_DARWIN_OS
619 /* Open the resource fork of a file. */
620 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
625 fname_len = strlen(fname);
626 rsrc_fname = get_pool_memory(PM_FNAME);
627 bstrncpy(rsrc_fname, fname, fname_len + 1);
628 bstrncpy(rsrc_fname + fname_len, _PATH_RSRCFORKSPEC,
629 strlen(_PATH_RSRCFORKSPEC) + 1);
630 bopen(bfd, rsrc_fname, flags, mode);
631 free_pool_memory(rsrc_fname);
637 int bclose(BFILE *bfd)
641 Dmsg1(400, "Close file %d\n", bfd->fid);
643 /* Close reader/writer program */
645 return python_close(bfd);
648 if (bfd->fid == -1) {
652 /* Close normal file */
653 stat = close(bfd->fid);
659 ssize_t bread(BFILE *bfd, void *buf, size_t count)
664 return python_read(bfd, buf, count);
666 stat = read(bfd->fid, buf, count);
671 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
676 return python_write(bfd, buf, count);
678 stat = write(bfd->fid, buf, count);
683 bool is_bopen(BFILE *bfd)
685 return bfd->fid >= 0;
688 off_t blseek(BFILE *bfd, off_t offset, int whence)
691 pos = lseek(bfd->fid, offset, whence);