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