Line data Source code
1 : #include "burp.h"
2 : #include "alloc.h"
3 : #include "attribs.h"
4 : #include "berrno.h"
5 : #include "log.h"
6 :
7 : #ifdef HAVE_DARWIN_OS
8 : #include <sys/paths.h>
9 : #endif
10 :
11 6 : void bfile_free(BFILE **bfd)
12 : {
13 6 : free_v((void **)bfd);
14 6 : }
15 :
16 : #ifdef HAVE_WIN32
17 :
18 : char *unix_name_to_win32(char *name);
19 : extern "C" HANDLE get_osfhandle(int fd);
20 :
21 : static void bfile_set_win32_api(BFILE *bfd, int on)
22 : {
23 : if(have_win32_api() && on)
24 : bfd->use_backup_api=1;
25 : else
26 : bfd->use_backup_api=0;
27 : }
28 :
29 : int have_win32_api(void)
30 : {
31 : return p_BackupRead && p_BackupWrite;
32 : }
33 :
34 : // Windows flags for the OpenEncryptedFileRaw functions
35 : #define CREATE_FOR_EXPORT 0
36 : // These are already defined
37 : //#define CREATE_FOR_IMPORT 1
38 : //#define CREATE_FOR_DIR 2
39 : //#define OVERWRITE_HIDDEN 4
40 :
41 : // Return 0 for success, non zero for error.
42 : static int bfile_open_encrypted(BFILE *bfd,
43 : const char *fname, int flags, mode_t mode)
44 : {
45 : ULONG ulFlags=0;
46 : char *win32_fname=NULL;
47 : char *win32_fname_wchar=NULL;
48 :
49 : if(!(p_OpenEncryptedFileRawA || p_OpenEncryptedFileRawW))
50 : {
51 : logp("no OpenEncryptedFileRaw pointers.\n");
52 : return -1;
53 : }
54 : if(p_OpenEncryptedFileRawW && p_MultiByteToWideChar)
55 : {
56 : if(!(win32_fname_wchar=make_win32_path_UTF8_2_wchar_w(fname)))
57 : logp("could not get widename!");
58 : }
59 : if(!(win32_fname=unix_name_to_win32((char *)fname)))
60 : return -1;
61 :
62 : if((flags & O_CREAT) /* Create */
63 : || (flags & O_WRONLY)) /* Open existing for write */
64 : {
65 : ulFlags |= CREATE_FOR_IMPORT;
66 : ulFlags |= OVERWRITE_HIDDEN;
67 : if(bfd->winattr & FILE_ATTRIBUTE_DIRECTORY)
68 : {
69 : mkdir(fname, 0777);
70 : ulFlags |= CREATE_FOR_DIR;
71 : }
72 : }
73 : else
74 : {
75 : /* Open existing for read */
76 : ulFlags=CREATE_FOR_EXPORT;
77 : }
78 :
79 : if(p_OpenEncryptedFileRawW && p_MultiByteToWideChar)
80 : {
81 : int ret;
82 : // unicode open
83 : ret=p_OpenEncryptedFileRawW((LPCWSTR)win32_fname_wchar,
84 : ulFlags, &(bfd->pvContext));
85 : if(ret) bfd->mode=BF_CLOSED;
86 : else bfd->mode=BF_READ;
87 : goto end;
88 : }
89 : else
90 : {
91 : int ret;
92 : // ascii open
93 : ret=p_OpenEncryptedFileRawA(win32_fname,
94 : ulFlags, &(bfd->pvContext));
95 : if(ret) bfd->mode=BF_CLOSED;
96 : else bfd->mode=BF_READ;
97 : goto end;
98 : }
99 :
100 : end:
101 : if(win32_fname_wchar) free(win32_fname_wchar);
102 : if(win32_fname) free(win32_fname);
103 : return bfd->mode==BF_CLOSED;
104 : }
105 :
106 : static int bfile_error(BFILE *bfd)
107 : {
108 : if(bfd)
109 : {
110 : bfd->lerror=GetLastError();
111 : bfd->berrno=b_errno_win32;
112 : }
113 : errno=b_errno_win32;
114 : return -1;
115 : }
116 :
117 : // Return 0 for success, non zero for error.
118 : static int bfile_open(BFILE *bfd, struct asfd *asfd,
119 : const char *fname, int flags, mode_t mode)
120 : {
121 : DWORD dwaccess;
122 : DWORD dwflags;
123 : DWORD dwshare;
124 : char *win32_fname=NULL;
125 : char *win32_fname_wchar=NULL;
126 :
127 : if(bfd->winattr & FILE_ATTRIBUTE_ENCRYPTED)
128 : return bfile_open_encrypted(bfd, fname, flags, mode);
129 :
130 : if(!(p_CreateFileA || p_CreateFileW)) return -1;
131 :
132 : if(!(win32_fname=unix_name_to_win32((char *)fname))) return -1;
133 :
134 : if(p_CreateFileW && p_MultiByteToWideChar
135 : && !(win32_fname_wchar=make_win32_path_UTF8_2_wchar_w(fname)))
136 : logp("could not get widename!");
137 :
138 : if(flags & O_CREAT)
139 : {
140 : /* Create */
141 :
142 : if(bfd->winattr & FILE_ATTRIBUTE_DIRECTORY)
143 : mkdir(fname, 0777);
144 :
145 : if(bfd->use_backup_api)
146 : {
147 : dwaccess=GENERIC_WRITE
148 : | FILE_ALL_ACCESS
149 : | WRITE_OWNER
150 : | WRITE_DAC
151 : | ACCESS_SYSTEM_SECURITY;
152 : dwflags=FILE_FLAG_BACKUP_SEMANTICS;
153 : }
154 : else
155 : {
156 : dwaccess=GENERIC_WRITE;
157 : dwflags=0;
158 : }
159 :
160 : if(p_CreateFileW && p_MultiByteToWideChar)
161 : // unicode open for create write
162 : bfd->fh=p_CreateFileW((LPCWSTR)win32_fname_wchar,
163 : dwaccess, /* Requested access */
164 : 0, /* Shared mode */
165 : NULL, /* SecurityAttributes */
166 : CREATE_ALWAYS, /* CreationDisposition */
167 : dwflags, /* Flags and attributes */
168 : NULL); /* TemplateFile */
169 : else
170 : // ascii open
171 : bfd->fh=p_CreateFileA(win32_fname,
172 : dwaccess, /* Requested access */
173 : 0, /* Shared mode */
174 : NULL, /* SecurityAttributes */
175 : CREATE_ALWAYS, /* CreationDisposition */
176 : dwflags, /* Flags and attributes */
177 : NULL); /* TemplateFile */
178 :
179 : bfd->mode=BF_WRITE;
180 : }
181 : else if(flags & O_WRONLY)
182 : {
183 : /* Open existing for write */
184 : if(bfd->use_backup_api)
185 : {
186 : dwaccess=GENERIC_WRITE
187 : | WRITE_OWNER
188 : | WRITE_DAC;
189 : dwflags=FILE_FLAG_BACKUP_SEMANTICS
190 : | FILE_FLAG_OPEN_REPARSE_POINT;
191 : }
192 : else
193 : {
194 : dwaccess=GENERIC_WRITE;
195 : dwflags=0;
196 : }
197 :
198 : if(p_CreateFileW && p_MultiByteToWideChar)
199 : // unicode open for open existing write
200 : bfd->fh=p_CreateFileW((LPCWSTR)win32_fname_wchar,
201 : dwaccess, /* Requested access */
202 : 0, /* Shared mode */
203 : NULL, /* SecurityAttributes */
204 : OPEN_EXISTING, /* CreationDisposition */
205 : dwflags, /* Flags and attributes */
206 : NULL); /* TemplateFile */
207 : else
208 : // ascii open
209 : bfd->fh=p_CreateFileA(win32_fname,
210 : dwaccess, /* Requested access */
211 : 0, /* Shared mode */
212 : NULL, /* SecurityAttributes */
213 : OPEN_EXISTING, /* CreationDisposition */
214 : dwflags, /* Flags and attributes */
215 : NULL); /* TemplateFile */
216 :
217 : bfd->mode=BF_WRITE;
218 :
219 : }
220 : else
221 : {
222 : /* Read */
223 : if(bfd->use_backup_api)
224 : {
225 : dwaccess=GENERIC_READ|READ_CONTROL
226 : | ACCESS_SYSTEM_SECURITY;
227 : dwflags=FILE_FLAG_BACKUP_SEMANTICS
228 : | FILE_FLAG_SEQUENTIAL_SCAN
229 : | FILE_FLAG_OPEN_REPARSE_POINT;
230 : dwshare=FILE_SHARE_READ
231 : | FILE_SHARE_WRITE
232 : | FILE_SHARE_DELETE;
233 : }
234 : else
235 : {
236 : dwaccess=GENERIC_READ;
237 : dwflags=0;
238 : dwshare=FILE_SHARE_READ
239 : | FILE_SHARE_WRITE;
240 : }
241 :
242 : if(p_CreateFileW && p_MultiByteToWideChar)
243 : // unicode open for open existing read
244 : bfd->fh=p_CreateFileW((LPCWSTR)win32_fname_wchar,
245 : dwaccess, /* Requested access */
246 : dwshare, /* Share modes */
247 : NULL, /* SecurityAttributes */
248 : OPEN_EXISTING, /* CreationDisposition */
249 : dwflags, /* Flags and attributes */
250 : NULL); /* TemplateFile */
251 : else
252 : // ascii open
253 : bfd->fh=p_CreateFileA(win32_fname,
254 : dwaccess, /* Requested access */
255 : dwshare, /* Share modes */
256 : NULL, /* SecurityAttributes */
257 : OPEN_EXISTING, /* CreationDisposition */
258 : dwflags, /* Flags and attributes */
259 : NULL); /* TemplateFile */
260 :
261 : bfd->mode=BF_READ;
262 : }
263 :
264 : if(bfd->fh==INVALID_HANDLE_VALUE)
265 : {
266 : bfile_error(bfd);
267 : bfd->mode=BF_CLOSED;
268 : }
269 : else
270 : {
271 : if(!(bfd->path=strdup_w(fname, __func__)))
272 : return -1;
273 : }
274 : bfd->lpContext=NULL;
275 : if(win32_fname_wchar) free(win32_fname_wchar);
276 : if(win32_fname) free(win32_fname);
277 : return bfd->mode==BF_CLOSED;
278 : }
279 :
280 : static int bfile_close_encrypted(BFILE *bfd, struct asfd *asfd)
281 : {
282 : CloseEncryptedFileRaw(bfd->pvContext);
283 : if(bfd->mode==BF_WRITE)
284 : attribs_set(asfd,
285 : bfd->path, &bfd->statp, bfd->winattr, bfd->cntr);
286 : bfd->pvContext=NULL;
287 : bfd->mode=BF_CLOSED;
288 : if(bfd->path)
289 : {
290 : free(bfd->path);
291 : bfd->path=NULL;
292 : }
293 : return 0;
294 : }
295 :
296 : // Return 0 on success, -1 on error.
297 : static int bfile_close(BFILE *bfd, struct asfd *asfd)
298 : {
299 : int ret=-1;
300 :
301 : if(!bfd) return 0;
302 :
303 : if(bfd->mode==BF_CLOSED) return 0;
304 :
305 : if(bfd->winattr & FILE_ATTRIBUTE_ENCRYPTED)
306 : return bfile_close_encrypted(bfd, asfd);
307 :
308 : /*
309 : * We need to tell the API to release the buffer it
310 : * allocated in lpContext. We do so by calling the
311 : * API one more time, but with the Abort bit set.
312 : */
313 : if(bfd->use_backup_api && bfd->mode==BF_READ)
314 : {
315 : BYTE buf[10];
316 : if(bfd->lpContext
317 : && !p_BackupRead(bfd->fh,
318 : buf, /* buffer */
319 : (DWORD)0, /* bytes to read */
320 : &bfd->rw_bytes, /* bytes read */
321 : 1, /* Abort */
322 : 1, /* ProcessSecurity */
323 : &bfd->lpContext)) /* Read context */
324 : {
325 : bfile_error(NULL);
326 : goto end;
327 : }
328 : }
329 : else if(bfd->use_backup_api && bfd->mode==BF_WRITE)
330 : {
331 : BYTE buf[10];
332 : if(bfd->lpContext
333 : && !p_BackupWrite(bfd->fh,
334 : buf, /* buffer */
335 : (DWORD)0, /* bytes to read */
336 : &bfd->rw_bytes, /* bytes written */
337 : 1, /* Abort */
338 : 1, /* ProcessSecurity */
339 : &bfd->lpContext)) /* Write context */
340 : {
341 : bfile_error(NULL);
342 : goto end;
343 : }
344 : }
345 : if(!CloseHandle(bfd->fh))
346 : {
347 : bfile_error(NULL);
348 : goto end;
349 : }
350 :
351 : if(bfd->mode==BF_WRITE)
352 : attribs_set(asfd,
353 : bfd->path, &bfd->statp, bfd->winattr, bfd->cntr);
354 : bfd->lpContext=NULL;
355 : bfd->mode=BF_CLOSED;
356 :
357 : ret=0;
358 : end:
359 : if(bfd->path)
360 : {
361 : free(bfd->path);
362 : bfd->path=NULL;
363 : }
364 : return ret;
365 : }
366 :
367 : // Returns: bytes read on success, or 0 on EOF, -1 on error.
368 : static ssize_t bfile_read(BFILE *bfd, void *buf, size_t count)
369 : {
370 : bfd->rw_bytes=0;
371 :
372 : if(bfd->use_backup_api)
373 : {
374 : if(!p_BackupRead(bfd->fh,
375 : (BYTE *)buf,
376 : count,
377 : &bfd->rw_bytes,
378 : 0, /* no Abort */
379 : 1, /* Process Security */
380 : &bfd->lpContext)) /* Context */
381 : return bfile_error(bfd);
382 : }
383 : else
384 : {
385 : if(!ReadFile(bfd->fh,
386 : buf,
387 : count,
388 : &bfd->rw_bytes,
389 : NULL))
390 : return bfile_error(bfd);
391 : }
392 :
393 : return (ssize_t)bfd->rw_bytes;
394 : }
395 :
396 : static ssize_t bfile_write(BFILE *bfd, void *buf, size_t count)
397 : {
398 : bfd->rw_bytes = 0;
399 :
400 : if(bfd->use_backup_api)
401 : {
402 : if(!p_BackupWrite(bfd->fh,
403 : (BYTE *)buf,
404 : count,
405 : &bfd->rw_bytes,
406 : 0, /* No abort */
407 : 1, /* Process Security */
408 : &bfd->lpContext)) /* Context */
409 : return bfile_error(bfd);
410 : }
411 : else
412 : {
413 : if(!WriteFile(bfd->fh,
414 : buf,
415 : count,
416 : &bfd->rw_bytes,
417 : NULL))
418 : return bfile_error(bfd);
419 : }
420 : return (ssize_t)bfd->rw_bytes;
421 : }
422 :
423 : #else
424 :
425 5 : static int bfile_close(BFILE *bfd, struct asfd *asfd)
426 : {
427 5 : if(!bfd || bfd->mode==BF_CLOSED) return 0;
428 :
429 0 : if(!close(bfd->fd))
430 : {
431 0 : if(bfd->mode==BF_WRITE)
432 : attribs_set(asfd, bfd->path,
433 0 : &bfd->statp, bfd->winattr, bfd->cntr);
434 0 : bfd->mode=BF_CLOSED;
435 0 : bfd->fd=-1;
436 0 : free_w(&bfd->path);
437 0 : return 0;
438 : }
439 0 : free_w(&bfd->path);
440 0 : return -1;
441 : }
442 :
443 0 : static int bfile_open(BFILE *bfd,
444 : struct asfd *asfd, const char *fname, int flags, mode_t mode)
445 : {
446 0 : if(!bfd) return 0;
447 0 : if(bfd->mode!=BF_CLOSED && bfd->close(bfd, asfd))
448 0 : return -1;
449 0 : if((bfd->fd=open(fname, flags, mode))<0)
450 0 : return -1;
451 0 : if(flags & O_CREAT || flags & O_WRONLY)
452 0 : bfd->mode=BF_WRITE;
453 : else
454 0 : bfd->mode=BF_READ;
455 0 : if(!(bfd->path=strdup_w(fname, __func__)))
456 0 : return -1;
457 0 : return 0;
458 : }
459 :
460 0 : static ssize_t bfile_read(BFILE *bfd, void *buf, size_t count)
461 : {
462 0 : return read(bfd->fd, buf, count);
463 : }
464 :
465 0 : static ssize_t bfile_write(BFILE *bfd, void *buf, size_t count)
466 : {
467 0 : return write(bfd->fd, buf, count);
468 : }
469 :
470 : #endif
471 :
472 0 : static int bfile_open_for_send(BFILE *bfd, struct asfd *asfd,
473 : const char *fname, int64_t winattr, int atime,
474 : struct cntr *cntr, enum protocol protocol)
475 : {
476 0 : if(protocol==PROTO_1
477 0 : && bfd->mode!=BF_CLOSED)
478 : {
479 : #ifdef HAVE_WIN32
480 : if(bfd->path && !strcmp(bfd->path, fname))
481 : {
482 : // Already open after reading the VSS data.
483 : // Time now for the actual file data.
484 : return 0;
485 : }
486 : else
487 : {
488 : #endif
489 : // Close the open bfd so that it can be
490 : // used again
491 0 : bfd->close(bfd, asfd);
492 : #ifdef HAVE_WIN32
493 : }
494 : #endif
495 : }
496 :
497 0 : bfile_init(bfd, winattr, cntr);
498 0 : if(bfile_open(bfd, asfd, fname, O_RDONLY|O_BINARY
499 : #ifdef O_NOATIME
500 : |atime?0:O_NOATIME
501 : #endif
502 0 : , 0))
503 : {
504 : berrno be;
505 0 : berrno_init(&be);
506 : logw(asfd, cntr,
507 : "Could not open %s: %s\n",
508 0 : fname, berrno_bstrerror(&be, errno));
509 0 : return -1;
510 : }
511 0 : return 0;
512 : }
513 :
514 32815 : void bfile_setup_funcs(BFILE *bfd)
515 : {
516 32815 : bfd->open=bfile_open;
517 32815 : bfd->close=bfile_close;
518 32815 : bfd->read=bfile_read;
519 32815 : bfd->write=bfile_write;
520 32815 : bfd->open_for_send=bfile_open_for_send;
521 : #ifdef HAVE_WIN32
522 : bfd->set_win32_api=bfile_set_win32_api;
523 : #endif
524 32815 : }
525 :
526 5 : void bfile_init(BFILE *bfd, int64_t winattr, struct cntr *cntr)
527 : {
528 5 : memset(bfd, 0, sizeof(BFILE));
529 5 : bfd->mode=BF_CLOSED;
530 5 : bfd->winattr=winattr;
531 5 : bfd->cntr=cntr;
532 5 : if(!bfd->open) bfile_setup_funcs(bfd);
533 : #ifdef HAVE_WIN32
534 : bfile_set_win32_api(bfd, 1);
535 : #else
536 5 : bfd->fd=-1;
537 : #endif
538 5 : }
539 :
540 5 : BFILE *bfile_alloc(void)
541 : {
542 5 : return (BFILE *)calloc_w(1, sizeof(BFILE), __func__);
543 : }
|