From 71bfb92607ce2312c8adb7359a6d883473c51748 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Tue, 10 Apr 2012 16:37:03 +0200 Subject: 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). --- ChangeLog | 4 ++++ example/fusexmp_fh.c | 3 +++ include/fuse.h | 8 +++++++- lib/fuse.c | 27 +++++++++++++++++++++++++++ 4 files changed, 41 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index fab6ee1..c8d9323 100644 --- 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 * Interpret octal escape codes in options. Requested by Jan diff --git a/example/fusexmp_fh.c b/example/fusexmp_fh.c index 57053ca..e9524c6 100644 --- a/example/fusexmp_fh.c +++ b/example/fusexmp_fh.c @@ -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[]) diff --git a/include/fuse.h b/include/fuse.h index b05152d..36b168c 100644 --- a/include/fuse.h +++ b/include/fuse.h @@ -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 diff --git a/lib/fuse.c b/lib/fuse.c index e01f450..4922361 100644 --- a/lib/fuse.c +++ b/lib/fuse.c @@ -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 */ -- cgit v1.2.3