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