summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2001-10-23 19:26:04 +0000
committerMiklos Szeredi <miklos@szeredi.hu>2001-10-23 19:26:04 +0000
commitbc22e7bec727bc72d91a3001fbda976f1adf352d (patch)
treead5df343d392838aca0dd517814e351108976087
downloadfuse-bc22e7bec727bc72d91a3001fbda976f1adf352d.tar.gz
Imported sourcesstart
-rw-r--r--Makefile33
-rw-r--r--dev.c133
-rw-r--r--dir.c87
-rw-r--r--fuse.h17
-rw-r--r--fuse_i.h69
-rw-r--r--fusemount.c87
-rw-r--r--inode.c161
-rw-r--r--main.c61
8 files changed, 648 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..aedd26d
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,33 @@
+CC = gcc
+
+KCFLAGS = -O2 -Wall -Wstrict-prototypes -fno-strict-aliasing -pipe
+KCPPFLAGS = -I /lib/modules/`uname -r`/build/include/ -D__KERNEL__ -DMODULE -D_LOOSE_KERNEL_NAMES
+
+CFLAGS = -Wall -W -g
+CPPFLAGS =
+
+all: fuse.o fusemount
+
+dev.o: dev.c
+ $(CC) $(KCFLAGS) $(KCPPFLAGS) -c dev.c
+
+inode.o: inode.c
+ $(CC) $(KCFLAGS) $(KCPPFLAGS) -c inode.c
+
+dir.o: dir.c
+ $(CC) $(KCFLAGS) $(KCPPFLAGS) -c dir.c
+
+main.o: main.c
+ $(CC) $(KCFLAGS) $(KCPPFLAGS) -c main.c
+
+fuse_objs = dev.o inode.o dir.o main.o
+
+fuse.o: $(fuse_objs)
+ ld -r -o fuse.o $(fuse_objs)
+
+fusemount: fusemount.o
+
+clean:
+ rm -f *.o
+ rm -f fusemount
+ rm -f *~
diff --git a/dev.c b/dev.c
new file mode 100644
index 0000000..c7dd247
--- /dev/null
+++ b/dev.c
@@ -0,0 +1,133 @@
+/*
+ FUSE: Filesystem in Userspace
+ Copyright (C) 2001 Miklos Szeredi (mszeredi@inf.bme.hu)
+
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
+*/
+
+#include "fuse_i.h"
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/smp_lock.h>
+#include <linux/poll.h>
+#include <linux/file.h>
+#include <linux/proc_fs.h>
+
+static struct proc_dir_entry *proc_fs_fuse;
+struct proc_dir_entry *proc_fuse_dev;
+
+static ssize_t fuse_dev_read(struct file *file, char *buf, size_t nbytes,
+ loff_t *off)
+{
+ printk(KERN_DEBUG "fuse_dev_read\n");
+ return 0;
+}
+
+static ssize_t fuse_dev_write(struct file *file, const char *buf,
+ size_t nbytes, loff_t *off)
+{
+ printk(KERN_DEBUG "fuse_dev_write <%.*s>\n", (int) nbytes, buf);
+ return nbytes;
+}
+
+
+static unsigned int fuse_dev_poll(struct file *file, poll_table *wait)
+{
+ printk(KERN_DEBUG "fuse_dev_poll\n");
+ return 0;
+}
+
+static int fuse_dev_open(struct inode *inode, struct file *file)
+{
+ int res;
+ struct fuse_conn *fc;
+
+ printk(KERN_DEBUG "fuse_dev_open\n");
+
+ res = -ENOMEM;
+ fc = kmalloc(sizeof(*fc), GFP_KERNEL);
+ if(!fc)
+ goto out;
+
+ fc->sb = NULL;
+ fc->file = file;
+
+ lock_kernel();
+ file->private_data = fc;
+ unlock_kernel();
+ res = 0;
+
+ out:
+ return res;
+}
+
+static int fuse_dev_release(struct inode *inode, struct file *file)
+{
+ struct fuse_conn *fc = file->private_data;
+
+ printk(KERN_DEBUG "fuse_dev_release\n");
+
+ lock_kernel();
+ fc->file = NULL;
+ fuse_release_conn(fc);
+ unlock_kernel();
+ return 0;
+}
+
+static struct file_operations fuse_dev_operations = {
+ owner: THIS_MODULE,
+ read: fuse_dev_read,
+ write: fuse_dev_write,
+ poll: fuse_dev_poll,
+ open: fuse_dev_open,
+ release: fuse_dev_release,
+};
+
+int fuse_dev_init()
+{
+ int res;
+
+ proc_fs_fuse = NULL;
+ proc_fuse_dev = NULL;
+
+ res = -EIO;
+ proc_fs_fuse = proc_mkdir("fuse", proc_root_fs);
+ if(!proc_fs_fuse) {
+ printk("fuse: failed to create directory in /proc/fs\n");
+ goto err;
+ }
+
+ proc_fs_fuse->owner = THIS_MODULE;
+ proc_fuse_dev = create_proc_entry("dev", S_IFSOCK | S_IRUGO | S_IWUGO,
+ proc_fs_fuse);
+ if(!proc_fuse_dev) {
+ printk("fuse: failed to create entry in /proc/fs/fuse\n");
+ goto err;
+ }
+
+ proc_fuse_dev->proc_fops = &fuse_dev_operations;
+
+ return 0;
+
+ err:
+ fuse_dev_cleanup();
+ return res;
+
+}
+
+void fuse_dev_cleanup()
+{
+ if(proc_fs_fuse) {
+ remove_proc_entry("dev", proc_fs_fuse);
+ remove_proc_entry("fuse", proc_root_fs);
+ }
+}
+
+/*
+ * Local Variables:
+ * indent-tabs-mode: t
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/dir.c b/dir.c
new file mode 100644
index 0000000..afa6106
--- /dev/null
+++ b/dir.c
@@ -0,0 +1,87 @@
+/*
+ FUSE: Filesystem in Userspace
+ Copyright (C) 2001 Miklos Szeredi (mszeredi@inf.bme.hu)
+
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
+*/
+
+
+#include "fuse.h"
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/smp_lock.h>
+#include <linux/sched.h>
+#include <linux/file.h>
+
+static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry)
+{
+ printk(KERN_DEBUG "fuse_lookup: %li\n", dir->i_ino);
+
+ return NULL;
+}
+
+static int fuse_permission(struct inode *inode, int mask)
+{
+ printk(KERN_DEBUG "fuse_permission: %li, 0%o\n", inode->i_ino, mask);
+
+ return 0;
+}
+
+static int fuse_revalidate(struct dentry *dentry)
+{
+ printk(KERN_DEBUG "fuse_revalidate: %li\n",
+ dentry->d_inode->i_ino);
+
+ return 0;
+}
+static int fuse_readdir(struct file *file, void *dirent, filldir_t filldir)
+{
+ printk(KERN_DEBUG "fuse_readdir: %li\n",
+ file->f_dentry->d_inode->i_ino);
+
+ return 0;
+}
+
+static int fuse_open(struct inode *inode, struct file *file)
+{
+ printk(KERN_DEBUG "fuse_open: %li\n", inode->i_ino);
+
+ return 0;
+}
+
+static int fuse_release(struct inode *inode, struct file *file)
+{
+ printk(KERN_DEBUG "fuse_release: %li\n", inode->i_ino);
+
+ return 0;
+}
+
+static struct inode_operations fuse_dir_inode_operations =
+{
+ lookup: fuse_lookup,
+ permission: fuse_permission,
+ revalidate: fuse_revalidate,
+};
+
+static struct file_operations fuse_dir_operations = {
+ read: generic_read_dir,
+ readdir: fuse_readdir,
+ open: fuse_open,
+ release: fuse_release,
+};
+
+void fuse_dir_init(struct inode *inode)
+{
+ inode->i_op = &fuse_dir_inode_operations;
+ inode->i_fop = &fuse_dir_operations;
+}
+
+
+/*
+ * Local Variables:
+ * indent-tabs-mode: t
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/fuse.h b/fuse.h
new file mode 100644
index 0000000..df71221
--- /dev/null
+++ b/fuse.h
@@ -0,0 +1,17 @@
+/* -*- indent-tabs-mode: t; c-basic-offset: 8; -*- */
+/*
+ FUSE: Filesystem in Userspace
+ Copyright (C) 2001 Miklos Szeredi (mszeredi@inf.bme.hu)
+
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
+*/
+
+
+#define FUSE_MOUNT_VERSION 1
+
+struct fuse_mount_data {
+ int version;
+ int fd;
+};
+
diff --git a/fuse_i.h b/fuse_i.h
new file mode 100644
index 0000000..5e1cc1c
--- /dev/null
+++ b/fuse_i.h
@@ -0,0 +1,69 @@
+/*
+ FUSE: Filesystem in Userspace
+ Copyright (C) 2001 Miklos Szeredi (mszeredi@inf.bme.hu)
+
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
+*/
+
+#include <linux/fs.h>
+
+#define FUSE_VERSION "0.1"
+
+/**
+ * A Fuse connection.
+ *
+ * This structure is created, when the client device is opened, and is
+ * destroyed, when the client device is closed _and_ the filesystem is
+ * umounted.
+ */
+struct fuse_conn {
+ /** The superblock of the mounted filesystem */
+ struct super_block *sb;
+
+ /** The opened client device */
+ struct file *file;
+};
+
+/**
+ * The proc entry for the client device ("/proc/fs/fuse/dev")
+ */
+extern struct proc_dir_entry *proc_fuse_dev;
+
+/**
+ * Fill in the directory operations
+ */
+void fuse_dir_init(struct inode *inode);
+
+
+/**
+ * Check if the connection can be released, and if yes, then free the
+ * connection structure
+ */
+void fuse_release_conn(struct fuse_conn *fc);
+
+/**
+ * Initialize the client device
+ */
+int fuse_dev_init(void);
+
+/**
+ * Cleanup the client device
+ */
+void fuse_dev_cleanup(void);
+
+/**
+ * Initialize the fuse filesystem
+ */
+int fuse_fs_init(void);
+
+/**
+ * Cleanup the fuse filesystem
+ */
+void fuse_fs_cleanup(void);
+
+/*
+ * Local Variables:
+ * indent-tabs-mode: t
+ * c-basic-offset: 8
+ */
diff --git a/fusemount.c b/fusemount.c
new file mode 100644
index 0000000..b4d3bc0
--- /dev/null
+++ b/fusemount.c
@@ -0,0 +1,87 @@
+/*
+ AVFS: A Virtual File System Library
+ Copyright (C) 1998-2001 Miklos Szeredi (mszeredi@inf.bme.hu)
+
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
+*/
+
+#include "fuse.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/mount.h>
+#include <mntent.h>
+
+
+int mount_fuse(const char *dev, const char *dir, int devfd)
+{
+ int res;
+ const char *type;
+ FILE *fd;
+ struct mntent ent;
+ struct fuse_mount_data data;
+
+ data.version = FUSE_MOUNT_VERSION;
+ data.fd = devfd;
+
+ type = "fuse";
+ res = mount(dev, dir, type, MS_MGC_VAL | MS_NOSUID | MS_NODEV, &data);
+
+ if(res == -1) {
+ fprintf(stderr, "mount failed: %s\n", strerror(errno));
+ return -1;
+ }
+
+ fd = setmntent("/etc/mtab", "a");
+ if(fd == NULL) {
+ fprintf(stderr, "setmntent(\"/etc/mtab\") failed: %s\n",
+ strerror(errno));
+ return -1;
+ }
+
+ ent.mnt_fsname = (char *) dev;
+ ent.mnt_dir = (char *) dir;
+ ent.mnt_type = (char *) type;
+ ent.mnt_opts = "rw,nosuid,nodev";
+ ent.mnt_freq = 0;
+ ent.mnt_passno = 0;
+ res = addmntent(fd, & ent);
+ if(res != 0)
+ fprintf(stderr, "addmntent() failed: %s\n", strerror(errno));
+
+ endmntent(fd);
+
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ const char *dev;
+ const char *dir;
+ int devfd;
+
+ if(argc < 3) {
+ fprintf(stderr, "usage: %s dev dir\n", argv[0]);
+ exit(1);
+ }
+
+ dev = argv[1];
+ dir = argv[2];
+
+ devfd = open(dev, O_RDWR);
+ if(devfd == -1) {
+ fprintf(stderr, "failed to open %s: %s\n", dev, strerror(errno));
+ exit(1);
+ }
+
+ mount_fuse(dev, dir, devfd);
+
+ sleep(1000);
+
+ return 0;
+}
diff --git a/inode.c b/inode.c
new file mode 100644
index 0000000..77040fc
--- /dev/null
+++ b/inode.c
@@ -0,0 +1,161 @@
+/*
+ FUSE: Filesystem in Userspace
+ Copyright (C) 2001 Miklos Szeredi (mszeredi@inf.bme.hu)
+
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
+*/
+
+#include "fuse.h"
+#include "fuse_i.h"
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/smp_lock.h>
+#include <linux/sched.h>
+#include <linux/file.h>
+
+#define FUSE_SUPER_MAGIC 0x65735546
+
+static void fuse_read_inode(struct inode *inode)
+{
+ printk(KERN_DEBUG "fuse_read_inode: %li\n", inode->i_ino);
+
+
+}
+
+static void fuse_put_super(struct super_block *sb)
+{
+ struct fuse_conn *fc = sb->u.generic_sbp;
+
+ printk(KERN_DEBUG "fuse_put_super\n");
+
+ fc->sb = NULL;
+ fuse_release_conn(fc);
+}
+
+static struct super_operations fuse_super_operations = {
+ read_inode: fuse_read_inode,
+ put_super: fuse_put_super,
+};
+
+
+static struct fuse_conn *get_conn(struct fuse_mount_data *d)
+{
+ struct fuse_conn *fc = NULL;
+ struct file *file;
+ struct inode *ino;
+
+ printk(KERN_DEBUG "fuse_read_super\n");
+
+ if(d == NULL) {
+ printk("fuse_read_super: Bad mount data\n");
+ return NULL;
+ }
+
+ if(d->version != FUSE_MOUNT_VERSION) {
+ printk("fuse_read_super: Bad mount version: %i\n", d->version);
+ return NULL;
+ }
+
+ file = fget(d->fd);
+ ino = NULL;
+ if(file)
+ ino = file->f_dentry->d_inode;
+
+ if(!ino || ino->u.generic_ip != proc_fuse_dev) {
+ printk("fuse_read_super: Bad file: %i\n", d->fd);
+ goto out;
+ }
+
+ fc = file->private_data;
+
+ out:
+ fput(file);
+ return fc;
+
+}
+
+static struct super_block *fuse_read_super(struct super_block *sb,
+ void *data, int silent)
+{
+ struct fuse_conn *fc;
+ struct inode *root;
+
+ fc = get_conn(data);
+ if(fc == NULL)
+ goto err;
+
+ if(fc->sb != NULL) {
+ printk("fuse_read_super: file already mounted\n");
+ goto err;
+ }
+
+ sb->u.generic_sbp = fc;
+ sb->s_blocksize = 1024;
+ sb->s_blocksize_bits = 10;
+ sb->s_magic = FUSE_SUPER_MAGIC;
+ sb->s_op = &fuse_super_operations;
+
+ root = iget(sb, 1);
+ if(!root) {
+ printk("fuse_read_super: failed to get root inode\n");
+ goto err;
+ }
+
+ printk(KERN_DEBUG "root inode: %ld/%d\n", root->i_ino, root->i_dev);
+
+ root->i_mode = S_IFDIR;
+ root->i_uid = 0;
+ root->i_gid = 0;
+ root->i_nlink = 2;
+ root->i_size = 0;
+ root->i_blksize = 1024;
+ root->i_blocks = 0;
+ root->i_atime = CURRENT_TIME;
+ root->i_mtime = CURRENT_TIME;
+ root->i_ctime = CURRENT_TIME;
+ fuse_dir_init(root);
+
+ sb->s_root = d_alloc_root(root);
+ if(!sb->s_root) {
+ printk("fuse_read_super: failed to allocate root dentry\n");
+ goto err_iput;
+ }
+
+ fc->sb = sb;
+
+ return sb;
+
+ err_iput:
+ iput(root);
+ err:
+ return NULL;
+}
+
+
+static DECLARE_FSTYPE(fuse_fs_type, "fuse", fuse_read_super, 0);
+
+int fuse_fs_init()
+{
+ int res;
+
+ res = register_filesystem(&fuse_fs_type);
+ if(res)
+ printk("fuse: failed to register filesystem\n");
+
+ return res;
+}
+
+void fuse_fs_cleanup()
+{
+ unregister_filesystem(&fuse_fs_type);
+}
+
+/*
+ * Local Variables:
+ * indent-tabs-mode: t
+ * c-basic-offset: 8
+ * End:
+ */
+
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..fa4ca8c
--- /dev/null
+++ b/main.c
@@ -0,0 +1,61 @@
+/*
+ FUSE: Filesystem in Userspace
+ Copyright (C) 2001 Miklos Szeredi (mszeredi@inf.bme.hu)
+
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
+*/
+
+#include "fuse_i.h"
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/smp_lock.h>
+#include <linux/slab.h>
+
+#define FUSE_VERSION "0.1"
+
+
+void fuse_release_conn(struct fuse_conn *fc)
+{
+ if(fc->sb == NULL && fc->file == NULL) {
+ printk(KERN_DEBUG "fuse: release connection\n");
+ kfree(fc);
+ }
+}
+
+int init_module(void)
+{
+ int res;
+
+ printk(KERN_DEBUG "fuse init (version %s)\n", FUSE_VERSION);
+
+ res = fuse_fs_init();
+ if(res)
+ goto err;
+
+ res = fuse_dev_init();
+ if(res)
+ goto err_fs_cleanup;
+
+ return 0;
+
+ err_fs_cleanup:
+ fuse_fs_cleanup();
+ err:
+ return res;
+}
+
+void cleanup_module(void)
+{
+ printk(KERN_DEBUG "fuse cleanup\n");
+
+ fuse_fs_cleanup();
+ fuse_dev_cleanup();
+}
+
+/*
+ * Local Variables:
+ * indent-tabs-mode: t
+ * c-basic-offset: 8
+ */