Example #1
0
// Return -1 for error, 0 for stuff read OK, 1 for end of files.
int manio_read_with_blk(struct manio *manio,
	struct sbuf *sb, struct blk *blk, struct sdirs *sdirs)
{
	while(1)
	{
		if(!manio->fzp)
		{
			if(manio_open_next_fpath(manio)) goto error;
			if(!manio->fzp) return 1; // No more files to read.
		}

		switch(sbuf_fill_from_file(sb, manio->fzp, blk,
			sdirs?sdirs->data:NULL))
		{
			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(sort_and_write_hooks_and_dindex(manio)
		  || fzp_close(&manio->fzp)) goto error;

		if(is_single_file(manio)) return 1;
	}

error:
	return -1;
}
Example #2
0
static int setup_cntr(struct asfd *asfd, const char *manifest,
        regex_t *regex, int srestore,
        enum action act, char status, struct conf **cconfs)
{
	int ars=0;
	int ret=-1;
	struct fzp *fzp=NULL;
	struct sbuf *sb=NULL;
	struct cntr *cntr=get_cntr(cconfs);

// FIX THIS: this is only trying to work for protocol1.
	if(get_protocol(cconfs)!=PROTO_1) return 0;

	if(!(sb=sbuf_alloc(PROTO_1))) goto end;
	if(!(fzp=fzp_gzopen(manifest, "rb")))
	{
		log_and_send(asfd, "could not open manifest");
		goto end;
	}
	while(1)
	{
		if((ars=sbuf_fill_from_file(sb, fzp, NULL, NULL)))
		{
			if(ars<0) goto end;
			// ars==1 means end ok
			break;
		}
		else
		{
			if(want_to_restore(srestore, sb, regex, cconfs))
			{
				cntr_add_phase1(cntr, sb->path.cmd, 0);
				if(sb->endfile.buf)
				  cntr_add_val(cntr,
					CMD_BYTES_ESTIMATED,
					strtoull(sb->endfile.buf,
						NULL, 10), 0);
			}
		}
		sbuf_free_content(sb);
	}
	ret=0;
end:
	sbuf_free(&sb);
	fzp_close(&fzp);
	return ret;
}
Example #3
0
// Return 0 for OK, -1 for error, 1 for finished reading the file.
static int get_next_set_of_hooks(struct hooks **hnew, struct sbuf *sb,
	struct fzp *spzp, char **path, uint64_t **fingerprints, size_t *len)
{
	struct blk blk;
	while(1)
	{
		switch(sbuf_fill_from_file(sb, spzp, NULL, NULL))
		{
			case -1: goto error;
			case 1:
				// Reached the end.
				if(hooks_alloc(hnew, path, fingerprints, len))
					goto error;
				return 1;
		}
		if(sb->path.cmd==CMD_MANIFEST)
		{
			if(hooks_alloc(hnew, path, fingerprints, len))
				break;
			*path=sb->path.buf;
			sb->path.buf=NULL;
			sbuf_free_content(sb);
			if(*hnew) return 0;
		}
		else if(sb->path.cmd==CMD_FINGERPRINT)
		{
			if(!(*fingerprints=(uint64_t *)realloc_w(*fingerprints,
				((*len)+1)*sizeof(uint64_t), __func__)))
					goto error;
			if(blk_set_from_iobuf_fingerprint(&blk, &sb->path))
				goto error;
			(*fingerprints)[(*len)++]=blk.fingerprint;
			sbuf_free_content(sb);
		}
		else
		{
			iobuf_log_unexpected(&sb->path, __func__);
			break;
		}
	}

error:
	sbuf_free_content(sb);
	return -1;
}
Example #4
0
// This deals with reading in the sparse index, as well as actual candidate
// manifests.
enum cand_ret candidate_load(struct candidate *candidate, const char *path,
	struct scores *scores)
{
	enum cand_ret ret=CAND_RET_PERM;
	struct fzp *fzp=NULL;
	struct sbuf *sb=NULL;
	struct blk *blk=NULL;

	if(!(sb=sbuf_alloc(PROTO_2))
	  || !(blk=blk_alloc()))
	{
		ret=CAND_RET_PERM;
		goto error;
	}
	
	if(!(fzp=fzp_gzopen(path, "rb")))
	{
		ret=CAND_RET_TEMP;
		goto error;
	}
	while(fzp)
	{
		sbuf_free_content(sb);
		switch(sbuf_fill_from_file(sb, fzp, blk, NULL))
		{
			case 1: goto end;
			case -1:
				logp("Error reading %s in %s, pos %d\n",
					path, __func__, fzp_tell(fzp));
				ret=CAND_RET_TEMP;
				goto error;
		}
		if(blk_fingerprint_is_hook(blk))
		{
			if(sparse_add_candidate(&blk->fingerprint, candidate))
			{
				ret=CAND_RET_PERM;
				goto error;
			}
		}
		else if(sb->path.cmd==CMD_MANIFEST)
		{
			if(!(candidate=candidates_add_new()))
			{
				ret=CAND_RET_PERM;
				goto error;
			}
			candidate->path=sb->path.buf;
			sb->path.buf=NULL;
		}
		blk->fingerprint=0;
	}

end:
	if(scores_grow(scores, candidates_len))
	{
		ret=CAND_RET_PERM;
		goto error;
	}
	candidates_set_score_pointers(candidates, candidates_len, scores);
	scores_reset(scores);
	//logp("Now have %d candidates\n", (int)candidates_len);
	ret=CAND_RET_OK;
error:
	fzp_close(&fzp);
	sbuf_free(&sb);
	blk_free(&blk);
	return ret;
}
Example #5
0
/* Need to make all the stuff that this does atomic so that existing backups
   never get broken, even if somebody turns the power off on the server. */
static int atomic_data_jiggle(struct sdirs *sdirs, struct fdirs *fdirs,
	int hardlinked_current, struct conf **cconfs)
{
	int ret=-1;
	char *datapth=NULL;
	char *tmpman=NULL;
	struct stat statp;

	char *deltabdir=NULL;
	char *deltafdir=NULL;
	char *sigpath=NULL;
	struct fzp *zp=NULL;
	struct sbuf *sb=NULL;

	struct fzp *delfp=NULL;

	logp("Doing the atomic data jiggle...\n");

	if(!(tmpman=get_tmp_filename(fdirs->manifest)))
		goto error;
	if(lstat(fdirs->manifest, &statp))
	{
		// Manifest does not exist - maybe the server was killed before
		// it could be renamed.
		logp("%s did not exist - trying %s\n", fdirs->manifest, tmpman);
		// Rename race condition is of no consequence, because manifest
		// already does not exist.
		do_rename(tmpman, fdirs->manifest);
	}
	if(!(zp=fzp_gzopen(fdirs->manifest, "rb")))
		goto error;

	if(!(deltabdir=prepend_s(fdirs->currentdup, "deltas.reverse"))
	  || !(deltafdir=prepend_s(sdirs->finishing, "deltas.forward"))
	  || !(sigpath=prepend_s(fdirs->currentdup, "sig.tmp"))
	  || !(sb=sbuf_alloc(PROTO_1)))
	{
		log_out_of_memory(__func__);
		goto error;
	}

	mkdir(fdirs->datadir, 0777);

	while(1)
	{
		switch(sbuf_fill_from_file(sb, zp, NULL, NULL))
		{
			case 0: break;
			case 1: goto end;
			default: goto error;
		}
		if(sb->protocol1->datapth.buf)
		{
			if(write_status(CNTR_STATUS_SHUFFLING,
				sb->protocol1->datapth.buf, get_cntr(cconfs))
			  || jiggle(sdirs, fdirs, sb, hardlinked_current,
				deltabdir, deltafdir,
				sigpath, &delfp, cconfs))
					goto error;
		}
		sbuf_free_content(sb);
	}

end:
	if(fzp_close(&delfp))
	{
		logp("error closing %s in atomic_data_jiggle\n",
			fdirs->deletionsfile);
		goto error;
	}

	if(maybe_delete_files_from_manifest(tmpman, fdirs, cconfs))
		goto error;

	// Remove the temporary data directory, we have probably removed
	// useful files from it.
	recursive_delete_dirs_only(deltafdir);

	ret=0;
error:
	fzp_close(&zp);
	fzp_close(&delfp);
	sbuf_free(&sb);
	free_w(&deltabdir);
	free_w(&deltafdir);
	free_w(&sigpath);
	free_w(&datapth);
	free_w(&tmpman);
	return ret;
}
Example #6
0
static int maybe_delete_files_from_manifest(const char *manifesttmp,
	struct fdirs *fdirs, struct conf **cconfs)
{
	int ars=0;
	int ret=-1;
	int pcmp=0;
	struct fzp *dfp=NULL;
	struct fzp *nmzp=NULL;
	struct fzp *omzp=NULL;
	struct sbuf *db=NULL;
	struct sbuf *mb=NULL;
	struct stat statp;

	if(lstat(fdirs->deletionsfile, &statp)) // No deletions, no problem.
		return 0;
	logp("Performing deletions on manifest\n");

	if(!(manifesttmp=get_tmp_filename(fdirs->manifest)))
		goto end;

        if(!(dfp=fzp_open(fdirs->deletionsfile, "rb"))
	  || !(omzp=fzp_gzopen(fdirs->manifest, "rb"))
	  || !(nmzp=fzp_gzopen(manifesttmp,
		comp_level(get_int(cconfs[OPT_COMPRESSION]))))
	  || !(db=sbuf_alloc(PROTO_1))
	  || !(mb=sbuf_alloc(PROTO_1)))
		goto end;

	while(omzp || dfp)
	{
		if(dfp && !db->path.buf
		  && (ars=sbuf_fill_from_file(db, dfp, NULL, NULL)))
		{
			if(ars<0) goto end;
			// ars==1 means it ended ok.
			fzp_close(&dfp);
		}
		if(omzp && !mb->path.buf
		  && (ars=sbuf_fill_from_file(mb, omzp, NULL, NULL)))
		{
			if(ars<0) goto end;
			// ars==1 means it ended ok.
			fzp_close(&omzp);
		}

		if(mb->path.buf && !db->path.buf)
		{
			if(sbuf_to_manifest(mb, nmzp)) goto end;
			sbuf_free_content(mb);
		}
		else if(!mb->path.buf && db->path.buf)
		{
			sbuf_free_content(db);
		}
		else if(!mb->path.buf && !db->path.buf)
		{
			continue;
		}
		else if(!(pcmp=sbuf_pathcmp(mb, db)))
		{
			// They were the same - do not write.
			sbuf_free_content(mb);
			sbuf_free_content(db);
		}
		else if(pcmp<0)
		{
			// Behind in manifest. Write.
			if(sbuf_to_manifest(mb, nmzp)) goto end;
			sbuf_free_content(mb);
		}
		else
		{
			// Behind in deletions file. Do not write.
			sbuf_free_content(db);
		}
	}

	ret=0;
end:
	if(fzp_close(&nmzp))
	{
		logp("error closing %s in %s\n", manifesttmp, __func__);
		ret=-1;
	}
	
	fzp_close(&dfp);
	fzp_close(&omzp);
	sbuf_free(&db);
	sbuf_free(&mb);
	if(!ret)
	{
		unlink(fdirs->deletionsfile);
		// The rename race condition is not a problem here, as long
		// as manifesttmp is the same path as that generated in the
		// atomic data jiggle.
		if(do_rename(manifesttmp, fdirs->manifest))
			return -1;
	}
	if(manifesttmp) unlink(manifesttmp);
	return ret;
}