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