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:
67 return _("GZIP data");
68 case STREAM_SPARSE_GZIP_DATA:
69 return _("GZIP sparse data");
70 case STREAM_WIN32_DATA:
71 return _("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:
77 return _("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:
83 return _("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 POOLMEM *win32_fname_wchar;
216 DWORD dwaccess, dwflags, dwshare;
218 /* Convert to Windows path format */
219 win32_fname = get_pool_memory(PM_FNAME);
220 win32_fname_wchar = get_pool_memory(PM_FNAME);
222 unix_name_to_win32(&win32_fname, (char *)fname);
224 if (!(p_CreateFileA || p_CreateFileW))
227 if (p_CreateFileW && p_MultiByteToWideChar)
228 UTF8_2_wchar(&win32_fname_wchar, win32_fname);
230 if (flags & O_CREAT) { /* Create */
231 if (bfd->use_backup_api) {
232 dwaccess = GENERIC_WRITE|FILE_ALL_ACCESS|WRITE_OWNER|WRITE_DAC|ACCESS_SYSTEM_SECURITY;
233 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
235 dwaccess = GENERIC_WRITE;
239 // unicode or ansii open for create write
240 if (p_CreateFileW && p_MultiByteToWideChar) {
241 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
242 dwaccess, /* Requested access */
244 NULL, /* SecurityAttributes */
245 CREATE_ALWAYS, /* CreationDisposition */
246 dwflags, /* Flags and attributes */
247 NULL); /* TemplateFile */
250 bfd->fh = p_CreateFileA(win32_fname,
251 dwaccess, /* Requested access */
253 NULL, /* SecurityAttributes */
254 CREATE_ALWAYS, /* CreationDisposition */
255 dwflags, /* Flags and attributes */
256 NULL); /* TemplateFile */
260 bfd->mode = BF_WRITE;
262 } else if (flags & O_WRONLY) { /* Open existing for write */
263 if (bfd->use_backup_api) {
264 dwaccess = GENERIC_WRITE|WRITE_OWNER|WRITE_DAC;
265 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
267 dwaccess = GENERIC_WRITE;
271 // unicode or ansii open for open existing write
272 if (p_CreateFileW && p_MultiByteToWideChar) {
273 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
274 dwaccess, /* Requested access */
276 NULL, /* SecurityAttributes */
277 OPEN_EXISTING, /* CreationDisposition */
278 dwflags, /* Flags and attributes */
279 NULL); /* TemplateFile */
282 bfd->fh = p_CreateFileA(win32_fname,
283 dwaccess, /* Requested access */
285 NULL, /* SecurityAttributes */
286 OPEN_EXISTING, /* CreationDisposition */
287 dwflags, /* Flags and attributes */
288 NULL); /* TemplateFile */
292 bfd->mode = BF_WRITE;
295 if (bfd->use_backup_api) {
296 dwaccess = GENERIC_READ|READ_CONTROL|ACCESS_SYSTEM_SECURITY;
297 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
298 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
300 dwaccess = GENERIC_READ;
302 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE;
305 // unicode or ansii open for open existing read
306 if (p_CreateFileW && p_MultiByteToWideChar) {
307 bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
308 dwaccess, /* Requested access */
309 dwshare, /* Share modes */
310 NULL, /* SecurityAttributes */
311 OPEN_EXISTING, /* CreationDisposition */
312 dwflags, /* Flags and attributes */
313 NULL); /* TemplateFile */
316 bfd->fh = p_CreateFileA(win32_fname,
317 dwaccess, /* Requested access */
318 dwshare, /* Share modes */
319 NULL, /* SecurityAttributes */
320 OPEN_EXISTING, /* CreationDisposition */
321 dwflags, /* Flags and attributes */
322 NULL); /* TemplateFile */
328 if (bfd->fh == INVALID_HANDLE_VALUE) {
329 bfd->lerror = GetLastError();
330 bfd->berrno = b_errno_win32;
331 errno = b_errno_win32;
332 bfd->mode = BF_CLOSED;
335 bfd->lpContext = NULL;
336 free_pool_memory(win32_fname_wchar);
337 free_pool_memory(win32_fname);
338 return bfd->mode == BF_CLOSED ? -1 : 1;
342 * Returns 0 on success
345 int bclose(BFILE *bfd)
350 free_pool_memory(bfd->errmsg);
353 if (bfd->mode == BF_CLOSED) {
356 if (bfd->use_backup_api && bfd->mode == BF_READ) {
358 if (!bfd->lpContext && !p_BackupRead(bfd->fh,
360 (DWORD)0, /* bytes to read */
361 &bfd->rw_bytes, /* bytes read */
363 1, /* ProcessSecurity */
364 &bfd->lpContext)) { /* Read context */
365 errno = b_errno_win32;
368 } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
370 if (!bfd->lpContext && !p_BackupWrite(bfd->fh,
372 (DWORD)0, /* bytes to read */
373 &bfd->rw_bytes, /* bytes written */
375 1, /* ProcessSecurity */
376 &bfd->lpContext)) { /* Write context */
377 errno = b_errno_win32;
381 if (!CloseHandle(bfd->fh)) {
383 errno = b_errno_win32;
385 bfd->mode = BF_CLOSED;
386 bfd->lpContext = NULL;
390 /* Returns: bytes read on success
394 ssize_t bread(BFILE *bfd, void *buf, size_t count)
398 if (bfd->use_backup_api) {
399 if (!p_BackupRead(bfd->fh,
404 1, /* Process Security */
405 &bfd->lpContext)) { /* Context */
406 bfd->lerror = GetLastError();
407 bfd->berrno = b_errno_win32;
408 errno = b_errno_win32;
412 if (!ReadFile(bfd->fh,
417 bfd->lerror = GetLastError();
418 bfd->berrno = b_errno_win32;
419 errno = b_errno_win32;
424 return (ssize_t)bfd->rw_bytes;
427 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
431 if (bfd->use_backup_api) {
432 if (!p_BackupWrite(bfd->fh,
437 1, /* Process Security */
438 &bfd->lpContext)) { /* Context */
439 bfd->lerror = GetLastError();
440 bfd->berrno = b_errno_win32;
441 errno = b_errno_win32;
445 if (!WriteFile(bfd->fh,
450 bfd->lerror = GetLastError();
451 bfd->berrno = b_errno_win32;
452 errno = b_errno_win32;
456 return (ssize_t)bfd->rw_bytes;
459 bool is_bopen(BFILE *bfd)
461 return bfd->mode != BF_CLOSED;
464 off_t blseek(BFILE *bfd, off_t offset, int whence)
466 /* ****FIXME**** this must be implemented if we want to read Win32 Archives */
470 #else /* Unix systems */
472 /* ===============================================================
476 * ===============================================================
478 void binit(BFILE *bfd)
480 memset(bfd, 0, sizeof(BFILE));
484 bool have_win32_api()
486 return false; /* no can do */
490 * Enables using the Backup API (win32_data).
491 * Returns true if function worked
492 * Returns false if failed (i.e. do not have Backup API on this machine)
494 bool set_win32_backup(BFILE *bfd)
496 return false; /* no can do */
500 bool set_portable_backup(BFILE *bfd)
502 return true; /* no problem */
506 * Return true if we are writing in portable format
507 * return false if not
509 bool is_portable_backup(BFILE *bfd)
511 return true; /* portable by definition */
514 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
517 if (bfd->prog && strcmp(prog, bfd->prog) == 0) {
518 return true; /* already setup */
521 if (python_set_prog(jcr, prog)) {
522 Dmsg1(000, "Set prog=%s\n", prog);
528 Dmsg0(000, "No prog set\n");
535 bool is_stream_supported(int stream)
537 /* No Win32 backup on this machine */
540 case STREAM_GZIP_DATA:
541 case STREAM_SPARSE_GZIP_DATA:
543 case STREAM_WIN32_DATA:
544 case STREAM_WIN32_GZIP_DATA:
545 #ifndef HAVE_DARWIN_OS
546 case STREAM_MACOS_FORK_DATA:
547 case STREAM_HFSPLUS_ATTRIBUTES:
553 case STREAM_GZIP_DATA:
554 case STREAM_SPARSE_GZIP_DATA:
556 case STREAM_UNIX_ATTRIBUTES:
557 case STREAM_FILE_DATA:
558 case STREAM_MD5_SIGNATURE:
559 case STREAM_UNIX_ATTRIBUTES_EX:
560 case STREAM_SPARSE_DATA:
561 case STREAM_PROGRAM_NAMES:
562 case STREAM_PROGRAM_DATA:
563 case STREAM_SHA1_SIGNATURE:
564 #ifdef HAVE_DARWIN_OS
565 case STREAM_MACOS_FORK_DATA:
566 case STREAM_HFSPLUS_ATTRIBUTES:
568 case 0: /* compatibility with old tapes */
575 /* Old file reader code */
578 POOLMEM *ecmd = get_pool_memory(PM_FNAME);
579 ecmd = edit_job_codes(bfd->jcr, ecmd, bfd->prog, fname);
581 if (flags & O_RDONLY) {
586 bfd->bpipe = open_bpipe(ecmd, 0, pmode);
587 if (bfd->bpipe == NULL) {
590 free_pool_memory(ecmd);
593 free_pool_memory(ecmd);
594 if (flags & O_RDONLY) {
595 bfd->fid = fileno(bfd->bpipe->rfd);
597 bfd->fid = fileno(bfd->bpipe->wfd);
605 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
607 /* Open reader/writer program */
609 Dmsg1(000, "Open file %d\n", bfd->fid);
610 return python_open(bfd, fname, flags, mode);
613 /* Normal file open */
614 bfd->fid = open(fname, flags, mode);
616 Dmsg1(400, "Open file %d\n", bfd->fid);
621 #ifdef HAVE_DARWIN_OS
622 /* Open the resource fork of a file. */
623 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
628 fname_len = strlen(fname);
629 rsrc_fname = get_pool_memory(PM_FNAME);
630 bstrncpy(rsrc_fname, fname, fname_len + 1);
631 bstrncpy(rsrc_fname + fname_len, _PATH_RSRCFORKSPEC,
632 strlen(_PATH_RSRCFORKSPEC) + 1);
633 bopen(bfd, rsrc_fname, flags, mode);
634 free_pool_memory(rsrc_fname);
640 int bclose(BFILE *bfd)
644 Dmsg1(400, "Close file %d\n", bfd->fid);
646 /* Close reader/writer program */
648 return python_close(bfd);
651 if (bfd->fid == -1) {
655 /* Close normal file */
656 stat = close(bfd->fid);
662 ssize_t bread(BFILE *bfd, void *buf, size_t count)
667 return python_read(bfd, buf, count);
669 stat = read(bfd->fid, buf, count);
674 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
679 return python_write(bfd, buf, count);
681 stat = write(bfd->fid, buf, count);
686 bool is_bopen(BFILE *bfd)
688 return bfd->fid >= 0;
691 off_t blseek(BFILE *bfd, off_t offset, int whence)
694 pos = lseek(bfd->fid, offset, whence);