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