Beispiel #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;
}
Beispiel #2
0
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);
}
Beispiel #3
0
/* filename is simply a pointer; dirname must have alloc'ed memory */
char *split_basename(const char *path, char *dirname)
{
	int length;
	char *filename;

	/* In the worst case, strrchr returns 0: leading '/' */
	filename = strrchr(path, '/') + 1;

	/* Strip trailing '/' from all directories except '/' itself */
	/* +1 to accomodate the null terminator */
	length = strlen(path) - strlen(filename);
	length = (length == 1 ? 2 : length);

	if (!dirname) {
		PHOENIXFS_DBG("split_basename:: path: %s, filename: %s",
			path, filename);
		return filename;
	}

	memcpy(dirname, path, length - 1);
	dirname[length - 1] = '\0';

	PHOENIXFS_DBG("split_basename:: path: %s, dirname: %s, filename: %s",
		path, dirname, filename);
	return filename;
}
Beispiel #4
0
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;
}
Beispiel #5
0
struct dir_record *find_dr(const char *path)
{
	struct dir_record *dr;
	uint16_t key = ~0;
	size_t length;

	length = (size_t) strlen((char *) path);
	key = compute_crc32(key, (const unsigned char *) path, length);
	if (!(dr = find(fsroot, key, 0))) {
		PHOENIXFS_DBG("find_dr:: missing %s", path);
		return NULL;
	}
	PHOENIXFS_DBG("find_dr:: found %s", path);
	return dr;
}
Beispiel #6
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;
}
Beispiel #7
0
/**
 * Format:
 * <> :=
 * num_keys | [key | name_len | name | [<load_vfr>][...]][...]
 */
struct node *load_dr_tree(FILE *infile)
{
	struct node *root;
	struct dir_record *dr;
	uint16_t key;
	uint16_t num_keys;
	uint16_t name_len;
	register int i;

	root = NULL;
	memset(&num_keys, 0, sizeof(uint16_t));
	fread(&num_keys, sizeof(uint16_t), 1, infile);
	for (i = 0; i < num_keys; i++) {
		memset(&key, 0, sizeof(uint16_t));
		fread(&key, sizeof(uint16_t), 1, infile);
		memset(&name_len, 0, sizeof(uint16_t));
		fread(&name_len, sizeof(uint16_t), 1, infile);
		memset(&path_buf, 0, PATH_MAX);
		fread(&path_buf, name_len * sizeof(unsigned char), 1, infile);
		PHOENIXFS_DBG("load_dr_tree:: %s", (const char *) path_buf);
		dr = make_dr((const char *) path_buf);
		root = insert(root, key, (void *) dr);
		dr->vroot = load_vfr_tree(infile);
	}
	return root;
}
Beispiel #8
0
/**
 * Format:
 * <> :=
 * num_keys | [key | name_len | name | [<dump_vfr>][...]][...]
 */
void dump_dr_tree(struct node *root, FILE *outfile)
{
	struct dir_record *dr;
	uint16_t name_len;
	register int i;
	node *iter;

	iter = root;
	while (!iter->is_leaf)
		iter = iter->pointers[0];
	fwrite(&(iter->num_keys), sizeof(uint16_t), 1, outfile);

	while (1) {
		for (i = 0; i < iter->num_keys; i++) {
			/* Write the key */
			fwrite(&(iter->keys[i]), sizeof(uint16_t), 1, outfile);
			dr = find(root, iter->keys[i], 0);

			/* Compute name_len; write name_len and name */
			name_len = strlen((const char *) dr->name);
			fwrite(&name_len, sizeof(uint16_t), 1, outfile);
			fwrite(dr->name, name_len * sizeof(unsigned char), 1, outfile);
			PHOENIXFS_DBG("dump_dr_tree:: %s", (const char *) dr->name);

			dump_vfr_tree(dr->vroot, outfile);
		}
		if (iter->pointers[BTREE_ORDER - 1] != NULL)
			iter = iter->pointers[BTREE_ORDER - 1];
		else
			break;
	}
}
Beispiel #9
0
/**
 * Format:
 * <> :=
 * num_keys | [key | name_len | name | rev_nr | [<load_frs>][...]][...]
 */
struct node *load_vfr_tree(FILE *infile)
{
	struct node *root;
	struct vfile_record *vfr;
	uint16_t key;
	uint16_t num_keys;
	uint16_t name_len;
	uint8_t rev_nr;
	register int i, j;

	root = NULL;
	memset(&num_keys, 0, sizeof(uint16_t));
	fread(&num_keys, sizeof(uint16_t), 1, infile);
	for (i = 0; i < num_keys; i++) {
		memset(&key, 0, sizeof(uint16_t));
		fread(&key, sizeof(uint16_t), 1, infile);
		memset(&name_len, 0, sizeof(uint16_t));
		fread(&name_len, sizeof(uint16_t), 1, infile);
		memset(&path_buf, 0, PATH_MAX);
		fread(&path_buf, name_len * sizeof(unsigned char), 1, infile);
		memset(&rev_nr, 0, sizeof(uint8_t));
		fread(&rev_nr, sizeof(uint8_t), 1, infile);
		vfr = make_vfr((const char *) path_buf);
		root = insert(root, key, (void *) vfr);
		for (j = 0; j < rev_nr; j++) {
			vfr->history[j] = malloc(sizeof(struct file_record));
			memset(vfr->history[j], 0, sizeof(struct file_record));
			fread(vfr->history[j], sizeof(struct file_record), 1, infile);
			PHOENIXFS_DBG("load_vfr_tree:: %s [%d]", vfr->name, j);
		}
		vfr->HEAD = rev_nr - 1;
	}
	return root;
}
Beispiel #10
0
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);
}
Beispiel #11
0
static int phoenixfs_chmod(const char *path, mode_t mode)
{
	PHOENIXFS_DBG("chmod:: %s", path);
	build_xpath(xpath, path, 0);
	if (chmod(xpath, mode) < 0)
		return -errno;
	return 0;
}
Beispiel #12
0
static void phoenixfs_destroy(void *userdata)
{
	FILE *outfile;

	/* Persist the fstree */
	sprintf(xpath, "%s/.git/fstree", ROOTENV->fsback);
	if (!(outfile = fopen(xpath, "wb"))) {
		PHOENIXFS_DBG("destroy:: Can't open .git/fstree to persist");
		return;
	}
	PHOENIXFS_DBG("destroy:: dumping fstree");
	fstree_dump_tree(outfile);
	fclose(outfile);
	PHOENIXFS_DBG("destroy:: packing loose objects");
	sprintf(xpath, "%s/.git/loose", ROOTENV->fsback);
	dump_packing_info(xpath);
}
Beispiel #13
0
static int phoenixfs_truncate(const char *path, off_t newsize)
{
	PHOENIXFS_DBG("truncate:: %s to %lld", path, (long long int)newsize);
	build_xpath(xpath, path, 0);
	if (truncate(xpath, newsize) < 0)
		return -errno;
	return 0;
}
Beispiel #14
0
static int phoenixfs_mkdir(const char *path, mode_t mode)
{
	PHOENIXFS_DBG("mkdir:: %s", path);
	build_xpath(xpath, path, 0);
	if (mkdir(xpath, mode) < 0)
		return -errno;
	return 0;
}
Beispiel #15
0
static int phoenixfs_statfs(const char *path, struct statvfs *statv)
{
	PHOENIXFS_DBG("statfs:: %s", path);
	build_xpath(xpath, path, 0);
	if (statvfs(xpath, statv) < 0)
		return -errno;
	return 0;
}
Beispiel #16
0
static int phoenixfs_mknod(const char *path, mode_t mode, dev_t dev)
{
	PHOENIXFS_DBG("mknod:: %s", path);
	build_xpath(xpath, path, 0);
	if (mknod(xpath, mode, dev) < 0)
		return -errno;
	return 0;
}
Beispiel #17
0
static int phoenixfs_access(const char *path, int mask)
{
	PHOENIXFS_DBG("access:: %s", path);
	build_xpath(xpath, path, 0);
	if (access(xpath, mask) < 0)
		return -errno;
	return 0;
}
Beispiel #18
0
static int phoenixfs_utime(const char *path, struct utimbuf *ubuf)
{
	PHOENIXFS_DBG("utime:: %s", path);
	build_xpath(xpath, path, 0);
	if (utime(xpath, ubuf) < 0)
		return -errno;
	return 0;
}
Beispiel #19
0
static int phoenixfs_fgetattr(const char *path, struct stat *stbuf,
			struct fuse_file_info *fi)
{
	PHOENIXFS_DBG("fgetattr:: %s", path);

	if (fstat(fi->fh, stbuf) < 0)
		return -errno;
	return 0;
}
Beispiel #20
0
struct file_record *find_fr(const char *path, int rev)
{
	struct vfile_record *vfr;
	struct file_record *fr;

	if (!(vfr = find_vfr(path))) {
		PHOENIXFS_DBG("find_fr:: not found %s", path);
		return NULL;
	}
	/* Translate rev to mean "number of revs before HEAD" */
	rev = (vfr->HEAD - rev) % REV_TRUNCATE;
	if (!(fr = vfr->history[rev])) {
		PHOENIXFS_DBG("find_fr:: not found %s", path);
		return NULL;
	}
	PHOENIXFS_DBG("find_fr:: found %s", path);
	return fr;
}
Beispiel #21
0
static int phoenixfs_ftruncate(const char *path,
			off_t offset, struct fuse_file_info *fi)
{
	PHOENIXFS_DBG("ftruncate:: %s", path);
	build_xpath(xpath, path, 0);
	if (ftruncate(fi->fh, offset) < 0)
		return -errno;
	return 0;
}
Beispiel #22
0
static int phoenixfs_readlink(const char *path, char *link, size_t size)
{
	/* Always pass through to underlying filesystem */
	PHOENIXFS_DBG("readlink:: %s", path);
	build_xpath(xpath, path, 0);
	if (readlink(xpath, link, size - 1) < 0)
		return -errno;
	return 0;
}
Beispiel #23
0
static int phoenixfs_rmdir(const char *path)
{
	/* Always pass through to underlying filesystem */
	PHOENIXFS_DBG("rmdir:: %s", path);
	build_xpath(xpath, path, 0);
	if (rmdir(xpath) < 0)
		return -errno;
	return 0;
}
Beispiel #24
0
void insert_fr(struct vfile_record *vfr, struct file_record *fr)
{
	int newHEAD;

	newHEAD = (vfr->HEAD + 1) % REV_TRUNCATE;
	vfr->history[newHEAD] = fr;
	vfr->HEAD = newHEAD;
	PHOENIXFS_DBG("insert_fr:: %s [%d]", vfr->name, vfr->HEAD);
}
Beispiel #25
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;
}
Beispiel #26
0
/**
 * Format:
 * <> :=
 * (struct file_record)
 */
static void dump_frs(struct vfile_record *vfr, uint8_t start_rev,
		uint8_t rev_nr, FILE *outfile)
{
	while (start_rev < rev_nr) {
		fwrite(vfr->history[start_rev],
			sizeof(struct file_record), 1, outfile);
		PHOENIXFS_DBG("dump_frs:: %s [%u]", vfr->name, start_rev);
		start_rev = (start_rev + 1) % REV_TRUNCATE;
	}
}
Beispiel #27
0
static int phoenixfs_unlink(const char *path)
{
	/* Always pass through to underlying filesystem */
	PHOENIXFS_DBG("unlink:: %s", path);
	fstree_remove_file(path);
	build_xpath(xpath, path, 0);
	if (unlink(xpath) < 0)
		return -errno;
	return 0;
}
Beispiel #28
0
void insert_vfr(struct dir_record *dr, struct vfile_record *vfr)
{
	uint16_t key = ~0;
	size_t length;

	length = (size_t) strlen((char *) vfr->name);
	key = compute_crc32(key, (const unsigned char *) vfr->name, length);
	PHOENIXFS_DBG("insert_vfr:: %08X", key);
	dr->vroot = insert(dr->vroot, key, vfr);
}
Beispiel #29
0
void insert_dr(struct dir_record *dr)
{
	uint16_t key = ~0;
	size_t length;

	length = (size_t) strlen((char *) dr->name);
	key = compute_crc32(key, (const unsigned char *) dr->name, length);
	PHOENIXFS_DBG("insert_dr:: %08X", key);
	fsroot = insert(fsroot, key, dr);
}
Beispiel #30
0
struct dir_record *make_dr(const char *path)
{
	struct dir_record *dr;

	PHOENIXFS_DBG("make_dr:: %s", path);
	if (!(dr = malloc(sizeof(struct dir_record))))
		return NULL;
	memcpy(dr->name, path, strlen(path) + 1);
	dr->vroot = NULL;
	return dr;
}