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