예제 #1
0
파일: manio.c 프로젝트: jkniiv/burp
// Return -1 for error, 0 for stuff read OK, 1 for end of files.
int manio_sbuf_fill(struct manio *manio, struct asfd *asfd,
	struct sbuf *sb, struct blk *blk,
	struct dpth *dpth, struct conf *conf)
{
	int ars;

	while(1)
	{
		if(!manio->zp)
		{
			if(open_next_fpath(manio)) goto error;
			if(!manio->zp) return 1; // No more files to read.
			manio->first_entry=1;
		}
		else
		{
			manio->first_entry=0;
		}
		if((ars=sbuf_fill_from_gzfile(sb, asfd, manio->zp, blk,
			dpth?dpth->base_path:NULL, conf))<0) goto error;
		else if(!ars)
			return 0; // Got something.

		// Reached the end of the current file.
		// Maybe there is another file to continue with.
		if(manio_close(manio)) goto error;

		// If in burp1 mode, there is only one file, so end.
		if(manio->protocol==PROTO_BURP1) return 1;
	}

error:
	manio_close(manio);
	return -1;
}
예제 #2
0
파일: test_manio.c 프로젝트: ZungBang/burp
END_TEST

static void test_manifest_tell_seek(enum protocol protocol, int phase)
{
	struct slist *slist;
	struct manio *manio;
	struct sbuf *sb=NULL;
	man_off_t *offset=NULL;
	int entries=1000;
	prng_init(0);
	base64_init();
	hexmap_init();
	recursive_delete(path);

	slist=build_manifest(path, protocol, entries, phase);
	fail_unless(slist!=NULL);

	sb=slist->head;
	fail_unless((manio=do_manio_open(path, "rb", protocol, phase))!=NULL);
	read_manifest(&sb, manio, 0, entries/2, protocol, phase);
	fail_unless((offset=manio_tell(manio))!=NULL);
	fail_unless(sb!=NULL);
	fail_unless(!manio_close(&manio));

	fail_unless((manio=do_manio_open(path, "rb", protocol, phase))!=NULL);
	fail_unless(!manio_seek(manio, offset));
	read_manifest(&sb, manio, entries/2, entries, protocol, phase);
	fail_unless(sb==NULL);
	fail_unless(!manio_close(&manio));
	fail_unless(!manio);

	slist_free(&slist);
	man_off_t_free(&offset);
	tear_down();
}
예제 #3
0
파일: manios.c 프로젝트: Lacoste/burp
int manios_close(struct manios **manios)
{
	int ret=0;
	if(!manios || !*manios) return 0;
	ret|=manio_close(&(*manios)->current);
	ret|=manio_close(&(*manios)->phase1);
	ret|=manio_close(&(*manios)->changed);
	ret|=manio_close(&(*manios)->unchanged);
	free_v((void **)manios);
	return ret;
}
예제 #4
0
파일: build_manifest.c 프로젝트: grke/burp
struct slist *build_manifest_with_data_files(const char *path,
	const char *datapath, int entries, int data_files)
{
	struct blk *b=NULL;
	struct slist *slist=NULL;
	struct manio *manio=NULL;
	struct fzp *fzp=NULL;
	char spath[256]="";
	char cpath[256]="";

	fail_unless((manio=manio_open_phase3(path, "wb", PROTO_2,
		RMANIFEST_RELATIVE))!=NULL);
	slist=do_build_manifest(manio, PROTO_2, entries, data_files);
	fail_unless(!manio_close(&manio));

	for(b=slist->blist->head; b; b=b->next)
	{
		snprintf(spath, sizeof(spath), "%s/%s", datapath,
			uint64_to_savepathstr(b->savepath));
		if(strcmp(spath, cpath))
		{
			snprintf(cpath, sizeof(cpath), "%s", spath);
			fzp_close(&fzp);
		}
		if(!fzp)
		{
			fail_unless(!build_path_w(cpath));
			fail_unless((fzp=fzp_open(cpath, "wb"))!=NULL);
		}
		fzp_printf(fzp, "%c%04X%s", CMD_DATA, strlen("data"), "data");
	}
	fzp_close(&fzp);

	return slist;
}
예제 #5
0
파일: manio.c 프로젝트: pkdevbox/burp
static struct manio *do_manio_open(const char *manifest, const char *mode,
	enum protocol protocol, int phase)
{
	struct manio *manio=NULL;
	if(!(manio=manio_alloc())
	  || !(manio->manifest=strdup_w(manifest, __func__))
	  || !(manio->mode=strdup_w(mode, __func__))
	  || !(manio->offset=man_off_t_alloc()))
		goto error;
	manio->protocol=protocol;
	manio->phase=phase;
	if(!strcmp(manio->mode, MANIO_MODE_APPEND))
	{
		if(manio->phase!=2)
		{
			logp("manio append mode only works for phase 2.\n");
			logp("%s has phase: %s\n",
				manio->manifest, manio->phase);
			goto error;
		}
		if(manio_open_last_fpath(manio))
			goto error;
	}
	else
	{
		if(manio_open_next_fpath(manio))
			goto error;
	}
	return manio;
error:
	manio_close(&manio);
	return NULL;
}
예제 #6
0
파일: manio.c 프로젝트: adrianimboden/burp
static int manio_set_mode(struct manio *manio, const char *mode)
{
	if(manio_close(manio)) return -1;
	free_w(&manio->mode);
	if(!(manio->mode=strdup_w(mode, __func__)))
		return -1;
	manio->offset.fcount=0;
	return 0;
}
예제 #7
0
파일: manio.c 프로젝트: adrianimboden/burp
// Return -1 for error, 0 for stuff read OK, 1 for end of files.
static int do_manio_sbuf_fill(struct manio *manio, struct asfd *asfd,
	struct sbuf *sb, struct blk *blk,
	struct sdirs *sdirs, struct conf **confs, int phase1)
{
	int ars;

	while(1)
	{
		if(!manio->fzp)
		{
			if(manio_open_next_fpath(manio)) goto error;
			if(!manio->fzp) return 1; // No more files to read.
		}

		if(manio->protocol==PROTO_2 || phase1)
		{
			ars=sbuf_fill(sb, asfd, manio->fzp, blk,
				sdirs?sdirs->data:NULL, confs);
		}
		else
		{
			ars=sbufl_fill(sb, asfd, manio->fzp, confs);
		}
		switch(ars)
		{
			case 0: return 0; // Got something.
			case 1: break; // Keep going.
			default: goto error; // Error.
		}

		// Reached the end of the current file.
		// Maybe there is another file to continue with.
		if(manio_close(manio)) goto error;

		// If in protocol1 mode, there is only one file, so end.
		if(manio->protocol==PROTO_1) return 1;
	}

error:
	manio_close(manio);
	return -1;
}
예제 #8
0
파일: resume.c 프로젝트: ZungBang/burp
man_off_t *do_resume(struct sdirs *sdirs,
                     struct dpth *dpth, struct conf **cconfs)
{
    man_off_t *p1pos=NULL;
    struct manio *cmanio=NULL;
    struct manio *umanio=NULL;
    struct manio *p1manio=NULL;
    enum protocol protocol=get_protocol(cconfs);

    logp("Begin phase1 (read previous file system scan)\n");
    if(!(p1manio=manio_open_phase1(sdirs->phase1data, "rb", protocol))
            || read_phase1(p1manio, cconfs))
        goto end;
    manio_close(&p1manio);

    // First, open them in append mode, so that they will be created if
    // they do not exist.
    if(!(cmanio=manio_open_phase2(sdirs->changed, "ab", protocol))
            || !(umanio=manio_open_phase2(sdirs->unchanged, "ab", protocol)))
        goto end;
    manio_close(&cmanio);
    manio_close(&umanio);

    if(!(p1pos=do_resume_work(sdirs, dpth, cconfs))) goto end;

    if(dpth_incr(dpth)) goto end;

    logp("End phase1 (read previous file system scan)\n");
end:
    manio_close(&p1manio);
    manio_close(&cmanio);
    manio_close(&umanio);
    return p1pos;
}
예제 #9
0
파일: build_manifest.c 프로젝트: grke/burp
static struct slist *build_manifest_phase2(const char *path,
	enum protocol protocol, int entries)
{
	struct slist *slist=NULL;
	struct manio *manio=NULL;

	fail_unless((manio=manio_open_phase2(path, "wb", protocol))!=NULL);
	slist=do_build_manifest(manio,
		protocol, entries, 0 /*with_data_files*/);
	fail_unless(!manio_close(&manio));

	return slist;
}
예제 #10
0
파일: build_manifest.c 프로젝트: grke/burp
void build_manifest_phase2_from_slist(const char *path,
	struct slist *slist, enum protocol protocol, int short_write)
{
	struct sbuf *sb;
	struct manio *manio=NULL;

	for(sb=slist->head; sb; sb=sb->next)
		set_sbuf(slist, sb, 0 /* with_data_files */);

	fail_unless((manio=manio_open_phase2(path, "wb", protocol))!=NULL);

	for(sb=slist->head; sb; sb=sb->next)
	{
		fail_unless(!manio_write_sbuf(manio, sb));
		if(protocol==PROTO_2)
		{
			struct blk *blk=NULL;
			for(blk=sb->protocol2->bstart;
				blk && blk!=sb->protocol2->bend; blk=blk->next)
			{
				fail_unless(!manio_write_sig_and_path(manio,
					blk));
			}
			if(sbuf_is_filedata(sb) || sbuf_is_vssdata(sb))
			{
				struct iobuf endfile;
				iobuf_from_str(&endfile,
					CMD_END_FILE, (char *)"0:0");
				fail_unless(!iobuf_send_msg_fzp(&endfile,
					manio->fzp));
			}
			hack_protocol2_attr(&sb->attr);
		}
	}

	if(short_write)
	{
		man_off_t *pos;
		fail_unless((pos=manio_tell(manio))!=NULL);
		if(pos->offset>=short_write) pos->offset-=short_write;
		fail_unless(!manio_close_and_truncate(&manio,
			pos, 0 /* compression */));
		man_off_t_free(&pos);
	}
	fail_unless(!manio_close(&manio));
}
예제 #11
0
파일: backup_phase2.c 프로젝트: EmisFR/burp
static int maybe_add_from_scan(struct manios *manios,
	struct slist *slist, struct asfd *chfd, struct sbuf **csb)
{
	int ret=-1;
	struct sbuf *snew=NULL;

	while(1)
	{
		sbuf_free(&snew);
		if(!manios->phase1) return 0;
		// Limit the amount loaded into memory at any one time.
		if(slist && slist->head)
		{
			if(slist->head->protocol2->index
			  - slist->tail->protocol2->index>4096)
				return 0;
		}
		if(!(snew=sbuf_alloc(PROTO_2))) goto end;

		switch(manio_read(manios->phase1, snew))
		{
			case 0: break;
			case 1: manio_close(&manios->phase1);
				ret=0; // Finished.
			default: goto end;
		}

		switch(entry_changed(snew, manios, chfd, csb))
		{
			case 0: continue; // No change.
			case 1: break;
			default: goto end; // Error.
		}

		if(data_needed(snew)) snew->flags|=SBUF_NEED_DATA;

		slist_add_sbuf(slist, snew);
		snew=NULL;
	}
	return 0;
end:
	sbuf_free(&snew);
	return ret;
}
예제 #12
0
파일: manio.c 프로젝트: pkdevbox/burp
int manio_close_and_truncate(struct manio **manio,
	man_off_t *offset, int compression)
{
	int ret=-1;
	errno=0;
	if(!is_single_file(*manio)
	  && remove_trailing_files(*manio, offset))
		goto end;
	if(manio_close(manio)) goto end;
	if(fzp_truncate(offset->fpath, FZP_FILE, offset->offset, compression))
	{
		logp("Could not fzp_truncate %s in %s(): %s\n",
			offset->fpath, __func__, strerror(errno));
		goto end;
	}
	ret=0;
end:
	return ret;
}
예제 #13
0
파일: manio.c 프로젝트: jkniiv/burp
static int manio_free_contents(struct manio *manio)
{
	int ret=0;
	if(!manio) return ret;
	if(manio_close(manio)) ret=-1;
	if(manio->base_dir) free(manio->base_dir);
	if(manio->directory) free(manio->directory);
	if(manio->fpath) free(manio->fpath);
	if(manio->lpath) free(manio->lpath);
	if(manio->mode) free(manio->mode);
	if(manio->hook_dir) free(manio->hook_dir);
	if(manio->hook_sort)
	{
		int i;
		for(i=0; i<MANIFEST_SIG_MAX; i++)
			if(manio->hook_sort[i]) free(manio->hook_sort[i]);
		free(manio->hook_sort);
	}
	memset(manio, 0, sizeof(struct manio));
	return ret;
}
예제 #14
0
파일: manio.c 프로젝트: adrianimboden/burp
static int manio_free_content(struct manio *manio)
{
	int ret=0;
	if(!manio) return ret;
	if(manio_close(manio)) ret=-1;
	man_off_free_content(&manio->offset);
	free_w(&manio->base_dir);
	free_w(&manio->directory);
	free_w(&manio->mode);
	free_w(&manio->hook_dir);
	free_w(&manio->rdirectory);
	if(manio->hook_sort)
	{
		int i;
		for(i=0; i<MANIFEST_SIG_MAX; i++)
			free_w(&(manio->hook_sort[i]));
		free_v((void **)&manio->hook_sort);
	}
	memset(manio, 0, sizeof(struct manio));
	return ret;
}
예제 #15
0
파일: browse.c 프로젝트: pkdevbox/burp
static int browse_manifest_start(struct asfd *srfd, struct cstat *cstat,
	struct bu *bu, const char *browse, struct conf **confs)
{
	int ret=-1;
	char *manifest=NULL;
	struct sbuf *sb=NULL;
	struct manio *manio=NULL;

	if(!(manifest=prepend_s(bu->path,
		cstat->protocol==PROTO_1?"manifest.gz":"manifest"))
	  || !(manio=manio_open(manifest, "rb", cstat->protocol))
	  || !(sb=sbuf_alloc(cstat->protocol)))
		goto end;
	if(get_int(confs[OPT_MONITOR_BROWSE_CACHE]))
		ret=cache_load(srfd, manio, sb, cstat, bu);
	else
		ret=do_browse_manifest(srfd, manio, sb, browse);
end:
	free_w(&manifest);
	manio_close(&manio);
	sbuf_free(&sb);
	return ret;
}
예제 #16
0
파일: build_manifest.c 프로젝트: grke/burp
static struct slist *build_manifest_phase1(const char *path,
	enum protocol protocol, int entries)
{
	struct sbuf *sb;
	struct slist *slist=NULL;
	struct manio *manio=NULL;

	slist=build_slist_phase1(NULL /*prefix*/, protocol, entries);

	fail_unless((manio=manio_open_phase1(path, "wb", protocol))!=NULL);

	for(sb=slist->head; sb; sb=sb->next)
	{
		fail_unless(!manio_write_sbuf(manio, sb));
		if(protocol==PROTO_2) hack_protocol2_attr(&sb->attr);
	}

	fail_unless(!send_msg_fzp(manio->fzp,
		CMD_GEN, "phase1end", strlen("phase1end")));

	fail_unless(!manio_close(&manio));
	return slist;
}
예제 #17
0
파일: manio.c 프로젝트: pkdevbox/burp
struct manio *manio_open_phase3(const char *manifest, const char *mode,
	enum protocol protocol, const char *rmanifest)
{
	struct manio *manio=NULL;

	if(!(manio=do_manio_open(manifest, mode, protocol, 3)))
		goto end;

	if(protocol==PROTO_2 && rmanifest)
	{
		char *hooksdir=NULL;
		char *dindexdir=NULL;
		if(!(hooksdir=prepend_s(manifest, "hooks"))
		  || !(dindexdir=prepend_s(manifest, "dindex"))
		  || init_write_hooks(manio, hooksdir, rmanifest)
		  || init_write_dindex(manio, dindexdir))
			manio_close(&manio);
		free_w(&hooksdir);
		free_w(&dindexdir);
	}

end:
	return manio;
}
예제 #18
0
파일: build_manifest.c 프로젝트: grke/burp
void build_manifest_phase1_from_slist(const char *path,
	struct slist *slist, enum protocol protocol)
{
	struct sbuf *sb;
	struct manio *manio=NULL;
	struct iobuf datapth;
	struct iobuf endfile;
	iobuf_init(&datapth);
	iobuf_init(&endfile);

	for(sb=slist->head; sb; sb=sb->next)
		set_sbuf(slist, sb, 0 /* with_data_files */);

	fail_unless((manio=manio_open_phase1(path, "wb", protocol))!=NULL);

	for(sb=slist->head; sb; sb=sb->next)
	{
		// Might be given an slist that has datapth or endfile set,
		// which should not go into a phase1 scan. Deal with it.
		if(sb->protocol1
		  && sb->protocol1->datapth.buf)
			iobuf_move(&datapth, &sb->protocol1->datapth);
		if(sb->endfile.buf)
			iobuf_move(&endfile, &sb->endfile);
		fail_unless(!manio_write_sbuf(manio, sb));
		if(datapth.buf)
			iobuf_move(&sb->protocol1->datapth, &datapth);
		if(endfile.buf)
			iobuf_move(&sb->endfile, &endfile);
	}

	fail_unless(!send_msg_fzp(manio->fzp,
		CMD_GEN, "phase1end", strlen("phase1end")));

	fail_unless(!manio_close(&manio));
}
예제 #19
0
// Combine the phase1 and phase2 files into a new manifest.
int backup_phase3_server_all(struct sdirs *sdirs, struct conf **confs)
{
	int ret=-1;
	int pcmp=0;
	struct blk *blk=NULL;
	struct sbuf *usb=NULL;
	struct sbuf *csb=NULL;
	char *manifesttmp=NULL;
	struct manio *newmanio=NULL;
	struct manio *chmanio=NULL;
	struct manio *unmanio=NULL;
	enum protocol protocol=get_protocol(confs);
	struct cntr *cntr=get_cntr(confs);
	const char *rmanifest_relative=NULL;

	logp("Begin phase3 (merge manifests)\n");

	if(protocol==PROTO_2)
		rmanifest_relative=get_rmanifest_relative(sdirs, confs);

	if(!(manifesttmp=get_tmp_filename(sdirs->manifest))
	  || !(newmanio=manio_open_phase3(manifesttmp,
		comp_level(get_int(confs[OPT_COMPRESSION])),
		protocol, rmanifest_relative))
	  || !(chmanio=manio_open_phase2(sdirs->changed, "rb", protocol))
	  || !(unmanio=manio_open_phase2(sdirs->unchanged, "rb", protocol))
	  || !(usb=sbuf_alloc(protocol))
	  || !(csb=sbuf_alloc(protocol)))
		goto end;

	while(chmanio || unmanio)
	{
		if(!blk && !(blk=blk_alloc())) goto end;

		if(unmanio
		  && !usb->path.buf)
		{
			switch(manio_read(unmanio, usb))
			{
				case -1: goto end;
				case 1: manio_close(&unmanio);
			}
		}

		if(chmanio
		  && !csb->path.buf)
		{
			switch(manio_read(chmanio, csb))
			{
				case -1: goto end;
				case 1: manio_close(&chmanio);
			}
		}

		if(usb->path.buf && !csb->path.buf)
		{
			if(write_status(CNTR_STATUS_MERGING,
				usb->path.buf, cntr)) goto end;
			switch(manio_copy_entry(
				usb, usb, &blk, unmanio, newmanio))
			{
				case -1: goto end;
				case 1: manio_close(&unmanio);
			}
		}
		else if(!usb->path.buf && csb->path.buf)
		{
			if(write_status(CNTR_STATUS_MERGING,
				csb->path.buf, cntr)) goto end;
			switch(manio_copy_entry(
				csb, csb, &blk, chmanio, newmanio))
			{
				case -1: goto end;
				case 1: manio_close(&chmanio);
			}
		}
		else if(!usb->path.buf && !csb->path.buf)
		{
			continue;
		}
		else if(!(pcmp=sbuf_pathcmp(usb, csb)))
		{
			// They were the same - write one.
			if(write_status(CNTR_STATUS_MERGING,
				csb->path.buf, cntr)) goto end;
			switch(manio_copy_entry(
				csb, csb, &blk, chmanio, newmanio))
			{
				case -1: goto end;
				case 1: manio_close(&chmanio);
			}
		}
		else if(pcmp<0)
		{
			if(write_status(CNTR_STATUS_MERGING,
				usb->path.buf, cntr)) goto end;
			switch(manio_copy_entry(
				usb, usb, &blk, unmanio, newmanio))
			{
				case -1: goto end;
				case 1: manio_close(&unmanio);
			}
		}
		else
		{
			if(write_status(CNTR_STATUS_MERGING,
				csb->path.buf, cntr)) goto end;
			switch(manio_copy_entry(
				csb, csb, &blk, chmanio, newmanio))
			{
				case -1: goto end;
				case 1: manio_close(&chmanio);
			}
		}
	}

	// Flush to disk.
	if(manio_close(&newmanio))
	{
		logp("error gzclosing %s in backup_phase3_server\n",
			manifesttmp);
		goto end;
	}

	// Rename race condition should be of no consequence here, as the
	// manifest should just get recreated automatically.
	if(do_rename(manifesttmp, sdirs->manifest))
		goto end;
	else
	{
		recursive_delete(sdirs->changed);
		recursive_delete(sdirs->unchanged);
	}

	logp("End phase3 (merge manifests)\n");
	ret=0;
end:
	manio_close(&newmanio);
	manio_close(&chmanio);
	manio_close(&unmanio);
	sbuf_free(&csb);
	sbuf_free(&usb);
	blk_free(&blk);
	free_w(&manifesttmp);
	return ret;
}
예제 #20
0
파일: restore.c 프로젝트: pkdevbox/burp
// Used when restoring a hard link that we have not restored the destination
// for. Read through the manifest from the beginning and substitute the path
// and data to the new location.
static int 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)
{
	int ret=-1;
	struct sbuf *need_data=NULL;
	int last_ent_was_dir=0;
	struct sbuf *hb=NULL;
	struct manio *manio=NULL;
	struct blk *blk=NULL;
	int pcmp;
	enum protocol protocol=get_protocol(cconfs);
	struct cntr *cntr=get_cntr(cconfs);

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

	if(protocol==PROTO_2)
	{
		  if(!(blk=blk_alloc()))
                	goto end;
	}

	while(1)
	{
		switch(manio_read_with_blk(manio,
			hb, 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(hb->endfile.buf)
			{
				sbuf_free_content(hb);
				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);
		}

		pcmp=pathcmp(lp->name, hb->path.buf);

		if(!pcmp && (sbuf_is_filedata(hb) || sbuf_is_vssdata(hb)))
		{
			// Copy the path from sb to hb.
			free_w(&hb->path.buf);
			if(!(hb->path.buf=strdup_w(sb->path.buf, __func__)))
				goto end;
			// Should now be able to restore the original data
			// to the new location.
			ret=restore_sbuf(asfd, hb, bu, act, sdirs,
			  cntr_status, cconfs, need_data, manifest, slist);
			// May still need to get protocol2 data.
			if(!ret && need_data->path.buf) continue;
			break;
		}

		sbuf_free_content(hb);
		// Break out once we have gone past the entry that we are
		// interested in.
		if(pcmp<0) break;
	}
end:
	blk_free(&blk);
	sbuf_free(&hb);
	manio_close(&manio);
	return ret;
}
예제 #21
0
int backup_phase2_server(struct async *as, struct sdirs *sdirs,
	const char *manifest_dir, int resume, struct conf *conf)
{
	int ret=-1;
	int sigs_end=0;
	int backup_end=0;
	int requests_end=0;
	int blk_requests_end=0;
	struct slist *slist=NULL;
	struct blist *blist=NULL;
	struct iobuf *wbuf=NULL;
	struct dpth *dpth=NULL;
	struct manio *cmanio=NULL;	// current manifest
	struct manio *p1manio=NULL;	// phase1 scan manifest
	struct manio *chmanio=NULL;	// changed manifest
	struct manio *unmanio=NULL;	// unchanged manifest
	// This is used to tell the client that a number of consecutive blocks
	// have been found and can be freed.
	uint64_t wrap_up=0;
	// Main fd is first in the list.
	struct asfd *asfd=as->asfd;
	// Champ chooser fd is second in the list.
	struct asfd *chfd=asfd->next;

	logp("Phase 2 begin (recv backup data)\n");

	//if(champ_chooser_init(sdirs->data, conf)
	if(!(cmanio=manio_alloc())
	  || !(p1manio=manio_alloc())
	  || !(chmanio=manio_alloc())
	  || !(unmanio=manio_alloc())
	  || manio_init_read(cmanio, sdirs->cmanifest)
	  || manio_init_read(p1manio, sdirs->phase1data)
	  || manio_init_write(chmanio, sdirs->changed)
	  || manio_init_write(unmanio, sdirs->unchanged)
	  || !(slist=slist_alloc())
	  || !(blist=blist_alloc())
	  || !(wbuf=iobuf_alloc())
	  || !(dpth=dpth_alloc(sdirs->data))
	  || dpth_init(dpth))
		goto end;

	// The phase1 manifest looks the same as a burp1 one.
	manio_set_protocol(p1manio, PROTO_BURP1);

	while(!backup_end)
	{
		if(maybe_add_from_scan(asfd,
			p1manio, cmanio, unmanio, slist, conf))
				goto end;

		if(!wbuf->len)
		{
			if(get_wbuf_from_sigs(wbuf, slist, blist,
			  sigs_end, &blk_requests_end, dpth, conf))
				goto end;
			if(!wbuf->len)
			{
				get_wbuf_from_files(wbuf, slist,
					p1manio, &requests_end);
			}
		}

		if(wbuf->len)
			asfd->append_all_to_write_buffer(asfd, wbuf);

		append_for_champ_chooser(chfd, blist, sigs_end);

		if(as->read_write(as))
		{
			logp("error in %s\n", __func__);
			goto end;
		}

		while(asfd->rbuf->buf)
		{
			if(deal_with_read(asfd->rbuf, slist, blist,
				conf, &sigs_end, &backup_end, dpth))
					goto end;
			// Get as much out of the
			// readbuf as possible.
			if(asfd->parse_readbuf(asfd)) goto end;
		}
		while(chfd->rbuf->buf)
		{
			if(deal_with_read_from_chfd(asfd, chfd,
				blist, &wrap_up, dpth)) goto end;
			// Get as much out of the
			// readbuf as possible.
			if(chfd->parse_readbuf(chfd)) goto end;
		}

		if(write_to_changed_file(asfd, chfd, chmanio,
			slist, blist, dpth, backup_end, conf))
				goto end;
	}

	// Hack: If there are some entries left after the last entry that
	// contains block data, it will not be written to the changed file
	// yet because the last entry of block data has not had
	// sb->burp2->bend set.
	if(slist->head && slist->head->next)
	{
		slist->head=slist->head->next;
		if(write_to_changed_file(asfd, chfd, chmanio,
			slist, blist, dpth, backup_end, conf))
				goto end;
	}

	if(manio_close(unmanio)
	  || manio_close(chmanio))
		goto end;

	if(blist->head)
	{
		logp("ERROR: finishing but still want block: %lu\n",
			blist->head->index);
		goto end;
	}

	// Need to release the last left. There should be one at most.
	if(dpth->head && dpth->head->next)
	{
		logp("ERROR: More data locks remaining after: %s\n",
			dpth->head->save_path);
		goto end;
	}
	if(dpth_release_all(dpth)) goto end;

	ret=0;
end:
	logp("End backup\n");
	slist_free(slist);
	blist_free(blist);
	iobuf_free_content(asfd->rbuf);
	iobuf_free_content(chfd->rbuf);
	// Write buffer did not allocate 'buf'. 
	if(wbuf) wbuf->buf=NULL;
	iobuf_free(wbuf);
	dpth_release_all(dpth);
	dpth_free(&dpth);
	manio_free(&cmanio);
	manio_free(&p1manio);
	manio_free(&chmanio);
	manio_free(&unmanio);
	return ret;
}
예제 #22
0
파일: restore.c 프로젝트: pkdevbox/burp
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;
}
예제 #23
0
파일: resume.c 프로젝트: ZungBang/burp
// Return p1manio position.
static man_off_t *do_resume_work(struct sdirs *sdirs,
                                 struct dpth *dpth, struct conf **cconfs)
{
    man_off_t *pos=NULL;
    man_off_t *p1pos=NULL;
    struct iobuf *chb=NULL;
    struct manio *cmanio=NULL;
    struct manio *umanio=NULL;
    struct manio *p1manio=NULL;
    enum protocol protocol=get_protocol(cconfs);
    struct cntr *cntr=get_cntr(cconfs);
    int compression=get_int(cconfs[OPT_COMPRESSION]);

    if(!(p1manio=manio_open_phase1(sdirs->phase1data, "rb", protocol))
            || !(cmanio=manio_open_phase2(sdirs->changed, "rb", protocol))
            || !(umanio=manio_open_phase2(sdirs->unchanged, "rb", protocol)))
        goto end;

    if(!(chb=iobuf_alloc()))
        return NULL;

    logp("Setting up resume positions...\n");

    if(get_last_good_entry(cmanio, chb, cntr, dpth, protocol, &pos))
        goto error;
    if(manio_close_and_truncate(&cmanio, pos, compression)) goto error;
    man_off_t_free(&pos);
    if(chb->buf)
    {
        logp("  last good entry:    %s\n", chb->buf);
        // Now need to go to the appropriate places in p1manio and
        // unchanged.
        if(forward_past_entry(p1manio, chb, protocol, &p1pos))
            goto error;

        // The unchanged file needs to be positioned just before the
        // found entry, otherwise it ends up having a duplicated entry.
        if(forward_before_entry(umanio,
                                chb, cntr, dpth, protocol, &pos))
            goto error;
        if(manio_close_and_truncate(&umanio, pos, compression))
            goto error;
        man_off_t_free(&pos);
    }
    else
    {
        logp("  nothing previously transferred\n");
        if(!(p1pos=manio_tell(p1manio)))
            goto error;
        if(!(pos=manio_tell(umanio)))
            goto error;
        if(manio_close_and_truncate(&umanio, pos, compression))
            goto error;
    }

    // Now should have all file pointers in the right places to resume.

    goto end;
error:
    man_off_t_free(&p1pos);
end:
    iobuf_free(&chb);
    man_off_t_free(&pos);
    manio_close(&p1manio);
    manio_close(&cmanio);
    manio_close(&umanio);
    return p1pos;
}
예제 #24
0
파일: list.c 프로젝트: ZungBang/burp
static int list_manifest(const char *fullpath)
{
    int ret=0;
    struct sbuf *sb=NULL;
    struct manio *manio=NULL;
    char *manifest_dir=NULL;
    char *last_bd_match=NULL;
    size_t bdlen=0;

    if(!(manifest_dir=prepend_s(fullpath,
                                protocol==PROTO_1?"manifest.gz":"manifest"))
            || !(manio=manio_open(manifest_dir, "rb", protocol))
            || !(sb=sbuf_alloc(protocol)))
    {
        log_and_send_oom(asfd);
        goto error;
    }

    if(browsedir) bdlen=strlen(browsedir);

    while(1)
    {
        sbuf_free_content(sb);

        switch(manio_read(manio, sb))
        {
        case 0:
            break;
        case 1:
            if(browsedir && *browsedir && !last_bd_match)
                asfd_write_wrapper_str(asfd,
                                       CMD_ERROR,
                                       "directory not found");
            goto end; // Finished OK.
        default:
            goto error;
        }

        if(protocol==PROTO_2 && sb->endfile.buf)
            continue;
        if(sbuf_is_metadata(sb))
            continue;

        if(write_status(CNTR_STATUS_LISTING, sb->path.buf, cntr))
            goto error;

        if(browsedir)
        {
            int r;
            if((r=check_browsedir(browsedir,
                                  sb, bdlen, &last_bd_match))<0)
                goto error;
            if(!r) continue;
        }

        if(regex && !regex_check(regex, sb->path.buf))
            continue;

        if(asfd_write_wrapper(asfd, &sb->attr)
                || asfd_write_wrapper(asfd, &sb->path))
            goto error;
        if(sbuf_is_link(sb)
                && asfd_write_wrapper(asfd, &sb->link))
            goto error;
    }

error:
    ret=-1;
end:
    sbuf_free(&sb);
    free_w(&manifest_dir);
    manio_close(&manio);
    free_w(&last_bd_match);
    return ret;
}
예제 #25
0
파일: manio.c 프로젝트: adrianimboden/burp
static int reset_sig_count_and_close(struct manio *manio)
{
	if(manio_close(manio)) return -1;
	manio->sig_count=0;
	return 0;
}
예제 #26
0
int backup_phase2_server_protocol1(struct async *as, struct sdirs *sdirs,
	const char *incexc, int resume, struct conf **cconfs)
{
	int ret=0;
	struct manio *p1manio=NULL;
	struct dpth *dpth=NULL;
	char *deltmppath=NULL;
	char *last_requested=NULL;
	// Where to write changed data.
	// Data is not getting written to a compressed file.
	// This is important for recovery if the power goes.
	struct fzp *chfp=NULL;
	struct fzp *ucfp=NULL; // unchanged data
	struct fzp *cmanfp=NULL; // previous (current) manifest.
	struct sbuf *cb=NULL; // file list in current manifest
	struct sbuf *p1b=NULL; // file list from client
	struct sbuf *rb=NULL; // receiving file from client
	struct asfd *asfd=as->asfd;
	int breaking=0;
	int breakcount=0;
	if(get_int(cconfs[OPT_BREAKPOINT])>=2000
	  && get_int(cconfs[OPT_BREAKPOINT])<3000)
	{
		breaking=get_int(cconfs[OPT_BREAKPOINT]);
		breakcount=breaking-2000;
	}

	logp("Begin phase2 (receive file data)\n");

	if(!(dpth=dpth_alloc())
	  || dpth_protocol1_init(dpth, sdirs->currentdata,
		get_int(cconfs[OPT_MAX_STORAGE_SUBDIRS])))
			goto error;

	if(open_previous_manifest(&cmanfp, sdirs, incexc, cconfs))
		goto error;

	if(get_int(cconfs[OPT_DIRECTORY_TREE]))
	{
		// Need to make sure we do not try to create a path that is
		// too long.
		if(build_path_w(sdirs->treepath)) goto error;
		treepathlen=strlen(sdirs->treepath);
		init_fs_max(sdirs->treepath);
	}

	if(!(p1manio=manio_alloc())
	  || manio_init_read(p1manio, sdirs->phase1data)
	  || !(cb=sbuf_alloc(cconfs))
	  || !(p1b=sbuf_alloc(cconfs))
	  || !(rb=sbuf_alloc(cconfs)))
		goto error;

	manio_set_protocol(p1manio, PROTO_1);

	if(resume && do_resume(p1manio, sdirs, dpth, cconfs))
		goto error;

	// Unchanged and changed should now be truncated correctly, we just
	// have to open them for appending.
	if(!(ucfp=fzp_open(sdirs->unchanged, "a+b"))
	  || !(chfp=fzp_open(sdirs->changed, "a+b")))
		goto error;

	if(manio_closed(p1manio)
	  && manio_open_next_fpath(p1manio))
		goto error;

	while(1)
	{
		if(breaking)
		{
			if(breakcount--==0) return breakpoint(cconfs, __func__);
		}

		//printf("in loop, %s %s %c\n",
		//	cmanfp?"got cmanfp":"no cmanfp",
		//	rb->path.buf?:"no rb->path",
	 	//	rb->path.buf?'X':rb->path.cmd);
		if(write_status(CNTR_STATUS_BACKUP,
			rb->path.buf?rb->path.buf:p1b->path.buf, cconfs))
				goto error;
		if(last_requested
		  || manio_closed(p1manio)
		  || asfd->writebuflen)
		{
			switch(do_stuff_to_receive(asfd, sdirs,
				cconfs, rb, chfp, dpth, &last_requested))
			{
				case 0: break;
				case 1: goto end; // Finished ok.
				case -1: goto error;
			}
		}

		switch(do_stuff_to_send(asfd, p1b, &last_requested))
		{
			case 0: break;
			case 1: continue;
			case -1: goto error;
		}

		if(manio_closed(p1manio)) continue;

		sbuf_free_content(p1b);

		switch(manio_sbuf_fill_phase1(p1manio, asfd,
			p1b, NULL, sdirs, cconfs))
		{
			case 0: break;
			case 1: manio_close(p1manio);
				if(asfd->write_str(asfd,
				  CMD_GEN, "backupphase2end")) goto error;
				break;
			case -1: goto error;
		}

		if(!cmanfp)
		{
			// No old manifest, need to ask for a new file.
			if(process_new(sdirs, cconfs, p1b, ucfp))
				goto error;
			continue;
		}

		// Have an old manifest, look for it there.

		// Might already have it, or be ahead in the old
		// manifest.
		if(cb->path.buf) switch(maybe_process_file(asfd,
			sdirs, cb, p1b, ucfp, cconfs))
		{
			case 0: break;
			case 1: continue;
			case -1: goto error;
		}

		while(cmanfp)
		{
			sbuf_free_content(cb);
			switch(sbufl_fill(cb, asfd, cmanfp, cconfs))
			{
				case 0: break;
				case 1: fzp_close(&cmanfp);
					if(process_new(sdirs, cconfs, p1b,
						ucfp)) goto error;
					continue;
				case -1: goto error;
			}
			switch(maybe_process_file(asfd, sdirs,
				cb, p1b, ucfp, cconfs))
			{
				case 0: continue;
				case 1: break;
				case -1: goto error;
			}
			break;
		}
	}

error:
	ret=-1;
end:
	if(fzp_close(&chfp))
	{
		logp("error closing %s in %s\n", sdirs->changed, __func__);
		ret=-1;
	}
	if(fzp_close(&ucfp))
	{
		logp("error closing %s in %s\n", sdirs->unchanged, __func__);
		ret=-1;
	}
	free_w(&deltmppath);
	sbuf_free(&cb);
	sbuf_free(&p1b);
	sbuf_free(&rb);
	manio_free(&p1manio);
	fzp_close(&cmanfp);
	dpth_free(&dpth);
	if(!ret) unlink(sdirs->phase1data);

	logp("End phase2 (receive file data)\n");

	return ret;
}
예제 #27
0
int backup_phase1_server_all(struct async *as,
	struct sdirs *sdirs, struct conf **confs)
{
	int ret=-1;
	struct sbuf *sb=NULL;
	char *phase1tmp=NULL;
	struct asfd *asfd=as->asfd;
	struct manio *manio=NULL;
	enum protocol protocol=get_protocol(confs);
	struct cntr *cntr=get_cntr(confs);

	logp("Begin phase1 (file system scan)\n");

	if(!(phase1tmp=get_tmp_filename(sdirs->phase1data))
	  || !(manio=manio_open_phase1(phase1tmp,
		comp_level(get_int(confs[OPT_COMPRESSION])), protocol))
	  || !(sb=sbuf_alloc(protocol)))
		goto error;

	while(1)
	{
		sbuf_free_content(sb);
		switch(sbuf_fill_from_net(sb, asfd, NULL, NULL, cntr))
		{
			case 0: break;
			case 1: // Last thing the client sends is
				// 'backupphase2', and it wants an 'ok' reply.
				if(asfd->write_str(asfd, CMD_GEN, "ok")
				  || send_msg_fzp(manio->fzp, CMD_GEN,
					"phase1end", strlen("phase1end")))
						goto error;
				goto end;
			case -1:
			default: goto error;
		}
		if(write_status(CNTR_STATUS_SCANNING, sb->path.buf, cntr)
		  || manio_write_sbuf(manio, sb))
			goto error;
		cntr_add_phase1(cntr, sb->path.cmd, 0);

		if(sbuf_is_filedata(sb))
		{
			cntr_add_val(cntr, CMD_BYTES_ESTIMATED,
				(uint64_t)sb->statp.st_size, 0);
		}
	}

end:
	if(manio_close(&manio))
	{
		logp("error closing %s in backup_phase1_server\n", phase1tmp);
		goto error;
	}

	if(check_quota(as, cntr,
		get_uint64_t(confs[OPT_HARD_QUOTA]),
		get_uint64_t(confs[OPT_SOFT_QUOTA])))
			goto error;

	// Possible rename race condition is of no consequence here, because
	// the working directory will always get deleted if phase1 is not
	// complete.
	if(do_rename(phase1tmp, sdirs->phase1data))
		goto error;

	//cntr_print(p1cntr, cntr, ACTION_BACKUP);

	logp("End phase1 (file system scan)\n");
	ret=0;
error:
	free_w(&phase1tmp);
	manio_close(&manio);
	sbuf_free(&sb);
	return ret;
}