Line data Source code
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 :
32 7 : static enum asl_ret restore_end_func(struct asfd *asfd,
33 : __attribute__ ((unused)) struct conf **confs,
34 : __attribute__ ((unused)) void *param)
35 : {
36 7 : if(!strcmp(asfd->rbuf->buf, "restoreend ok"))
37 : return ASL_END_OK;
38 : // Old v2 clients send something slightly different.
39 0 : if(!strcmp(asfd->rbuf->buf, "restoreend_ok"))
40 : return ASL_END_OK;
41 0 : iobuf_log_unexpected(asfd->rbuf, __func__);
42 0 : return ASL_END_ERROR;
43 : }
44 :
45 7 : static int restore_end(struct asfd *asfd, struct conf **confs)
46 : {
47 7 : if(asfd->write_str(asfd, CMD_GEN, "restoreend")) return -1;
48 7 : return asfd->simple_loop(asfd, confs, NULL, __func__, restore_end_func);
49 : }
50 :
51 : static int srestore_matches(struct strlist *s, const char *path)
52 : {
53 0 : int r=0;
54 0 : if(!s->flag) return 0; // Do not know how to do excludes yet.
55 0 : 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.
63 0 : static int srestore_check(struct conf **confs, const char *path)
64 : {
65 0 : struct strlist *l=get_strlist(confs[OPT_INCEXCDIR]);
66 :
67 : // If no includes specified, restore everything.
68 0 : if(!l) return 1;
69 :
70 0 : for(; l; l=l->next)
71 0 : if(srestore_matches(l, path))
72 : return 1;
73 : return 0;
74 : }
75 :
76 0 : 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 0 : char *last=NULL;
85 :
86 : do {
87 0 : if(!rl_iobuf->buf)
88 : {
89 0 : 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 0 : default: return -1; // Error.
94 : }
95 : }
96 :
97 0 : if(last && pathcmp(rl_iobuf->buf, last)!=1)
98 : {
99 0 : logw(asfd, cntr,
100 : "Input file ordering problem: '%s' '%s'",
101 : last, rl_iobuf->buf);
102 : }
103 :
104 0 : switch(pathcmp(rl_iobuf->buf, path))
105 : {
106 : case 0: return 1; // Successful match.
107 0 : case 1: return 0; // Ahead in input, no match.
108 : default:
109 : // Behind, need to read more from input.
110 0 : free_w(&last);
111 0 : last=rl_iobuf->buf;
112 0 : rl_iobuf->buf=NULL;
113 : }
114 : } while (1);
115 :
116 : return 0;
117 : }
118 :
119 46 : 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 46 : 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 46 : if(!get_int(cconfs[OPT_CLIENT_IS_WINDOWS])
134 2 : || get_int(cconfs[OPT_VSS_RESTORE])!=VSS_RESTORE_ON)
135 : {
136 44 : if(sbuf_is_vssdata(sb))
137 : return 0;
138 : // Do not send VSS directory data to non-windows.
139 44 : if(S_ISDIR(sb->statp.st_mode)
140 2 : && sbuf_is_filedata(sb)
141 2 : && !sbuf_is_metadata(sb))
142 : return 0;
143 : }
144 : }
145 : return
146 : (!input_fzp
147 0 : || restore_list_check(asfd, get_cntr(cconfs),
148 0 : input_fzp, input_iobuf, sb->path.buf))
149 44 : && (!srestore
150 0 : || srestore_check(cconfs, sb->path.buf))
151 88 : && (!regex
152 0 : || regex_check(regex, sb->path.buf));
153 : }
154 :
155 7 : 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 7 : if(!get_string(cconfs[OPT_RESTORE_LIST]))
162 : return 0;
163 :
164 0 : if(!(*rl_fzp=fzp_open(sdirs->restore_list, "rb"))
165 0 : || !(*rl_iobuf=iobuf_alloc()))
166 : return -1;
167 :
168 : return 0;
169 : }
170 :
171 7 : 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 7 : int ars=0;
176 7 : int ret=-1;
177 7 : struct fzp *fzp=NULL;
178 7 : struct sbuf *sb=NULL;
179 7 : struct cntr *cntr=NULL;
180 7 : struct fzp *rl_fzp=NULL;
181 7 : struct iobuf *rl_iobuf=NULL;
182 :
183 7 : cntr=get_cntr(cconfs);
184 7 : if(!cntr) return 0;
185 0 : cntr->bno=(int)bu->bno;
186 :
187 : // FIX THIS: this is only trying to work for protocol1.
188 0 : if(get_protocol(cconfs)!=PROTO_1) return 0;
189 :
190 0 : if(maybe_open_restore_list(cconfs, &rl_fzp, &rl_iobuf, sdirs))
191 : goto end;
192 :
193 0 : if(!(sb=sbuf_alloc(PROTO_1))) goto end;
194 0 : if(!(fzp=fzp_gzopen(manifest, "rb")))
195 : {
196 0 : log_and_send(asfd, "could not open manifest");
197 : goto end;
198 : }
199 : while(1)
200 : {
201 0 : if((ars=sbuf_fill_from_file(sb, fzp, NULL)))
202 : {
203 0 : if(ars<0) goto end;
204 : // ars==1 means end ok
205 : break;
206 : }
207 : else
208 : {
209 0 : if(want_to_restore(asfd, srestore,
210 : rl_fzp, rl_iobuf,
211 : sb, regex, act, cconfs))
212 : {
213 0 : cntr_add_phase1(cntr, sb->path.cmd, 0);
214 0 : if(sb->endfile.buf)
215 0 : cntr_add_val(cntr,
216 : CMD_BYTES_ESTIMATED,
217 0 : strtoull(sb->endfile.buf,
218 : NULL, 10));
219 : }
220 : }
221 0 : sbuf_free_content(sb);
222 : }
223 0 : ret=0;
224 : end:
225 0 : iobuf_free(&rl_iobuf);
226 0 : fzp_close(&rl_fzp);
227 0 : sbuf_free(&sb);
228 0 : 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 :
237 0 : static void log_missing_block(struct asfd *asfd, struct cntr *cntr,
238 : struct blk *blk, struct sbuf *need_data)
239 : {
240 0 : uint16_t datno=0;
241 : char *savepathstr;
242 0 : savepathstr=uint64_to_savepathstr_with_sig_uint(blk->savepath, &datno);
243 0 : logw(asfd, cntr, "%s: Missing block %s:%d\n",
244 : iobuf_to_printable(&need_data->path), savepathstr, datno);
245 0 : }
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.
250 0 : 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 0 : int ret=-1;
257 0 : struct sbuf *need_data=NULL;
258 0 : int last_ent_was_dir=0;
259 0 : struct sbuf *hb=NULL;
260 0 : struct manio *manio=NULL;
261 0 : struct blk *blk=NULL;
262 : int pcmp;
263 0 : enum protocol protocol=get_protocol(cconfs);
264 0 : struct cntr *cntr=get_cntr(cconfs);
265 :
266 0 : if(!(manio=manio_open(manifest, "rb", protocol))
267 0 : || !(need_data=sbuf_alloc(protocol))
268 0 : || !(hb=sbuf_alloc(protocol)))
269 : goto end;
270 :
271 0 : if(protocol==PROTO_2)
272 : {
273 0 : if(!(blk=blk_alloc()))
274 : goto end;
275 : }
276 :
277 : while(1)
278 : {
279 0 : if(blk)
280 0 : blk->got_save_path=0;
281 0 : switch(manio_read_with_blk(manio,
282 0 : hb, need_data->path.buf?blk:NULL))
283 : {
284 : case 0: break; // Keep going.
285 0 : case 1: ret=0; goto end; // Finished OK.
286 : default: goto end; // Error;
287 : }
288 :
289 0 : if(protocol==PROTO_2)
290 : {
291 0 : if(hb->endfile.buf)
292 : {
293 0 : sbuf_free_content(hb);
294 0 : continue;
295 : }
296 0 : if(blk->got_save_path)
297 : {
298 0 : blk->got_save_path=0;
299 0 : if(rblk_retrieve_data(asfd, cntr,
300 0 : blk, sdirs->data))
301 : {
302 0 : log_missing_block(asfd, cntr,
303 : blk, need_data);
304 0 : continue;
305 : }
306 : }
307 0 : if(blk->data)
308 : {
309 0 : if(protocol2_extra_restore_stream_bits(asfd,
310 : blk, slist, act, need_data,
311 : last_ent_was_dir, cntr)) goto end;
312 0 : continue;
313 : }
314 0 : sbuf_free_content(need_data);
315 : }
316 :
317 0 : pcmp=pathcmp(lp->name, hb->path.buf);
318 :
319 0 : if(!pcmp && (sbuf_is_filedata(hb) || sbuf_is_vssdata(hb)))
320 : {
321 : // Copy the path from sb to hb.
322 0 : free_w(&hb->path.buf);
323 0 : if(!(hb->path.buf=strdup_w(sb->path.buf, __func__)))
324 : goto end;
325 0 : hb->path.len = sb->path.len;
326 : // Should now be able to restore the original data
327 : // to the new location.
328 0 : 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 0 : if(!ret && need_data->path.buf) continue;
332 : break;
333 : }
334 :
335 0 : sbuf_free_content(hb);
336 : // Break out once we have gone past the entry that we are
337 : // interested in.
338 0 : if(pcmp<0) break;
339 : }
340 : end:
341 0 : blk_free(&blk);
342 0 : sbuf_free(&hb);
343 0 : manio_close(&manio);
344 0 : return ret;
345 : }
346 :
347 42 : 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 42 : if(write_status(cntr_status, sb->path.buf, get_cntr(cconfs)))
355 : return -1;
356 :
357 42 : if(sb->path.cmd==CMD_HARD_LINK)
358 : {
359 1 : struct f_link *lp=NULL;
360 1 : struct f_link **bucket=NULL;
361 1 : 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 0 : 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 42 : if(get_protocol(cconfs)==PROTO_1)
379 : {
380 10 : return restore_sbuf_protocol1(asfd, sb, bu,
381 : act, sdirs, cconfs);
382 : }
383 : else
384 : {
385 32 : return restore_sbuf_protocol2(asfd, sb,
386 : act, get_cntr(cconfs), need_data);
387 : }
388 : }
389 :
390 44 : 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 44 : int ret=-1;
403 : struct sbuf *xb;
404 :
405 44 : if(!(*sb)->path.buf)
406 : {
407 0 : logp("Got NULL path!\n");
408 0 : return -1;
409 : }
410 :
411 : // Check if we have any directories waiting to be restored.
412 44 : while((xb=slist->head))
413 : {
414 1 : 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 0 : if(restore_sbuf(asfd, xb, bu,
424 : act, sdirs, cntr_status, cconfs, need_data, manifest,
425 : slist))
426 : goto end;
427 0 : if(get_protocol(cconfs)==PROTO_2
428 0 : && sbuf_is_filedata(xb)
429 0 : && get_int(cconfs[OPT_CLIENT_IS_WINDOWS]))
430 : {
431 : // Windows directories need endfile to be sent.
432 0 : if(asfd->write(asfd, &xb->endfile))
433 : goto end;
434 : }
435 0 : slist->head=xb->next;
436 0 : 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 44 : if(S_ISDIR((*sb)->statp.st_mode)
448 : // Hack for metadata for now - just do it straight away.
449 2 : && !sbuf_is_metadata(*sb))
450 : {
451 : // Add to the head of the list instead of the tail.
452 2 : (*sb)->next=slist->head;
453 2 : slist->head=*sb;
454 :
455 2 : *last_ent_was_dir=1;
456 :
457 : // Allocate a new sb.
458 2 : if(!(*sb=sbuf_alloc(get_protocol(cconfs)))) goto end;
459 : }
460 : else
461 : {
462 42 : *last_ent_was_dir=0;
463 42 : 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 :
473 7 : 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 7 : int ret=-1;
478 : struct sbuf *sb;
479 7 : struct sbuf *need_data=NULL;
480 7 : if(!(need_data=sbuf_alloc(get_protocol(cconfs)))) goto end;
481 : // Restore any directories that are left in the list.
482 9 : for(sb=slist->head; sb; sb=sb->next)
483 : {
484 2 : if(get_protocol(cconfs)==PROTO_1)
485 : {
486 0 : if(restore_sbuf_protocol1(asfd, sb, bu, act,
487 : sdirs, cconfs))
488 : goto end;
489 : }
490 : else
491 : {
492 2 : if(restore_sbuf_protocol2(asfd, sb, act,
493 : get_cntr(cconfs), NULL))
494 : goto end;
495 2 : if(sbuf_is_filedata(sb)
496 2 : && get_int(cconfs[OPT_CLIENT_IS_WINDOWS]))
497 : {
498 : // Windows directories need endfile to be sent.
499 2 : if(asfd->write(asfd, &sb->endfile))
500 : goto end;
501 : }
502 : }
503 : }
504 : ret=0;
505 : end:
506 7 : sbuf_free(&need_data);
507 7 : return ret;
508 : }
509 :
510 7 : 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 7 : int ret=-1;
516 7 : int last_ent_was_dir=0;
517 7 : int last_ent_was_skipped=0;
518 7 : struct sbuf *sb=NULL;
519 7 : struct iobuf *rbuf=asfd->rbuf;
520 7 : struct manio *manio=NULL;
521 7 : struct blk *blk=NULL;
522 7 : struct sbuf *need_data=NULL;
523 7 : enum protocol protocol=get_protocol(cconfs);
524 7 : struct cntr *cntr=get_cntr(cconfs);
525 : struct iobuf interrupt;
526 7 : struct fzp *rl_fzp=NULL;
527 7 : struct iobuf *rl_iobuf=NULL;
528 :
529 7 : iobuf_init(&interrupt);
530 :
531 7 : if(protocol==PROTO_2)
532 : {
533 : static int rs_sent=0;
534 6 : if(!(blk=blk_alloc()))
535 : goto end;
536 6 : if(!rs_sent)
537 : {
538 6 : rs_sent=1;
539 6 : if(asfd->write_str(asfd,
540 : CMD_GEN, "restore_stream")
541 6 : || asfd_read_expect(asfd,
542 : CMD_GEN, "restore_stream_ok"))
543 : goto end;
544 : }
545 : }
546 :
547 7 : if(maybe_open_restore_list(cconfs, &rl_fzp, &rl_iobuf, sdirs))
548 : goto end;
549 :
550 7 : if(!(manio=manio_open(manifest, "rb", protocol))
551 7 : || !(need_data=sbuf_alloc(protocol))
552 7 : || !(sb=sbuf_alloc(protocol)))
553 : goto end;
554 :
555 : while(1)
556 : {
557 431 : iobuf_free_content(rbuf);
558 431 : if(asfd->as->read_quick(asfd->as))
559 : {
560 0 : logp("read quick error\n");
561 0 : goto end;
562 : }
563 431 : if(rbuf->buf) switch(rbuf->cmd)
564 : {
565 : case CMD_MESSAGE:
566 : case CMD_WARNING:
567 : {
568 0 : log_recvd(rbuf, cntr, 0);
569 0 : continue;
570 : }
571 : case CMD_INTERRUPT:
572 5 : if(protocol==PROTO_2)
573 : {
574 5 : iobuf_free_content(&interrupt);
575 5 : 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 5 : continue;
583 : default:
584 0 : iobuf_log_unexpected(rbuf, __func__);
585 0 : goto end;
586 : }
587 :
588 426 : if(blk)
589 415 : blk->got_save_path=0;
590 426 : switch(manio_read_with_blk(manio,
591 426 : sb, need_data->path.buf?blk:NULL))
592 : {
593 : case 0: break; // Keep going.
594 7 : case 1: ret=0; goto end; // Finished OK.
595 : default: goto end; // Error;
596 : }
597 :
598 419 : if(protocol==PROTO_2)
599 : {
600 409 : if(sb->endfile.buf)
601 : {
602 25 : if(act==ACTION_RESTORE && !last_ent_was_skipped)
603 : {
604 23 : if(last_ent_was_dir)
605 : {
606 : // Delay sending endfile until
607 : // we actually send the
608 : // directory.
609 2 : struct sbuf *xb=slist->head;
610 2 : iobuf_free_content(&xb->endfile);
611 2 : iobuf_move(&xb->endfile,
612 2 : &sb->endfile);
613 : }
614 : else
615 : {
616 21 : if(asfd->write(asfd,
617 : &sb->endfile))
618 : goto end;
619 : }
620 : }
621 25 : sbuf_free_content(sb);
622 25 : iobuf_free_content(&interrupt);
623 25 : continue;
624 : }
625 384 : if(interrupt.buf)
626 : {
627 61 : if(!need_data->path.buf)
628 : {
629 1 : iobuf_free_content(&interrupt);
630 : }
631 60 : else if(!iobuf_pathcmp(&need_data->path,
632 : &interrupt))
633 : {
634 32 : continue;
635 : }
636 : }
637 352 : if(blk->got_save_path)
638 : {
639 316 : blk->got_save_path=0;
640 316 : if(rblk_retrieve_data(asfd, cntr,
641 316 : blk, sdirs->data))
642 : {
643 0 : log_missing_block(asfd, cntr,
644 : blk, need_data);
645 0 : continue;
646 : }
647 : }
648 352 : if(blk->data)
649 : {
650 316 : if(protocol2_extra_restore_stream_bits(asfd,
651 : blk, slist, act, need_data,
652 : last_ent_was_dir, cntr)) goto end;
653 316 : continue;
654 : }
655 36 : sbuf_free_content(need_data);
656 : }
657 :
658 46 : if(want_to_restore(asfd, srestore, rl_fzp, rl_iobuf,
659 : sb, regex, act, cconfs))
660 : {
661 44 : last_ent_was_skipped=0;
662 44 : 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 2 : last_ent_was_skipped=1;
670 2 : if(sbuf_is_filedata(sb) || sbuf_is_vssdata(sb))
671 : {
672 : // Add it to the list of filedata that was not
673 : // restored.
674 2 : struct f_link **bucket=NULL;
675 2 : if(!linkhash_search(&sb->statp, &bucket)
676 1 : && linkhash_add(sb->path.buf, &sb->statp, bucket))
677 : goto end;
678 : }
679 : }
680 :
681 46 : sbuf_free_content(sb);
682 : }
683 : end:
684 7 : iobuf_free(&rl_iobuf);
685 7 : fzp_close(&rl_fzp);
686 7 : blk_free(&blk);
687 7 : sbuf_free(&sb);
688 7 : sbuf_free(&need_data);
689 7 : iobuf_free_content(rbuf);
690 7 : iobuf_free_content(&interrupt);
691 7 : manio_close(&manio);
692 7 : return ret;
693 : }
694 :
695 7 : 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 7 : int ret=-1;
700 : // For out-of-sequence directory restoring so that the
701 : // timestamps come out right:
702 7 : struct slist *slist=NULL;
703 7 : struct cntr *cntr=NULL;
704 :
705 7 : if(linkhash_init()
706 7 : || !(slist=slist_alloc()))
707 : goto end;
708 :
709 7 : if(get_protocol(cconfs)==PROTO_2)
710 6 : rblks_init(get_uint64_t(cconfs[OPT_RBLK_MEMORY_MAX]));
711 :
712 7 : if(restore_stream(asfd, sdirs, slist,
713 : bu, manifest, regex,
714 : srestore, cconfs, act, cntr_status))
715 : goto end;
716 :
717 7 : if(restore_remaining_dirs(asfd, bu, slist,
718 : act, sdirs, cconfs)) goto end;
719 :
720 7 : if(cconfs) cntr=get_cntr(cconfs);
721 7 : cntr_set_bytes(cntr, asfd);
722 7 : cntr_print(cntr, act);
723 7 : if(cntr_stats_to_file(cntr, bu->path, act))
724 : goto end;
725 7 : ret=0;
726 : end:
727 7 : slist_free(&slist);
728 7 : linkhash_free();
729 7 : rblks_free();
730 7 : return ret;
731 : }
732 :
733 7 : static int get_logpaths(struct bu *bu, const char *file,
734 : char **logpath, char **logpathz)
735 : {
736 7 : if(!(*logpath=prepend_s(bu->path, file))
737 7 : || !(*logpathz=prepend(*logpath, ".gz")))
738 : return -1;
739 : return 0;
740 : }
741 :
742 7 : 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 7 : if(lock_test(sdirs->lock_storage_for_write->path))
748 : {
749 0 : logm(asfd, cconfs, "Another process is currently backing up or deleting for this client.\n");
750 0 : return;
751 : }
752 :
753 7 : if(!check_for_rubble(sdirs))
754 : return;
755 :
756 0 : for(b=bu; b && b->next; b=b->next)
757 : {
758 0 : if(b->flags & BU_CURRENT)
759 : break; // Warning.
760 0 : if(protocol==PROTO_2)
761 : return; // No warning.
762 0 : if(b->flags & BU_HARDLINKED)
763 : return; // No warning.
764 : }
765 :
766 0 : logw(asfd, get_cntr(cconfs),
767 : "The latest backup needs recovery, but continuing anyway.\n");
768 : }
769 :
770 7 : 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 7 : int ret=-1;
775 7 : char *manifest=NULL;
776 7 : char *logpath=NULL;
777 7 : char *logpathz=NULL;
778 : enum protocol protocol;
779 : enum cntr_status cntr_status;
780 7 : struct lock *lock=NULL;
781 7 : char *lockfile=NULL;
782 : static int manifest_count=0;
783 :
784 7 : protocol=get_protocol(cconfs);
785 7 : if(protocol==PROTO_2
786 6 : && blks_generate_init())
787 : goto end;
788 :
789 7 : if(!(lockfile=prepend_s(bu->path, "lockfile.read"))
790 7 : || !(lock=lock_alloc_and_init(lockfile)))
791 : goto end;
792 7 : lock_get(lock);
793 7 : if(lock->status!=GET_LOCK_GOT)
794 : {
795 0 : char msg[256]="";
796 0 : snprintf(msg, sizeof(msg), "Another process is restoring or verifying backup %s.\n", bu->timestamp);
797 0 : log_and_send(asfd, msg);
798 : goto end;
799 : }
800 :
801 : // For sending status information up to the server.
802 7 : cntr_status=CNTR_STATUS_RESTORING;
803 :
804 7 : if(act==ACTION_RESTORE) cntr_status=CNTR_STATUS_RESTORING;
805 0 : else if(act==ACTION_VERIFY) cntr_status=CNTR_STATUS_VERIFYING;
806 :
807 7 : if((act==ACTION_RESTORE && get_logpaths(bu, "restorelog",
808 : &logpath, &logpathz))
809 7 : || (act==ACTION_VERIFY && get_logpaths(bu, "verifylog",
810 : &logpath, &logpathz))
811 7 : || !(manifest=prepend_s(bu->path,
812 7 : get_protocol(cconfs)==PROTO_1?
813 : "manifest.gz":"manifest")))
814 : {
815 0 : log_and_send_oom(asfd);
816 0 : goto end;
817 : }
818 :
819 7 : if(log_fzp_set(logpath, cconfs))
820 : {
821 0 : char msg[256]="";
822 0 : snprintf(msg, sizeof(msg),
823 : "could not open log file: %s", logpath);
824 0 : log_and_send(asfd, msg);
825 : goto end;
826 : }
827 :
828 7 : *dir_for_notify=strdup_w(bu->path, __func__);
829 :
830 7 : 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 7 : if(setup_cntr(asfd, manifest,
836 : regex, srestore, cconfs, act, bu, sdirs))
837 : goto end;
838 :
839 7 : 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 7 : if(cntr_send_bu(asfd, bu, cconfs, cntr_status))
848 : goto end;
849 : }
850 :
851 7 : parallelism_warnings(asfd, cconfs, sdirs, bu, protocol);
852 :
853 : // Now, do the actual restore.
854 7 : ret=actual_restore(asfd, bu, manifest,
855 : regex, srestore, act, sdirs, cntr_status, cconfs);
856 : end:
857 7 : log_fzp_set(NULL, cconfs);
858 7 : if(logpath && logpathz)
859 7 : compress_file(logpath, logpathz,
860 : get_int(cconfs[OPT_COMPRESSION]));
861 7 : free_w(&manifest);
862 7 : free_w(&logpath);
863 7 : free_w(&logpathz);
864 7 : if(protocol==PROTO_2)
865 6 : blks_generate_free();
866 7 : free_w(&lockfile);
867 7 : lock_release(lock);
868 7 : lock_free(&lock);
869 7 : manifest_count++;
870 7 : return ret;
871 : }
872 :
873 10 : 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 10 : int ret=-1;
878 10 : uint8_t found=0;
879 10 : struct bu *bu=NULL;
880 10 : struct bu *bu_list=NULL;
881 10 : unsigned long bno=0;
882 10 : regex_t *regex=NULL;
883 10 : const char *regexstr=get_string(confs[OPT_REGEX]);
884 10 : const char *backup=get_string(confs[OPT_BACKUP]);
885 :
886 10 : logp("in do_restore\n");
887 :
888 10 : if(regexstr
889 1 : && *regexstr
890 1 : && !(regex=regex_compile(regexstr)))
891 : {
892 1 : char msg[256]="";
893 1 : snprintf(msg, sizeof(msg), "unable to compile regex: %s\n",
894 : regexstr);
895 1 : log_and_send(asfd, msg);
896 : goto end;
897 : }
898 :
899 9 : if(bu_get_list(sdirs, &bu_list))
900 : goto end;
901 :
902 9 : if(bu_list &&
903 : (!backup
904 7 : || !*backup
905 7 : || (!(bno=strtoul(backup, NULL, 10)) && *backup!='a')))
906 : {
907 0 : found=1;
908 : // No backup specified, do the most recent.
909 0 : for(bu=bu_list; bu && bu->next; bu=bu->next) { }
910 0 : ret=restore_manifest(asfd, bu, regex, srestore,
911 : act, sdirs, dir_for_notify, confs);
912 : }
913 :
914 9 : if(!found) for(bu=bu_list; bu; bu=bu->next)
915 : {
916 7 : if(!strcmp(bu->timestamp, backup)
917 7 : || bu->bno==bno || (backup && *backup=='a'))
918 : {
919 7 : found=1;
920 : //logp("got: %s\n", bu->path);
921 7 : ret|=restore_manifest(asfd, bu, regex, srestore,
922 : act, sdirs, dir_for_notify, confs);
923 7 : if(backup && *backup=='a')
924 0 : continue;
925 : break;
926 : }
927 : }
928 :
929 9 : bu_list_free(&bu_list);
930 :
931 :
932 9 : if(found)
933 : {
934 : // Restore has nearly completed OK.
935 7 : ret=restore_end(asfd, confs);
936 : }
937 : else
938 : {
939 2 : logp("backup not found\n");
940 2 : asfd->write_str(asfd, CMD_ERROR, "backup not found");
941 2 : ret=-1;
942 : }
943 : end:
944 10 : regex_free(®ex);
945 10 : return ret;
946 : }
|