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