fix
authorMiklos Szeredi <miklos@szeredi.hu>
Thu, 25 Aug 2005 15:19:06 +0000 (15:19 +0000)
committerMiklos Szeredi <miklos@szeredi.hu>
Thu, 25 Aug 2005 15:19:06 +0000 (15:19 +0000)
ChangeLog
example/fusexmp_fh.c
example/hello_ll.c
include/fuse.h
include/fuse_lowlevel.h
kernel/fuse_kernel.h
lib/fuse.c
lib/fuse_lowlevel.c
test/test.c

index faf35590690c6d2d47ca254590afb662c10ee2fb..c44e8ffff8ce76dd03ef6dfe05c7bda9adc8bb91 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2005-08-25  Miklos Szeredi <miklos@szeredi.hu>
+
+       * lib: add userspace side of ftruncate() method for experimentation
+
 2005-08-23  Miklos Szeredi <miklos@szeredi.hu>
 
        * lib: add userspace side of create() method for experimentation
index a1d2283c6662f3ef5e891c9c4a6f7dd479b5dabe..17bd77e61c90ee5e383c9de81d3152810ab5f2e1 100644 (file)
@@ -193,6 +193,20 @@ static int xmp_truncate(const char *path, off_t size)
     return 0;
 }
 
+static int xmp_ftruncate(const char *path, off_t size,
+                         struct fuse_file_info *fi)
+{
+    int res;
+
+    (void) path;
+
+    res = ftruncate(fi->fh, size);
+    if(res == -1)
+        return -errno;
+
+    return 0;
+}
+
 static int xmp_utime(const char *path, struct utimbuf *buf)
 {
     int res;
@@ -353,6 +367,7 @@ static struct fuse_operations xmp_oper = {
     .chmod     = xmp_chmod,
     .chown     = xmp_chown,
     .truncate  = xmp_truncate,
+    .ftruncate = xmp_ftruncate,
     .utime     = xmp_utime,
     .open      = xmp_open,
     .read      = xmp_read,
index f5a2baf1067c5f0ed0e6208e48bd7903ec87dfd1..882f2cd9e37dd3725bb5a8093f7d1d33e7cb10df 100644 (file)
@@ -40,10 +40,13 @@ static int hello_stat(fuse_ino_t ino, struct stat *stbuf)
     return 0;
 }
 
-static void hello_ll_getattr(fuse_req_t req, fuse_ino_t ino)
+static void hello_ll_getattr(fuse_req_t req, fuse_ino_t ino,
+                             struct fuse_file_info *fi)
 {
     struct stat stbuf;
 
+    (void) fi;
+
     memset(&stbuf, 0, sizeof(stbuf));
     if (hello_stat(ino, &stbuf) == -1)
         fuse_reply_err(req, ENOENT);
index 6251158a90f2205c860de5e49c867094d94d5b76..39982dc2d071b5c90fda99ffed6b19ea0f85e301 100644 (file)
@@ -313,6 +313,8 @@ struct fuse_operations {
     int (*access) (const char *, int);
 
     int (*create) (const char *, mode_t, struct fuse_file_info *);
+
+    int (*ftruncate) (const char *, off_t, struct fuse_file_info *);
 };
 
 /** Extra context that may be needed by some filesystems
index a8e3e3e159f3ce25cf6207b229d282e70f54f753..a1c475e6bfa642ec1fe1dcd124763feeaab6ef4c 100644 (file)
@@ -78,9 +78,9 @@ struct fuse_lowlevel_ops {
 
     void (*lookup) (fuse_req_t req, fuse_ino_t parent, const char *name);
     void (*forget) (fuse_req_t req, fuse_ino_t ino, unsigned long nlookup);
-    void (*getattr)(fuse_req_t req, fuse_ino_t ino);
+    void (*getattr)(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi);
     void (*setattr)(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
-                     int to_set);
+                    int to_set, struct fuse_file_info *fi);
     void (*access) (fuse_req_t req, fuse_ino_t ino, int mask);
     void (*readlink)(fuse_req_t req, fuse_ino_t ino);
     void (*mknod)  (fuse_req_t req, fuse_ino_t parent, const char *name,
index aa6b2985743b7b6f4cee93fcde05bbe17d63fe6d..e1d8a0c8638fffbb2adbe2ac441c19a1041a47f1 100644 (file)
@@ -107,7 +107,8 @@ enum fuse_opcode {
        FUSE_SETLK         = 32,
        FUSE_SETLKW        = 33,
        FUSE_ACCESS        = 34,
-       FUSE_CREATE        = 35
+       FUSE_CREATE        = 35,
+       FUSE_FSETATTR      = 36
 };
 
 /* Conservative buffer size for the client */
@@ -163,6 +164,11 @@ struct fuse_setattr_in {
        struct fuse_attr attr;
 };
 
+struct fuse_fsetattr_in {
+       __u64   fh;
+       struct fuse_setattr_in setattr;
+};
+
 struct fuse_open_in {
        __u32   flags;
        __u32   mode;
index 237dee1efd6e8c01f82a50147388c0dee4907830..7f8ed3d57a9b06b1c962c076b10e3e1a4bc048da 100644 (file)
@@ -612,13 +612,16 @@ static void fuse_forget(fuse_req_t req, fuse_ino_t ino, unsigned long nlookup)
     fuse_reply_none(req);
 }
 
-static void fuse_getattr(fuse_req_t req, fuse_ino_t ino)
+static void fuse_getattr(fuse_req_t req, fuse_ino_t ino,
+                         struct fuse_file_info *fi)
 {
     struct fuse *f = req_fuse_prepare(req);
     struct stat buf;
     char *path;
     int err;
 
+    (void) fi;
+
     err = -ENOENT;
     pthread_rwlock_rdlock(&f->tree_lock);
     path = get_path(f, ino);
@@ -661,12 +664,15 @@ static int do_chown(struct fuse *f, const char *path, struct stat *attr,
     return err;
 }
 
-static int do_truncate(struct fuse *f, const char *path, struct stat *attr)
+static int do_truncate(struct fuse *f, const char *path, struct stat *attr,
+                       struct fuse_file_info *fi)
 {
     int err;
 
     err = -ENOSYS;
-    if (f->op.truncate)
+    if (fi && f->op.ftruncate)
+        err = f->op.ftruncate(path, attr->st_size, fi);
+    else if (f->op.truncate)
         err = f->op.truncate(path, attr->st_size);
 
     return err;
@@ -686,7 +692,7 @@ static int do_utime(struct fuse *f, const char *path, struct stat *attr)
 }
 
 static void fuse_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
-                         int valid)
+                         int valid, struct fuse_file_info *fi)
 {
     struct fuse *f = req_fuse_prepare(req);
     struct stat buf;
@@ -705,7 +711,7 @@ static void fuse_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
             if (!err && (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID)))
                 err = do_chown(f, path, attr, valid);
             if (!err && (valid & FUSE_SET_ATTR_SIZE))
-                err = do_truncate(f, path, attr);
+                err = do_truncate(f, path, attr, fi);
             if (!err && (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) == (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME))
                 err = do_utime(f, path, attr);
             if (!err)
index 893f723c3a871e636dbe6bdfa1cee09727b3ee48..3bbc2969e92da0797d8d68ff835160ec1cdcbb9d 100644 (file)
@@ -74,6 +74,7 @@ static const char *opname(enum fuse_opcode opcode)
     case FUSE_SETLKW:          return "SETLKW";
     case FUSE_ACCESS:          return "ACCESS";
     case FUSE_CREATE:          return "CREATE";
+    case FUSE_FSETATTR:                return "FSETATTR";
     default:                   return "???";
     }
 }
@@ -394,23 +395,33 @@ static void do_forget(fuse_req_t req, fuse_ino_t nodeid,
 static void do_getattr(fuse_req_t req, fuse_ino_t nodeid)
 {
     if (req->f->op.getattr)
-        req->f->op.getattr(req, nodeid);
+        req->f->op.getattr(req, nodeid, NULL);
     else
         fuse_reply_err(req, ENOSYS);
 }
 
 static void do_setattr(fuse_req_t req, fuse_ino_t nodeid,
-                       struct fuse_setattr_in *arg)
+                       struct fuse_setattr_in *arg, struct fuse_file_info *fi)
 {
     if (req->f->op.setattr) {
         struct stat stbuf;
         memset(&stbuf, 0, sizeof(stbuf));
         convert_attr(&arg->attr, &stbuf);
-        req->f->op.setattr(req, nodeid, &stbuf, arg->valid);
+        req->f->op.setattr(req, nodeid, &stbuf, arg->valid, fi);
     } else
         fuse_reply_err(req, ENOSYS);
 }
 
+static void do_fsetattr(fuse_req_t req, fuse_ino_t nodeid,
+                       struct fuse_fsetattr_in *arg)
+{
+    struct fuse_file_info fi;
+
+    memset(&fi, 0, sizeof(fi));
+    fi.fh = arg->fh;
+    do_setattr(req, nodeid, &arg->setattr, &fi);
+}
+
 static void do_access(fuse_req_t req, fuse_ino_t nodeid,
                       struct fuse_access_in *arg)
 {
@@ -813,7 +824,11 @@ static void fuse_ll_process(void *data, const char *buf, size_t len,
         break;
 
     case FUSE_SETATTR:
-        do_setattr(req, in->nodeid, (struct fuse_setattr_in *) inarg);
+        do_setattr(req, in->nodeid, (struct fuse_setattr_in *) inarg, NULL);
+        break;
+
+    case FUSE_FSETATTR:
+        do_fsetattr(req, in->nodeid, (struct fuse_fsetattr_in *) inarg);
         break;
 
     case FUSE_READLINK:
index 0f409ad549cf639094008d75cfd09565c95377d8..3fba7454f3c649860ec5a1ae74373889dcbefaff 100644 (file)
@@ -364,7 +364,6 @@ static int create_dir(const char *path, const char **dir_files)
     return 0;
 }
 
-
 int test_truncate(int len)
 {
     const char *data = testdata;
@@ -412,6 +411,73 @@ int test_truncate(int len)
     return 0;
 }
 
+int test_ftruncate(int len, int mode)
+{
+    const char *data = testdata;
+    int datalen = testdatalen;
+    int res;
+    int fd;
+
+    start_test("ftruncate(%u) mode: 0%03o", len, mode);
+    res = create_file(testfile, data, datalen);
+    if (res == -1)
+        return -1;
+
+    fd = open(testfile, O_WRONLY);
+    if (fd == -1) {
+        PERROR("open");
+        return -1;
+    }
+
+    res = fchmod(fd, mode);
+    if (res == -1) {
+        PERROR("fchmod");
+        close(fd);
+        return -1;
+    }
+    res = check_mode(testfile, mode);
+    if (res == -1) {
+        close(fd);
+        return -1;
+    }
+    res = ftruncate(fd, len);
+    if (res == -1) {
+        PERROR("ftruncate");
+        close(fd);
+        return -1;
+    }
+    close(fd);
+    res = check_size(testfile, len);
+    if (res == -1)
+        return -1;
+
+    if (len > 0) {
+        if (len <= datalen) {
+            res = check_data(testfile, data, 0, len);
+            if (res == -1)
+                return -1;
+        } else {
+            res = check_data(testfile, data, 0, datalen);
+            if (res == -1)
+                return -1;
+            res = check_data(testfile, zerodata, datalen, len - datalen);
+            if (res == -1)
+                return -1;
+        }
+    }
+    res = unlink(testfile);
+    if (res == -1) {
+        PERROR("unlink");
+        return -1;
+    }
+    res = check_nonexist(testfile2);
+    if (res == -1)
+        return -1;
+
+    success();
+    return 0;
+}
+
 static int test_create(void)
 {
     const char *data = testdata;
@@ -612,6 +678,49 @@ static int do_test_open(int exist, int flags, const char *flags_str, int mode)
     return 0;
 }
 
+#define test_open_acc(flags, mode, err)  do_test_open_acc(flags, #flags, mode, err)
+
+static int do_test_open_acc(int flags, const char *flags_str, int mode, int err)
+{
+    const char *data = testdata;
+    int datalen = testdatalen;
+    int res;
+    int fd;
+
+    start_test("open_acc(%s) mode: 0%03o error: '%s'", flags_str, mode,
+               strerror(err));
+    unlink(testfile);
+    res = create_file(testfile, data, datalen);
+    if (res == -1)
+        return -1;
+
+    res = chmod(testfile, mode);
+    if (res == -1) {
+        PERROR("chmod");
+        return -1;
+    }
+    
+    res = check_mode(testfile, mode);
+    if (res == -1)
+        return -1;
+
+    fd = open(testfile, flags);
+    if (fd == -1) {
+        if (err != errno) {
+            PERROR("open");
+            return -1;
+        }
+    } else {
+        if (err) {
+            ERROR("open should have failed");
+            close(fd);
+            return -1;
+        }
+        close(fd);
+    }
+    success();
+    return 0;
+}
 
 static int test_symlink(void)
 {
@@ -849,6 +958,13 @@ int main(int argc, char *argv[])
     err += test_truncate(testdatalen / 2);
     err += test_truncate(testdatalen);
     err += test_truncate(testdatalen + 100);
+    err += test_ftruncate(0, 0600);
+    err += test_ftruncate(testdatalen / 2, 0600);
+    err += test_ftruncate(testdatalen, 0600);
+    err += test_ftruncate(testdatalen + 100, 0600);
+    err += test_ftruncate(0, 0400);
+    err += test_ftruncate(0, 0200);
+    err += test_ftruncate(0, 0000);
     err += test_open(0, O_RDONLY, 0);
     err += test_open(1, O_RDONLY, 0);
     err += test_open(1, O_RDWR, 0);
@@ -872,6 +988,19 @@ int main(int argc, char *argv[])
     err += test_open(1, O_RDWR | O_CREAT | O_EXCL, 0600);
     err += test_open(0, O_RDWR | O_CREAT | O_EXCL, 0000);
     err += test_open(1, O_RDWR | O_CREAT | O_EXCL, 0000);
+    err += test_open_acc(O_RDONLY, 0600, 0);
+    err += test_open_acc(O_WRONLY, 0600, 0);
+    err += test_open_acc(O_RDWR,   0600, 0);
+    err += test_open_acc(O_RDONLY, 0400, 0);
+    err += test_open_acc(O_RDONLY | O_TRUNC, 0400, EACCES);
+    err += test_open_acc(O_WRONLY, 0400, EACCES);
+    err += test_open_acc(O_RDWR,   0400, EACCES);
+    err += test_open_acc(O_RDONLY, 0200, EACCES);
+    err += test_open_acc(O_WRONLY, 0200, 0);
+    err += test_open_acc(O_RDWR,   0200, EACCES);
+    err += test_open_acc(O_RDONLY, 0000, EACCES);
+    err += test_open_acc(O_WRONLY, 0000, EACCES);
+    err += test_open_acc(O_RDWR,   0000, EACCES);
     
     unlink(testfile);
     unlink(testfile2);