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 "../hexmap.h"
11 #include "../linkhash.h"
12 #include "../lock.h"
13 #include "../log.h"
14 #include "../pathcmp.h"
15 #include "../prepend.h"
16 #include "../protocol2/blk.h"
17 #include "../regexp.h"
18 #include "../slist.h"
19 #include "../strlist.h"
20 #include "bu_get.h"
21 #include "child.h"
22 #include "compress.h"
23 #include "manio.h"
24 #include "protocol1/restore.h"
25 #include "protocol2/dpth.h"
26 #include "protocol2/rblk.h"
27 #include "protocol2/restore.h"
28 #include "../protocol2/rabin/rabin.h"
29 #include "rubble.h"
30 #include "sdirs.h"
31 
restore_end_func(struct asfd * asfd,struct conf ** confs,void * param)32 static enum asl_ret restore_end_func(struct asfd *asfd,
33 	__attribute__ ((unused)) struct conf **confs,
34 	__attribute__ ((unused)) void *param)
35 {
36 	if(!strcmp(asfd->rbuf->buf, "restoreend ok"))
37 		return ASL_END_OK;
38 	// Old v2 clients send something slightly different.
39 	if(!strcmp(asfd->rbuf->buf, "restoreend_ok"))
40 		return ASL_END_OK;
41 	iobuf_log_unexpected(asfd->rbuf, __func__);
42 	return ASL_END_ERROR;
43 }
44 
restore_end(struct asfd * asfd,struct conf ** confs)45 static int restore_end(struct asfd *asfd, struct conf **confs)
46 {
47 	if(asfd->write_str(asfd, CMD_GEN, "restoreend")) return -1;
48 	return asfd->simple_loop(asfd, confs, NULL, __func__, restore_end_func);
49 }
50 
srestore_matches(struct strlist * s,const char * path)51 static int srestore_matches(struct strlist *s, const char *path)
52 {
53 	int r=0;
54 	if(!s->flag) return 0; // Do not know how to do excludes yet.
55 	if((r=strncmp_w(path, s->path))) return 0; // no match
56 	if(!r) return 1; // exact match
57 	if(*(path+strlen(s->path)+1)=='/')
58 		return 1; // matched directory contents
59 	return 0; // no match
60 }
61 
62 // Used when restore is initiated from the server.
srestore_check(struct conf ** confs,const char * path)63 static int srestore_check(struct conf **confs, const char *path)
64 {
65 	struct strlist *l=get_strlist(confs[OPT_INCEXCDIR]);
66 
67 	// If no includes specified, restore everything.
68 	if(!l) return 1;
69 
70 	for(; l; l=l->next)
71 		if(srestore_matches(l, path))
72 			return 1;
73 	return 0;
74 }
75 
restore_list_check(struct asfd * asfd,struct cntr * cntr,struct fzp * rl_fzp,struct iobuf * rl_iobuf,const char * path)76 static int restore_list_check(
77 	struct asfd *asfd,
78 	struct cntr *cntr,
79 	struct fzp *rl_fzp,
80 	struct iobuf *rl_iobuf,
81 	const char *path
82 )
83 {
84 	char *last=NULL;
85 
86 	do {
87 		if(!rl_iobuf->buf)
88 		{
89 			switch(iobuf_fill_from_fzp(rl_iobuf, rl_fzp))
90 			{
91 				case 0: break; // OK, read something.
92 				case 1: return 0; // Finished, no match.
93 				default: return -1; // Error.
94 			}
95 		}
96 
97 		if(last && pathcmp(rl_iobuf->buf, last)!=1)
98 		{
99 			logw(asfd, cntr,
100 				"Input file ordering problem: '%s' '%s'",
101 					last, rl_iobuf->buf);
102 		}
103 
104 		switch(pathcmp(rl_iobuf->buf, path))
105 		{
106 			case 0: return 1; // Successful match.
107 			case 1: return 0; // Ahead in input, no match.
108 			default:
109 				// Behind, need to read more from input.
110 				free_w(&last);
111 				last=rl_iobuf->buf;
112 				rl_iobuf->buf=NULL;
113 		}
114 	} while (1);
115 
116 	return 0;
117 }
118 
want_to_restore(struct asfd * asfd,int srestore,struct fzp * input_fzp,struct iobuf * input_iobuf,struct sbuf * sb,regex_t * regex,enum action act,struct conf ** cconfs)119 static int want_to_restore(
120 	struct asfd *asfd,
121 	int srestore,
122 	struct fzp *input_fzp,
123 	struct iobuf *input_iobuf,
124 	struct sbuf *sb,
125 	regex_t *regex,
126 	enum action act,
127 	struct conf **cconfs
128 ) {
129 	if(act==ACTION_RESTORE)
130 	{
131 		// Do not send VSS data to non-windows, or to windows client
132 		// that asked us not to send it.
133 		if(!get_int(cconfs[OPT_CLIENT_IS_WINDOWS])
134 		  || get_int(cconfs[OPT_VSS_RESTORE])!=VSS_RESTORE_ON)
135 		{
136 			if(sbuf_is_vssdata(sb))
137 				return 0;
138 			// Do not send VSS directory data to non-windows.
139 			if(S_ISDIR(sb->statp.st_mode)
140 			  && sbuf_is_filedata(sb)
141 			  && !sbuf_is_metadata(sb))
142 				return 0;
143 		}
144 	}
145 	return
146 	  (!input_fzp
147 		|| restore_list_check(asfd, get_cntr(cconfs),
148 			input_fzp, input_iobuf, sb->path.buf))
149 	  && (!srestore
150 		|| srestore_check(cconfs, sb->path.buf))
151 	  && (!regex
152 		|| regex_check(regex, sb->path.buf));
153 }
154 
maybe_open_restore_list(struct conf ** cconfs,struct fzp ** rl_fzp,struct iobuf ** rl_iobuf,struct sdirs * sdirs)155 static int maybe_open_restore_list(
156 	struct conf **cconfs,
157 	struct fzp **rl_fzp,
158 	struct iobuf **rl_iobuf,
159 	struct sdirs *sdirs
160 ) {
161 	if(!get_string(cconfs[OPT_RESTORE_LIST]))
162 		return 0;
163 
164 	if(!(*rl_fzp=fzp_open(sdirs->restore_list, "rb"))
165 	  || !(*rl_iobuf=iobuf_alloc()))
166 		return -1;
167 
168 	return 0;
169 }
170 
setup_cntr(struct asfd * asfd,const char * manifest,regex_t * regex,int srestore,struct conf ** cconfs,enum action act,struct bu * bu,struct sdirs * sdirs)171 static int setup_cntr(struct asfd *asfd, const char *manifest,
172 	regex_t *regex, int srestore, struct conf **cconfs, enum action act,
173 	struct bu *bu, struct sdirs *sdirs)
174 {
175 	int ars=0;
176 	int ret=-1;
177 	struct fzp *fzp=NULL;
178 	struct sbuf *sb=NULL;
179 	struct cntr *cntr=NULL;
180 	struct fzp *rl_fzp=NULL;
181 	struct iobuf *rl_iobuf=NULL;
182 
183 	cntr=get_cntr(cconfs);
184 	if(!cntr) return 0;
185 	cntr->bno=(int)bu->bno;
186 
187 // FIX THIS: this is only trying to work for protocol1.
188 	if(get_protocol(cconfs)!=PROTO_1) return 0;
189 
190 	if(maybe_open_restore_list(cconfs, &rl_fzp, &rl_iobuf, sdirs))
191 		goto end;
192 
193 	if(!(sb=sbuf_alloc(PROTO_1))) goto end;
194 	if(!(fzp=fzp_gzopen(manifest, "rb")))
195 	{
196 		log_and_send(asfd, "could not open manifest");
197 		goto end;
198 	}
199 	while(1)
200 	{
201 		if((ars=sbuf_fill_from_file(sb, fzp, NULL)))
202 		{
203 			if(ars<0) goto end;
204 			// ars==1 means end ok
205 			break;
206 		}
207 		else
208 		{
209 			if(want_to_restore(asfd, srestore,
210 				rl_fzp, rl_iobuf,
211 				sb, regex, act, cconfs))
212 			{
213 				cntr_add_phase1(cntr, sb->path.cmd, 0);
214 				if(sb->endfile.buf)
215 				  cntr_add_val(cntr,
216 					CMD_BYTES_ESTIMATED,
217 					strtoull(sb->endfile.buf,
218 						NULL, 10));
219 			}
220 		}
221 		sbuf_free_content(sb);
222 	}
223 	ret=0;
224 end:
225 	iobuf_free(&rl_iobuf);
226 	fzp_close(&rl_fzp);
227 	sbuf_free(&sb);
228 	fzp_close(&fzp);
229 	return ret;
230 }
231 
232 static int restore_sbuf(struct asfd *asfd, struct sbuf *sb, struct bu *bu,
233 	enum action act, struct sdirs *sdirs, enum cntr_status cntr_status,
234 	struct conf **cconfs, struct sbuf *need_data, const char *manifest,
235 	struct slist *slist);
236 
log_missing_block(struct asfd * asfd,struct cntr * cntr,struct blk * blk,struct sbuf * need_data)237 static void log_missing_block(struct asfd *asfd, struct cntr *cntr,
238 	struct blk *blk, struct sbuf *need_data)
239 {
240 	uint16_t datno=0;
241 	char *savepathstr;
242 	savepathstr=uint64_to_savepathstr_with_sig_uint(blk->savepath, &datno);
243 	logw(asfd, cntr, "%s: Missing block %s:%d\n",
244 		iobuf_to_printable(&need_data->path), savepathstr, datno);
245 }
246 
247 // Used when restoring a hard link that we have not restored the destination
248 // for. Read through the manifest from the beginning and substitute the path
249 // and data to the new location.
hard_link_substitution(struct asfd * asfd,struct sbuf * sb,struct f_link * lp,struct bu * bu,enum action act,struct sdirs * sdirs,enum cntr_status cntr_status,struct conf ** cconfs,const char * manifest,struct slist * slist)250 static int hard_link_substitution(struct asfd *asfd,
251 	struct sbuf *sb, struct f_link *lp,
252 	struct bu *bu, enum action act, struct sdirs *sdirs,
253 	enum cntr_status cntr_status, struct conf **cconfs,
254 	const char *manifest, struct slist *slist)
255 {
256 	int ret=-1;
257 	struct sbuf *need_data=NULL;
258 	int last_ent_was_dir=0;
259 	struct sbuf *hb=NULL;
260 	struct manio *manio=NULL;
261 	struct blk *blk=NULL;
262 	int pcmp;
263 	enum protocol protocol=get_protocol(cconfs);
264 	struct cntr *cntr=get_cntr(cconfs);
265 
266 	if(!(manio=manio_open(manifest, "rb", protocol))
267 	  || !(need_data=sbuf_alloc(protocol))
268 	  || !(hb=sbuf_alloc(protocol)))
269 		goto end;
270 
271 	if(protocol==PROTO_2)
272 	{
273 		  if(!(blk=blk_alloc()))
274 			goto end;
275 	}
276 
277 	while(1)
278 	{
279 		if(blk)
280 			blk->got_save_path=0;
281 		switch(manio_read_with_blk(manio,
282 			hb, need_data->path.buf?blk:NULL))
283 		{
284 			case 0: break; // Keep going.
285 			case 1: ret=0; goto end; // Finished OK.
286 			default: goto end; // Error;
287 		}
288 
289 		if(protocol==PROTO_2)
290 		{
291 			if(hb->endfile.buf)
292 			{
293 				sbuf_free_content(hb);
294 				continue;
295 			}
296 			if(blk->got_save_path)
297 			{
298 				blk->got_save_path=0;
299 				if(rblk_retrieve_data(asfd, cntr,
300 					blk, sdirs->data))
301 				{
302 					log_missing_block(asfd, cntr,
303 						blk, need_data);
304 					continue;
305 				}
306 			}
307 			if(blk->data)
308 			{
309 				if(protocol2_extra_restore_stream_bits(asfd,
310 					blk, slist, act, need_data,
311 					last_ent_was_dir, cntr)) goto end;
312 				continue;
313 			}
314 			sbuf_free_content(need_data);
315 		}
316 
317 		pcmp=pathcmp(lp->name, hb->path.buf);
318 
319 		if(!pcmp && (sbuf_is_filedata(hb) || sbuf_is_vssdata(hb)))
320 		{
321 			// Copy the path from sb to hb.
322 			free_w(&hb->path.buf);
323 			if(!(hb->path.buf=strdup_w(sb->path.buf, __func__)))
324 				goto end;
325 			hb->path.len = sb->path.len;
326 			// Should now be able to restore the original data
327 			// to the new location.
328 			ret=restore_sbuf(asfd, hb, bu, act, sdirs,
329 			  cntr_status, cconfs, need_data, manifest, slist);
330 			// May still need to get protocol2 data.
331 			if(!ret && need_data->path.buf) continue;
332 			break;
333 		}
334 
335 		sbuf_free_content(hb);
336 		// Break out once we have gone past the entry that we are
337 		// interested in.
338 		if(pcmp<0) break;
339 	}
340 end:
341 	blk_free(&blk);
342 	sbuf_free(&hb);
343 	manio_close(&manio);
344 	return ret;
345 }
346 
restore_sbuf(struct asfd * asfd,struct sbuf * sb,struct bu * bu,enum action act,struct sdirs * sdirs,enum cntr_status cntr_status,struct conf ** cconfs,struct sbuf * need_data,const char * manifest,struct slist * slist)347 static int restore_sbuf(struct asfd *asfd, struct sbuf *sb, struct bu *bu,
348 	enum action act, struct sdirs *sdirs, enum cntr_status cntr_status,
349 	struct conf **cconfs, struct sbuf *need_data, const char *manifest,
350 	struct slist *slist)
351 {
352 	//printf("%s: %s\n", act==ACTION_RESTORE?"restore":"verify",
353 	//  iobuf_to_printable(&sb->path));
354 	if(timed_operation_status_only(cntr_status, sb->path.buf, cconfs))
355 		return -1;
356 
357 	if(sb->path.cmd==CMD_HARD_LINK)
358 	{
359 		struct f_link *lp=NULL;
360 		struct f_link **bucket=NULL;
361 		if((lp=linkhash_search(&sb->statp, &bucket)))
362 		{
363 			// It is in the list of stuff that is in the manifest,
364 			// but was skipped on this restore.
365 			// Need to go through the manifest from the beginning,
366 			// and substitute in the data to restore to this
367 			// location.
368 			return hard_link_substitution(asfd, sb, lp,
369 				bu, act, sdirs,
370 				cntr_status, cconfs, manifest, slist);
371 			// FIX THIS: Would be nice to remember the new link
372 			// location so that further hard links would link to
373 			// it instead of doing the hard_link_substitution
374 			// business over again.
375 		}
376 	}
377 
378 	if(get_protocol(cconfs)==PROTO_1)
379 	{
380 		return restore_sbuf_protocol1(asfd, sb, bu,
381 		  act, sdirs, cconfs);
382 	}
383 	else
384 	{
385 		return restore_sbuf_protocol2(asfd, sb,
386 		  act, get_cntr(cconfs), need_data);
387 	}
388 }
389 
restore_ent(struct asfd * asfd,struct sbuf ** sb,struct slist * slist,struct bu * bu,enum action act,struct sdirs * sdirs,enum cntr_status cntr_status,struct conf ** cconfs,struct sbuf * need_data,int * last_ent_was_dir,const char * manifest)390 static int restore_ent(struct asfd *asfd,
391 	struct sbuf **sb,
392 	struct slist *slist,
393 	struct bu *bu,
394 	enum action act,
395 	struct sdirs *sdirs,
396 	enum cntr_status cntr_status,
397 	struct conf **cconfs,
398 	struct sbuf *need_data,
399 	int *last_ent_was_dir,
400 	const char *manifest)
401 {
402 	int ret=-1;
403 	struct sbuf *xb;
404 
405 	if(!(*sb)->path.buf)
406 	{
407 		logp("Got NULL path!\n");
408 		return -1;
409 	}
410 
411 	// Check if we have any directories waiting to be restored.
412 	while((xb=slist->head))
413 	{
414 		if(is_subdir(xb->path.buf, (*sb)->path.buf))
415 		{
416 			// We are still in a subdir.
417 			break;
418 		}
419 		else
420 		{
421 			// Can now restore xb because nothing else is fiddling
422 			// in a subdirectory.
423 			if(restore_sbuf(asfd, xb, bu,
424 			  act, sdirs, cntr_status, cconfs, need_data, manifest,
425 			  slist))
426 				goto end;
427 			if(get_protocol(cconfs)==PROTO_2
428 			  && sbuf_is_filedata(xb)
429 			  && get_int(cconfs[OPT_CLIENT_IS_WINDOWS]))
430 			{
431 				// Windows directories need endfile to be sent.
432 				if(asfd->write(asfd, &xb->endfile))
433 					goto end;
434 			}
435 			slist->head=xb->next;
436 			sbuf_free(&xb);
437 		}
438 	}
439 
440 	/* If it is a directory, need to remember it and restore it later, so
441 	   that the permissions come out right. */
442 	/* Meta data of directories will also have the stat stuff set to be a
443 	   directory, so will also come out at the end. */
444 	/* FIX THIS: for Windows, need to read and remember the blocks that
445 	   go with the directories. Probably have to do the same for metadata
446 	   that goes with directories. */
447 	if(S_ISDIR((*sb)->statp.st_mode)
448 	  // Hack for metadata for now - just do it straight away.
449 	  && !sbuf_is_metadata(*sb))
450 	{
451 		// Add to the head of the list instead of the tail.
452 		(*sb)->next=slist->head;
453 		slist->head=*sb;
454 
455 		*last_ent_was_dir=1;
456 
457 		// Allocate a new sb.
458 		if(!(*sb=sbuf_alloc(get_protocol(cconfs)))) goto end;
459 	}
460 	else
461 	{
462 		*last_ent_was_dir=0;
463 		if(restore_sbuf(asfd, *sb, bu,
464 		  act, sdirs, cntr_status, cconfs, need_data, manifest,
465 		  slist))
466 			goto end;
467 	}
468 	ret=0;
469 end:
470 	return ret;
471 }
472 
restore_remaining_dirs(struct asfd * asfd,struct bu * bu,struct slist * slist,enum action act,struct sdirs * sdirs,struct conf ** cconfs)473 static int restore_remaining_dirs(struct asfd *asfd, struct bu *bu,
474 	struct slist *slist, enum action act, struct sdirs *sdirs,
475 	struct conf **cconfs)
476 {
477 	int ret=-1;
478 	struct sbuf *sb;
479 	struct sbuf *need_data=NULL;
480 	if(!(need_data=sbuf_alloc(get_protocol(cconfs)))) goto end;
481 	// Restore any directories that are left in the list.
482 	for(sb=slist->head; sb; sb=sb->next)
483 	{
484 		if(get_protocol(cconfs)==PROTO_1)
485 		{
486 			if(restore_sbuf_protocol1(asfd, sb, bu, act,
487 				sdirs, cconfs))
488 					goto end;
489 		}
490 		else
491 		{
492 			if(restore_sbuf_protocol2(asfd, sb, act,
493 				get_cntr(cconfs), NULL))
494 					goto end;
495 			if(sbuf_is_filedata(sb)
496 			  && get_int(cconfs[OPT_CLIENT_IS_WINDOWS]))
497 			{
498 				// Windows directories need endfile to be sent.
499 				if(asfd->write(asfd, &sb->endfile))
500 					goto end;
501 			}
502 		}
503 	}
504 	ret=0;
505 end:
506 	sbuf_free(&need_data);
507 	return ret;
508 }
509 
restore_stream(struct asfd * asfd,struct sdirs * sdirs,struct slist * slist,struct bu * bu,const char * manifest,regex_t * regex,int srestore,struct conf ** cconfs,enum action act,enum cntr_status cntr_status)510 static int restore_stream(struct asfd *asfd, struct sdirs *sdirs,
511 	struct slist *slist, struct bu *bu, const char *manifest,
512 	regex_t *regex, int srestore, struct conf **cconfs, enum action act,
513 	enum cntr_status cntr_status)
514 {
515 	int ret=-1;
516 	int last_ent_was_dir=0;
517 	int last_ent_was_skipped=0;
518 	struct sbuf *sb=NULL;
519 	struct iobuf *rbuf=asfd->rbuf;
520 	struct manio *manio=NULL;
521 	struct blk *blk=NULL;
522 	struct sbuf *need_data=NULL;
523 	enum protocol protocol=get_protocol(cconfs);
524 	struct cntr *cntr=get_cntr(cconfs);
525 	struct iobuf interrupt;
526 	struct fzp *rl_fzp=NULL;
527 	struct iobuf *rl_iobuf=NULL;
528 
529 	iobuf_init(&interrupt);
530 
531 	if(protocol==PROTO_2)
532 	{
533 		static int rs_sent=0;
534 		if(!(blk=blk_alloc()))
535 			goto end;
536 		if(!rs_sent)
537 		{
538 			rs_sent=1;
539 			if(asfd->write_str(asfd,
540 				CMD_GEN, "restore_stream")
541 			  || asfd_read_expect(asfd,
542 				CMD_GEN, "restore_stream_ok"))
543 					goto end;
544 		}
545 	}
546 
547 	if(maybe_open_restore_list(cconfs, &rl_fzp, &rl_iobuf, sdirs))
548 		goto end;
549 
550 	if(!(manio=manio_open(manifest, "rb", protocol))
551 	  || !(need_data=sbuf_alloc(protocol))
552 	  || !(sb=sbuf_alloc(protocol)))
553 		goto end;
554 
555 	while(1)
556 	{
557 		iobuf_free_content(rbuf);
558 		if(asfd->as->read_quick(asfd->as))
559 		{
560 			logp("read quick error\n");
561 			goto end;
562 		}
563 		if(rbuf->buf) switch(rbuf->cmd)
564 		{
565 			case CMD_MESSAGE:
566 			case CMD_WARNING:
567 			{
568 				log_recvd(rbuf, cntr, 0);
569 				continue;
570 			}
571 			case CMD_INTERRUPT:
572 				if(protocol==PROTO_2)
573 				{
574 					iobuf_free_content(&interrupt);
575 					iobuf_move(&interrupt, rbuf);
576 				}
577 				// PROTO_1:
578 				// Client wanted to interrupt the
579 				// sending of a file. But if we are
580 				// here, we have already moved on.
581 				// Ignore.
582 				continue;
583 			default:
584 				iobuf_log_unexpected(rbuf, __func__);
585 				goto end;
586 		}
587 
588 		if(blk)
589 			blk->got_save_path=0;
590 		switch(manio_read_with_blk(manio,
591 			sb, need_data->path.buf?blk:NULL))
592 		{
593 			case 0: break; // Keep going.
594 			case 1: ret=0; goto end; // Finished OK.
595 			default: goto end; // Error;
596 		}
597 
598 		if(protocol==PROTO_2)
599 		{
600 			if(sb->endfile.buf)
601 			{
602 				if(act==ACTION_RESTORE && !last_ent_was_skipped)
603 				{
604 					if(last_ent_was_dir)
605 					{
606 						// Delay sending endfile until
607 						// we actually send the
608 						// directory.
609 						struct sbuf *xb=slist->head;
610 						iobuf_free_content(&xb->endfile);
611 						iobuf_move(&xb->endfile,
612 							&sb->endfile);
613 					}
614 					else
615 					{
616 						if(asfd->write(asfd,
617 							&sb->endfile))
618 								goto end;
619 					}
620 				}
621 				sbuf_free_content(sb);
622 				iobuf_free_content(&interrupt);
623 				continue;
624 			}
625 			if(interrupt.buf)
626 			{
627 				if(!need_data->path.buf)
628 				{
629 					iobuf_free_content(&interrupt);
630 				}
631 				else if(!iobuf_pathcmp(&need_data->path,
632 					&interrupt))
633 				{
634 					continue;
635 				}
636 			}
637 			if(blk->got_save_path)
638 			{
639 				blk->got_save_path=0;
640 				if(rblk_retrieve_data(asfd, cntr,
641 					blk, sdirs->data))
642 				{
643 					log_missing_block(asfd, cntr,
644 						blk, need_data);
645 					continue;
646 				}
647 			}
648 			if(blk->data)
649 			{
650 				if(protocol2_extra_restore_stream_bits(asfd,
651 					blk, slist, act, need_data,
652 					last_ent_was_dir, cntr)) goto end;
653 				continue;
654 			}
655 			sbuf_free_content(need_data);
656 		}
657 
658 		if(want_to_restore(asfd, srestore, rl_fzp, rl_iobuf,
659 			sb, regex, act, cconfs))
660 		{
661 			last_ent_was_skipped=0;
662 			if(restore_ent(asfd, &sb, slist,
663 				bu, act, sdirs, cntr_status, cconfs,
664 				need_data, &last_ent_was_dir, manifest))
665 					goto end;
666 		}
667 		else
668 		{
669 			last_ent_was_skipped=1;
670 			if(sbuf_is_filedata(sb) || sbuf_is_vssdata(sb))
671 			{
672 				// Add it to the list of filedata that was not
673 				// restored.
674 				struct f_link **bucket=NULL;
675 				if(!linkhash_search(&sb->statp, &bucket)
676 				  && linkhash_add(sb->path.buf, &sb->statp, bucket))
677 					goto end;
678 			}
679 		}
680 
681 		sbuf_free_content(sb);
682 	}
683 end:
684 	iobuf_free(&rl_iobuf);
685 	fzp_close(&rl_fzp);
686 	blk_free(&blk);
687 	sbuf_free(&sb);
688 	sbuf_free(&need_data);
689 	iobuf_free_content(rbuf);
690 	iobuf_free_content(&interrupt);
691 	manio_close(&manio);
692 	return ret;
693 }
694 
actual_restore(struct asfd * asfd,struct bu * bu,const char * manifest,regex_t * regex,int srestore,enum action act,struct sdirs * sdirs,enum cntr_status cntr_status,struct conf ** cconfs)695 static int actual_restore(struct asfd *asfd, struct bu *bu,
696 	const char *manifest, regex_t *regex, int srestore, enum action act,
697 	struct sdirs *sdirs, enum cntr_status cntr_status, struct conf **cconfs)
698 {
699 	int ret=-1;
700 	// For out-of-sequence directory restoring so that the
701 	// timestamps come out right:
702 	struct slist *slist=NULL;
703 	struct cntr *cntr=NULL;
704 
705 	if(linkhash_init()
706 	  || !(slist=slist_alloc()))
707 		goto end;
708 
709 	if(get_protocol(cconfs)==PROTO_2)
710 		rblks_init(get_uint64_t(cconfs[OPT_RBLK_MEMORY_MAX]));
711 
712 	if(restore_stream(asfd, sdirs, slist,
713 		bu, manifest, regex,
714 		srestore, cconfs, act, cntr_status))
715 			goto end;
716 
717 	if(restore_remaining_dirs(asfd, bu, slist,
718 		act, sdirs, cconfs)) goto end;
719 
720 	if(cconfs) cntr=get_cntr(cconfs);
721 	cntr_set_bytes(cntr, asfd);
722 	cntr_print(cntr, act);
723 	if(cntr_stats_to_file(cntr, bu->path, act))
724 		goto end;
725 	ret=0;
726 end:
727 	slist_free(&slist);
728 	linkhash_free();
729 	rblks_free();
730 	return ret;
731 }
732 
get_logpaths(struct bu * bu,const char * file,char ** logpath,char ** logpathz)733 static int get_logpaths(struct bu *bu, const char *file,
734 	char **logpath, char **logpathz)
735 {
736 	if(!(*logpath=prepend_s(bu->path, file))
737 	  || !(*logpathz=prepend(*logpath, ".gz")))
738 		return -1;
739 	return 0;
740 }
741 
parallelism_warnings(struct asfd * asfd,struct conf ** cconfs,struct sdirs * sdirs,struct bu * bu,enum protocol protocol)742 static void parallelism_warnings(struct asfd *asfd, struct conf **cconfs,
743 	struct sdirs *sdirs, struct bu *bu, enum protocol protocol)
744 {
745 	struct bu *b;
746 
747 	if(lock_test(sdirs->lock_storage_for_write->path))
748 	{
749 		logm(asfd, cconfs, "Another process is currently backing up or deleting for this client.\n");
750 		return;
751 	}
752 
753 	if(!check_for_rubble(sdirs))
754 		return;
755 
756 	for(b=bu; b && b->next; b=b->next)
757 	{
758 		if(b->flags & BU_CURRENT)
759 			break; // Warning.
760 		if(protocol==PROTO_2)
761 			return; // No warning.
762 		if(b->flags & BU_HARDLINKED)
763 			return; // No warning.
764 	}
765 
766 	logw(asfd, get_cntr(cconfs),
767 		"The latest backup needs recovery, but continuing anyway.\n");
768 }
769 
restore_manifest(struct asfd * asfd,struct bu * bu,regex_t * regex,int srestore,enum action act,struct sdirs * sdirs,char ** dir_for_notify,struct conf ** cconfs)770 static int restore_manifest(struct asfd *asfd, struct bu *bu,
771 	regex_t *regex, int srestore, enum action act, struct sdirs *sdirs,
772 	char **dir_for_notify, struct conf **cconfs)
773 {
774 	int ret=-1;
775 	char *manifest=NULL;
776 	char *logpath=NULL;
777 	char *logpathz=NULL;
778 	enum protocol protocol;
779 	enum cntr_status cntr_status;
780 	struct lock *lock=NULL;
781 	char *lockfile=NULL;
782 	static int manifest_count=0;
783 
784 	protocol=get_protocol(cconfs);
785 	if(protocol==PROTO_2
786 	  && blks_generate_init())
787 		goto end;
788 
789 	if(!(lockfile=prepend_s(bu->path, "lockfile.read"))
790 	  || !(lock=lock_alloc_and_init(lockfile)))
791 		goto end;
792 	lock_get(lock);
793 	if(lock->status!=GET_LOCK_GOT)
794 	{
795 		char msg[256]="";
796 		snprintf(msg, sizeof(msg), "Another process is restoring or verifying backup %s.\n", bu->timestamp);
797 		log_and_send(asfd, msg);
798 		goto end;
799 	}
800 
801 	// For sending status information up to the server.
802 	cntr_status=CNTR_STATUS_RESTORING;
803 
804 	if(act==ACTION_RESTORE) cntr_status=CNTR_STATUS_RESTORING;
805 	else if(act==ACTION_VERIFY) cntr_status=CNTR_STATUS_VERIFYING;
806 
807 	if((act==ACTION_RESTORE && get_logpaths(bu, "restorelog",
808 		&logpath, &logpathz))
809 	  || (act==ACTION_VERIFY && get_logpaths(bu, "verifylog",
810 		&logpath, &logpathz))
811 	  || !(manifest=prepend_s(bu->path,
812 		get_protocol(cconfs)==PROTO_1?
813 			"manifest.gz":"manifest")))
814 	{
815 		log_and_send_oom(asfd);
816 		goto end;
817 	}
818 
819 	if(log_fzp_set(logpath, cconfs))
820 	{
821 		char msg[256]="";
822 		snprintf(msg, sizeof(msg),
823 				"could not open log file: %s", logpath);
824 		log_and_send(asfd, msg);
825 		goto end;
826 	}
827 
828 	*dir_for_notify=strdup_w(bu->path, __func__);
829 
830 	log_restore_settings(cconfs, srestore);
831 
832 	// First, do a pass through the manifest to set up cntr.
833 	// This is the equivalent of a phase1 scan during backup.
834 
835 	if(setup_cntr(asfd, manifest,
836 		regex, srestore, cconfs, act, bu, sdirs))
837 			goto end;
838 
839 	if(!manifest_count)
840 	{
841 		// FIX THIS: Only send the counters once, otherwise the
842 		// client will break on '-b a' because it does not expect
843 		// multiple sets of counters to turn up.
844 		// This means that the client side 'expected' counter will be
845 		// confusing in that case. Live with it for now.
846 		// However, the server side log will be OK.
847 		if(cntr_send_bu(asfd, bu, cconfs, cntr_status))
848 			goto end;
849 	}
850 
851 	parallelism_warnings(asfd, cconfs, sdirs, bu, protocol);
852 
853 	// Now, do the actual restore.
854 	ret=actual_restore(asfd, bu, manifest,
855 		  regex, srestore, act, sdirs, cntr_status, cconfs);
856 end:
857 	log_fzp_set(NULL, cconfs);
858 	if(logpath && logpathz)
859 		compress_file(logpath, logpathz,
860 			get_int(cconfs[OPT_COMPRESSION]));
861 	free_w(&manifest);
862 	free_w(&logpath);
863 	free_w(&logpathz);
864 	if(protocol==PROTO_2)
865 		blks_generate_free();
866 	free_w(&lockfile);
867 	lock_release(lock);
868 	lock_free(&lock);
869 	manifest_count++;
870 	return ret;
871 }
872 
do_restore_server(struct asfd * asfd,struct sdirs * sdirs,enum action act,int srestore,char ** dir_for_notify,struct conf ** confs)873 int do_restore_server(struct asfd *asfd, struct sdirs *sdirs,
874 	enum action act, int srestore,
875 	char **dir_for_notify, struct conf **confs)
876 {
877 	int ret=-1;
878 	uint8_t found=0;
879 	struct bu *bu=NULL;
880 	struct bu *bu_list=NULL;
881 	unsigned long bno=0;
882 	regex_t *regex=NULL;
883 	const char *regexstr=get_string(confs[OPT_REGEX]);
884 	const char *backup=get_string(confs[OPT_BACKUP]);
885 	int regex_case_insensitive=get_int(confs[OPT_REGEX_CASE_INSENSITIVE]);
886 
887 	logp("in do_restore\n");
888 
889 	if(regexstr
890 	  && *regexstr
891 	  && !(regex=regex_compile_restore(regexstr, regex_case_insensitive)))
892 	{
893 		char msg[256]="";
894 		snprintf(msg, sizeof(msg), "unable to compile regex: %s\n",
895 			regexstr);
896 		log_and_send(asfd, msg);
897 		goto end;
898 	}
899 
900 	if(bu_get_list(sdirs, &bu_list))
901 		goto end;
902 
903 	if(bu_list &&
904 	   (!backup
905 	 || !*backup
906 	 || (!(bno=strtoul(backup, NULL, 10)) && *backup!='a')))
907 	{
908 		found=1;
909 		// No backup specified, do the most recent.
910 		for(bu=bu_list; bu && bu->next; bu=bu->next) { }
911 		ret=restore_manifest(asfd, bu, regex, srestore,
912 				act, sdirs, dir_for_notify, confs);
913 	}
914 
915 	if(!found) for(bu=bu_list; bu; bu=bu->next)
916 	{
917 		if(!strcmp(bu->timestamp, backup)
918 		  || bu->bno==bno || (backup && *backup=='a'))
919 		{
920 			found=1;
921 			//logp("got: %s\n", bu->path);
922 			ret|=restore_manifest(asfd, bu, regex, srestore,
923 				act, sdirs, dir_for_notify, confs);
924 			if(backup && *backup=='a')
925 				continue;
926 			break;
927 		}
928 	}
929 
930 	bu_list_free(&bu_list);
931 
932 
933 	if(found)
934 	{
935 		// Restore has nearly completed OK.
936 		ret=restore_end(asfd, confs);
937 	}
938 	else
939 	{
940 		logp("backup not found\n");
941 		asfd->write_str(asfd, CMD_ERROR, "backup not found");
942 		ret=-1;
943 	}
944 end:
945 	regex_free(&regex);
946 	return ret;
947 }
948