1 #include "../burp.h"
2 #include "../cmd.h"
3 #include "../cntr.h"
4 #include "../iobuf.h"
5 #include "../log.h"
6 #include "../pathcmp.h"
7 #include "../sbuf.h"
8 #include "dpth.h"
9 #include "resume.h"
10 #include "backup_phase1.h"
11 #include "protocol1/dpth.h"
12
13 // Used on resume, this just reads the phase1 file and sets up cntr.
read_phase1(struct manio * p1manio,struct conf ** cconfs)14 static int read_phase1(struct manio *p1manio, struct conf **cconfs)
15 {
16 int ret=-1;
17 struct sbuf *p1b;
18 enum protocol protocol=get_protocol(cconfs);
19 struct cntr *cntr=get_cntr(cconfs);
20 if(!(p1b=sbuf_alloc(protocol))) return -1;
21 while(1)
22 {
23 sbuf_free_content(p1b);
24 switch(manio_read(p1manio, p1b))
25 {
26 case 0: break;
27 case 1: ret=0;
28 default: goto end;
29 }
30 cntr_add_phase1(cntr, p1b->path.cmd, 0);
31
32 if(sbuf_is_estimatable(p1b))
33 cntr_add_val(cntr, CMD_BYTES_ESTIMATED,
34 (uint64_t)p1b->statp.st_size);
35 }
36 end:
37 sbuf_free(&p1b);
38 return ret;
39 }
40
set_higher_datapth(struct sbuf * sb,struct dpth * dpth)41 static int set_higher_datapth(struct sbuf *sb, struct dpth *dpth)
42 {
43 // Make sure we end up with the highest datapth we can possibly
44 // find - dpth_protocol1_set_from_string() will only set it if
45 // it is higher.
46 if(sb->protocol1 && sb->protocol1->datapth.buf
47 && dpth_protocol1_set_from_string(dpth,
48 sb->protocol1->datapth.buf))
49 {
50 logp("unable to set datapath: %s\n",
51 iobuf_to_printable(&sb->protocol1->datapth));
52 return -1;
53 }
54 return 0;
55 }
56
57 #ifndef UTEST
58 static
59 #endif
forward_past_entry(struct manio * manio,struct iobuf * target,enum protocol protocol,man_off_t ** pos)60 int forward_past_entry(struct manio *manio, struct iobuf *target,
61 enum protocol protocol, man_off_t **pos)
62 {
63 struct sbuf *sb=NULL;
64
65 if(!(sb=sbuf_alloc(protocol)))
66 goto error;
67
68 man_off_t_free(pos);
69 if(!(*pos=manio_tell(manio)))
70 {
71 logp("Could not manio_tell first pos in %s(): %s\n",
72 __func__, strerror(errno));
73 goto error;
74 }
75
76 while(1)
77 {
78 sbuf_free_content(sb);
79 man_off_t_free(pos);
80 if(!(*pos=manio_tell(manio)))
81 {
82 logp("Could not manio_tell top pos in %s(): %s\n",
83 __func__, strerror(errno));
84 goto error;
85 }
86
87 switch(manio_read(manio, sb))
88 {
89 case 0:
90 break;
91 case 1:
92 if(!(*pos)->offset)
93 {
94 // This is OK. I've seen it happen
95 // when the current manifest is an
96 // empty backup.
97 logp("Empty file in %s()\n", __func__);
98 sbuf_free(&sb);
99 return 0;
100 }
101 logp("End of file in %s()\n", __func__);
102 goto error;
103 default:
104 logp("Error in %s()\n", __func__);
105 goto error;
106 }
107
108 switch(iobuf_pathcmp(target, &sb->path))
109 {
110 case 0:
111 // Exact match, we want to be past here.
112 if(protocol==PROTO_2
113 && manio->phase==0
114 && !sb->endfile.buf)
115 {
116 // This is the current manio, and we
117 // need one more read to get us past
118 // endfile.
119 sbuf_free_content(sb);
120 switch(manio_read(manio, sb))
121 {
122 case 0:
123 break;
124 case 1:
125 logp("End of file finishing up in %s()\n", __func__);
126 goto error;
127 default:
128 logp("Error finishing up in %s()\n", __func__);
129 goto error;
130 }
131 if(sb->path.buf)
132 {
133 logp("Not expecting %s in %s()\n",
134 iobuf_to_printable(&sb->path),
135 __func__);
136 goto error;
137 }
138 if(!sb->endfile.buf)
139 {
140 logp("Was expecting endfile in %s()\n",
141 __func__);
142 goto error;
143 }
144 // Drop through to tell the position.
145 }
146 man_off_t_free(pos);
147 if(!(*pos=manio_tell(manio)))
148 {
149 logp("Could not manio_tell pos in %s(): "
150 "%s\n", __func__, strerror(errno));
151 goto error;
152 }
153 sbuf_free(&sb);
154 return 0;
155 case -1:
156 // Gone past the match, we want to return to
157 // the previous tell.
158 sbuf_free(&sb);
159 return 0;
160 default:
161 // Not gone far enough yet, continue.
162 break;
163 }
164 }
165
166 error:
167 sbuf_free(&sb);
168 man_off_t_free(pos);
169 return -1;
170 }
171
172 #ifndef UTEST
173 static
174 #endif
forward_before_entry(struct manio * manio,struct iobuf * target,struct cntr * cntr,struct dpth * dpth,enum protocol protocol,man_off_t ** pos)175 int forward_before_entry(struct manio *manio, struct iobuf *target,
176 struct cntr *cntr, struct dpth *dpth, enum protocol protocol,
177 man_off_t **pos)
178 {
179 int ars=0;
180 struct sbuf *sb=NULL;
181
182 if(!(sb=sbuf_alloc(protocol)))
183 goto error;
184
185 man_off_t_free(pos);
186 if(!(*pos=manio_tell(manio)))
187 {
188 logp("Could not manio_tell first pos in %s(): %s\n",
189 __func__, strerror(errno));
190 goto error;
191 }
192
193 while(1)
194 {
195 if(sb->endfile.buf
196 || (sb->path.buf && !sbuf_is_filedata(sb)))
197 {
198 man_off_t_free(pos);
199 if(!(*pos=manio_tell(manio)))
200 {
201 logp("Could not manio_tell pos in %s(): "
202 "%s\n", __func__, strerror(errno));
203 goto error;
204 }
205 }
206
207 sbuf_free_content(sb);
208 ars=manio_read(manio, sb);
209 if(dpth && set_higher_datapth(sb, dpth)) goto error;
210
211 switch(ars)
212 {
213 case 0: break;
214 case 1:
215 sbuf_free(&sb);
216 return 0;
217 default:
218 logp("Error in %s(), but continuing\n",
219 __func__);
220 // Treat error in unchanged manio as
221 // OK - could have been a short write.
222 sbuf_free(&sb);
223 return 0;
224 }
225
226 if(iobuf_pathcmp(target, &sb->path)<=0)
227 {
228 sbuf_free(&sb);
229 return 0;
230 }
231
232 if(cntr)
233 {
234 if(sb->endfile.buf)
235 {
236 uint64_t e=strtoull(sb->endfile.buf, NULL, 10);
237 cntr_add_bytes(cntr, e);
238 }
239 }
240 }
241
242 error:
243 sbuf_free(&sb);
244 man_off_t_free(pos);
245 return -1;
246 }
247
248 #ifndef UTEST
249 static
250 #endif
get_last_good_entry(struct manio * manio,struct iobuf * result,struct cntr * cntr,struct dpth * dpth,enum protocol protocol,man_off_t ** pos)251 int get_last_good_entry(struct manio *manio, struct iobuf *result,
252 struct cntr *cntr, struct dpth *dpth, enum protocol protocol,
253 man_off_t **pos)
254 {
255 int ars=0;
256 int got_vss_start=0;
257 struct sbuf *sb=NULL;
258 struct iobuf lastpath;
259
260 if(!(sb=sbuf_alloc(protocol)))
261 goto error;
262
263 iobuf_init(&lastpath);
264
265 man_off_t_free(pos);
266 if(!(*pos=manio_tell(manio)))
267 {
268 logp("Could not manio_tell first pos in %s(): %s\n",
269 __func__, strerror(errno));
270 goto error;
271 }
272
273 while(1)
274 {
275 if(sb->path.buf && !got_vss_start)
276 {
277 iobuf_free_content(&lastpath);
278 iobuf_move(&lastpath, &sb->path);
279 if(!sbuf_is_filedata(sb)
280 && !sbuf_is_vssdata(sb))
281 {
282 iobuf_free_content(result);
283 iobuf_move(result, &lastpath);
284
285 man_off_t_free(pos);
286 if(!(*pos=manio_tell(manio)))
287 {
288 logp("Could not manio_tell pos in %s(): %s\n",
289 __func__, strerror(errno));
290 goto error;
291 }
292 }
293 }
294 if(sb->endfile.buf && !got_vss_start)
295 {
296 iobuf_free_content(result);
297 iobuf_move(result, &lastpath);
298
299 man_off_t_free(pos);
300 if(!(*pos=manio_tell(manio)))
301 {
302 logp("Could not manio_tell pos in %s(): %s\n",
303 __func__, strerror(errno));
304 goto error;
305 }
306 }
307
308 sbuf_free_content(sb);
309 ars=manio_read(manio, sb);
310 if(dpth && set_higher_datapth(sb, dpth)) goto error;
311
312 switch(ars)
313 {
314 case 0: break;
315 case 1: iobuf_free_content(&lastpath);
316 sbuf_free(&sb);
317 return 0;
318 default:
319 if(result->buf)
320 logp("Error after %s in %s()\n",
321 iobuf_to_printable(result),
322 __func__);
323 // Treat error in changed manio as
324 // OK - could have been a short write.
325 iobuf_free_content(&lastpath);
326 sbuf_free(&sb);
327 return 0;
328 }
329
330 // Some hacks for split_vss.
331 switch(sb->path.cmd)
332 {
333 case CMD_VSS:
334 case CMD_ENC_VSS:
335 got_vss_start=1;
336 break;
337 case CMD_VSS_T:
338 case CMD_ENC_VSS_T:
339 got_vss_start=0;
340 break;
341 case CMD_FILE:
342 case CMD_ENC_FILE:
343 if(S_ISDIR(sb->statp.st_mode))
344 got_vss_start=0;
345 break;
346 default:
347 break;
348 }
349
350 if(cntr)
351 {
352 if(sb->endfile.buf)
353 {
354 uint64_t e=strtoull(sb->endfile.buf, NULL, 10);
355 cntr_add_bytes(cntr, e);
356 }
357 }
358 }
359
360 error:
361 iobuf_free_content(&lastpath);
362 sbuf_free(&sb);
363 man_off_t_free(pos);
364 return -1;
365 }
366
add_to_cntr(struct cntr * cntr,enum cmd cmd,enum cntr_manio cntr_manio)367 static int add_to_cntr(
368 struct cntr *cntr,
369 enum cmd cmd,
370 enum cntr_manio cntr_manio
371 ) {
372 switch(cntr_manio)
373 {
374 case CNTR_MANIO_NEW:
375 cntr_add(cntr, cmd, 0);
376 break;
377 case CNTR_MANIO_CHANGED:
378 cntr_add_changed(cntr, cmd);
379 break;
380 case CNTR_MANIO_SAME:
381 cntr_add_same(cntr, cmd);
382 break;
383 case CNTR_MANIO_DELETED:
384 cntr_add_deleted(cntr, cmd);
385 break;
386 default:
387 logp("Unknown counter in %s(): %c\n",
388 __func__, cntr_manio);
389 return -1;
390 }
391 return 0;
392 }
393
forward_past_entry_counter(struct manio * manio,struct iobuf * target,struct cntr * cntr,man_off_t ** pos)394 static int forward_past_entry_counter(
395 struct manio *manio,
396 struct iobuf *target,
397 struct cntr *cntr,
398 man_off_t **pos
399 ) {
400 char what[1];
401 struct iobuf rbuf;
402
403 iobuf_init(&rbuf);
404
405 while(1)
406 {
407 iobuf_free_content(&rbuf);
408 man_off_t_free(pos);
409 if(!(*pos=manio_tell(manio)))
410 {
411 logp("Could not manio_tell top pos in %s(): %s\n",
412 __func__, strerror(errno));
413 goto error;
414 }
415
416 switch(fzp_read_ensure(manio->fzp, what, sizeof(what), __func__))
417 {
418 case 0: break;
419 case 1: return 0;
420 default:
421 logp("Error read in %s(), but continuing\n",
422 __func__);
423 // Treat error in unchanged manio as
424 // OK - could have been a short write.
425 iobuf_free_content(&rbuf);
426 return 0;
427 }
428
429 switch(iobuf_fill_from_fzp(&rbuf, manio->fzp))
430 {
431 case 0: break;
432 case 1:
433 iobuf_free_content(&rbuf);
434 return 0;
435 default:
436 logp("Error in %s(), but continuing\n",
437 __func__);
438 // Treat error in unchanged manio as
439 // OK - could have been a short write.
440 iobuf_free_content(&rbuf);
441 return 0;
442 }
443
444 switch(iobuf_pathcmp(target, &rbuf))
445 {
446 case 0:
447 add_to_cntr(cntr, rbuf.cmd, what[0]);
448 // Exact match, we want to be past here.
449 man_off_t_free(pos);
450 if(!(*pos=manio_tell(manio)))
451 {
452 logp("Could not manio_tell pos in %s(): "
453 "%s\n", __func__, strerror(errno));
454 goto error;
455 }
456 iobuf_free_content(&rbuf);
457 return 0;
458 case -1:
459 // Gone past the match, we want to return to
460 // the previous tell. Do not add_to_cntr,
461 // or we will have one too many.
462 iobuf_free_content(&rbuf);
463 return 0;
464 default:
465 // Not gone far enough yet, continue.
466 add_to_cntr(cntr, rbuf.cmd, what[0]);
467 break;
468 }
469 }
470
471 error:
472 iobuf_free_content(&rbuf);
473 man_off_t_free(pos);
474 return -1;
475 }
476
tell_and_truncate(struct manio ** manio,int compression)477 static int tell_and_truncate(struct manio **manio, int compression)
478 {
479 int ret=-1;
480 man_off_t *pos=NULL;
481 if(!(pos=manio_tell(*manio))) {
482 logp("Could not get pos in %s\n", __func__);
483 goto end;
484 }
485 if(manio_close_and_truncate(manio, pos, compression))
486 goto end;
487 ret=0;
488 end:
489 man_off_t_free(&pos);
490 return ret;
491 }
492
493 // Return p1manio position.
do_resume_work(man_off_t ** pos_phase1,man_off_t ** pos_current,struct sdirs * sdirs,struct dpth * dpth,struct conf ** cconfs)494 static int do_resume_work(
495 man_off_t **pos_phase1,
496 man_off_t **pos_current,
497 struct sdirs *sdirs,
498 struct dpth *dpth, struct conf **cconfs
499 ) {
500 int ret=-1;
501 man_off_t *pos=NULL;
502 struct iobuf *chb=NULL;
503 struct manio *cmanio=NULL;
504 struct manio *chmanio=NULL;
505 struct manio *unmanio=NULL;
506 struct manio *p1manio=NULL;
507 struct manio *counters_d=NULL;
508 struct manio *counters_n=NULL;
509 enum protocol protocol=get_protocol(cconfs);
510 struct cntr *cntr=get_cntr(cconfs);
511 int compression=get_int(cconfs[OPT_COMPRESSION]);
512
513 if(!(cmanio=manio_open(sdirs->cmanifest,
514 MANIO_MODE_READ, protocol))
515 || !(p1manio=manio_open_phase1(sdirs->phase1data,
516 MANIO_MODE_READ, protocol))
517 || !(chmanio=manio_open_phase2(sdirs->changed,
518 MANIO_MODE_READ, protocol))
519 || !(unmanio=manio_open_phase2(sdirs->unchanged,
520 MANIO_MODE_READ, protocol))
521 // The counters are always flat files, which is given by PROTO_1.
522 || !(counters_d=manio_open_phase2(sdirs->counters_d,
523 MANIO_MODE_READ, PROTO_1))
524 || !(counters_n=manio_open_phase2(sdirs->counters_n,
525 MANIO_MODE_READ, PROTO_1)))
526 goto end;
527
528 if(!(chb=iobuf_alloc()))
529 goto error;
530
531 logp("Setting up resume positions...\n");
532
533 if(get_last_good_entry(chmanio, chb, cntr, dpth, protocol, &pos)
534 || manio_close_and_truncate(&chmanio, pos, compression))
535 goto error;
536
537 man_off_t_free(&pos);
538
539 if(chb->buf)
540 {
541 logp(" last good entry: %s\n",
542 iobuf_to_printable(chb));
543 // Now need to go to the appropriate places in p1manio, cmanio
544 // and unmanio.
545
546 logp(" setting pos_phase1\n");
547 if(forward_past_entry(p1manio, chb, protocol, pos_phase1))
548 goto error;
549
550 // This sets pos_current. This manifest may not exist.
551 if(cmanio->fzp)
552 {
553 logp(" setting pos_current\n");
554 if (forward_past_entry(cmanio,
555 chb, protocol, pos_current))
556 goto error;
557 }
558
559 // The unchanged manio needs to be positioned just before the
560 // found entry, otherwise it ends up having a duplicated entry.
561 if(forward_before_entry(unmanio,
562 chb, cntr, dpth, protocol, &pos))
563 goto error;
564 if(manio_close_and_truncate(&unmanio, pos, compression))
565 goto error;
566 man_off_t_free(&pos);
567
568 logp(" setting entry counter_d\n");
569 if(forward_past_entry_counter(counters_d, chb, cntr, &pos))
570 goto error;
571 if(manio_close_and_truncate(&counters_d, pos, 0))
572 goto error;
573 man_off_t_free(&pos);
574
575 logp(" setting entry counter_n\n");
576 if(forward_past_entry_counter(counters_n, chb, cntr, &pos))
577 goto error;
578 if(manio_close_and_truncate(&counters_n, pos, 0))
579 goto error;
580 man_off_t_free(&pos);
581 }
582 else
583 {
584 logp(" nothing previously transferred\n");
585 if(!(*pos_phase1=manio_tell(p1manio))) {
586 logp("Could not get pos_phase1 in %s\n", __func__);
587 goto error;
588 }
589 if(tell_and_truncate(&unmanio, compression)
590 || tell_and_truncate(&counters_d, 0)
591 || tell_and_truncate(&counters_n, 0))
592 goto error;
593 }
594
595 // Now should have all manios truncated correctly, with pos_phase1 and
596 // pos_current set correctly in order to resume.
597 ret=0;
598 goto end;
599 error:
600 man_off_t_free(pos_phase1);
601 man_off_t_free(pos_current);
602 end:
603 iobuf_free(&chb);
604 man_off_t_free(&pos);
605 manio_close(&p1manio);
606 manio_close(&cmanio);
607 manio_close(&chmanio);
608 manio_close(&unmanio);
609 manio_close(&counters_d);
610 manio_close(&counters_n);
611 return ret;
612 }
613
do_resume(man_off_t ** pos_phase1,man_off_t ** pos_current,struct sdirs * sdirs,struct dpth * dpth,struct conf ** cconfs)614 int do_resume(
615 man_off_t **pos_phase1,
616 man_off_t **pos_current,
617 struct sdirs *sdirs,
618 struct dpth *dpth,
619 struct conf **cconfs
620 ) {
621 int ret=-1;
622 struct manio *chmanio=NULL;
623 struct manio *unmanio=NULL;
624 struct manio *p1manio=NULL;
625 struct manio *counters_d=NULL;
626 struct manio *counters_n=NULL;
627 enum protocol protocol=get_protocol(cconfs);
628
629 logp("Begin phase1 (read previous file system scan)\n");
630 if(!(p1manio=manio_open_phase1(sdirs->phase1data, "rb", protocol))
631 || read_phase1(p1manio, cconfs))
632 goto end;
633 manio_close(&p1manio);
634
635 // First, open them in append mode, so that they will be created if
636 // they do not exist.
637 if(!(chmanio=manio_open_phase2(sdirs->changed, "ab", protocol))
638 || !(unmanio=manio_open_phase2(sdirs->unchanged, "ab", protocol))
639 || !(counters_d=manio_open_phase2(sdirs->counters_d, "ab", PROTO_1))
640 || !(counters_n=manio_open_phase2(sdirs->counters_n, "ab", PROTO_1)))
641 goto end;
642 manio_close(&chmanio);
643 manio_close(&unmanio);
644 manio_close(&counters_d);
645 manio_close(&counters_n);
646
647 if(do_resume_work(pos_phase1, pos_current, sdirs, dpth, cconfs))
648 goto end;
649
650 if(dpth_incr(dpth)) goto end;
651
652 logp("End phase1 (read previous file system scan)\n");
653 ret=0;
654 end:
655 manio_close(&p1manio);
656 manio_close(&chmanio);
657 manio_close(&unmanio);
658 manio_close(&counters_d);
659 manio_close(&counters_n);
660 return ret;
661 }
662