コード例 #1
0
ファイル: fuse.c プロジェクト: artagnon/phoenixfs
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;
}
コード例 #2
0
ファイル: fstree.c プロジェクト: Avick/phoenixfs
void fstree_remove_file(const char *path)
{
	struct dir_record *dr;
	struct vfile_record *vfr;
	uint16_t key = ~0;
	size_t length;
	char *filename;
	int rev;

	filename = split_basename(path, dirname);
	length = (size_t) strlen((char *) filename);
	key = compute_crc32(key, (const unsigned char *) filename, length);

	if (!(dr = find_dr(dirname))) {
		PHOENIXFS_DBG("fstree_remove_file:: missing %s", dirname);
		return;
	}
	if (!(vfr = find(dr->vroot, key, 0))) {
		PHOENIXFS_DBG("fstree_remove_file:: missing %s", filename);
		return;
	}
	for (rev = 0; ; rev++) {
		if (!vfr->history[rev])
			break;
		free(vfr->history[rev]);
	}
	PHOENIXFS_DBG("fstree_remove_file:: %s", path);
	delete(dr->vroot, key);
}
コード例 #3
0
ファイル: fuse.c プロジェクト: artagnon/phoenixfs
static int phoenixfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
			off_t offset, struct fuse_file_info *fi)
{
	DIR *dp;
	struct dirent *de;
	struct stat st;
	void *record;
	struct node *iter_root, *iter;
	struct vfile_record *vfr;
	struct dir_record *dr;
	register int i;

	dp = (DIR *) (uintptr_t) fi->fh;

	if (!(de = readdir(dp)))
		return -errno;

	/* Fill directories from backing FS */
	do {
		/* Hide the .git directory, and enumerate only directories */
		if (strcmp(de->d_name, ".git") && de->d_type == DT_DIR) {
			PHOENIXFS_DBG("readdir:: fs: %s", de->d_name);
			if (filler(buf, de->d_name, NULL, 0))
				return -ENOMEM;
		}
	} while ((de = readdir(dp)) != NULL);

	/* Fill files from fstree */
	if (!(dr = find_dr(path)) || !dr->vroot) {
		PHOENIXFS_DBG("readdir:: fstree: blank");
		return 0;
	}
	iter_root = dr->vroot;
	iter = dr->vroot;

	/* Use only the leaves */
	while (!iter->is_leaf)
		iter = iter->pointers[0];

	while (1) {
		for (i = 0; i < iter->num_keys; i++) {
			if (!(record = find(iter_root, iter->keys[i], 0)))
				PHOENIXFS_DBG("readdir:: key listing issue");
			vfr = (struct vfile_record *) record;
			fill_stat(&st, vfr->history[vfr->HEAD]);
			PHOENIXFS_DBG("readdir:: tree fill: %s", (const char *) vfr->name);
			if (filler(buf, (const char *) vfr->name, &st, 0))
				return -ENOMEM;
		}
		if (iter->pointers && iter->pointers[BTREE_ORDER - 1] != NULL)
			iter = iter->pointers[BTREE_ORDER - 1];
		else
			break;
	}
	return 0;
}
コード例 #4
0
ファイル: fstree.c プロジェクト: Avick/phoenixfs
void fstree_insert_update_file(const char *path, const char *follow)
{
	struct dir_record *dr;
	struct vfile_record *vfr;
	struct file_record *fr, *new_fr;
	uint16_t key = ~0;
	char *filename;
	size_t length;

	filename = split_basename(path, dirname);
	if (!(dr = find_dr(dirname)))
		goto DR;
	else {
		length = (size_t) strlen((char *) filename);
		key = compute_crc32(key, (const unsigned char *) filename, length);
		if (!(vfr = find(dr->vroot, key, 0))) {
			PHOENIXFS_DBG("fstree_insert_update_file:: missing vfr: %s", filename);
			goto VFR;
		}
		else {
			if (vfr->HEAD >= 0)
				fr = vfr->history[vfr->HEAD];
			else
				fr = NULL;
			goto FR;
		}
	}
DR:
	dr = make_dr(dirname);
	insert_dr(dr);
VFR:
	vfr = make_vfr(filename);
	insert_vfr(dr, vfr);
FR:
	if (!(new_fr = make_fr(path, follow))) {
		PHOENIXFS_DBG("fstree_insert_update_file:: Can't make fr %s", path);
		return;
	}

	/* If content is present in the old fr, don't make a new fr */
	if (fr && !memcmp(fr->sha1, new_fr->sha1, 20)) {
		PHOENIXFS_DBG("fstree_insert_update_file:: unmodified: %s", path);
		free(new_fr);
		return;
	}
	insert_fr(vfr, new_fr);
}
コード例 #5
0
ファイル: fstree.c プロジェクト: Avick/phoenixfs
struct vfile_record *find_vfr(const char *path)
{
	uint16_t key = ~0;
	struct dir_record *dr;
	struct vfile_record *vfr;
	char *filename;
	size_t length;

	filename = split_basename(path, dirname);
	if (!(dr = find_dr(dirname)) || !dr->vroot) {
		PHOENIXFS_DBG("find_vfr:: not found %s", path);
		return NULL;
	}
	length = (size_t) strlen((char *) filename);
	key = compute_crc32(key, (const unsigned char *) filename, length);
	if (!(vfr = find(dr->vroot, key, 0))) {
		PHOENIXFS_DBG("find_vfr:: not found %s", path);
		return NULL;
	}
	PHOENIXFS_DBG("find_vfr:: found %s", path);
	return vfr;
}
コード例 #6
0
ファイル: fuse.c プロジェクト: artagnon/phoenixfs
static int phoenixfs_opendir(const char *path, struct fuse_file_info *fi)
{
	struct dir_record *dr;
	DIR *dp;

	PHOENIXFS_DBG("opendir:: %s", path);
	build_xpath(xpath, path, 0);

	/* Try underlying fs */
	if (!(dp = opendir(xpath))) {
		/* Try fstree */
		if (!(dr = find_dr(path)))
			return -ENOENT;
		else {
			/* Make the directory and open it */
			mkdir(xpath, S_IRUSR | S_IWUSR | S_IXUSR);
			dp = opendir(xpath);
		}
	}
	fi->fh = (intptr_t) dp;
	return 0;
}
コード例 #7
0
ファイル: fuse.c プロジェクト: artagnon/phoenixfs
static int phoenixfs_rename(const char *path, const char *newpath)
{
	char xnewpath[PATH_MAX];
	struct dir_record *dr;
	struct vfile_record *vfr, *new_vfr;
	char *filename, *newfilename;
	uint16_t key = ~0;
	size_t length;
	uint8_t start_rev, rev_nr;

	PHOENIXFS_DBG("rename:: %s to %s", path, newpath);
	build_xpath(xpath, path, 0);
	build_xpath(xnewpath, newpath, 0);
	if (rename(xpath, xnewpath) < 0)
		return -errno;

	/* Update fstree */
	filename = split_basename(path, xpath);
	if (!(dr = find_dr(xpath))) {
		PHOENIXFS_DBG("rename:: Missing dr for %s", xpath);
		return 0;
	}

	/* Find the old vfr to copy out data from and remove */
	length = (size_t) strlen((char *) filename);
	key = compute_crc32(key, (const unsigned char *) filename, length);
	if (!(vfr = find(dr->vroot, key, 0))) {
		PHOENIXFS_DBG("rename:: Missing vfr for %s", path);
		return 0;
	}

	/* Make a new vfr and copy out history from old vfr */
	newfilename = split_basename(path, NULL);
	new_vfr = make_vfr(newfilename);

	/* Compute start_rev and rev_nr */
	if (vfr->HEAD < 0) {
		start_rev = 0;
		rev_nr = 0;
	} else if (vfr->history[(vfr->HEAD + 1) % REV_TRUNCATE]) {
		/* History is full, and is probably wrapping around */
		start_rev = (vfr->HEAD + 1) % REV_TRUNCATE;
		rev_nr = 20;
	} else {
		/* History is not completely filled */
		start_rev = 0;
		rev_nr = vfr->HEAD + 1;
	}
	PHOENIXFS_DBG("rename:: copying %d revisions", rev_nr);
	while (start_rev < rev_nr) {
		new_vfr->history[start_rev] = vfr->history[start_rev];
		start_rev = (start_rev + 1) % REV_TRUNCATE;
	}
	new_vfr->HEAD = rev_nr - 1;
	insert_vfr(dr, new_vfr);

	/* Remove old vfr */
	dr->vroot = remove_entry(dr->vroot, key);

	return 0;
}