aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--configure.in22
-rw-r--r--example/.cvsignore1
-rw-r--r--example/Makefile.am2
-rw-r--r--example/fusexmp.c40
-rw-r--r--include/linux/fuse.h2
-rw-r--r--kernel/Makefile.am18
-rw-r--r--kernel/dir.c15
-rw-r--r--lib/fuse.c99
8 files changed, 149 insertions, 50 deletions
diff --git a/configure.in b/configure.in
index 7451681..8f3b279 100644
--- a/configure.in
+++ b/configure.in
@@ -18,16 +18,36 @@ if test -z "$kernelsrc"; then
if test -e $buildlink; then
kernelsrc=`(cd $buildlink; /bin/pwd)`
else
- AC_MSG_RESULT([not found])
+ AC_MSG_RESULT([Not found])
AC_MSG_ERROR([
*** Please specify the location of the kernel source with
*** the '--with-kernel=SRCDIR' option])
fi
fi
AC_MSG_RESULT([$kernelsrc])
+AC_MSG_CHECKING([kernel source version])
+kernsrcver=`AC_TRY_RUN([
+#include "$kernelsrc/include/linux/version.h"
+#include <stdio.h>
+
+int main() {
+printf("%s\n", UTS_RELEASE);
+ return 0;
+}
+], , , true)`
+
+if test -z "$kernsrcver"; then
+ AC_MSG_RESULT([Not found])
+ AC_MSG_ERROR([
+*** Cannot determine the version of the linux kernel source. Please
+*** configure the kernel before running this script])
+fi
+AC_MSG_RESULT([$kernsrcver])
KERNINCLUDE=$kernelsrc/include
AC_SUBST(KERNINCLUDE)
+kmoduledir=/lib/modules/$kernsrcver
+AC_SUBST(kmoduledir)
AC_OUTPUT([Makefile kernel/Makefile lib/Makefile example/Makefile include/Makefile include/linux/Makefile])
diff --git a/example/.cvsignore b/example/.cvsignore
index e440faf..bcfd8b2 100644
--- a/example/.cvsignore
+++ b/example/.cvsignore
@@ -1,3 +1,4 @@
Makefile.in
Makefile
.deps
+fusexmp
diff --git a/example/Makefile.am b/example/Makefile.am
index 0e666b5..4d89206 100644
--- a/example/Makefile.am
+++ b/example/Makefile.am
@@ -4,4 +4,4 @@ bin_PROGRAMS = fusexmp
fusexmp_SOURCES = fusexmp.c
-fusexmp_LDADD = ../lib/libfuse.a
+fusexmp_LDADD = ../lib/libfuse.a -lpthread
diff --git a/example/fusexmp.c b/example/fusexmp.c
index b00039d..4c831dc 100644
--- a/example/fusexmp.c
+++ b/example/fusexmp.c
@@ -388,22 +388,52 @@ static struct fuse_operations xmp_oper = {
int main(int argc, char *argv[])
{
int res;
- if(argc != 2) {
- fprintf(stderr, "usage: %s mount_dir\n", argv[0]);
+ int argctr;
+ char *mnt;
+ int flags;
+
+ if(argc < 2) {
+ fprintf(stderr,
+ "usage: %s [options] mount_dir\n"
+ "Options:\n"
+ " -d enable debug output\n"
+ " -s disable multithreaded operation\n",
+ argv[0]);
exit(1);
}
+ flags = FUSE_MULTITHREAD;
+ for(argctr = 1; argctr < argc && argv[argctr][0] == '-'; argctr ++) {
+ switch(argv[argctr][1]) {
+ case 'd':
+ flags |= FUSE_DEBUG;
+ break;
+
+ case 's':
+ flags &= ~FUSE_MULTITHREAD;
+ break;
+
+ default:
+ fprintf(stderr, "invalid option: %s\n", argv[argctr]);
+ exit(1);
+ }
+ }
+ if(argctr != argc - 1) {
+ fprintf(stderr, "missing or surplus argument\n");
+ exit(1);
+ }
+ mnt = argv[argctr];
+
set_signal_handlers();
atexit(cleanup);
setgroups(0, NULL);
- xmp_fuse = fuse_new(0,0);
- res = fuse_mount(xmp_fuse, argv[1]);
+ xmp_fuse = fuse_new(flags, 0);
+ res = fuse_mount(xmp_fuse, mnt);
if(res == -1)
exit(1);
fuse_set_operations(xmp_fuse, &xmp_oper);
-
fuse_loop(xmp_fuse);
return 0;
diff --git a/include/linux/fuse.h b/include/linux/fuse.h
index 22897d4..4f64336 100644
--- a/include/linux/fuse.h
+++ b/include/linux/fuse.h
@@ -111,7 +111,7 @@ struct fuse_setattr_in {
};
struct fuse_setattr_out {
- unsigned long long newsize;
+ struct fuse_attr attr;
};
struct fuse_open_in {
diff --git a/kernel/Makefile.am b/kernel/Makefile.am
index cefcf63..4edce67 100644
--- a/kernel/Makefile.am
+++ b/kernel/Makefile.am
@@ -2,15 +2,25 @@
EXTRA_DIST = dev.c dir.c file.c inode.c util.c fuse_i.h
+CC = @CC@
+CFLAGS = -O2 -Wall -Wstrict-prototypes -fno-strict-aliasing -pipe
+CPPFAGS = -I@KERNINCLUDE@ -I../include -D__KERNEL__ -DMODULE -D_LOOSE_KERNEL_NAMES
+INSTALL = @INSTALL@
+fusemoduledir = @kmoduledir@/kernel/fs/fuse
+
+SUFFIXES = .c .o .s
+
+
all-local: fuse.o
+install-exec-local: fuse.o
+ $(mkinstalldirs) $(DESTDIR)$(fusemoduledir)
+ $(INSTALL) -m 644 fuse.o $(DESTDIR)$(fusemoduledir)/fuse.o
+ /sbin/depmod -a
+
clean-local:
rm -f *.o *.s
-CFLAGS = -O2 -Wall -Wstrict-prototypes -fno-strict-aliasing -pipe
-CPPFAGS = -I@KERNINCLUDE@ -I../include -D__KERNEL__ -DMODULE -D_LOOSE_KERNEL_NAMES
-
-SUFFIXES = .c .o .s
.c.o:
$(CC) $(CFLAGS) $(CPPFAGS) -c $<
diff --git a/kernel/dir.c b/kernel/dir.c
index a4018ca..87f7241 100644
--- a/kernel/dir.c
+++ b/kernel/dir.c
@@ -19,7 +19,8 @@ static struct file_operations fuse_dir_operations;
static struct dentry_operations fuse_dentry_opertations;
-#define FUSE_REVALIDATE_TIME (HZ / 100)
+/* FIXME: This should be user configurable */
+#define FUSE_REVALIDATE_TIME (1 * HZ)
static void change_attributes(struct inode *inode, struct fuse_attr *attr)
{
@@ -528,13 +529,13 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr)
out.arg = &outarg;
request_send(fc, &in, &out);
- if(!out.h.error && (attr->ia_valid & ATTR_SIZE)) {
- if(outarg.newsize > attr->ia_size)
- outarg.newsize = attr->ia_size;
-
- vmtruncate(inode, outarg.newsize);
- }
+ if(!out.h.error) {
+ if(attr->ia_valid & ATTR_SIZE &&
+ outarg.attr.size < inode->i_size)
+ vmtruncate(inode, outarg.attr.size);
+ change_attributes(inode, &outarg.attr);
+ }
return out.h.error;
}
diff --git a/lib/fuse.c b/lib/fuse.c
index fc2358b..50ba52e 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -419,6 +419,58 @@ static void do_getattr(struct fuse *f, struct fuse_in_header *in)
send_reply(f, in, res, &arg, sizeof(arg));
}
+int do_chmod(struct fuse *f, struct fuse_cred *cred, const char *path,
+ struct fuse_attr *attr)
+{
+ int res;
+
+ res = -ENOSYS;
+ if(f->op.chmod)
+ res = f->op.chmod(cred, path, attr->mode);
+
+ return res;
+}
+
+int do_chown(struct fuse *f, struct fuse_cred *cred, const char *path,
+ struct fuse_attr *attr, int valid)
+{
+ int res;
+ uid_t uid = (valid & FATTR_UID) ? attr->uid : (uid_t) -1;
+ gid_t gid = (valid & FATTR_GID) ? attr->gid : (gid_t) -1;
+
+ res = -ENOSYS;
+ if(f->op.chown)
+ res = f->op.chown(cred, path, uid, gid);
+
+ return res;
+}
+
+int do_truncate(struct fuse *f, struct fuse_cred *cred, const char *path,
+ struct fuse_attr *attr)
+{
+ int res;
+
+ res = -ENOSYS;
+ if(f->op.truncate)
+ res = f->op.truncate(cred, path, attr->size);
+
+ return res;
+}
+
+int do_utime(struct fuse *f, struct fuse_cred *cred, const char *path,
+ struct fuse_attr *attr)
+{
+ int res;
+ struct utimbuf buf;
+ buf.actime = attr->atime;
+ buf.modtime = attr->mtime;
+ res = -ENOSYS;
+ if(f->op.utime)
+ res = f->op.utime(cred, path, &buf);
+
+ return res;
+}
+
static void do_setattr(struct fuse *f, struct fuse_in_header *in,
struct fuse_setattr_in *arg)
{
@@ -433,39 +485,24 @@ static void do_setattr(struct fuse *f, struct fuse_in_header *in,
res = -ENOENT;
path = get_path(f, in->ino);
if(path != NULL) {
- res = 0;
- if(!res && (valid & FATTR_MODE)) {
- res = -ENOSYS;
- if(f->op.chmod)
- res = f->op.chmod(&cred, path, attr->mode);
- }
- if(!res && (valid & (FATTR_UID | FATTR_GID))) {
- uid_t uid = (valid & FATTR_UID) ? attr->uid : (uid_t) -1;
- gid_t gid = (valid & FATTR_GID) ? attr->gid : (gid_t) -1;
-
- res = -ENOSYS;
- if(f->op.chown)
- res = f->op.chown(&cred, path, uid, gid);
- }
- if(!res && (valid & FATTR_SIZE)) {
- res = -ENOSYS;
- if(f->op.truncate && f->op.getattr) {
- res = f->op.truncate(&cred, path, attr->size);
- if(!res) {
- struct stat buf;
- res = f->op.getattr(&cred, path, &buf);
- outarg.newsize = buf.st_size;
- }
+ res = -ENOSYS;
+ if(f->op.getattr) {
+ res = 0;
+ if(!res && (valid & FATTR_MODE))
+ res = do_chmod(f, &cred, path, attr);
+ if(!res && (valid & (FATTR_UID | FATTR_GID)))
+ res = do_chown(f, &cred, path, attr, valid);
+ if(!res && (valid & FATTR_SIZE))
+ res = do_truncate(f, &cred, path, attr);
+ if(!res && (valid & FATTR_UTIME))
+ res = do_utime(f, &cred, path, attr);
+ if(!res) {
+ struct stat buf;
+ res = f->op.getattr(&cred, path, &buf);
+ if(!res)
+ convert_stat(&buf, &outarg.attr);
}
}
- if(!res && (valid & FATTR_UTIME)) {
- struct utimbuf buf;
- buf.actime = attr->atime;
- buf.modtime = attr->mtime;
- res = -ENOSYS;
- if(f->op.utime)
- res = f->op.utime(&cred, path, &buf);
- }
free(path);
}
send_reply(f, in, res, &outarg, sizeof(outarg));