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) 2000-2003 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,
36 void unix_name_to_win32(POOLMEM **win32_name, char *name);
37 extern "C" HANDLE get_osfhandle(int fd);
40 void binit(BFILE *bfd)
43 bfd->mode = BF_CLOSED;
44 bfd->use_backup_api = p_BackupRead && p_BackupWrite;
46 bfd->lpContext = NULL;
51 * Enables/disables using the Backup API (win32_data).
52 * Returns 1 if function worked
53 * Returns 0 if failed (i.e. do not have Backup API on this machine)
55 int set_win32_data(BFILE *bfd, int enable)
58 bfd->use_backup_api = 0;
61 /* We enable if possible here */
62 bfd->use_backup_api = p_BackupRead && p_BackupWrite;
63 return bfd->use_backup_api;
66 int is_win32_data(BFILE *bfd)
68 return bfd->use_backup_api;
71 HANDLE bget_handle(BFILE *bfd)
74 if (!bfd->use_win_api) {
75 return get_osfhandle(bfd->fid);
81 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
86 if (!bfd->use_win_api) {
87 bfd->fid = open(fname, flags, mode);
89 bfd->mode = BF_READ; /* not important if BF_READ or BF_WRITE */
95 /* Convert to Windows path format */
96 win32_fname = get_pool_memory(PM_FNAME);
97 unix_name_to_win32(&win32_fname, (char *)fname);
99 if (flags & O_CREAT) {
100 bfd->fh = CreateFile(win32_fname,
101 GENERIC_WRITE|FILE_ALL_ACCESS|WRITE_OWNER|WRITE_DAC|ACCESS_SYSTEM_SECURITY, /* access */
103 NULL, /* SecurityAttributes */
104 CREATE_ALWAYS, /* CreationDisposition */
105 FILE_FLAG_BACKUP_SEMANTICS, /* Flags and attributes */
106 NULL); /* TemplateFile */
107 bfd->mode = BF_WRITE;
108 } else if (flags & O_WRONLY) { /* creating */
109 bfd->fh = CreateFile(win32_fname,
110 FILE_ALL_ACCESS|WRITE_OWNER|WRITE_DAC|ACCESS_SYSTEM_SECURITY, /* access */
112 NULL, /* SecurityAttributes */
113 OPEN_EXISTING, /* CreationDisposition */
114 FILE_FLAG_BACKUP_SEMANTICS, /* Flags and attributes */
116 bfd->mode = BF_WRITE;
118 bfd->fh = CreateFile(win32_fname,
119 GENERIC_READ|READ_CONTROL|ACCESS_SYSTEM_SECURITY, /* access */
120 FILE_SHARE_READ, /* shared mode */
121 NULL, /* SecurityAttributes */
122 OPEN_EXISTING, /* CreationDisposition */
123 FILE_FLAG_BACKUP_SEMANTICS, /* Flags and attributes */
124 NULL); /* TemplateFile */
128 if (bfd->fh == INVALID_HANDLE_VALUE) {
129 bfd->lerror = GetLastError();
130 bfd->mode = BF_CLOSED;
133 bfd->lpContext = NULL;
134 return bfd->mode == BF_CLOSED ? -1 : 1;
138 * Returns 0 on success
141 int bclose(BFILE *bfd)
145 if (!bfd->use_win_api) {
146 int stat = close(bfd->fid);
148 bfd->mode = BF_CLOSED;
153 free_pool_memory(bfd->errmsg);
156 if (bfd->mode == BF_CLOSED) {
159 if (bfd->use_backup_api && bfd->mode == BF_READ) {
161 if (!bfd->lpContext && !p_BackupRead(bfd->fh,
163 (DWORD)0, /* bytes to read */
164 &bfd->rw_bytes, /* bytes read */
166 1, /* ProcessSecurity */
167 &bfd->lpContext)) { /* Read context */
170 } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
172 if (!bfd->lpContext && !p_BackupWrite(bfd->fh,
174 (DWORD)0, /* bytes to read */
175 &bfd->rw_bytes, /* bytes written */
177 1, /* ProcessSecurity */
178 &bfd->lpContext)) { /* Write context */
182 if (!CloseHandle(bfd->fh)) {
185 bfd->mode = BF_CLOSED;
186 bfd->lpContext = NULL;
191 * Generate error message
193 char *berror(BFILE *bfd)
197 if (!bfd->use_win_api) {
198 return strerror(errno);
201 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
202 FORMAT_MESSAGE_FROM_SYSTEM,
209 strip_trailing_junk(msg);
211 bfd->errmsg = get_pool_memory(PM_FNAME);
213 pm_strcpy(&bfd->errmsg, msg);
218 /* Returns: bytes read on success
222 ssize_t bread(BFILE *bfd, void *buf, size_t count)
225 if (!bfd->use_win_api) {
226 return read(bfd->fid, buf, count);
231 if (bfd->use_backup_api) {
232 if (!p_BackupRead(bfd->fh,
237 1, /* Process Security */
238 &bfd->lpContext)) { /* Context */
239 bfd->lerror = GetLastError();
243 if (!ReadFile(bfd->fh,
248 bfd->lerror = GetLastError();
253 return (ssize_t)bfd->rw_bytes;
256 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
259 if (!bfd->use_win_api) {
260 return write(bfd->fid, buf, count);
265 if (bfd->use_backup_api) {
266 if (!p_BackupWrite(bfd->fh,
271 1, /* Process Security */
272 &bfd->lpContext)) { /* Context */
273 bfd->lerror = GetLastError();
277 if (!WriteFile(bfd->fh,
282 bfd->lerror = GetLastError();
286 return (ssize_t)bfd->rw_bytes;
289 int is_bopen(BFILE *bfd)
291 return bfd->mode != BF_CLOSED;
294 off_t blseek(BFILE *bfd, off_t offset, int whence)
297 if (!bfd->use_win_api) {
298 return lseek(bfd->fid, offset, whence);
301 /* ****FIXME**** this is needed if we want to read Win32 Archives */
305 #else /* Unix systems */
307 /* ===============================================================
311 * ===============================================================
313 void binit(BFILE *bfd)
318 int is_win32_data(BFILE *bfd)
324 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
326 bfd->fid = open(fname, flags, mode);
331 int bclose(BFILE *bfd)
333 int stat = close(bfd->fid);
339 ssize_t bread(BFILE *bfd, void *buf, size_t count)
342 stat = read(bfd->fid, buf, count);
347 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
350 stat = write(bfd->fid, buf, count);
355 int is_bopen(BFILE *bfd)
357 return bfd->fid >= 0;
360 off_t blseek(BFILE *bfd, off_t offset, int whence)
363 pos = lseek(bfd->fid, offset, whence);
368 char *berror(BFILE *bfd)
370 return strerror(bfd->berrno);