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