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