Example #1
0
// a = length of struct bu array
// i = position to restore from
static int restore_manifest(struct bu *arr, int a, int i, const char *tmppath1, const char *tmppath2, regex_t *regex, int srestore, enum action act, const char *client, char **dir_for_notify, struct cntr *p1cntr, struct cntr *cntr, struct config *cconf)
{
	int ret=0;
	gzFile zp=NULL;
	char *manifest=NULL;
	char *datadir=NULL;
	FILE *logfp=NULL;
	char *logpath=NULL;
	char *logpathz=NULL;
	// For sending status information up to the server.
	char status=STATUS_RESTORING;

	if(act==ACTION_RESTORE) status=STATUS_RESTORING;
	else if(act==ACTION_VERIFY) status=STATUS_VERIFYING;

	if(
	    (act==ACTION_RESTORE && !(logpath=prepend_s(arr[i].path, "restorelog", strlen("restorelog"))))
	 || (act==ACTION_RESTORE && !(logpathz=prepend_s(arr[i].path, "restorelog.gz", strlen("restorelog.gz"))))
	 || (act==ACTION_VERIFY && !(logpath=prepend_s(arr[i].path, "verifylog", strlen("verifylog"))))
	 || (act==ACTION_VERIFY && !(logpathz=prepend_s(arr[i].path, "verifylog.gz", strlen("verifylog.gz"))))
	 || !(manifest=prepend_s(arr[i].path, "manifest.gz", strlen("manifest.gz"))))
	{
		log_and_send_oom(__FUNCTION__);
		ret=-1;
	}
	else if(!(logfp=open_file(logpath, "ab")) || set_logfp(logfp, cconf))
	{
		char msg[256]="";
		snprintf(msg, sizeof(msg),
			"could not open log file: %s", logpath);
		log_and_send(msg);
		ret=-1;
	}

	*dir_for_notify=strdup(arr[i].path);

	log_restore_settings(cconf, srestore);

	// First, do a pass through the manifest to set up the counters.
	// This is the equivalent of a phase1 scan during backup.
	if(!ret && !(zp=gzopen_file(manifest, "rb")))
	{
		log_and_send("could not open manifest");
		ret=-1;
	}
	else
	{
		int ars=0;
		int quit=0;
		struct sbuf sb;
		init_sbuf(&sb);
		while(!quit)
		{
			if((ars=sbuf_fill(NULL, zp, &sb, cntr)))
			{
				if(ars<0) ret=-1;
				// ars==1 means end ok
				quit++;
			}
			else
			{
				if((!srestore
				    || check_srestore(cconf, sb.path))
				  && check_regex(regex, sb.path))
				{
					do_filecounter(p1cntr, sb.cmd, 0);
					if(sb.endfile)
					  do_filecounter_bytes(p1cntr,
                 			    strtoull(sb.endfile, NULL, 10));
/*
					if(sb.cmd==CMD_FILE
					  || sb.cmd==CMD_ENC_FILE
					  || sb.cmd==CMD_METADATA
					  || sb.cmd==CMD_ENC_METADATA
					  || sb.cmd==CMD_VSS
					  || sb.cmd==CMD_ENC_VSS
					  || sb.cmd==CMD_VSS_T
					  || sb.cmd==CMD_ENC_VSS_T
					  || sb.cmd==CMD_EFS_FILE)
						do_filecounter_bytes(p1cntr,
							(unsigned long long)
							sb.statp.st_size);
*/
				}
			}
			free_sbuf(&sb);
		}
		free_sbuf(&sb);
		gzclose_fp(&zp);
	}

	if(cconf->send_client_counters)
	{
		if(send_counters(client, p1cntr, cntr))
		{
			ret=-1;
		}
	}

	// Now, do the actual restore.
	if(!ret && !(zp=gzopen_file(manifest, "rb")))
	{
		log_and_send("could not open manifest");
		ret=-1;
	}
	else
	{
		char cmd;
		int s=0;
		int quit=0;
		size_t len=0;
		struct sbuf sb;
		// For out-of-sequence directory restoring so that the
		// timestamps come out right:
		int scount=0;
		struct sbuf **sblist=NULL;

		init_sbuf(&sb);

		while(!quit)
		{
			int ars=0;
			char *buf=NULL;
			if(async_read_quick(&cmd, &buf, &len))
			{
				logp("read quick error\n");
				ret=-1; quit++; break;
			}
			if(buf)
			{
				//logp("got read quick\n");
				if(cmd==CMD_WARNING)
				{
					logp("WARNING: %s\n", buf);
					do_filecounter(cntr, cmd, 0);
					free(buf); buf=NULL;
					continue;
				}
				else if(cmd==CMD_INTERRUPT)
				{
					// Client wanted to interrupt the
					// sending of a file. But if we are
					// here, we have already moved on.
					// Ignore.
					free(buf); buf=NULL;
					continue;
				}
				else
				{
					logp("unexpected cmd from client: %c:%s\n", cmd, buf);
					free(buf); buf=NULL;
					ret=-1; quit++; break;
				}
			}

			if((ars=sbuf_fill(NULL, zp, &sb, cntr)))
			{
				if(ars<0) ret=-1;
				// ars==1 means end ok
				quit++;
			}
			else
			{
				if((!srestore
				    || check_srestore(cconf, sb.path))
				  && check_regex(regex, sb.path)
				  && restore_ent(client,
					&sb, &sblist, &scount,
					arr, a, i, tmppath1, tmppath2,
					act, status, cconf,
					cntr, p1cntr))
				{
					ret=-1;
					quit++;
				}
			}
			free_sbuf(&sb);
		}
		gzclose_fp(&zp);
		// Restore any directories that are left in the list.
		if(!ret) for(s=scount-1; s>=0; s--)
		{
			if(restore_sbuf(sblist[s], arr, a, i,
				tmppath1, tmppath2, act, client, status,
				p1cntr, cntr, cconf))
			{
				ret=-1;
				break;
			}
		}
		free_sbufs(sblist, scount);

		if(!ret) ret=do_restore_end(act, cntr);

		//print_endcounter(cntr);
		print_filecounters(p1cntr, cntr, act);

		reset_filecounter(p1cntr, time(NULL));
		reset_filecounter(cntr, time(NULL));
	}
	set_logfp(NULL, cconf);
	compress_file(logpath, logpathz, cconf);
	if(manifest) free(manifest);
	if(datadir) free(datadir);
	if(logpath) free(logpath);
	if(logpathz) free(logpathz);
	return ret;
}
Example #2
0
static int 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)
{
	int ret=-1;
	int last_ent_was_dir=0;
	struct sbuf *sb=NULL;
	struct iobuf *rbuf=asfd->rbuf;
	struct manio *manio=NULL;
	struct blk *blk=NULL;
	struct sbuf *need_data=NULL;
	enum protocol protocol=get_protocol(cconfs);
	struct cntr *cntr=get_cntr(cconfs);

	if(protocol==PROTO_2)
	{
		if(asfd->write_str(asfd, CMD_GEN, "restore_stream")
		  || asfd->read_expect(asfd, CMD_GEN, "restore_stream_ok")
		  || !(blk=blk_alloc()))
                	goto end;
	}

	if(!(manio=manio_open(manifest, "rb", protocol))
	  || !(need_data=sbuf_alloc(protocol))
	  || !(sb=sbuf_alloc(protocol)))
		goto end;

	while(1)
	{
		iobuf_free_content(rbuf);
		if(asfd->as->read_quick(asfd->as))
		{
			logp("read quick error\n");
			goto end;
		}
		if(rbuf->buf) switch(rbuf->cmd)
		{
			case CMD_MESSAGE:
			case CMD_WARNING:
			{
				log_recvd(rbuf, cntr, 0);
				continue;
			}
			case CMD_INTERRUPT:
				// Client wanted to interrupt the
				// sending of a file. But if we are
				// here, we have already moved on.
				// Ignore.
				continue;
			default:
				iobuf_log_unexpected(rbuf, __func__);
				goto end;
		}

		switch(manio_read_with_blk(manio,
			sb, need_data->path.buf?blk:NULL, sdirs))
		{
			case 0: break; // Keep going.
			case 1: ret=0; goto end; // Finished OK.
			default: goto end; // Error;
		}

		if(protocol==PROTO_2)
		{
			if(sb->endfile.buf)
			{
				sbuf_free_content(sb);
				continue;
			}
			if(blk->data)
			{
				if(protocol2_extra_restore_stream_bits(asfd,
					blk, slist, act, need_data,
					last_ent_was_dir, cntr)) goto end;
				continue;
			}
			sbuf_free_content(need_data);
		}

		if(want_to_restore(srestore, sb, regex, cconfs))
		{
			if(restore_ent(asfd, &sb, slist,
				bu, act, sdirs, cntr_status, cconfs,
				need_data, &last_ent_was_dir, manifest))
					goto end;
		}
		else if(sbuf_is_filedata(sb) || sbuf_is_vssdata(sb))
		{
			// Add it to the list of filedata that was not
			// restored.
			struct f_link **bucket=NULL;
			if(!linkhash_search(&sb->statp, &bucket)
			  && linkhash_add(sb->path.buf, &sb->statp, bucket))
				goto end;
		}

		sbuf_free_content(sb);
	}
end:
	blk_free(&blk);
	sbuf_free(&sb);
	sbuf_free(&need_data);
	iobuf_free_content(rbuf);
	manio_close(&manio);
	return ret;
}