Пример #1
0
int build_xpath(char *xpath, const char *path, int rev)
{
	struct file_record *fr;
	char sha1_digest[40];

	if (!rev) {
		/* Search on FS */
		strcpy(xpath, ROOTENV->fsback);
		strcat(xpath, path);
		return 0;
	}
	if (!(fr = find_fr(path, rev))) {
		PHOENIXFS_DBG("build_xpath:: missing: %s@%d", path, rev);
		/* Might be a directory; copy and give to caller */
		strcpy(xpath, path);
		return -1;
	}
	print_sha1(sha1_digest, fr->sha1);
	sprintf(xpath, "%s/.git/loose/%s", ROOTENV->fsback, sha1_digest);
	if (access(xpath, F_OK) < 0) {
		/* Try extracting from packfile */
		sprintf(xpath, "%s/.git/loose", ROOTENV->fsback);
		if (unpack_entry(fr->sha1, xpath) < 0)
			return -1;
		else
			PHOENIXFS_DBG("open:: pack %s", sha1_digest);
	}
	else
		PHOENIXFS_DBG("open:: loose %s", sha1_digest);

	return 0;
}
Пример #2
0
static int phoenixfs_getattr(const char *path, struct stat *stbuf)
{
	struct file_record *fr;
	struct dir_record *dr;
	int rev;

	rev = parse_pathspec(xpath, path);
	build_xpath(openpath, xpath, rev);
	PHOENIXFS_DBG("getattr:: %s %d", openpath, rev);

	/* Try underlying FS */
	if (lstat(openpath, stbuf) < 0) {
		/* Try fstree */
		if (!(dr = find_dr(xpath))) {
			if (!(fr = find_fr(xpath, rev)))
				return -ENOENT;
			else {
				memset(stbuf, 0, sizeof(struct stat));
				fill_stat(stbuf, fr);
				return 0;
			}
		}
		memset(stbuf, 0, sizeof(struct stat));
		stbuf->st_mode = S_IFDIR | 0755;
	}
	return 0;
}
Пример #3
0
static int phoenixfs_open(const char *path, struct fuse_file_info *fi)
{
	int rev, fd;
	FILE *infile, *fsfile;
	char fspath[PATH_MAX];
	struct file_record *fr;
	char sha1_digest[40];

	rev = parse_pathspec(xpath, path);
	build_xpath(fspath, xpath, 0);

	/* Skip zinflate for entries not in fstree */
	if (!(fr = find_fr(xpath, rev)))
		goto END;

	/* Build openpath by hand */
	print_sha1(sha1_digest, fr->sha1);
	sprintf(openpath, "%s/.git/loose/%s", ROOTENV->fsback, sha1_digest);
	if (access(openpath, F_OK) < 0) {
		/* Try extracting from packfile */
		sprintf(xpath, "%s/.git/loose", ROOTENV->fsback);
		if (unpack_entry(fr->sha1, xpath) < 0)
			return -ENOENT;
		else
			PHOENIXFS_DBG("open:: pack %s", sha1_digest);
	}
	else
		PHOENIXFS_DBG("open:: loose %s", sha1_digest);

	/* zinflate openpath onto fspath */
	PHOENIXFS_DBG("open:: zinflate %s onto %s", sha1_digest, fspath);
	if (!(infile = fopen(openpath, "rb")) ||
		!(fsfile = fopen(fspath, "wb+")))
		return -errno;
	if (zinflate(infile, fsfile) != Z_OK)
		PHOENIXFS_DBG("open:: zinflate issue");
	fclose(infile);
	fclose(fsfile);
END:
	if ((fd = open(fspath, fi->flags)) < 0)
		return -errno;
	fi->fh = fd;
	return 0;
}
Пример #4
0
static int phoenixfs_release(const char *path, struct fuse_file_info *fi)
{
	struct file_record *fr;
	FILE *infile, *outfile;
	struct stat st;
	unsigned char sha1[20];
	char sha1_digest[40];
	char outfilename[40];
	char inpath[PATH_MAX];
	char outpath[PATH_MAX];
	int rev, ret;

	pthread_mutex_lock(&phoenixfs_mutexlock);

	/* Don't recursively backup history */
	if ((rev = parse_pathspec(xpath, path))) {
		PHOENIXFS_DBG("release:: history: %s", path);

		/* Inflate the original version back onto the filesystem */
		if (!(fr = find_fr(xpath, 0))) {
			PHOENIXFS_DBG("release:: Can't find revision 0!");
			pthread_mutex_unlock(&phoenixfs_mutexlock);
			return 0;
		}
		print_sha1(sha1_digest, fr->sha1);
		sprintf(inpath, "%s/.git/loose/%s", ROOTENV->fsback, sha1_digest);
		build_xpath(outpath, xpath, 0);

		if (!(infile = fopen(inpath, "rb")) ||
			!(outfile = fopen(outpath, "wb+"))) {
			pthread_mutex_unlock(&phoenixfs_mutexlock);
			return -errno;
		}
		PHOENIXFS_DBG("release:: history: zinflate %s onto %s",
			sha1_digest, outpath);
		rewind(infile);
		rewind(outfile);
		if (zinflate(infile, outfile) != Z_OK)
			PHOENIXFS_DBG("release:: zinflate issue");
		fflush(outfile);
		fclose(infile);
		fclose(outfile);

		if (close(fi->fh) < 0) {
			PHOENIXFS_DBG("release:: can't really close");
			pthread_mutex_unlock(&phoenixfs_mutexlock);
			return -errno;
		}
		pthread_mutex_unlock(&phoenixfs_mutexlock);
		return 0;
	}

	/* Attempt to create a backup */
	build_xpath(xpath, path, 0);
	if (!(infile = fopen(xpath, "rb")) ||
		(lstat(xpath, &st) < 0)) {
		pthread_mutex_unlock(&phoenixfs_mutexlock);
		return -errno;
	}
	if ((ret = sha1_file(infile, st.st_size, sha1)) < 0) {
		fclose(infile);
		pthread_mutex_unlock(&phoenixfs_mutexlock);
		return ret;
	}
	print_sha1(outfilename, sha1);
	sprintf(outpath, "%s/.git/loose/%s", ROOTENV->fsback, outfilename);
	if (!access(outpath, F_OK)) {
		/* SHA1 match; don't overwrite file as an optimization */
		PHOENIXFS_DBG("release:: not overwriting: %s", outpath);
		goto END;
	}
	if (!(outfile = fopen(outpath, "wb"))) {
		fclose(infile);
		pthread_mutex_unlock(&phoenixfs_mutexlock);
		return -errno;
	}

	/* Rewind and seek back */
	rewind(infile);
	PHOENIXFS_DBG("release:: zdeflate %s onto %s", xpath, outfilename);
	if (zdeflate(infile, outfile, -1) != Z_OK)
		PHOENIXFS_DBG("release:: zdeflate issue");
	mark_for_packing(sha1, st.st_size);
	fclose(outfile);
END:
	fclose(infile);
	if (close(fi->fh) < 0) {
		PHOENIXFS_DBG("release:: can't really close");
		return -errno;
	}

	/* Update the fstree */
	fstree_insert_update_file(path, NULL);

	pthread_mutex_unlock(&phoenixfs_mutexlock);
	return 0;
}