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