Line data Source code
1 : #include "../burp.h"
2 : #include "../alloc.h"
3 : #include "../asfd.h"
4 : #include "../async.h"
5 : #include "../attribs.h"
6 : #include "../berrno.h"
7 : #include "../cmd.h"
8 : #include "../cntr.h"
9 : #include "../fsops.h"
10 : #include "../handy.h"
11 : #include "../log.h"
12 : #include "../prepend.h"
13 : #include "../protocol2/blk.h"
14 : #include "cvss.h"
15 : #include "protocol1/restore.h"
16 : #include "protocol2/restore.h"
17 : #include "restore.h"
18 :
19 7 : int restore_interrupt(struct asfd *asfd,
20 : struct sbuf *sb, const char *msg, struct cntr *cntr,
21 : enum protocol protocol)
22 : {
23 7 : int ret=0;
24 7 : char *path=NULL;
25 7 : struct iobuf *rbuf=asfd->rbuf;
26 :
27 7 : if(cntr)
28 : {
29 0 : cntr_add(cntr, CMD_WARNING, 1);
30 0 : logp("WARNING: %s\n", msg);
31 0 : if(asfd->write_str(asfd, CMD_WARNING, msg)) goto end;
32 : }
33 :
34 : // If it is file data, get the server
35 : // to interrupt the flow and move on.
36 14 : if(!iobuf_is_filedata(&sb->path)
37 7 : && !iobuf_is_vssdata(&sb->path))
38 : return 0;
39 :
40 7 : if(protocol==PROTO_1)
41 0 : path=sb->protocol1->datapth.buf;
42 7 : else if(protocol==PROTO_2)
43 7 : path=sb->path.buf;
44 :
45 7 : if(!path) return 0;
46 :
47 7 : if(asfd->write_str(asfd, CMD_INTERRUPT, path))
48 : goto end;
49 :
50 : // Read to the end file marker.
51 : while(1)
52 : {
53 714 : iobuf_free_content(rbuf);
54 714 : if(asfd->read(asfd))
55 : goto end;
56 714 : if(!rbuf->len) continue;
57 :
58 714 : switch(rbuf->cmd)
59 : {
60 : case CMD_APPEND:
61 : case CMD_DATA:
62 : continue;
63 : case CMD_END_FILE:
64 : ret=0;
65 : goto end;
66 : default:
67 0 : iobuf_log_unexpected(rbuf, __func__);
68 0 : goto end;
69 : }
70 : }
71 : end:
72 7 : iobuf_free_content(rbuf);
73 7 : return ret;
74 : }
75 :
76 6 : static int make_link(struct asfd *asfd,
77 : const char *fname, const char *lnk, enum cmd cmd, struct cntr *cntr,
78 : const char *restore_prefix)
79 : {
80 6 : int ret=-1;
81 :
82 : #ifdef HAVE_WIN32
83 : logw(asfd, cntr, "windows seems not to support hardlinks or symlinks\n");
84 : #else
85 6 : unlink(fname);
86 6 : if(cmd==CMD_HARD_LINK)
87 : {
88 1 : char *flnk=NULL;
89 1 : if(!(flnk=prepend_s(restore_prefix, lnk)))
90 : {
91 0 : log_out_of_memory(__func__);
92 0 : return -1;
93 : }
94 : //printf("%s -> %s\n", fname, flnk);
95 1 : ret=link(flnk, fname);
96 1 : free_w(&flnk);
97 : }
98 5 : else if(cmd==CMD_SOFT_LINK)
99 : {
100 : //printf("%s -> %s\n", fname, lnk);
101 5 : ret=symlink(lnk, fname);
102 : }
103 : else
104 : {
105 0 : logp("unexpected link command: %c\n", cmd);
106 0 : ret=-1;
107 : }
108 : #endif
109 :
110 6 : if(ret) logp("could not %slink %s -> %s: %s\n",
111 : cmd==CMD_HARD_LINK?"hard":"sym",
112 0 : fname, lnk, strerror(errno));
113 :
114 : return ret;
115 : }
116 :
117 : // FIX THIS: Maybe should be in bfile.c.
118 18 : enum ofr_e open_for_restore(struct asfd *asfd, BFILE *bfd, const char *path,
119 : struct sbuf *sb, int vss_restore, struct cntr *cntr,
120 : enum protocol protocol)
121 : {
122 : static int flags;
123 18 : if(bfd->mode!=BF_CLOSED)
124 : {
125 : #ifdef HAVE_WIN32
126 : if(bfd->path && !strcmp(bfd->path, path))
127 : {
128 : // Already open after restoring the VSS data.
129 : // Time now for the actual file data.
130 : return OFR_OK;
131 : }
132 : else
133 : {
134 : #endif
135 12 : if(bfd->close(bfd, asfd))
136 : {
137 : logp("error closing %s in %s()\n",
138 0 : path, __func__);
139 0 : return OFR_ERROR;
140 : }
141 : #ifdef HAVE_WIN32
142 : }
143 : #endif
144 : }
145 :
146 : #ifdef HAVE_WIN32
147 : // Some massive hacks to work around times that winattr was not
148 : // getting set correctly inside server side backups.
149 : // The EFS one will stop burp segfaulting when restoring affected
150 : // EFS files.
151 : if(sb->path.cmd==CMD_EFS_FILE)
152 : sb->winattr |= FILE_ATTRIBUTE_ENCRYPTED;
153 : if(S_ISDIR(sb->statp.st_mode))
154 : sb->winattr |= FILE_ATTRIBUTE_DIRECTORY;
155 : #endif
156 :
157 18 : bfile_init(bfd, sb->winattr, cntr);
158 : #ifdef HAVE_WIN32
159 : bfd->set_win32_api(bfd, vss_restore);
160 : #endif
161 18 : if(S_ISDIR(sb->statp.st_mode))
162 : {
163 : // Windows directories are treated as having file data.
164 0 : flags=O_WRONLY|O_BINARY;
165 0 : mkdir(path, 0777);
166 : }
167 : else
168 18 : flags=O_WRONLY|O_BINARY|O_CREAT|O_TRUNC;
169 :
170 18 : if(bfd->open(bfd, asfd, path, flags, S_IRUSR | S_IWUSR))
171 : {
172 : berrno be;
173 0 : berrno_init(&be);
174 0 : char msg[256]="";
175 : snprintf(msg, sizeof(msg), "Could not open for writing %s: %s",
176 0 : path, berrno_bstrerror(&be, errno));
177 0 : if(restore_interrupt(asfd, sb, msg, cntr, protocol))
178 : return OFR_ERROR;
179 0 : return OFR_CONTINUE;
180 : }
181 : // Add attributes to bfd so that they can be set when it is closed.
182 18 : bfd->winattr=sb->winattr;
183 18 : memcpy(&bfd->statp, &sb->statp, sizeof(struct stat));
184 18 : return OFR_OK;
185 : }
186 :
187 : static char *build_msg(const char *text, const char *param)
188 : {
189 : static char msg[256]="";
190 : snprintf(msg, sizeof(msg), text, param);
191 : return msg;
192 : }
193 :
194 : #ifndef HAVE_WIN32
195 0 : static void do_logw(struct asfd *asfd, struct cntr *cntr,
196 : const char *text, const char *param)
197 : {
198 0 : logw(asfd, cntr, "%s", build_msg(text, param));
199 0 : }
200 : #endif
201 :
202 0 : static int warn_and_interrupt(struct asfd *asfd, struct sbuf *sb,
203 : struct cntr *cntr, enum protocol protocol,
204 : const char *text, const char *param)
205 : {
206 : return restore_interrupt(asfd, sb, build_msg(text, param), cntr,
207 0 : protocol);
208 : }
209 :
210 0 : static int restore_special(struct asfd *asfd, struct sbuf *sb,
211 : const char *fname, enum action act, struct cntr *cntr,
212 : enum protocol protocol)
213 : {
214 0 : int ret=0;
215 0 : char *rpath=NULL;
216 : #ifdef HAVE_WIN32
217 : logw(asfd, cntr, "Cannot restore special files to Windows: %s\n", fname);
218 : goto end;
219 : #else
220 0 : struct stat statp=sb->statp;
221 :
222 0 : if(act==ACTION_VERIFY)
223 : {
224 0 : cntr_add(cntr, CMD_SPECIAL, 1);
225 0 : return 0;
226 : }
227 :
228 0 : if(build_path(fname, "", &rpath, NULL))
229 : {
230 : // failed - do a warning
231 0 : if(restore_interrupt(asfd, sb,
232 : build_msg("build path failed: %s", fname),
233 0 : cntr, protocol))
234 0 : ret=-1;
235 : goto end;
236 : }
237 0 : if(S_ISFIFO(statp.st_mode))
238 : {
239 0 : if(mkfifo(rpath, statp.st_mode) && errno!=EEXIST)
240 : do_logw(asfd, cntr,
241 0 : "Cannot make fifo: %s\n", strerror(errno));
242 : else
243 : {
244 0 : attribs_set(asfd, rpath, &statp, sb->winattr, cntr);
245 0 : cntr_add(cntr, CMD_SPECIAL, 1);
246 : }
247 : }
248 0 : else if(S_ISSOCK(statp.st_mode))
249 : {
250 0 : if(mksock(rpath))
251 : do_logw(asfd, cntr,
252 0 : "Cannot make socket: %s\n", strerror(errno));
253 : else
254 : {
255 0 : attribs_set(asfd, rpath, &statp, sb->winattr, cntr);
256 0 : cntr_add(cntr, CMD_SPECIAL, 1);
257 : }
258 : }
259 : #ifdef S_IFDOOR // Solaris high speed RPC mechanism
260 : else if (S_ISDOOR(statp.st_mode))
261 : do_logw(asfd, cntr,
262 : "Skipping restore of door file: %s\n", fname);
263 : #endif
264 : #ifdef S_IFPORT // Solaris event port for handling AIO
265 : else if (S_ISPORT(statp.st_mode))
266 : do_logw(asfd, cntr,
267 : "Skipping restore of event port file: %s\n", fname);
268 : #endif
269 0 : else if(mknod(fname, statp.st_mode, statp.st_rdev) && errno!=EEXIST)
270 0 : do_logw(asfd, cntr, "Cannot make node: %s\n", strerror(errno));
271 : else
272 : {
273 0 : attribs_set(asfd, rpath, &statp, sb->winattr, cntr);
274 0 : cntr_add(cntr, CMD_SPECIAL, 1);
275 : }
276 : #endif
277 : end:
278 0 : free_w(&rpath);
279 0 : return ret;
280 : }
281 :
282 0 : int restore_dir(struct asfd *asfd, struct sbuf *sb,
283 : const char *dname, enum action act, struct cntr *cntr,
284 : enum protocol protocol)
285 : {
286 0 : int ret=0;
287 0 : char *rpath=NULL;
288 0 : if(act==ACTION_RESTORE)
289 : {
290 0 : if(build_path(dname, "", &rpath, NULL))
291 : {
292 : ret=warn_and_interrupt(asfd, sb, cntr, protocol,
293 0 : "build path failed: %s", dname);
294 0 : goto end;
295 : }
296 0 : else if(is_dir_lstat(rpath)<=0)
297 : {
298 0 : if(mkdir(rpath, 0777))
299 : {
300 : ret=warn_and_interrupt(asfd, sb, cntr, protocol,
301 0 : "mkdir error: %s", strerror(errno));
302 0 : goto end;
303 : }
304 : }
305 0 : attribs_set(asfd, rpath, &(sb->statp), sb->winattr, cntr);
306 0 : if(!ret) cntr_add(cntr, sb->path.cmd, 1);
307 : }
308 0 : else cntr_add(cntr, sb->path.cmd, 1);
309 : end:
310 0 : free_w(&rpath);
311 0 : return ret;
312 : }
313 :
314 6 : static int restore_link(struct asfd *asfd, struct sbuf *sb,
315 : const char *fname, enum action act, struct cntr *cntr,
316 : enum protocol protocol, const char *restore_prefix)
317 : {
318 6 : int ret=0;
319 :
320 6 : if(act==ACTION_RESTORE)
321 : {
322 6 : char *rpath=NULL;
323 6 : if(build_path(fname, "", &rpath, NULL))
324 : {
325 : ret=warn_and_interrupt(asfd, sb, cntr, protocol,
326 0 : "build path failed: %s", fname);
327 0 : goto end;
328 : }
329 6 : else if(make_link(asfd,
330 : fname, sb->link.buf, sb->link.cmd,
331 6 : cntr, restore_prefix))
332 : {
333 : ret=warn_and_interrupt(asfd, sb, cntr, protocol,
334 0 : "could not create link", "");
335 0 : goto end;
336 : }
337 : else if(!ret)
338 : {
339 : attribs_set(asfd, fname,
340 6 : &(sb->statp), sb->winattr, cntr);
341 6 : cntr_add(cntr, sb->path.cmd, 1);
342 : }
343 6 : free_w(&rpath);
344 : }
345 0 : else cntr_add(cntr, sb->path.cmd, 1);
346 : end:
347 6 : return ret;
348 : }
349 :
350 : static void strip_invalid_characters(char **path)
351 : {
352 : #ifdef HAVE_WIN32
353 : char *ch = *path;
354 : if (ch[0] != 0 && ch[1] != 0) {
355 : ch += 2;
356 : while (*ch) {
357 : switch (*ch) {
358 : case ':':
359 : case '<':
360 : case '>':
361 : case '*':
362 : case '?':
363 : case '|':
364 : *ch = '_';
365 : break;
366 : }
367 : ch++;
368 : }
369 : }
370 : #endif
371 : }
372 :
373 : static const char *act_str(enum action act)
374 : {
375 : static const char *ret=NULL;
376 20 : if(act==ACTION_RESTORE) ret="restore";
377 0 : else ret="verify";
378 20 : return ret;
379 : }
380 :
381 : // Return 1 for ok, -1 for error, 0 for too many components stripped.
382 0 : static int strip_path_components(struct asfd *asfd,
383 : struct sbuf *sb, int strip, struct cntr *cntr, enum protocol protocol)
384 : {
385 0 : int s=0;
386 0 : char *tmp=NULL;
387 0 : char *cp=sb->path.buf;
388 0 : char *dp=NULL;
389 0 : for(s=0; cp && *cp && s<strip; s++)
390 : {
391 0 : if(!(dp=strchr(cp, '/')))
392 : {
393 0 : char msg[256]="";
394 : snprintf(msg, sizeof(msg),
395 0 : "Stripped too many components: %s", sb->path.buf);
396 0 : if(restore_interrupt(asfd, sb, msg, cntr, protocol))
397 : return -1;
398 0 : return 0;
399 : }
400 0 : cp=dp+1;
401 : }
402 0 : if(!cp)
403 : {
404 0 : char msg[256]="";
405 : snprintf(msg, sizeof(msg),
406 0 : "Stripped too many components: %s", sb->path.buf);
407 0 : if(restore_interrupt(asfd, sb, msg, cntr, protocol))
408 : return -1;
409 0 : return 0;
410 : }
411 0 : if(!(tmp=strdup_w(cp, __func__)))
412 : return -1;
413 0 : free_w(&sb->path.buf);
414 0 : sb->path.buf=tmp;
415 0 : return 1;
416 : }
417 :
418 32 : static int overwrite_ok(struct sbuf *sb,
419 : int overwrite,
420 : #ifdef HAVE_WIN32
421 : BFILE *bfd,
422 : #endif
423 : const char *fullpath)
424 : {
425 : struct stat checkstat;
426 :
427 : // User specified overwrite is OK.
428 : #ifdef HAVE_WIN32
429 : if(overwrite) return 1;
430 : #else
431 : // User specified overwrite is OK,
432 : // UNLESS we are trying to overwrite the file with trailing VSS data.
433 32 : if(overwrite)
434 : return (sb->path.cmd!=CMD_VSS_T
435 0 : && sb->path.cmd!=CMD_ENC_VSS_T);
436 : #endif
437 :
438 32 : if(!S_ISDIR(sb->statp.st_mode)
439 32 : && sb->path.cmd!=CMD_METADATA
440 32 : && sb->path.cmd!=CMD_ENC_METADATA
441 32 : && sb->path.cmd!=CMD_VSS
442 32 : && sb->path.cmd!=CMD_ENC_VSS)
443 : {
444 : #ifdef HAVE_WIN32
445 : // If Windows previously got some VSS data, it needs to append
446 : // the file data to the already open bfd.
447 : // And trailing VSS data.
448 : if(bfd->mode!=BF_CLOSED
449 : && (sb->path.cmd==CMD_FILE || sb->path.cmd==CMD_ENC_FILE
450 : || sb->path.cmd==CMD_VSS_T || sb->path.cmd==CMD_ENC_VSS_T)
451 : && bfd->path && !strcmp(bfd->path, fullpath))
452 : return 1;
453 : #endif
454 : // If we have file data and the destination is
455 : // a fifo, it is OK to write to the fifo.
456 64 : if((sb->path.cmd==CMD_FILE || sb->path.cmd==CMD_ENC_FILE)
457 32 : && S_ISFIFO(sb->statp.st_mode))
458 : return 1;
459 :
460 : // File path exists. Do not overwrite.
461 32 : if(!lstat(fullpath, &checkstat)) return 0;
462 : }
463 :
464 : return 1;
465 : }
466 :
467 14 : static int write_data(struct asfd *asfd, BFILE *bfd, struct blk *blk)
468 : {
469 14 : if(bfd->mode==BF_CLOSED)
470 0 : logp("Got data without an open file\n");
471 : else
472 : {
473 : int w;
474 14 : if((w=bfd->write(bfd, blk->data, blk->length))<=0)
475 : {
476 : logp("%s(): error when appending %d: %d\n",
477 0 : __func__, blk->length, w);
478 0 : asfd->write_str(asfd, CMD_ERROR, "write failed");
479 : return -1;
480 : }
481 : }
482 : return 0;
483 : }
484 :
485 : #define RESTORE_STREAM "restore_stream"
486 : #define RESTORE_SPOOL "restore_spool"
487 :
488 : static char *restore_style=NULL;
489 :
490 2 : static enum asl_ret restore_style_func(struct asfd *asfd,
491 : struct conf **confs, void *param)
492 : {
493 2 : char msg[32]="";
494 2 : restore_style=NULL;
495 2 : if(strcmp(asfd->rbuf->buf, RESTORE_STREAM)
496 0 : && strcmp(asfd->rbuf->buf, RESTORE_SPOOL))
497 : {
498 0 : iobuf_log_unexpected(asfd->rbuf, __func__);
499 0 : return ASL_END_ERROR;
500 : }
501 2 : snprintf(msg, sizeof(msg), "%s_ok", asfd->rbuf->buf);
502 2 : if(asfd->write_str(asfd, CMD_GEN, msg))
503 : return ASL_END_ERROR;
504 2 : restore_style=asfd->rbuf->buf;
505 2 : iobuf_init(asfd->rbuf);
506 2 : return ASL_END_OK;
507 : }
508 :
509 8 : static char *get_restore_style(struct asfd *asfd, struct conf **confs)
510 : {
511 8 : if(get_protocol(confs)==PROTO_1)
512 5 : return strdup_w(RESTORE_STREAM, __func__);
513 3 : if(asfd->simple_loop(asfd, confs, NULL, __func__,
514 3 : restore_style_func)) return NULL;
515 2 : return restore_style;
516 : }
517 :
518 0 : static enum asl_ret restore_spool_func(struct asfd *asfd,
519 : struct conf **confs, void *param)
520 : {
521 : static char **datpath;
522 : static struct iobuf *rbuf;
523 0 : datpath=(char **)param;
524 0 : rbuf=asfd->rbuf;
525 0 : if(!strncmp_w(rbuf->buf, "dat="))
526 : {
527 0 : char *fpath=NULL;
528 0 : if(!(fpath=prepend_s(*datpath, rbuf->buf+4))
529 0 : || build_path_w(fpath)
530 0 : || receive_a_file(asfd, fpath, get_cntr(confs)))
531 : return ASL_END_ERROR;
532 0 : iobuf_free_content(rbuf);
533 : }
534 0 : else if(!strcmp(rbuf->buf, "datfilesend"))
535 : {
536 0 : if(asfd->write_str(asfd, CMD_GEN, "datfilesend_ok"))
537 : return ASL_END_ERROR;
538 0 : return ASL_END_OK;
539 : }
540 : return ASL_CONTINUE;
541 : }
542 :
543 0 : static int restore_spool(struct asfd *asfd, struct conf **confs, char **datpath)
544 : {
545 0 : const char *restore_spool=get_string(confs[OPT_RESTORE_SPOOL]);
546 0 : logp("Spooling restore to: %s\n", restore_spool);
547 :
548 0 : if(!(*datpath=prepend_s(restore_spool, "incoming-data")))
549 : return -1;
550 :
551 : return asfd->simple_loop(asfd, confs, datpath,
552 0 : __func__, restore_spool_func);
553 : }
554 :
555 8 : int do_restore_client(struct asfd *asfd,
556 : struct conf **confs, enum action act, int vss_restore)
557 : {
558 8 : int ret=-1;
559 8 : char msg[512]="";
560 8 : struct sbuf *sb=NULL;
561 8 : struct blk *blk=NULL;
562 8 : BFILE *bfd=NULL;
563 8 : char *fullpath=NULL;
564 8 : char *style=NULL;
565 8 : char *datpath=NULL;
566 8 : struct cntr *cntr=get_cntr(confs);
567 8 : enum protocol protocol=get_protocol(confs);
568 8 : int strip=get_int(confs[OPT_STRIP]);
569 8 : int overwrite=get_int(confs[OPT_OVERWRITE]);
570 8 : const char *backup=get_string(confs[OPT_BACKUP]);
571 8 : const char *regex=get_string(confs[OPT_REGEX]);
572 8 : const char *restore_prefix=get_string(confs[OPT_RESTOREPREFIX]);
573 8 : const char *encryption_password=get_string(confs[OPT_ENCRYPTION_PASSWORD]);
574 :
575 8 : if(!(bfd=bfile_alloc())) goto end;
576 :
577 8 : bfile_init(bfd, 0, cntr);
578 :
579 : snprintf(msg, sizeof(msg), "%s %s:%s", act_str(act),
580 16 : backup?backup:"", regex?regex:"");
581 8 : logp("doing %s\n", msg);
582 16 : if(asfd->write_str(asfd, CMD_GEN, msg)
583 8 : || asfd_read_expect(asfd, CMD_GEN, "ok"))
584 : goto error;
585 8 : logp("doing %s confirmed\n", act_str(act));
586 :
587 : #if defined(HAVE_WIN32)
588 : if(act==ACTION_RESTORE) win32_enable_backup_privileges();
589 : #endif
590 :
591 8 : if(!(style=get_restore_style(asfd, confs)))
592 : goto error;
593 7 : if(!strcmp(style, RESTORE_SPOOL))
594 : {
595 0 : if(restore_spool(asfd, confs, &datpath))
596 : goto error;
597 : }
598 : else
599 7 : logp("Streaming restore direct\n");
600 :
601 7 : logf("\n");
602 :
603 7 : if(get_int(confs[OPT_SEND_CLIENT_CNTR]) && cntr_recv(asfd, confs))
604 : goto error;
605 :
606 46 : if(!(sb=sbuf_alloc(protocol))
607 7 : || (protocol==PROTO_2 && !(blk=blk_alloc())))
608 : {
609 0 : log_and_send_oom(asfd, __func__);
610 0 : goto error;
611 : }
612 :
613 : while(1)
614 : {
615 52 : sbuf_free_content(sb);
616 52 : if(protocol==PROTO_1)
617 13 : sb->flags |= SBUF_CLIENT_RESTORE_HACK;
618 :
619 52 : switch(sbuf_fill_from_net(sb, asfd, blk, datpath, cntr))
620 : {
621 : case 0: break;
622 4 : case 1: if(asfd->write_str(asfd, CMD_GEN,
623 4 : "restoreend ok")) goto error;
624 : goto end; // It was OK.
625 : default:
626 : case -1: goto error;
627 : }
628 :
629 46 : if(protocol==PROTO_2)
630 : {
631 37 : if(blk->data)
632 : {
633 14 : int wret=0;
634 14 : if(act==ACTION_VERIFY)
635 0 : cntr_add(cntr, CMD_DATA, 1);
636 : else
637 14 : wret=write_data(asfd, bfd, blk);
638 14 : if(!datpath) blk_free_content(blk);
639 14 : blk->data=NULL;
640 14 : if(wret) goto error;
641 : continue;
642 : }
643 23 : else if(sb->endfile.buf)
644 : {
645 : continue;
646 : }
647 : }
648 :
649 32 : switch(sb->path.cmd)
650 : {
651 : case CMD_DIRECTORY:
652 : case CMD_FILE:
653 : case CMD_ENC_FILE:
654 : case CMD_SOFT_LINK:
655 : case CMD_HARD_LINK:
656 : case CMD_SPECIAL:
657 : case CMD_METADATA:
658 : case CMD_ENC_METADATA:
659 : case CMD_VSS:
660 : case CMD_ENC_VSS:
661 : case CMD_VSS_T:
662 : case CMD_ENC_VSS_T:
663 : case CMD_EFS_FILE:
664 32 : if(strip)
665 : {
666 : int s;
667 : s=strip_path_components(asfd,
668 0 : sb, strip, cntr, protocol);
669 0 : if(s<0) goto error;
670 0 : if(s==0)
671 : {
672 : // Too many components stripped
673 : // - carry on.
674 : continue;
675 : }
676 : // It is OK, sb.path is now stripped.
677 : }
678 32 : free_w(&fullpath);
679 32 : if(!(fullpath=prepend_s(restore_prefix,
680 32 : sb->path.buf)))
681 : {
682 0 : log_and_send_oom(asfd, __func__);
683 0 : goto error;
684 : }
685 32 : if(act==ACTION_RESTORE)
686 : {
687 32 : strip_invalid_characters(&fullpath);
688 32 : if(!overwrite_ok(sb, overwrite,
689 : #ifdef HAVE_WIN32
690 : bfd,
691 : #endif
692 64 : fullpath))
693 : {
694 7 : char msg[512]="";
695 : // Something exists at that path.
696 : snprintf(msg, sizeof(msg),
697 7 : "Path exists: %s\n", fullpath);
698 7 : if(restore_interrupt(asfd,
699 7 : sb, msg, cntr, protocol))
700 : goto error;
701 7 : continue;
702 : }
703 : }
704 : break;
705 : case CMD_MESSAGE:
706 : case CMD_WARNING:
707 0 : log_recvd(&sb->path, cntr, 1);
708 0 : logf("\n");
709 0 : continue;
710 : default:
711 : break;
712 : }
713 :
714 25 : switch(sb->path.cmd)
715 : {
716 : // These are the same in both protocol1 and protocol2.
717 : case CMD_DIRECTORY:
718 0 : if(restore_dir(asfd, sb, fullpath, act, cntr,
719 0 : protocol))
720 : goto error;
721 : continue;
722 : case CMD_SOFT_LINK:
723 : case CMD_HARD_LINK:
724 6 : if(restore_link(asfd, sb, fullpath, act, cntr,
725 6 : protocol, restore_prefix))
726 : goto error;
727 : continue;
728 : case CMD_SPECIAL:
729 0 : if(restore_special(asfd, sb,
730 0 : fullpath, act, cntr, protocol))
731 : goto error;
732 : continue;
733 : default:
734 : break;
735 : }
736 :
737 19 : if(protocol==PROTO_2)
738 : {
739 14 : if(restore_switch_protocol2(asfd, sb, fullpath, act,
740 14 : bfd, vss_restore, cntr))
741 : goto error;
742 : }
743 : else
744 : {
745 5 : if(restore_switch_protocol1(asfd, sb, fullpath, act,
746 5 : bfd, vss_restore, cntr, encryption_password))
747 : goto error;
748 : }
749 : }
750 :
751 : end:
752 : ret=0;
753 : error:
754 : // It is possible for a fd to still be open.
755 8 : bfd->close(bfd, asfd);
756 8 : bfile_free(&bfd);
757 :
758 8 : cntr_print_end(cntr);
759 8 : cntr_print(cntr, act);
760 :
761 12 : if(!ret) logp("%s finished\n", act_str(act));
762 4 : else logp("ret: %d\n", ret);
763 :
764 8 : sbuf_free(&sb);
765 8 : free_w(&style);
766 8 : if(datpath)
767 : {
768 0 : recursive_delete(datpath);
769 0 : free_w(&datpath);
770 : }
771 8 : free_w(&fullpath);
772 8 : blk_free(&blk);
773 :
774 8 : return ret;
775 : }
|