build and install fixes
diff --git a/configure.in b/configure.in
index 7451681..8f3b279 100644
--- a/configure.in
+++ b/configure.in
@@ -18,16 +18,36 @@
 	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 @@
 
 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 @@
 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_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 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 @@
 	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 @@
     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 @@
     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));