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