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,
34 extern int generate_job_event(JCR *jcr, const char *event);
37 #include <sys/paths.h>
40 /* ===============================================================
42 * U N I X AND W I N D O W S
44 * ===============================================================
47 bool is_win32_stream(int stream)
50 case STREAM_WIN32_DATA:
51 case STREAM_WIN32_GZIP_DATA:
57 const char *stream_to_ascii(int stream)
62 case STREAM_GZIP_DATA:
64 case STREAM_SPARSE_GZIP_DATA:
65 return "GZIP sparse data";
66 case STREAM_WIN32_DATA:
68 case STREAM_WIN32_GZIP_DATA:
69 return "Win32 GZIP data";
70 case STREAM_UNIX_ATTRIBUTES:
71 return "File attributes";
72 case STREAM_FILE_DATA:
74 case STREAM_MD5_SIGNATURE:
75 return "MD5 signature";
76 case STREAM_UNIX_ATTRIBUTES_EX:
77 return "Extended attributes";
78 case STREAM_SPARSE_DATA:
80 case STREAM_PROGRAM_NAMES:
81 return "Program names";
82 case STREAM_PROGRAM_DATA:
83 return "Program data";
84 case STREAM_SHA1_SIGNATURE:
85 return "SHA1 signature";
86 case STREAM_MACOS_FORK_DATA:
87 return "HFS+ resource fork";
88 case STREAM_HFSPLUS_ATTRIBUTES:
89 return "HFS+ Finder Info";
91 sprintf(buf, "%d", stream);
92 return (const char *)buf;
98 /* ===============================================================
102 * ===============================================================
105 #if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
107 void unix_name_to_win32(POOLMEM **win32_name, char *name);
108 extern "C" HANDLE get_osfhandle(int fd);
112 void binit(BFILE *bfd)
114 memset(bfd, 0, sizeof(BFILE));
116 bfd->mode = BF_CLOSED;
117 bfd->use_backup_api = have_win32_api();
121 * Enables using the Backup API (win32_data).
122 * Returns 1 if function worked
123 * Returns 0 if failed (i.e. do not have Backup API on this machine)
125 bool set_win32_backup(BFILE *bfd)
127 /* We enable if possible here */
128 bfd->use_backup_api = have_win32_api();
129 return bfd->use_backup_api;
133 bool set_portable_backup(BFILE *bfd)
135 bfd->use_backup_api = false;
139 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
147 * Return 1 if we are NOT using Win32 BackupWrite()
150 bool is_portable_backup(BFILE *bfd)
152 return !bfd->use_backup_api;
155 bool have_win32_api()
157 return p_BackupRead && p_BackupWrite;
163 * Return 1 if we support the stream
164 * 0 if we do not support the stream
166 bool is_stream_supported(int stream)
168 /* No Win32 backup on this machine */
171 case STREAM_GZIP_DATA:
172 case STREAM_SPARSE_GZIP_DATA:
175 case STREAM_WIN32_DATA:
176 case STREAM_WIN32_GZIP_DATA:
177 return have_win32_api();
179 case STREAM_MACOS_FORK_DATA:
180 case STREAM_HFSPLUS_ATTRIBUTES:
185 case STREAM_GZIP_DATA:
186 case STREAM_SPARSE_GZIP_DATA:
188 case STREAM_UNIX_ATTRIBUTES:
189 case STREAM_FILE_DATA:
190 case STREAM_MD5_SIGNATURE:
191 case STREAM_UNIX_ATTRIBUTES_EX:
192 case STREAM_SPARSE_DATA:
193 case STREAM_PROGRAM_NAMES:
194 case STREAM_PROGRAM_DATA:
195 case STREAM_SHA1_SIGNATURE:
196 case 0: /* compatibility with old tapes */
202 HANDLE bget_handle(BFILE *bfd)
207 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
209 POOLMEM *win32_fname;
210 DWORD dwaccess, dwflags, dwshare;
212 /* Convert to Windows path format */
213 win32_fname = get_pool_memory(PM_FNAME);
214 unix_name_to_win32(&win32_fname, (char *)fname);
216 if (flags & O_CREAT) { /* Create */
217 if (bfd->use_backup_api) {
218 dwaccess = GENERIC_WRITE|FILE_ALL_ACCESS|WRITE_OWNER|WRITE_DAC|ACCESS_SYSTEM_SECURITY;
219 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
221 dwaccess = GENERIC_WRITE;
224 bfd->fh = CreateFile(win32_fname,
225 dwaccess, /* Requested access */
227 NULL, /* SecurityAttributes */
228 CREATE_ALWAYS, /* CreationDisposition */
229 dwflags, /* Flags and attributes */
230 NULL); /* TemplateFile */
231 bfd->mode = BF_WRITE;
233 } else if (flags & O_WRONLY) { /* Open existing for write */
234 if (bfd->use_backup_api) {
235 dwaccess = GENERIC_WRITE|WRITE_OWNER|WRITE_DAC;
236 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
238 dwaccess = GENERIC_WRITE;
241 bfd->fh = CreateFile(win32_fname,
242 dwaccess, /* Requested access */
244 NULL, /* SecurityAttributes */
245 OPEN_EXISTING, /* CreationDisposition */
246 dwflags, /* Flags and attributes */
247 NULL); /* TemplateFile */
248 bfd->mode = BF_WRITE;
251 if (bfd->use_backup_api) {
252 dwaccess = GENERIC_READ|READ_CONTROL|ACCESS_SYSTEM_SECURITY;
253 dwflags = FILE_FLAG_BACKUP_SEMANTICS;
254 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
256 dwaccess = GENERIC_READ;
258 dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE;
260 bfd->fh = CreateFile(win32_fname,
261 dwaccess, /* Requested access */
262 dwshare, /* Share modes */
263 NULL, /* SecurityAttributes */
264 OPEN_EXISTING, /* CreationDisposition */
265 dwflags, /* Flags and attributes */
266 NULL); /* TemplateFile */
270 if (bfd->fh == INVALID_HANDLE_VALUE) {
271 bfd->lerror = GetLastError();
272 bfd->berrno = b_errno_win32;
273 errno = b_errno_win32;
274 bfd->mode = BF_CLOSED;
277 bfd->lpContext = NULL;
278 free_pool_memory(win32_fname);
279 return bfd->mode == BF_CLOSED ? -1 : 1;
283 * Returns 0 on success
286 int bclose(BFILE *bfd)
291 free_pool_memory(bfd->errmsg);
294 if (bfd->mode == BF_CLOSED) {
297 if (bfd->use_backup_api && bfd->mode == BF_READ) {
299 if (!bfd->lpContext && !p_BackupRead(bfd->fh,
301 (DWORD)0, /* bytes to read */
302 &bfd->rw_bytes, /* bytes read */
304 1, /* ProcessSecurity */
305 &bfd->lpContext)) { /* Read context */
306 errno = b_errno_win32;
309 } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
311 if (!bfd->lpContext && !p_BackupWrite(bfd->fh,
313 (DWORD)0, /* bytes to read */
314 &bfd->rw_bytes, /* bytes written */
316 1, /* ProcessSecurity */
317 &bfd->lpContext)) { /* Write context */
318 errno = b_errno_win32;
322 if (!CloseHandle(bfd->fh)) {
324 errno = b_errno_win32;
326 bfd->mode = BF_CLOSED;
327 bfd->lpContext = NULL;
331 /* Returns: bytes read on success
335 ssize_t bread(BFILE *bfd, void *buf, size_t count)
339 if (bfd->use_backup_api) {
340 if (!p_BackupRead(bfd->fh,
345 1, /* Process Security */
346 &bfd->lpContext)) { /* Context */
347 bfd->lerror = GetLastError();
348 bfd->berrno = b_errno_win32;
349 errno = b_errno_win32;
353 if (!ReadFile(bfd->fh,
358 bfd->lerror = GetLastError();
359 bfd->berrno = b_errno_win32;
360 errno = b_errno_win32;
365 return (ssize_t)bfd->rw_bytes;
368 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
372 if (bfd->use_backup_api) {
373 if (!p_BackupWrite(bfd->fh,
378 1, /* Process Security */
379 &bfd->lpContext)) { /* Context */
380 bfd->lerror = GetLastError();
381 bfd->berrno = b_errno_win32;
382 errno = b_errno_win32;
386 if (!WriteFile(bfd->fh,
391 bfd->lerror = GetLastError();
392 bfd->berrno = b_errno_win32;
393 errno = b_errno_win32;
397 return (ssize_t)bfd->rw_bytes;
400 bool is_bopen(BFILE *bfd)
402 return bfd->mode != BF_CLOSED;
405 off_t blseek(BFILE *bfd, off_t offset, int whence)
407 /* ****FIXME**** this must be implemented if we want to read Win32 Archives */
411 #else /* Unix systems */
413 /* ===============================================================
417 * ===============================================================
419 void binit(BFILE *bfd)
421 memset(bfd, 0, sizeof(BFILE));
425 bool have_win32_api()
427 return false; /* no can do */
431 * Enables using the Backup API (win32_data).
432 * Returns true if function worked
433 * Returns false if failed (i.e. do not have Backup API on this machine)
435 bool set_win32_backup(BFILE *bfd)
437 return false; /* no can do */
441 bool set_portable_backup(BFILE *bfd)
443 return true; /* no problem */
447 * Return true if we are writing in portable format
448 * return false if not
450 bool is_portable_backup(BFILE *bfd)
452 return true; /* portable by definition */
455 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
457 if (bfd->prog && strcmp(prog, bfd->prog) == 0) {
458 return true; /* already setup */
460 int stat = generate_job_event(jcr, "Reader");
461 if (stat == 1 && bfd->pio.fo && bfd->pio.fr && bfd->pio.fc) {
472 bool is_stream_supported(int stream)
474 /* No Win32 backup on this machine */
477 case STREAM_GZIP_DATA:
478 case STREAM_SPARSE_GZIP_DATA:
480 case STREAM_WIN32_DATA:
481 case STREAM_WIN32_GZIP_DATA:
482 #ifndef HAVE_DARWIN_OS
483 case STREAM_MACOS_FORK_DATA:
484 case STREAM_HFSPLUS_ATTRIBUTES:
490 case STREAM_GZIP_DATA:
491 case STREAM_SPARSE_GZIP_DATA:
493 case STREAM_UNIX_ATTRIBUTES:
494 case STREAM_FILE_DATA:
495 case STREAM_MD5_SIGNATURE:
496 case STREAM_UNIX_ATTRIBUTES_EX:
497 case STREAM_SPARSE_DATA:
498 case STREAM_PROGRAM_NAMES:
499 case STREAM_PROGRAM_DATA:
500 case STREAM_SHA1_SIGNATURE:
501 #ifdef HAVE_DARWIN_OS
502 case STREAM_MACOS_FORK_DATA:
503 case STREAM_HFSPLUS_ATTRIBUTES:
505 case 0: /* compatibility with old tapes */
512 /* Old file reader code */
515 POOLMEM *ecmd = get_pool_memory(PM_FNAME);
516 ecmd = edit_job_codes(bfd->jcr, ecmd, bfd->prog, fname);
518 if (flags & O_RDONLY) {
523 bfd->bpipe = open_bpipe(ecmd, 0, pmode);
524 if (bfd->bpipe == NULL) {
527 free_pool_memory(ecmd);
530 free_pool_memory(ecmd);
531 if (flags & O_RDONLY) {
532 bfd->fid = fileno(bfd->bpipe->rfd);
534 bfd->fid = fileno(bfd->bpipe->wfd);
542 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
544 /* Open reader/writer program */
550 /* Normal file open */
551 bfd->fid = open(fname, flags, mode);
553 Dmsg1(400, "Open file %d\n", bfd->fid);
558 #ifdef HAVE_DARWIN_OS
559 /* Open the resource fork of a file. */
560 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
565 fname_len = strlen(fname);
566 rsrc_fname = get_pool_memory(PM_FNAME);
567 bstrncpy(rsrc_fname, fname, fname_len + 1);
568 bstrncpy(rsrc_fname + fname_len, _PATH_RSRCFORKSPEC,
569 strlen(_PATH_RSRCFORKSPEC) + 1);
570 bopen(bfd, rsrc_fname, flags, mode);
571 free_pool_memory(rsrc_fname);
576 /* Old prog close code */
578 if (bfd->prog && bfd->bpipe) {
579 stat = close_bpipe(bfd->bpipe);
588 int bclose(BFILE *bfd)
591 Dmsg1(400, "Close file %d\n", bfd->fid);
592 if (bfd->fid == -1) {
595 /* Close reader/writer program */
600 /* Close normal file */
601 stat = close(bfd->fid);
607 ssize_t bread(BFILE *bfd, void *buf, size_t count)
610 stat = read(bfd->fid, buf, count);
615 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
618 stat = write(bfd->fid, buf, count);
623 bool is_bopen(BFILE *bfd)
625 return bfd->fid >= 0;
628 off_t blseek(BFILE *bfd, off_t offset, int whence)
631 pos = lseek(bfd->fid, offset, whence);