1 #include "../burp.h"
2 #include "../alloc.h"
3 #include "../asfd.h"
4 #include "../async.h"
5 #include "../bu.h"
6 #include "../cmd.h"
7 #include "../cntr.h"
8 #include "../cstat.h"
9 #include "../handy.h"
10 #include "../hexmap.h"
11 #include "../linkhash.h"
12 #include "../lock.h"
13 #include "../log.h"
14 #include "../pathcmp.h"
15 #include "../prepend.h"
16 #include "../protocol2/blk.h"
17 #include "../regexp.h"
18 #include "../slist.h"
19 #include "../strlist.h"
20 #include "bu_get.h"
21 #include "child.h"
22 #include "compress.h"
23 #include "manio.h"
24 #include "protocol1/restore.h"
25 #include "protocol2/dpth.h"
26 #include "protocol2/rblk.h"
27 #include "protocol2/restore.h"
28 #include "../protocol2/rabin/rabin.h"
29 #include "rubble.h"
30 #include "sdirs.h"
31
restore_end_func(struct asfd * asfd,struct conf ** confs,void * param)32 static enum asl_ret restore_end_func(struct asfd *asfd,
33 __attribute__ ((unused)) struct conf **confs,
34 __attribute__ ((unused)) void *param)
35 {
36 if(!strcmp(asfd->rbuf->buf, "restoreend ok"))
37 return ASL_END_OK;
38 // Old v2 clients send something slightly different.
39 if(!strcmp(asfd->rbuf->buf, "restoreend_ok"))
40 return ASL_END_OK;
41 iobuf_log_unexpected(asfd->rbuf, __func__);
42 return ASL_END_ERROR;
43 }
44
restore_end(struct asfd * asfd,struct conf ** confs)45 static int restore_end(struct asfd *asfd, struct conf **confs)
46 {
47 if(asfd->write_str(asfd, CMD_GEN, "restoreend")) return -1;
48 return asfd->simple_loop(asfd, confs, NULL, __func__, restore_end_func);
49 }
50
srestore_matches(struct strlist * s,const char * path)51 static int srestore_matches(struct strlist *s, const char *path)
52 {
53 int r=0;
54 if(!s->flag) return 0; // Do not know how to do excludes yet.
55 if((r=strncmp_w(path, s->path))) return 0; // no match
56 if(!r) return 1; // exact match
57 if(*(path+strlen(s->path)+1)=='/')
58 return 1; // matched directory contents
59 return 0; // no match
60 }
61
62 // Used when restore is initiated from the server.
srestore_check(struct conf ** confs,const char * path)63 static int srestore_check(struct conf **confs, const char *path)
64 {
65 struct strlist *l=get_strlist(confs[OPT_INCEXCDIR]);
66
67 // If no includes specified, restore everything.
68 if(!l) return 1;
69
70 for(; l; l=l->next)
71 if(srestore_matches(l, path))
72 return 1;
73 return 0;
74 }
75
restore_list_check(struct asfd * asfd,struct cntr * cntr,struct fzp * rl_fzp,struct iobuf * rl_iobuf,const char * path)76 static int restore_list_check(
77 struct asfd *asfd,
78 struct cntr *cntr,
79 struct fzp *rl_fzp,
80 struct iobuf *rl_iobuf,
81 const char *path
82 )
83 {
84 char *last=NULL;
85
86 do {
87 if(!rl_iobuf->buf)
88 {
89 switch(iobuf_fill_from_fzp(rl_iobuf, rl_fzp))
90 {
91 case 0: break; // OK, read something.
92 case 1: return 0; // Finished, no match.
93 default: return -1; // Error.
94 }
95 }
96
97 if(last && pathcmp(rl_iobuf->buf, last)!=1)
98 {
99 logw(asfd, cntr,
100 "Input file ordering problem: '%s' '%s'",
101 last, rl_iobuf->buf);
102 }
103
104 switch(pathcmp(rl_iobuf->buf, path))
105 {
106 case 0: return 1; // Successful match.
107 case 1: return 0; // Ahead in input, no match.
108 default:
109 // Behind, need to read more from input.
110 free_w(&last);
111 last=rl_iobuf->buf;
112 rl_iobuf->buf=NULL;
113 }
114 } while (1);
115
116 return 0;
117 }
118
want_to_restore(struct asfd * asfd,int srestore,struct fzp * input_fzp,struct iobuf * input_iobuf,struct sbuf * sb,regex_t * regex,enum action act,struct conf ** cconfs)119 static int want_to_restore(
120 struct asfd *asfd,
121 int srestore,
122 struct fzp *input_fzp,
123 struct iobuf *input_iobuf,
124 struct sbuf *sb,
125 regex_t *regex,
126 enum action act,
127 struct conf **cconfs
128 ) {
129 if(act==ACTION_RESTORE)
130 {
131 // Do not send VSS data to non-windows, or to windows client
132 // that asked us not to send it.
133 if(!get_int(cconfs[OPT_CLIENT_IS_WINDOWS])
134 || get_int(cconfs[OPT_VSS_RESTORE])!=VSS_RESTORE_ON)
135 {
136 if(sbuf_is_vssdata(sb))
137 return 0;
138 // Do not send VSS directory data to non-windows.
139 if(S_ISDIR(sb->statp.st_mode)
140 && sbuf_is_filedata(sb)
141 && !sbuf_is_metadata(sb))
142 return 0;
143 }
144 }
145 return
146 (!input_fzp
147 || restore_list_check(asfd, get_cntr(cconfs),
148 input_fzp, input_iobuf, sb->path.buf))
149 && (!srestore
150 || srestore_check(cconfs, sb->path.buf))
151 && (!regex
152 || regex_check(regex, sb->path.buf));
153 }
154
maybe_open_restore_list(struct conf ** cconfs,struct fzp ** rl_fzp,struct iobuf ** rl_iobuf,struct sdirs * sdirs)155 static int maybe_open_restore_list(
156 struct conf **cconfs,
157 struct fzp **rl_fzp,
158 struct iobuf **rl_iobuf,
159 struct sdirs *sdirs
160 ) {
161 if(!get_string(cconfs[OPT_RESTORE_LIST]))
162 return 0;
163
164 if(!(*rl_fzp=fzp_open(sdirs->restore_list, "rb"))
165 || !(*rl_iobuf=iobuf_alloc()))
166 return -1;
167
168 return 0;
169 }
170
setup_cntr(struct asfd * asfd,const char * manifest,regex_t * regex,int srestore,struct conf ** cconfs,enum action act,struct bu * bu,struct sdirs * sdirs)171 static int setup_cntr(struct asfd *asfd, const char *manifest,
172 regex_t *regex, int srestore, struct conf **cconfs, enum action act,
173 struct bu *bu, struct sdirs *sdirs)
174 {
175 int ars=0;
176 int ret=-1;
177 struct fzp *fzp=NULL;
178 struct sbuf *sb=NULL;
179 struct cntr *cntr=NULL;
180 struct fzp *rl_fzp=NULL;
181 struct iobuf *rl_iobuf=NULL;
182
183 cntr=get_cntr(cconfs);
184 if(!cntr) return 0;
185 cntr->bno=(int)bu->bno;
186
187 // FIX THIS: this is only trying to work for protocol1.
188 if(get_protocol(cconfs)!=PROTO_1) return 0;
189
190 if(maybe_open_restore_list(cconfs, &rl_fzp, &rl_iobuf, sdirs))
191 goto end;
192
193 if(!(sb=sbuf_alloc(PROTO_1))) goto end;
194 if(!(fzp=fzp_gzopen(manifest, "rb")))
195 {
196 log_and_send(asfd, "could not open manifest");
197 goto end;
198 }
199 while(1)
200 {
201 if((ars=sbuf_fill_from_file(sb, fzp, NULL)))
202 {
203 if(ars<0) goto end;
204 // ars==1 means end ok
205 break;
206 }
207 else
208 {
209 if(want_to_restore(asfd, srestore,
210 rl_fzp, rl_iobuf,
211 sb, regex, act, cconfs))
212 {
213 cntr_add_phase1(cntr, sb->path.cmd, 0);
214 if(sb->endfile.buf)
215 cntr_add_val(cntr,
216 CMD_BYTES_ESTIMATED,
217 strtoull(sb->endfile.buf,
218 NULL, 10));
219 }
220 }
221 sbuf_free_content(sb);
222 }
223 ret=0;
224 end:
225 iobuf_free(&rl_iobuf);
226 fzp_close(&rl_fzp);
227 sbuf_free(&sb);
228 fzp_close(&fzp);
229 return ret;
230 }
231
232 static int restore_sbuf(struct asfd *asfd, struct sbuf *sb, struct bu *bu,
233 enum action act, struct sdirs *sdirs, enum cntr_status cntr_status,
234 struct conf **cconfs, struct sbuf *need_data, const char *manifest,
235 struct slist *slist);
236
log_missing_block(struct asfd * asfd,struct cntr * cntr,struct blk * blk,struct sbuf * need_data)237 static void log_missing_block(struct asfd *asfd, struct cntr *cntr,
238 struct blk *blk, struct sbuf *need_data)
239 {
240 uint16_t datno=0;
241 char *savepathstr;
242 savepathstr=uint64_to_savepathstr_with_sig_uint(blk->savepath, &datno);
243 logw(asfd, cntr, "%s: Missing block %s:%d\n",
244 iobuf_to_printable(&need_data->path), savepathstr, datno);
245 }
246
247 // Used when restoring a hard link that we have not restored the destination
248 // for. Read through the manifest from the beginning and substitute the path
249 // and data to the new location.
hard_link_substitution(struct asfd * asfd,struct sbuf * sb,struct f_link * lp,struct bu * bu,enum action act,struct sdirs * sdirs,enum cntr_status cntr_status,struct conf ** cconfs,const char * manifest,struct slist * slist)250 static int hard_link_substitution(struct asfd *asfd,
251 struct sbuf *sb, struct f_link *lp,
252 struct bu *bu, enum action act, struct sdirs *sdirs,
253 enum cntr_status cntr_status, struct conf **cconfs,
254 const char *manifest, struct slist *slist)
255 {
256 int ret=-1;
257 struct sbuf *need_data=NULL;
258 int last_ent_was_dir=0;
259 struct sbuf *hb=NULL;
260 struct manio *manio=NULL;
261 struct blk *blk=NULL;
262 int pcmp;
263 enum protocol protocol=get_protocol(cconfs);
264 struct cntr *cntr=get_cntr(cconfs);
265
266 if(!(manio=manio_open(manifest, "rb", protocol))
267 || !(need_data=sbuf_alloc(protocol))
268 || !(hb=sbuf_alloc(protocol)))
269 goto end;
270
271 if(protocol==PROTO_2)
272 {
273 if(!(blk=blk_alloc()))
274 goto end;
275 }
276
277 while(1)
278 {
279 if(blk)
280 blk->got_save_path=0;
281 switch(manio_read_with_blk(manio,
282 hb, need_data->path.buf?blk:NULL))
283 {
284 case 0: break; // Keep going.
285 case 1: ret=0; goto end; // Finished OK.
286 default: goto end; // Error;
287 }
288
289 if(protocol==PROTO_2)
290 {
291 if(hb->endfile.buf)
292 {
293 sbuf_free_content(hb);
294 continue;
295 }
296 if(blk->got_save_path)
297 {
298 blk->got_save_path=0;
299 if(rblk_retrieve_data(asfd, cntr,
300 blk, sdirs->data))
301 {
302 log_missing_block(asfd, cntr,
303 blk, need_data);
304 continue;
305 }
306 }
307 if(blk->data)
308 {
309 if(protocol2_extra_restore_stream_bits(asfd,
310 blk, slist, act, need_data,
311 last_ent_was_dir, cntr)) goto end;
312 continue;
313 }
314 sbuf_free_content(need_data);
315 }
316
317 pcmp=pathcmp(lp->name, hb->path.buf);
318
319 if(!pcmp && (sbuf_is_filedata(hb) || sbuf_is_vssdata(hb)))
320 {
321 // Copy the path from sb to hb.
322 free_w(&hb->path.buf);
323 if(!(hb->path.buf=strdup_w(sb->path.buf, __func__)))
324 goto end;
325 hb->path.len = sb->path.len;
326 // Should now be able to restore the original data
327 // to the new location.
328 ret=restore_sbuf(asfd, hb, bu, act, sdirs,
329 cntr_status, cconfs, need_data, manifest, slist);
330 // May still need to get protocol2 data.
331 if(!ret && need_data->path.buf) continue;
332 break;
333 }
334
335 sbuf_free_content(hb);
336 // Break out once we have gone past the entry that we are
337 // interested in.
338 if(pcmp<0) break;
339 }
340 end:
341 blk_free(&blk);
342 sbuf_free(&hb);
343 manio_close(&manio);
344 return ret;
345 }
346
restore_sbuf(struct asfd * asfd,struct sbuf * sb,struct bu * bu,enum action act,struct sdirs * sdirs,enum cntr_status cntr_status,struct conf ** cconfs,struct sbuf * need_data,const char * manifest,struct slist * slist)347 static int restore_sbuf(struct asfd *asfd, struct sbuf *sb, struct bu *bu,
348 enum action act, struct sdirs *sdirs, enum cntr_status cntr_status,
349 struct conf **cconfs, struct sbuf *need_data, const char *manifest,
350 struct slist *slist)
351 {
352 //printf("%s: %s\n", act==ACTION_RESTORE?"restore":"verify",
353 // iobuf_to_printable(&sb->path));
354 if(timed_operation_status_only(cntr_status, sb->path.buf, cconfs))
355 return -1;
356
357 if(sb->path.cmd==CMD_HARD_LINK)
358 {
359 struct f_link *lp=NULL;
360 struct f_link **bucket=NULL;
361 if((lp=linkhash_search(&sb->statp, &bucket)))
362 {
363 // It is in the list of stuff that is in the manifest,
364 // but was skipped on this restore.
365 // Need to go through the manifest from the beginning,
366 // and substitute in the data to restore to this
367 // location.
368 return hard_link_substitution(asfd, sb, lp,
369 bu, act, sdirs,
370 cntr_status, cconfs, manifest, slist);
371 // FIX THIS: Would be nice to remember the new link
372 // location so that further hard links would link to
373 // it instead of doing the hard_link_substitution
374 // business over again.
375 }
376 }
377
378 if(get_protocol(cconfs)==PROTO_1)
379 {
380 return restore_sbuf_protocol1(asfd, sb, bu,
381 act, sdirs, cconfs);
382 }
383 else
384 {
385 return restore_sbuf_protocol2(asfd, sb,
386 act, get_cntr(cconfs), need_data);
387 }
388 }
389
restore_ent(struct asfd * asfd,struct sbuf ** sb,struct slist * slist,struct bu * bu,enum action act,struct sdirs * sdirs,enum cntr_status cntr_status,struct conf ** cconfs,struct sbuf * need_data,int * last_ent_was_dir,const char * manifest)390 static int restore_ent(struct asfd *asfd,
391 struct sbuf **sb,
392 struct slist *slist,
393 struct bu *bu,
394 enum action act,
395 struct sdirs *sdirs,
396 enum cntr_status cntr_status,
397 struct conf **cconfs,
398 struct sbuf *need_data,
399 int *last_ent_was_dir,
400 const char *manifest)
401 {
402 int ret=-1;
403 struct sbuf *xb;
404
405 if(!(*sb)->path.buf)
406 {
407 logp("Got NULL path!\n");
408 return -1;
409 }
410
411 // Check if we have any directories waiting to be restored.
412 while((xb=slist->head))
413 {
414 if(is_subdir(xb->path.buf, (*sb)->path.buf))
415 {
416 // We are still in a subdir.
417 break;
418 }
419 else
420 {
421 // Can now restore xb because nothing else is fiddling
422 // in a subdirectory.
423 if(restore_sbuf(asfd, xb, bu,
424 act, sdirs, cntr_status, cconfs, need_data, manifest,
425 slist))
426 goto end;
427 if(get_protocol(cconfs)==PROTO_2
428 && sbuf_is_filedata(xb)
429 && get_int(cconfs[OPT_CLIENT_IS_WINDOWS]))
430 {
431 // Windows directories need endfile to be sent.
432 if(asfd->write(asfd, &xb->endfile))
433 goto end;
434 }
435 slist->head=xb->next;
436 sbuf_free(&xb);
437 }
438 }
439
440 /* If it is a directory, need to remember it and restore it later, so
441 that the permissions come out right. */
442 /* Meta data of directories will also have the stat stuff set to be a
443 directory, so will also come out at the end. */
444 /* FIX THIS: for Windows, need to read and remember the blocks that
445 go with the directories. Probably have to do the same for metadata
446 that goes with directories. */
447 if(S_ISDIR((*sb)->statp.st_mode)
448 // Hack for metadata for now - just do it straight away.
449 && !sbuf_is_metadata(*sb))
450 {
451 // Add to the head of the list instead of the tail.
452 (*sb)->next=slist->head;
453 slist->head=*sb;
454
455 *last_ent_was_dir=1;
456
457 // Allocate a new sb.
458 if(!(*sb=sbuf_alloc(get_protocol(cconfs)))) goto end;
459 }
460 else
461 {
462 *last_ent_was_dir=0;
463 if(restore_sbuf(asfd, *sb, bu,
464 act, sdirs, cntr_status, cconfs, need_data, manifest,
465 slist))
466 goto end;
467 }
468 ret=0;
469 end:
470 return ret;
471 }
472
restore_remaining_dirs(struct asfd * asfd,struct bu * bu,struct slist * slist,enum action act,struct sdirs * sdirs,struct conf ** cconfs)473 static int restore_remaining_dirs(struct asfd *asfd, struct bu *bu,
474 struct slist *slist, enum action act, struct sdirs *sdirs,
475 struct conf **cconfs)
476 {
477 int ret=-1;
478 struct sbuf *sb;
479 struct sbuf *need_data=NULL;
480 if(!(need_data=sbuf_alloc(get_protocol(cconfs)))) goto end;
481 // Restore any directories that are left in the list.
482 for(sb=slist->head; sb; sb=sb->next)
483 {
484 if(get_protocol(cconfs)==PROTO_1)
485 {
486 if(restore_sbuf_protocol1(asfd, sb, bu, act,
487 sdirs, cconfs))
488 goto end;
489 }
490 else
491 {
492 if(restore_sbuf_protocol2(asfd, sb, act,
493 get_cntr(cconfs), NULL))
494 goto end;
495 if(sbuf_is_filedata(sb)
496 && get_int(cconfs[OPT_CLIENT_IS_WINDOWS]))
497 {
498 // Windows directories need endfile to be sent.
499 if(asfd->write(asfd, &sb->endfile))
500 goto end;
501 }
502 }
503 }
504 ret=0;
505 end:
506 sbuf_free(&need_data);
507 return ret;
508 }
509
restore_stream(struct asfd * asfd,struct sdirs * sdirs,struct slist * slist,struct bu * bu,const char * manifest,regex_t * regex,int srestore,struct conf ** cconfs,enum action act,enum cntr_status cntr_status)510 static int restore_stream(struct asfd *asfd, struct sdirs *sdirs,
511 struct slist *slist, struct bu *bu, const char *manifest,
512 regex_t *regex, int srestore, struct conf **cconfs, enum action act,
513 enum cntr_status cntr_status)
514 {
515 int ret=-1;
516 int last_ent_was_dir=0;
517 int last_ent_was_skipped=0;
518 struct sbuf *sb=NULL;
519 struct iobuf *rbuf=asfd->rbuf;
520 struct manio *manio=NULL;
521 struct blk *blk=NULL;
522 struct sbuf *need_data=NULL;
523 enum protocol protocol=get_protocol(cconfs);
524 struct cntr *cntr=get_cntr(cconfs);
525 struct iobuf interrupt;
526 struct fzp *rl_fzp=NULL;
527 struct iobuf *rl_iobuf=NULL;
528
529 iobuf_init(&interrupt);
530
531 if(protocol==PROTO_2)
532 {
533 static int rs_sent=0;
534 if(!(blk=blk_alloc()))
535 goto end;
536 if(!rs_sent)
537 {
538 rs_sent=1;
539 if(asfd->write_str(asfd,
540 CMD_GEN, "restore_stream")
541 || asfd_read_expect(asfd,
542 CMD_GEN, "restore_stream_ok"))
543 goto end;
544 }
545 }
546
547 if(maybe_open_restore_list(cconfs, &rl_fzp, &rl_iobuf, sdirs))
548 goto end;
549
550 if(!(manio=manio_open(manifest, "rb", protocol))
551 || !(need_data=sbuf_alloc(protocol))
552 || !(sb=sbuf_alloc(protocol)))
553 goto end;
554
555 while(1)
556 {
557 iobuf_free_content(rbuf);
558 if(asfd->as->read_quick(asfd->as))
559 {
560 logp("read quick error\n");
561 goto end;
562 }
563 if(rbuf->buf) switch(rbuf->cmd)
564 {
565 case CMD_MESSAGE:
566 case CMD_WARNING:
567 {
568 log_recvd(rbuf, cntr, 0);
569 continue;
570 }
571 case CMD_INTERRUPT:
572 if(protocol==PROTO_2)
573 {
574 iobuf_free_content(&interrupt);
575 iobuf_move(&interrupt, rbuf);
576 }
577 // PROTO_1:
578 // Client wanted to interrupt the
579 // sending of a file. But if we are
580 // here, we have already moved on.
581 // Ignore.
582 continue;
583 default:
584 iobuf_log_unexpected(rbuf, __func__);
585 goto end;
586 }
587
588 if(blk)
589 blk->got_save_path=0;
590 switch(manio_read_with_blk(manio,
591 sb, need_data->path.buf?blk:NULL))
592 {
593 case 0: break; // Keep going.
594 case 1: ret=0; goto end; // Finished OK.
595 default: goto end; // Error;
596 }
597
598 if(protocol==PROTO_2)
599 {
600 if(sb->endfile.buf)
601 {
602 if(act==ACTION_RESTORE && !last_ent_was_skipped)
603 {
604 if(last_ent_was_dir)
605 {
606 // Delay sending endfile until
607 // we actually send the
608 // directory.
609 struct sbuf *xb=slist->head;
610 iobuf_free_content(&xb->endfile);
611 iobuf_move(&xb->endfile,
612 &sb->endfile);
613 }
614 else
615 {
616 if(asfd->write(asfd,
617 &sb->endfile))
618 goto end;
619 }
620 }
621 sbuf_free_content(sb);
622 iobuf_free_content(&interrupt);
623 continue;
624 }
625 if(interrupt.buf)
626 {
627 if(!need_data->path.buf)
628 {
629 iobuf_free_content(&interrupt);
630 }
631 else if(!iobuf_pathcmp(&need_data->path,
632 &interrupt))
633 {
634 continue;
635 }
636 }
637 if(blk->got_save_path)
638 {
639 blk->got_save_path=0;
640 if(rblk_retrieve_data(asfd, cntr,
641 blk, sdirs->data))
642 {
643 log_missing_block(asfd, cntr,
644 blk, need_data);
645 continue;
646 }
647 }
648 if(blk->data)
649 {
650 if(protocol2_extra_restore_stream_bits(asfd,
651 blk, slist, act, need_data,
652 last_ent_was_dir, cntr)) goto end;
653 continue;
654 }
655 sbuf_free_content(need_data);
656 }
657
658 if(want_to_restore(asfd, srestore, rl_fzp, rl_iobuf,
659 sb, regex, act, cconfs))
660 {
661 last_ent_was_skipped=0;
662 if(restore_ent(asfd, &sb, slist,
663 bu, act, sdirs, cntr_status, cconfs,
664 need_data, &last_ent_was_dir, manifest))
665 goto end;
666 }
667 else
668 {
669 last_ent_was_skipped=1;
670 if(sbuf_is_filedata(sb) || sbuf_is_vssdata(sb))
671 {
672 // Add it to the list of filedata that was not
673 // restored.
674 struct f_link **bucket=NULL;
675 if(!linkhash_search(&sb->statp, &bucket)
676 && linkhash_add(sb->path.buf, &sb->statp, bucket))
677 goto end;
678 }
679 }
680
681 sbuf_free_content(sb);
682 }
683 end:
684 iobuf_free(&rl_iobuf);
685 fzp_close(&rl_fzp);
686 blk_free(&blk);
687 sbuf_free(&sb);
688 sbuf_free(&need_data);
689 iobuf_free_content(rbuf);
690 iobuf_free_content(&interrupt);
691 manio_close(&manio);
692 return ret;
693 }
694
actual_restore(struct asfd * asfd,struct bu * bu,const char * manifest,regex_t * regex,int srestore,enum action act,struct sdirs * sdirs,enum cntr_status cntr_status,struct conf ** cconfs)695 static int actual_restore(struct asfd *asfd, struct bu *bu,
696 const char *manifest, regex_t *regex, int srestore, enum action act,
697 struct sdirs *sdirs, enum cntr_status cntr_status, struct conf **cconfs)
698 {
699 int ret=-1;
700 // For out-of-sequence directory restoring so that the
701 // timestamps come out right:
702 struct slist *slist=NULL;
703 struct cntr *cntr=NULL;
704
705 if(linkhash_init()
706 || !(slist=slist_alloc()))
707 goto end;
708
709 if(get_protocol(cconfs)==PROTO_2)
710 rblks_init(get_uint64_t(cconfs[OPT_RBLK_MEMORY_MAX]));
711
712 if(restore_stream(asfd, sdirs, slist,
713 bu, manifest, regex,
714 srestore, cconfs, act, cntr_status))
715 goto end;
716
717 if(restore_remaining_dirs(asfd, bu, slist,
718 act, sdirs, cconfs)) goto end;
719
720 if(cconfs) cntr=get_cntr(cconfs);
721 cntr_set_bytes(cntr, asfd);
722 cntr_print(cntr, act);
723 if(cntr_stats_to_file(cntr, bu->path, act))
724 goto end;
725 ret=0;
726 end:
727 slist_free(&slist);
728 linkhash_free();
729 rblks_free();
730 return ret;
731 }
732
get_logpaths(struct bu * bu,const char * file,char ** logpath,char ** logpathz)733 static int get_logpaths(struct bu *bu, const char *file,
734 char **logpath, char **logpathz)
735 {
736 if(!(*logpath=prepend_s(bu->path, file))
737 || !(*logpathz=prepend(*logpath, ".gz")))
738 return -1;
739 return 0;
740 }
741
parallelism_warnings(struct asfd * asfd,struct conf ** cconfs,struct sdirs * sdirs,struct bu * bu,enum protocol protocol)742 static void parallelism_warnings(struct asfd *asfd, struct conf **cconfs,
743 struct sdirs *sdirs, struct bu *bu, enum protocol protocol)
744 {
745 struct bu *b;
746
747 if(lock_test(sdirs->lock_storage_for_write->path))
748 {
749 logm(asfd, cconfs, "Another process is currently backing up or deleting for this client.\n");
750 return;
751 }
752
753 if(!check_for_rubble(sdirs))
754 return;
755
756 for(b=bu; b && b->next; b=b->next)
757 {
758 if(b->flags & BU_CURRENT)
759 break; // Warning.
760 if(protocol==PROTO_2)
761 return; // No warning.
762 if(b->flags & BU_HARDLINKED)
763 return; // No warning.
764 }
765
766 logw(asfd, get_cntr(cconfs),
767 "The latest backup needs recovery, but continuing anyway.\n");
768 }
769
restore_manifest(struct asfd * asfd,struct bu * bu,regex_t * regex,int srestore,enum action act,struct sdirs * sdirs,char ** dir_for_notify,struct conf ** cconfs)770 static int restore_manifest(struct asfd *asfd, struct bu *bu,
771 regex_t *regex, int srestore, enum action act, struct sdirs *sdirs,
772 char **dir_for_notify, struct conf **cconfs)
773 {
774 int ret=-1;
775 char *manifest=NULL;
776 char *logpath=NULL;
777 char *logpathz=NULL;
778 enum protocol protocol;
779 enum cntr_status cntr_status;
780 struct lock *lock=NULL;
781 char *lockfile=NULL;
782 static int manifest_count=0;
783
784 protocol=get_protocol(cconfs);
785 if(protocol==PROTO_2
786 && blks_generate_init())
787 goto end;
788
789 if(!(lockfile=prepend_s(bu->path, "lockfile.read"))
790 || !(lock=lock_alloc_and_init(lockfile)))
791 goto end;
792 lock_get(lock);
793 if(lock->status!=GET_LOCK_GOT)
794 {
795 char msg[256]="";
796 snprintf(msg, sizeof(msg), "Another process is restoring or verifying backup %s.\n", bu->timestamp);
797 log_and_send(asfd, msg);
798 goto end;
799 }
800
801 // For sending status information up to the server.
802 cntr_status=CNTR_STATUS_RESTORING;
803
804 if(act==ACTION_RESTORE) cntr_status=CNTR_STATUS_RESTORING;
805 else if(act==ACTION_VERIFY) cntr_status=CNTR_STATUS_VERIFYING;
806
807 if((act==ACTION_RESTORE && get_logpaths(bu, "restorelog",
808 &logpath, &logpathz))
809 || (act==ACTION_VERIFY && get_logpaths(bu, "verifylog",
810 &logpath, &logpathz))
811 || !(manifest=prepend_s(bu->path,
812 get_protocol(cconfs)==PROTO_1?
813 "manifest.gz":"manifest")))
814 {
815 log_and_send_oom(asfd);
816 goto end;
817 }
818
819 if(log_fzp_set(logpath, cconfs))
820 {
821 char msg[256]="";
822 snprintf(msg, sizeof(msg),
823 "could not open log file: %s", logpath);
824 log_and_send(asfd, msg);
825 goto end;
826 }
827
828 *dir_for_notify=strdup_w(bu->path, __func__);
829
830 log_restore_settings(cconfs, srestore);
831
832 // First, do a pass through the manifest to set up cntr.
833 // This is the equivalent of a phase1 scan during backup.
834
835 if(setup_cntr(asfd, manifest,
836 regex, srestore, cconfs, act, bu, sdirs))
837 goto end;
838
839 if(!manifest_count)
840 {
841 // FIX THIS: Only send the counters once, otherwise the
842 // client will break on '-b a' because it does not expect
843 // multiple sets of counters to turn up.
844 // This means that the client side 'expected' counter will be
845 // confusing in that case. Live with it for now.
846 // However, the server side log will be OK.
847 if(cntr_send_bu(asfd, bu, cconfs, cntr_status))
848 goto end;
849 }
850
851 parallelism_warnings(asfd, cconfs, sdirs, bu, protocol);
852
853 // Now, do the actual restore.
854 ret=actual_restore(asfd, bu, manifest,
855 regex, srestore, act, sdirs, cntr_status, cconfs);
856 end:
857 log_fzp_set(NULL, cconfs);
858 if(logpath && logpathz)
859 compress_file(logpath, logpathz,
860 get_int(cconfs[OPT_COMPRESSION]));
861 free_w(&manifest);
862 free_w(&logpath);
863 free_w(&logpathz);
864 if(protocol==PROTO_2)
865 blks_generate_free();
866 free_w(&lockfile);
867 lock_release(lock);
868 lock_free(&lock);
869 manifest_count++;
870 return ret;
871 }
872
do_restore_server(struct asfd * asfd,struct sdirs * sdirs,enum action act,int srestore,char ** dir_for_notify,struct conf ** confs)873 int do_restore_server(struct asfd *asfd, struct sdirs *sdirs,
874 enum action act, int srestore,
875 char **dir_for_notify, struct conf **confs)
876 {
877 int ret=-1;
878 uint8_t found=0;
879 struct bu *bu=NULL;
880 struct bu *bu_list=NULL;
881 unsigned long bno=0;
882 regex_t *regex=NULL;
883 const char *regexstr=get_string(confs[OPT_REGEX]);
884 const char *backup=get_string(confs[OPT_BACKUP]);
885 int regex_case_insensitive=get_int(confs[OPT_REGEX_CASE_INSENSITIVE]);
886
887 logp("in do_restore\n");
888
889 if(regexstr
890 && *regexstr
891 && !(regex=regex_compile_restore(regexstr, regex_case_insensitive)))
892 {
893 char msg[256]="";
894 snprintf(msg, sizeof(msg), "unable to compile regex: %s\n",
895 regexstr);
896 log_and_send(asfd, msg);
897 goto end;
898 }
899
900 if(bu_get_list(sdirs, &bu_list))
901 goto end;
902
903 if(bu_list &&
904 (!backup
905 || !*backup
906 || (!(bno=strtoul(backup, NULL, 10)) && *backup!='a')))
907 {
908 found=1;
909 // No backup specified, do the most recent.
910 for(bu=bu_list; bu && bu->next; bu=bu->next) { }
911 ret=restore_manifest(asfd, bu, regex, srestore,
912 act, sdirs, dir_for_notify, confs);
913 }
914
915 if(!found) for(bu=bu_list; bu; bu=bu->next)
916 {
917 if(!strcmp(bu->timestamp, backup)
918 || bu->bno==bno || (backup && *backup=='a'))
919 {
920 found=1;
921 //logp("got: %s\n", bu->path);
922 ret|=restore_manifest(asfd, bu, regex, srestore,
923 act, sdirs, dir_for_notify, confs);
924 if(backup && *backup=='a')
925 continue;
926 break;
927 }
928 }
929
930 bu_list_free(&bu_list);
931
932
933 if(found)
934 {
935 // Restore has nearly completed OK.
936 ret=restore_end(asfd, confs);
937 }
938 else
939 {
940 logp("backup not found\n");
941 asfd->write_str(asfd, CMD_ERROR, "backup not found");
942 ret=-1;
943 }
944 end:
945 regex_free(®ex);
946 return ret;
947 }
948