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