[Tux3] FUSE-Tux3 (At your own risk)

Conrad Meyer konrad at tylerc.org
Thu Sep 4 23:46:39 PDT 2008


I take no responsibility for this.

-- 
Conrad Meyer <konrad at tylerc.org>

fuse-tux3.c:

/*
 * FUSE-Tux3: Mount tux3 in userspace.
 * Copyright (C) 2008 Conrad Meyer <konrad at tylerc.org>
 * Large portions completely stolen from Daniel Phillip's tux3.c.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/* Compile: gcc -std=gnu99 buffer.c diskio.c fuse-tux3.c \
 *              -D_FILE_OFFSET_BITS=64 -lfuse -o fuse-tux3
 * (-D_FILE_OFFSET_BITS=64 might be only on 64 bit platforms, not sure.)
 * Run:
 * 1. Create a tux3 fs on __fuse__tux3fs using some combination of dd
 *    and ./tux3 make __fuse__tux3fs.
 * 2. Mount on foo/ like: ./fuse-tux3 -f foo/     (-f for foreground)
 */

#define FUSE_USE_VERSION 26

#include <fuse.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <sys/types.h>
#include "trace.h"
#include "tux3.h"
#include "buffer.h"
#include "diskio.h"

#define include_inode_c
#include "inode.c"

static int tux3_open(const char *path, struct fuse_file_info *fi);
static int tux3_read(const char *path, char *buf, 
		size_t size, off_t offset, struct fuse_file_info *fi);
static int tux3_write(const char *path, const char *buf, 
		size_t size, off_t offset, struct fuse_file_info *fi);
static int tux3_readdir(const char *path, void *buf,
		fuse_fill_dir_t filler, off_t offset,
		struct fuse_file_info *fi);
static int tux3_getattr(const char *path, struct stat *stbuf);
static int tux3_unlink(const char *path);
static int tux3_create(const char *path, mode_t mode,
		struct fuse_file_info *fi);

static struct fuse_operations tux3_oper =
{
	.read = tux3_read,
	.open = tux3_open,
	.write = tux3_write,
	.readdir = tux3_readdir,
	.getattr = tux3_getattr,
	.unlink = tux3_unlink,
	.create = tux3_create,
};

static fd_t fd;
static u64 volsize;
static const char *volname = "__fuse__tux3fs";
static struct sb *sb;
static struct dev *dev;
static const char *fp = "/hello";

int main(int argc, char **argv)
{
	fd = open(volname, O_RDWR, S_IRWXU);
	volsize = 0;
	if (fdsize64(fd, &volsize))
		error("fdsize64 failed for '%s' (%s)", volname, strerror(errno));
	dev = &(struct dev){ fd, .bits = 12 };
	init_buffers(dev, 1<<20);
	sb = &(struct sb){ };
	*sb = (struct sb){
		.max_inodes_per_block = 64,
		.entries_per_node = 20,
		.devmap = new_map(dev, NULL),
		.blockbits = dev->bits,
		.blocksize = 1 << dev->bits,
		.blockmask = (1 << dev->bits) - 1,
		.volblocks = volsize >> dev->bits,
		.freeblocks = volsize >> dev->bits,
		.itree = (struct btree){ .sb = sb, .ops = &itree_ops,
			.entries_per_leaf = 1 << (dev->bits - 6) } };

	sb->bitmap = new_inode(sb, 0);
	if (!sb->bitmap)
		goto eek;
	if ((errno = -load_sb(sb)))
		goto eek;
	if (!(sb->rootdir = new_inode(sb, 0xd)))
		goto eek;
	if ((errno = -open_inode(sb->rootdir)))
		goto eek;
	if ((errno = -open_inode(sb->bitmap)))
		goto eek;
	struct inode *inode = tuxcreate(sb->rootdir, fp, strlen(fp),
		&(struct iattr){ .mode = S_IFREG | S_IRWXU | S_IROTH |
			S_IRGRP });

	return fuse_main(argc, argv, &tux3_oper, NULL);

eek:
	fprintf(stderr, "Eek! %s\n", strerror(errno));
	return 1;
}

static int tux3_open(const char *path, struct fuse_file_info *fi)
{
	printf("---- open file ----\n");
	printf("flags: %i\n", fi->flags);
	fi->flags |= 0666;
	return 0;
}

static int tux3_read(const char *path, char *buf, 
		size_t size, off_t offset, struct fuse_file_info *fi)
{
	printf("---- read file ----\n");
	char *filename = path;
	struct inode *inode = tuxopen(sb->rootdir, filename, strlen(filename));
	struct file *file = &(struct file){ .f_inode = inode };
	printf("userspace tries to seek to %Li\n", (L)offset);
	if (offset >= inode->i_size)
	{
		printf("EOF!\n");
		errno = EOF;
		return 0;
	}
	tuxseek(file, offset);
	int read = tuxread(file, buf, size);
	if (read < 0)
	{
		errno = -read;
		goto eek;
	}
	if (offset + read > inode->i_size)
		return -EOF;
	return read;
eek:
	fprintf(stderr, "Eek! %s\n", strerror(errno));
	return -errno;
}

static int tux3_create(const char *path, mode_t mode,
		struct fuse_file_info *fi)
{
	char *filename = path;
	struct inode *inode = tuxopen(sb->rootdir, filename, strlen(filename));
	if (!inode) {
		printf("---- create file ----\n");
		inode = tuxcreate(sb->rootdir, filename, strlen(filename),
			&(struct iattr){ .mode = S_IFREG | 0666 });
		if (!inode) return -1;
	}
	return 0;
}

static int tux3_write(const char *path, const char *buf, size_t size,
		off_t offset, struct fuse_file_info *fi)
{
	printf("---- write file ----\n");
	char *filename = path;
	struct inode *inode = tuxopen(sb->rootdir, filename, strlen(filename));
	if (!inode) {
		printf("---- create file ----\n");
		inode = tuxcreate(sb->rootdir, filename, strlen(filename),
			&(struct iattr){ .mode = S_IFREG | S_IRWXU });
	}
	struct file *file = &(struct file){ .f_inode = inode };
	if (offset) {
		u64 seek = offset;
		printf("seek to %Li\n", (L)seek);
		tuxseek(file, seek);
	}

	int written = 0;
	if ((written = tuxwrite(file, buf, size)) < 0)
	{
		errno = -written;
		goto eek;
	}

	tuxsync(inode);
	if ((errno = -sync_super(sb)))
		goto eek;
	return written;
eek:
	fprintf(stderr, "Eek! %s\n", strerror(errno));
	return -errno;
}

static int tux3_readdir(const char *path, void *buf,
		fuse_fill_dir_t filler, off_t offset,
		struct fuse_file_info *fi)
{
	// this is completely wrong
	char *filename = path;
	fprintf(stderr, "--- readdir --- '%s'\n", filename);
	filler(buf, ".", NULL, 0);
	filler(buf, "..", NULL, 0);
	filler(buf, "hello", NULL, 0);
	return 0;
}

static int tux3_getattr(const char *path, struct stat *stbuf)
{
	// this is probably mostly wrong as well
	memset(stbuf, 0, sizeof(struct stat));
	if (strcmp(path, "/") == 0)
	{
		stbuf->st_mode = S_IFDIR | 0755;
		stbuf->st_nlink = 2;
		return 0;
	}
	char *filename = path;
	struct inode *inode = tuxopen(sb->rootdir, filename, strlen(filename));
	if (!inode)
		return -ENOENT;
	//stbuf->st_mode  = inode->i_mode;
	stbuf->st_mode = S_IFREG | 0666;
	stbuf->st_atime = inode->i_atime;
	stbuf->st_mtime = inode->i_mtime;
	stbuf->st_ctime = inode->i_ctime;
	stbuf->st_size  = inode->i_size;
	stbuf->st_uid   = inode->i_uid;
	stbuf->st_gid   = inode->i_gid;
	stbuf->st_nlink = inode->i_links;
	return 0;
}

static int tux3_unlink(const char *path)
{
	printf("---- delete file ----\n");
	struct buffer *buffer;
	char *filename = path;
	ext2_dirent *entry = ext2_find_entry(sb->rootdir, filename, strlen(filename), &buffer);
	struct inode *inode = new_inode(sb, entry->inum);
	int err = open_inode(inode);
	if (err) {
		errno = -err;
		goto eek;
	}
	btree_delete(&inode->btree, &(struct delete_info){ .key = inode->inum }, -1);
	if ((err = -ext2_delete_entry(buffer, entry)))
		goto eek;
	free_inode(inode);
eek:
	fprintf(stderr, "Eek! %s\n", strerror(errno));
	return -errno;
}



_______________________________________________
Tux3 mailing list
Tux3 at tux3.org
http://tux3.org/cgi-bin/mailman/listinfo/tux3



More information about the Tux3 mailing list