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