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