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;
216 /* Convert to Windows path format */
217 win32_fname = get_pool_memory(PM_FNAME);
218 unix_name_to_win32(&win32_fname, (char *)fname);
220 #if USE_WIN32_UNICODE
221 WCHAR win32_fname_wchar[MAX_PATH_UNICODE];
222 UTF8_2_wchar(win32_fname_wchar, win32_fname, MAX_PATH_UNICODE);
225 if (flags & O_CREAT) { /* Create */
226 if (bfd->use_backup_api) {
227 dwaccess = GENERIC_WRITE|FILE_ALL_ACCESS|WRITE_OWNER|WRITE_DAC|ACCESS_SYSTEM_SECURITY;
228 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
230 dwaccess = GENERIC_WRITE;
235 #if USE_WIN32_UNICODE
236 bfd->fh = CreateFileW(win32_fname_wchar,
238 bfd->fh = CreateFile(win32_fname,
240 dwaccess, /* Requested access */
242 NULL, /* SecurityAttributes */
243 CREATE_ALWAYS, /* CreationDisposition */
244 dwflags, /* Flags and attributes */
245 NULL); /* TemplateFile */
246 bfd->mode = BF_WRITE;
248 } else if (flags & O_WRONLY) { /* Open existing for write */
249 if (bfd->use_backup_api) {
250 dwaccess = GENERIC_WRITE|WRITE_OWNER|WRITE_DAC;
251 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
253 dwaccess = GENERIC_WRITE;
257 #if USE_WIN32_UNICODE
258 bfd->fh = CreateFileW(win32_fname_wchar,
260 bfd->fh = CreateFile(win32_fname,
262 dwaccess, /* Requested access */
264 NULL, /* SecurityAttributes */
265 OPEN_EXISTING, /* CreationDisposition */
266 dwflags, /* Flags and attributes */
267 NULL); /* TemplateFile */
268 bfd->mode = BF_WRITE;
271 if (bfd->use_backup_api) {
272 dwaccess = GENERIC_READ|READ_CONTROL|ACCESS_SYSTEM_SECURITY;
273 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
274 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
276 dwaccess = GENERIC_READ;
278 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE;
281 #if USE_WIN32_UNICODE
282 bfd->fh = CreateFileW(win32_fname_wchar,
284 bfd->fh = CreateFile(win32_fname,
286 dwaccess, /* Requested access */
287 dwshare, /* Share modes */
288 NULL, /* SecurityAttributes */
289 OPEN_EXISTING, /* CreationDisposition */
290 dwflags, /* Flags and attributes */
291 NULL); /* TemplateFile */
295 if (bfd->fh == INVALID_HANDLE_VALUE) {
296 bfd->lerror = GetLastError();
297 bfd->berrno = b_errno_win32;
298 errno = b_errno_win32;
299 bfd->mode = BF_CLOSED;
302 bfd->lpContext = NULL;
303 free_pool_memory(win32_fname);
304 return bfd->mode == BF_CLOSED ? -1 : 1;
308 * Returns 0 on success
311 int bclose(BFILE *bfd)
316 free_pool_memory(bfd->errmsg);
319 if (bfd->mode == BF_CLOSED) {
322 if (bfd->use_backup_api && bfd->mode == BF_READ) {
324 if (!bfd->lpContext && !p_BackupRead(bfd->fh,
326 (DWORD)0, /* bytes to read */
327 &bfd->rw_bytes, /* bytes read */
329 1, /* ProcessSecurity */
330 &bfd->lpContext)) { /* Read context */
331 errno = b_errno_win32;
334 } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
336 if (!bfd->lpContext && !p_BackupWrite(bfd->fh,
338 (DWORD)0, /* bytes to read */
339 &bfd->rw_bytes, /* bytes written */
341 1, /* ProcessSecurity */
342 &bfd->lpContext)) { /* Write context */
343 errno = b_errno_win32;
347 if (!CloseHandle(bfd->fh)) {
349 errno = b_errno_win32;
351 bfd->mode = BF_CLOSED;
352 bfd->lpContext = NULL;
356 /* Returns: bytes read on success
360 ssize_t bread(BFILE *bfd, void *buf, size_t count)
364 if (bfd->use_backup_api) {
365 if (!p_BackupRead(bfd->fh,
370 1, /* Process Security */
371 &bfd->lpContext)) { /* Context */
372 bfd->lerror = GetLastError();
373 bfd->berrno = b_errno_win32;
374 errno = b_errno_win32;
378 if (!ReadFile(bfd->fh,
383 bfd->lerror = GetLastError();
384 bfd->berrno = b_errno_win32;
385 errno = b_errno_win32;
390 return (ssize_t)bfd->rw_bytes;
393 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
397 if (bfd->use_backup_api) {
398 if (!p_BackupWrite(bfd->fh,
403 1, /* Process Security */
404 &bfd->lpContext)) { /* Context */
405 bfd->lerror = GetLastError();
406 bfd->berrno = b_errno_win32;
407 errno = b_errno_win32;
411 if (!WriteFile(bfd->fh,
416 bfd->lerror = GetLastError();
417 bfd->berrno = b_errno_win32;
418 errno = b_errno_win32;
422 return (ssize_t)bfd->rw_bytes;
425 bool is_bopen(BFILE *bfd)
427 return bfd->mode != BF_CLOSED;
430 off_t blseek(BFILE *bfd, off_t offset, int whence)
432 /* ****FIXME**** this must be implemented if we want to read Win32 Archives */
436 #else /* Unix systems */
438 /* ===============================================================
442 * ===============================================================
444 void binit(BFILE *bfd)
446 memset(bfd, 0, sizeof(BFILE));
450 bool have_win32_api()
452 return false; /* no can do */
456 * Enables using the Backup API (win32_data).
457 * Returns true if function worked
458 * Returns false if failed (i.e. do not have Backup API on this machine)
460 bool set_win32_backup(BFILE *bfd)
462 return false; /* no can do */
466 bool set_portable_backup(BFILE *bfd)
468 return true; /* no problem */
472 * Return true if we are writing in portable format
473 * return false if not
475 bool is_portable_backup(BFILE *bfd)
477 return true; /* portable by definition */
480 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
483 if (bfd->prog && strcmp(prog, bfd->prog) == 0) {
484 return true; /* already setup */
487 if (python_set_prog(jcr, prog)) {
488 Dmsg1(000, "Set prog=%s\n", prog);
494 Dmsg0(000, "No prog set\n");
501 bool is_stream_supported(int stream)
503 /* No Win32 backup on this machine */
506 case STREAM_GZIP_DATA:
507 case STREAM_SPARSE_GZIP_DATA:
509 case STREAM_WIN32_DATA:
510 case STREAM_WIN32_GZIP_DATA:
511 #ifndef HAVE_DARWIN_OS
512 case STREAM_MACOS_FORK_DATA:
513 case STREAM_HFSPLUS_ATTRIBUTES:
519 case STREAM_GZIP_DATA:
520 case STREAM_SPARSE_GZIP_DATA:
522 case STREAM_UNIX_ATTRIBUTES:
523 case STREAM_FILE_DATA:
524 case STREAM_MD5_SIGNATURE:
525 case STREAM_UNIX_ATTRIBUTES_EX:
526 case STREAM_SPARSE_DATA:
527 case STREAM_PROGRAM_NAMES:
528 case STREAM_PROGRAM_DATA:
529 case STREAM_SHA1_SIGNATURE:
530 #ifdef HAVE_DARWIN_OS
531 case STREAM_MACOS_FORK_DATA:
532 case STREAM_HFSPLUS_ATTRIBUTES:
534 case 0: /* compatibility with old tapes */
541 /* Old file reader code */
544 POOLMEM *ecmd = get_pool_memory(PM_FNAME);
545 ecmd = edit_job_codes(bfd->jcr, ecmd, bfd->prog, fname);
547 if (flags & O_RDONLY) {
552 bfd->bpipe = open_bpipe(ecmd, 0, pmode);
553 if (bfd->bpipe == NULL) {
556 free_pool_memory(ecmd);
559 free_pool_memory(ecmd);
560 if (flags & O_RDONLY) {
561 bfd->fid = fileno(bfd->bpipe->rfd);
563 bfd->fid = fileno(bfd->bpipe->wfd);
571 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
573 /* Open reader/writer program */
575 Dmsg1(000, "Open file %d\n", bfd->fid);
576 return python_open(bfd, fname, flags, mode);
579 /* Normal file open */
580 bfd->fid = open(fname, flags, mode);
582 Dmsg1(400, "Open file %d\n", bfd->fid);
587 #ifdef HAVE_DARWIN_OS
588 /* Open the resource fork of a file. */
589 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
594 fname_len = strlen(fname);
595 rsrc_fname = get_pool_memory(PM_FNAME);
596 bstrncpy(rsrc_fname, fname, fname_len + 1);
597 bstrncpy(rsrc_fname + fname_len, _PATH_RSRCFORKSPEC,
598 strlen(_PATH_RSRCFORKSPEC) + 1);
599 bopen(bfd, rsrc_fname, flags, mode);
600 free_pool_memory(rsrc_fname);
606 int bclose(BFILE *bfd)
610 Dmsg1(400, "Close file %d\n", bfd->fid);
612 /* Close reader/writer program */
614 return python_close(bfd);
617 if (bfd->fid == -1) {
621 /* Close normal file */
622 stat = close(bfd->fid);
628 ssize_t bread(BFILE *bfd, void *buf, size_t count)
633 return python_read(bfd, buf, count);
635 stat = read(bfd->fid, buf, count);
640 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
645 return python_write(bfd, buf, count);
647 stat = write(bfd->fid, buf, count);
652 bool is_bopen(BFILE *bfd)
654 return bfd->fid >= 0;
657 off_t blseek(BFILE *bfd, off_t offset, int whence)
660 pos = lseek(bfd->fid, offset, whence);