Browse Source

add ctime support

pull/706/head
Antonio SJ Musumeci 5 years ago
parent
commit
4b9f3de814
  1. 10
      libfuse/include/fuse_lowlevel.h
  2. 210
      libfuse/lib/fuse.c
  3. 141
      libfuse/lib/fuse_lowlevel.c
  4. 27
      libfuse/lib/fuse_misc.h

10
libfuse/include/fuse_lowlevel.h

@ -128,16 +128,6 @@ struct fuse_forget_data {
uint64_t nlookup; 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 * * Request methods and replies *
* ----------------------------------------------------------- */ * ----------------------------------------------------------- */

210
libfuse/lib/fuse.c

@ -2735,120 +2735,126 @@ fuse_fs_fchmod(struct fuse_fs *fs_,
return -ENOSYS; 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) ? 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 #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 #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) static void fuse_lib_access(fuse_req_t req, fuse_ino_t ino, int mask)

141
libfuse/lib/fuse_lowlevel.c

@ -54,35 +54,43 @@ static __attribute__((constructor)) void fuse_ll_init_pagesize(void)
pagesize = getpagesize(); 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) 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); 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) 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); 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) static void do_access(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)

27
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 #ifdef HAVE_STRUCT_STAT_ST_ATIM
/* Linux */ /* 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) #elif defined(HAVE_STRUCT_STAT_ST_ATIMESPEC)
/* FreeBSD */ /* 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 #else
#define ST_ATIM_NSEC(stbuf) 0 #define ST_ATIM_NSEC(stbuf) 0
#define ST_CTIM_NSEC(stbuf) 0 #define ST_CTIM_NSEC(stbuf) 0
#define ST_MTIM_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 #endif
Loading…
Cancel
Save