Add 'flag_utime_omit_ok' flag to fuse_operations
authorMiklos Szeredi <mszeredi@suse.cz>
Tue, 10 Apr 2012 14:37:03 +0000 (16:37 +0200)
committerMiklos Szeredi <mszeredi@suse.cz>
Tue, 10 Apr 2012 14:37:03 +0000 (16:37 +0200)
If the filesystem sets this flag then ->utimens() will receive UTIME_OMIT and
UTIME_NOW values as specified in utimensat(2).

ChangeLog
example/fusexmp_fh.c
include/fuse.h
lib/fuse.c

index fab6ee19cc70c08acec7167e225725e0ac0b6714..c8d93231d0cf3c85bb59a76b175e0f45afc4dbb5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,6 +3,10 @@
        * Check protocol version before sending notifications and return
        -ENOSYS if a particular notification is not supported.
 
+       * Add 'flag_utime_omit_ok' flag to fuse_operations.  If the
+       filesystem sets this flag then ->utimens() will receive UTIME_OMIT
+       and UTIME_NOW values as specified in utimensat(2).
+
 2012-01-27  Miklos Szeredi <miklos@szeredi.hu>
 
        * Interpret octal escape codes in options.  Requested by Jan
index 57053caef81b5757145421af6e2b0d68d730883a..e9524c6ce82ca3ac4a9775d8eb8c2e49fd3d8163 100644 (file)
@@ -539,6 +539,9 @@ static struct fuse_operations xmp_oper = {
        .flock          = xmp_flock,
 
        .flag_nullpath_ok = 1,
+#if HAVE_UTIMENSAT
+       .flag_utime_omit_ok = 1,
+#endif
 };
 
 int main(int argc, char *argv[])
index b05152d7dbc663b88e3a5a3cc7a0533be6a1e6c7..36b168cd9e5ddfb4604e182e4749b19401ab0f7c 100644 (file)
@@ -479,10 +479,16 @@ struct fuse_operations {
         */
        unsigned int flag_nopath:1;
 
+       /**
+        * Flag indicating that the filesystem accepts special
+        * UTIME_NOW and UTIME_OMIT values in its utimens operation.
+        */
+       unsigned int flag_utime_omit_ok:1;
+
        /**
         * Reserved flags, don't set
         */
-       unsigned int flag_reserved:30;
+       unsigned int flag_reserved:29;
 
        /**
         * Ioctl
index e01f4504c5ad7b0acc87dbb22c30b6f0856695de..49223612fb3c59213858eb9a948530ce6b1a278b 100644 (file)
@@ -132,6 +132,7 @@ struct fuse {
        int intr_installed;
        struct fuse_fs *fs;
        int nullpath_ok;
+       int utime_omit_ok;
        int curr_ticket;
        struct lock_queue_element *lockq;
        int pagesize;
@@ -2720,6 +2721,29 @@ static void fuse_lib_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
                                err = fuse_fs_truncate(f->fs, path,
                                                       attr->st_size);
                }
+#ifdef HAVE_UTIMENSAT
+               if (!err && f->utime_omit_ok &&
+                   (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME))) {
+                       struct timespec tv[2];
+
+                       tv[0].tv_sec = 0;
+                       tv[1].tv_sec = 0;
+                       tv[0].tv_nsec = UTIME_OMIT;
+                       tv[1].tv_nsec = UTIME_OMIT;
+
+                       if (valid & FUSE_SET_ATTR_ATIME_NOW)
+                               tv[0].tv_nsec = UTIME_NOW;
+                       else if (valid & FUSE_SET_ATTR_ATIME)
+                               tv[0] = attr->st_atim;
+
+                       if (valid & FUSE_SET_ATTR_MTIME_NOW)
+                               tv[1].tv_nsec = UTIME_NOW;
+                       else if (valid & FUSE_SET_ATTR_MTIME)
+                               tv[1] = attr->st_mtim;
+
+                       err = fuse_fs_utimens(f->fs, path, tv);
+               } else
+#endif
                if (!err &&
                    (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) ==
                    (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) {
@@ -4401,6 +4425,7 @@ static int fuse_push_module(struct fuse *f, const char *module,
        f->fs = newfs;
        f->nullpath_ok = newfs->op.flag_nullpath_ok && f->nullpath_ok;
        f->conf.nopath = newfs->op.flag_nopath && f->conf.nopath;
+       f->utime_omit_ok = newfs->op.flag_utime_omit_ok && f->utime_omit_ok;
        return 0;
 }
 
@@ -4496,6 +4521,7 @@ struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args,
        f->fs = fs;
        f->nullpath_ok = fs->op.flag_nullpath_ok;
        f->conf.nopath = fs->op.flag_nopath;
+       f->utime_omit_ok = fs->op.flag_utime_omit_ok;
 
        /* Oh f**k, this is ugly! */
        if (!fs->op.lock) {
@@ -4560,6 +4586,7 @@ struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args,
        if (f->conf.debug) {
                fprintf(stderr, "nullpath_ok: %i\n", f->nullpath_ok);
                fprintf(stderr, "nopath: %i\n", f->conf.nopath);
+               fprintf(stderr, "utime_omit_ok: %i\n", f->utime_omit_ok);
        }
 
        /* Trace topmost layer by default */