From 4b9f3de8144fb842ea6951d89312ac9be866c3ee Mon Sep 17 00:00:00 2001 From: Antonio SJ Musumeci Date: Mon, 10 Feb 2020 18:39:15 -0500 Subject: [PATCH] add ctime support --- libfuse/include/fuse_lowlevel.h | 10 -- libfuse/lib/fuse.c | 210 ++++++++++++++++---------------- libfuse/lib/fuse_lowlevel.c | 141 ++++++++++++--------- libfuse/lib/fuse_misc.h | 27 ++-- 4 files changed, 204 insertions(+), 184 deletions(-) diff --git a/libfuse/include/fuse_lowlevel.h b/libfuse/include/fuse_lowlevel.h index bed7afd9..c9e34d1f 100644 --- a/libfuse/include/fuse_lowlevel.h +++ b/libfuse/include/fuse_lowlevel.h @@ -128,16 +128,6 @@ struct fuse_forget_data { uint64_t nlookup; }; -/* 'to_set' flags in setattr */ -#define FUSE_SET_ATTR_MODE (1 << 0) -#define FUSE_SET_ATTR_UID (1 << 1) -#define FUSE_SET_ATTR_GID (1 << 2) -#define FUSE_SET_ATTR_SIZE (1 << 3) -#define FUSE_SET_ATTR_ATIME (1 << 4) -#define FUSE_SET_ATTR_MTIME (1 << 5) -#define FUSE_SET_ATTR_ATIME_NOW (1 << 7) -#define FUSE_SET_ATTR_MTIME_NOW (1 << 8) - /* ----------------------------------------------------------- * * Request methods and replies * * ----------------------------------------------------------- */ diff --git a/libfuse/lib/fuse.c b/libfuse/lib/fuse.c index 39cb42ea..aba3379c 100644 --- a/libfuse/lib/fuse.c +++ b/libfuse/lib/fuse.c @@ -2735,120 +2735,126 @@ fuse_fs_fchmod(struct fuse_fs *fs_, return -ENOSYS; } -static void fuse_lib_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, - int valid, struct fuse_file_info *fi) -{ - struct fuse *f = req_fuse_prepare(req); - struct stat buf; - char *path; - int err; - struct node *node; - struct fuse_file_info ffi = {0}; +static +void +fuse_lib_setattr(fuse_req_t req, + fuse_ino_t ino, + struct stat *attr, + int valid, + struct fuse_file_info *fi) +{ + struct fuse *f = req_fuse_prepare(req); + struct stat buf; + char *path; + int err; + struct node *node; + struct fuse_file_info ffi = {0}; - if(fi == NULL) - { - pthread_mutex_lock(&f->lock); - node = get_node(f,ino); - if(node->is_hidden) - { - fi = &ffi; - fi->fh = node->hidden_fh; - } - pthread_mutex_unlock(&f->lock); - } + if(fi == NULL) + { + pthread_mutex_lock(&f->lock); + node = get_node(f,ino); + if(node->is_hidden) + { + fi = &ffi; + fi->fh = node->hidden_fh; + } + pthread_mutex_unlock(&f->lock); + } - memset(&buf, 0, sizeof(buf)); + memset(&buf,0,sizeof(buf)); - path = NULL; + path = NULL; + err = ((fi == NULL) ? + get_path(f,ino,&path) : + get_path_nullok(f,ino,&path)); + + if(!err) + { + struct fuse_intr_data d; + + fuse_prepare_interrupt(f,req,&d); + + err = 0; + if (!err && (valid & FATTR_MODE)) err = ((fi == NULL) ? - get_path(f,ino,&path) : - get_path_nullok(f,ino,&path)); + fuse_fs_chmod(f->fs,path,attr->st_mode) : + fuse_fs_fchmod(f->fs,fi,attr->st_mode)); - if (!err) { - struct fuse_intr_data d; + if(!err && (valid & (FATTR_UID | FATTR_GID))) + { + uid_t uid = ((valid & FATTR_UID) ? attr->st_uid : (uid_t) -1); + gid_t gid = ((valid & FATTR_GID) ? attr->st_gid : (gid_t) -1); - fuse_prepare_interrupt(f, req, &d); + err = ((fi == NULL) ? + fuse_fs_chown(f->fs,path,uid,gid) : + fuse_fs_fchown(f->fs,fi,uid,gid)); + } + + if(!err && (valid & FATTR_SIZE)) + err = ((fi == NULL) ? + fuse_fs_truncate(f->fs,path,attr->st_size) : + fuse_fs_ftruncate(f->fs,path,attr->st_size,fi)); - err = 0; - if (!err && (valid & FUSE_SET_ATTR_MODE)) - err = ((fi == NULL) ? - fuse_fs_chmod(f->fs, path, attr->st_mode) : - fuse_fs_fchmod(f->fs, fi, attr->st_mode)); - - if (!err && (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID))) - { - uid_t uid = (valid & FUSE_SET_ATTR_UID) ? - attr->st_uid : (uid_t) -1; - gid_t gid = (valid & FUSE_SET_ATTR_GID) ? - attr->st_gid : (gid_t) -1; - - err = ((fi == NULL) ? - fuse_fs_chown(f->fs, path, uid, gid) : - fuse_fs_fchown(f->fs, fi, uid, gid)); - } - - if (!err && (valid & FUSE_SET_ATTR_SIZE)) - { - err = ((fi == NULL) ? - fuse_fs_truncate(f->fs, path, attr->st_size) : - fuse_fs_ftruncate(f->fs, path, attr->st_size, fi)); - } #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 = ((fi == NULL) ? - fuse_fs_utimens(f->fs, path, tv) : - fuse_fs_futimens(f->fs, fi, tv)); - } else + if(!err && f->utime_omit_ok && (valid & (FATTR_ATIME | FATTR_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 & FATTR_ATIME_NOW) + tv[0].tv_nsec = UTIME_NOW; + else if(valid & FATTR_ATIME) + tv[0] = attr->st_atim; + + if(valid & FATTR_MTIME_NOW) + tv[1].tv_nsec = UTIME_NOW; + else if(valid & FATTR_MTIME) + tv[1] = attr->st_mtim; + + err = ((fi == NULL) ? + fuse_fs_utimens(f->fs,path,tv) : + fuse_fs_futimens(f->fs,fi,tv)); + } + else #endif - if (!err && - (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) == - (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) { - struct timespec tv[2]; - tv[0].tv_sec = attr->st_atime; - tv[0].tv_nsec = ST_ATIM_NSEC(attr); - tv[1].tv_sec = attr->st_mtime; - tv[1].tv_nsec = ST_MTIM_NSEC(attr); - err = ((fi == NULL) ? - fuse_fs_utimens(f->fs, path, tv) : - fuse_fs_futimens(f->fs, fi, tv)); - } + if(!err && ((valid & (FATTR_ATIME|FATTR_MTIME)) == (FATTR_ATIME|FATTR_MTIME))) + { + struct timespec tv[2]; + tv[0].tv_sec = attr->st_atime; + tv[0].tv_nsec = ST_ATIM_NSEC(attr); + tv[1].tv_sec = attr->st_mtime; + tv[1].tv_nsec = ST_MTIM_NSEC(attr); + err = ((fi == NULL) ? + fuse_fs_utimens(f->fs,path,tv) : + fuse_fs_futimens(f->fs,fi,tv)); + } - if (!err) - err = ((fi == NULL) ? - fuse_fs_getattr(f->fs, path, &buf) : - fuse_fs_fgetattr(f->fs, path, &buf, fi)); + if(!err) + err = ((fi == NULL) ? + fuse_fs_getattr(f->fs,path,&buf) : + fuse_fs_fgetattr(f->fs,path,&buf,fi)); - fuse_finish_interrupt(f, req, &d); - free_path(f, ino, path); - } + fuse_finish_interrupt(f,req,&d); + free_path(f,ino,path); + } - if (!err) { - pthread_mutex_lock(&f->lock); - update_stat(get_node(f, ino), &buf); - pthread_mutex_unlock(&f->lock); - set_stat(f, ino, &buf); - fuse_reply_attr(req, &buf, f->conf.attr_timeout); - } else { - reply_err(req, err); - } + if(!err) + { + pthread_mutex_lock(&f->lock); + update_stat(get_node(f,ino),&buf); + pthread_mutex_unlock(&f->lock); + set_stat(f,ino,&buf); + fuse_reply_attr(req,&buf,f->conf.attr_timeout); + } + else + { + reply_err(req,err); + } } static void fuse_lib_access(fuse_req_t req, fuse_ino_t ino, int mask) diff --git a/libfuse/lib/fuse_lowlevel.c b/libfuse/lib/fuse_lowlevel.c index 01f35b45..816a6cb8 100644 --- a/libfuse/lib/fuse_lowlevel.c +++ b/libfuse/lib/fuse_lowlevel.c @@ -54,35 +54,43 @@ static __attribute__((constructor)) void fuse_ll_init_pagesize(void) pagesize = getpagesize(); } -static void convert_stat(const struct stat *stbuf, struct fuse_attr *attr) -{ - attr->ino = stbuf->st_ino; - attr->mode = stbuf->st_mode; - attr->nlink = stbuf->st_nlink; - attr->uid = stbuf->st_uid; - attr->gid = stbuf->st_gid; - attr->rdev = stbuf->st_rdev; - attr->size = stbuf->st_size; - attr->blksize = stbuf->st_blksize; - attr->blocks = stbuf->st_blocks; - attr->atime = stbuf->st_atime; - attr->mtime = stbuf->st_mtime; - attr->ctime = stbuf->st_ctime; - attr->atimensec = ST_ATIM_NSEC(stbuf); - attr->mtimensec = ST_MTIM_NSEC(stbuf); - attr->ctimensec = ST_CTIM_NSEC(stbuf); -} - -static void convert_attr(const struct fuse_setattr_in *attr, struct stat *stbuf) -{ - stbuf->st_mode = attr->mode; - stbuf->st_uid = attr->uid; - stbuf->st_gid = attr->gid; - stbuf->st_size = attr->size; - stbuf->st_atime = attr->atime; - stbuf->st_mtime = attr->mtime; - ST_ATIM_NSEC_SET(stbuf, attr->atimensec); - ST_MTIM_NSEC_SET(stbuf, attr->mtimensec); +static +void +convert_stat(const struct stat *stbuf_, + struct fuse_attr *attr_) +{ + attr_->ino = stbuf_->st_ino; + attr_->mode = stbuf_->st_mode; + attr_->nlink = stbuf_->st_nlink; + attr_->uid = stbuf_->st_uid; + attr_->gid = stbuf_->st_gid; + attr_->rdev = stbuf_->st_rdev; + attr_->size = stbuf_->st_size; + attr_->blksize = stbuf_->st_blksize; + attr_->blocks = stbuf_->st_blocks; + attr_->atime = stbuf_->st_atime; + attr_->mtime = stbuf_->st_mtime; + attr_->ctime = stbuf_->st_ctime; + attr_->atimensec = ST_ATIM_NSEC(stbuf_); + attr_->mtimensec = ST_MTIM_NSEC(stbuf_); + attr_->ctimensec = ST_CTIM_NSEC(stbuf_); +} + +static +void +convert_attr(const struct fuse_setattr_in *attr_, + struct stat *stbuf_) +{ + stbuf_->st_mode = attr_->mode; + stbuf_->st_uid = attr_->uid; + stbuf_->st_gid = attr_->gid; + stbuf_->st_size = attr_->size; + stbuf_->st_atime = attr_->atime; + stbuf_->st_mtime = attr_->mtime; + stbuf_->st_ctime = attr_->ctime; + ST_ATIM_NSEC_SET(stbuf_,attr_->atimensec); + ST_MTIM_NSEC_SET(stbuf_,attr_->mtimensec); + ST_CTIM_NSEC_SET(stbuf_,attr_->ctimensec); } static size_t iov_length(const struct iovec *iov, size_t count) @@ -297,9 +305,11 @@ static int send_reply_ok(fuse_req_t req, const void *arg, size_t argsize) return send_reply(req, 0, arg, argsize); } -int fuse_reply_err(fuse_req_t req, int err) +int +fuse_reply_err(fuse_req_t req_, + int err_) { - return send_reply(req, -err, NULL, 0); + return send_reply(req_,-err_,NULL,0); } void fuse_reply_none(fuse_req_t req) @@ -1053,35 +1063,46 @@ static void do_getattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) fuse_reply_err(req, ENOSYS); } -static void do_setattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) -{ - struct fuse_setattr_in *arg = (struct fuse_setattr_in *) inarg; - - if (req->f->op.setattr) { - struct fuse_file_info *fi = NULL; - struct fuse_file_info fi_store; - struct stat stbuf; - memset(&stbuf, 0, sizeof(stbuf)); - convert_attr(arg, &stbuf); - if (arg->valid & FATTR_FH) { - arg->valid &= ~FATTR_FH; - memset(&fi_store, 0, sizeof(fi_store)); - fi = &fi_store; - fi->fh = arg->fh; - } - arg->valid &= - FUSE_SET_ATTR_MODE | - FUSE_SET_ATTR_UID | - FUSE_SET_ATTR_GID | - FUSE_SET_ATTR_SIZE | - FUSE_SET_ATTR_ATIME | - FUSE_SET_ATTR_MTIME | - FUSE_SET_ATTR_ATIME_NOW | - FUSE_SET_ATTR_MTIME_NOW; - - req->f->op.setattr(req, nodeid, &stbuf, arg->valid, fi); - } else - fuse_reply_err(req, ENOSYS); +static +void +do_setattr(fuse_req_t req_, + fuse_ino_t nodeid_, + const void *inarg_) +{ + struct stat stbuf; + struct fuse_file_info *fi; + struct fuse_file_info fi_store; + struct fuse_setattr_in *arg; + + if(req_->f->op.setattr == NULL) + return (void)fuse_reply_err(req_,ENOSYS); + + fi = NULL; + arg = (struct fuse_setattr_in*)inarg_; + + memset(&stbuf,0,sizeof(stbuf)); + convert_attr(arg,&stbuf); + + if(arg->valid & FATTR_FH) + { + arg->valid &= ~FATTR_FH; + memset(&fi_store,0,sizeof(fi_store)); + fi = &fi_store; + fi->fh = arg->fh; + } + + arg->valid &= + (FATTR_MODE | + FATTR_UID | + FATTR_GID | + FATTR_SIZE | + FATTR_ATIME | + FATTR_MTIME | + FATTR_CTIME | + FATTR_ATIME_NOW | + FATTR_MTIME_NOW); + + req_->f->op.setattr(req_,nodeid_,&stbuf,arg->valid,fi); } static void do_access(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) diff --git a/libfuse/lib/fuse_misc.h b/libfuse/lib/fuse_misc.h index eedf0e0f..5fa14675 100644 --- a/libfuse/lib/fuse_misc.h +++ b/libfuse/lib/fuse_misc.h @@ -36,22 +36,25 @@ static inline void fuse_mutex_init(pthread_mutex_t *mut) #ifdef HAVE_STRUCT_STAT_ST_ATIM /* Linux */ -#define ST_ATIM_NSEC(stbuf) ((stbuf)->st_atim.tv_nsec) -#define ST_CTIM_NSEC(stbuf) ((stbuf)->st_ctim.tv_nsec) -#define ST_MTIM_NSEC(stbuf) ((stbuf)->st_mtim.tv_nsec) -#define ST_ATIM_NSEC_SET(stbuf, val) (stbuf)->st_atim.tv_nsec = (val) -#define ST_MTIM_NSEC_SET(stbuf, val) (stbuf)->st_mtim.tv_nsec = (val) +#define ST_ATIM_NSEC(stbuf) ((stbuf)->st_atim.tv_nsec) +#define ST_CTIM_NSEC(stbuf) ((stbuf)->st_ctim.tv_nsec) +#define ST_MTIM_NSEC(stbuf) ((stbuf)->st_mtim.tv_nsec) +#define ST_ATIM_NSEC_SET(stbuf,val) ((stbuf)->st_atim.tv_nsec = (val)) +#define ST_CTIM_NSEC_SET(stbuf,val) ((stbuf)->st_ctim.tv_nsec = (val)) +#define ST_MTIM_NSEC_SET(stbuf,val) ((stbuf)->st_mtim.tv_nsec = (val)) #elif defined(HAVE_STRUCT_STAT_ST_ATIMESPEC) /* FreeBSD */ -#define ST_ATIM_NSEC(stbuf) ((stbuf)->st_atimespec.tv_nsec) -#define ST_CTIM_NSEC(stbuf) ((stbuf)->st_ctimespec.tv_nsec) -#define ST_MTIM_NSEC(stbuf) ((stbuf)->st_mtimespec.tv_nsec) -#define ST_ATIM_NSEC_SET(stbuf, val) (stbuf)->st_atimespec.tv_nsec = (val) -#define ST_MTIM_NSEC_SET(stbuf, val) (stbuf)->st_mtimespec.tv_nsec = (val) +#define ST_ATIM_NSEC(stbuf) ((stbuf)->st_atimespec.tv_nsec) +#define ST_CTIM_NSEC(stbuf) ((stbuf)->st_ctimespec.tv_nsec) +#define ST_MTIM_NSEC(stbuf) ((stbuf)->st_mtimespec.tv_nsec) +#define ST_ATIM_NSEC_SET(stbuf,val) ((stbuf)->st_atimespec.tv_nsec = (val)) +#define ST_CTIM_NSEC_SET(stbuf,val) ((stbuf)->st_ctimespec.tv_nsec = (val)) +#define ST_MTIM_NSEC_SET(stbuf,val) ((stbuf)->st_mtimespec.tv_nsec = (val)) #else #define ST_ATIM_NSEC(stbuf) 0 #define ST_CTIM_NSEC(stbuf) 0 #define ST_MTIM_NSEC(stbuf) 0 -#define ST_ATIM_NSEC_SET(stbuf, val) do { } while (0) -#define ST_MTIM_NSEC_SET(stbuf, val) do { } while (0) +#define ST_ATIM_NSEC_SET(stbuf,val) do { } while (0) +#define ST_CTIM_NSEC_SET(stbuf,val) do { } while (0) +#define ST_MTIM_NSEC_SET(stbuf,val) do { } while (0) #endif