mirror of
https://github.com/libfuse/libfuse.git
synced 2024-11-27 06:04:27 +08:00
add ftruncate() method
This commit is contained in:
parent
d9079a75b1
commit
11509ce3fc
11
ChangeLog
11
ChangeLog
@ -1,15 +1,20 @@
|
||||
2005-10-26 Miklos Szeredi <miklos@szeredi.hu>
|
||||
|
||||
* Change kernel ABI version to 7.3
|
||||
|
||||
* Add ACCESS operation. This is called from the access() system
|
||||
call if 'default_permissions' mount option is not given, and is
|
||||
not called on kernels 2.4.*
|
||||
|
||||
* Fix kernel module compile if kernel source and build directories
|
||||
differ. Report and initial patch by John Eastman
|
||||
|
||||
* Add atomic CREATE+OPEN operation. This will only work with
|
||||
2.6.15 (presumably) or later Linux kernels.
|
||||
|
||||
* Add ftruncate() method. This will only work with 2.6.15
|
||||
(presumably) or later Linux kernels.
|
||||
|
||||
* Fix kernel module compile if kernel source and build directories
|
||||
differ. Report and initial patch by John Eastman
|
||||
|
||||
2005-10-18 Miklos Szeredi <miklos@szeredi.hu>
|
||||
|
||||
* lib: optimize buffer reallocation in fill_dir.
|
||||
|
@ -204,6 +204,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;
|
||||
@ -354,6 +368,7 @@ static struct fuse_operations xmp_oper = {
|
||||
.chmod = xmp_chmod,
|
||||
.chown = xmp_chown,
|
||||
.truncate = xmp_truncate,
|
||||
.ftruncate = xmp_ftruncate,
|
||||
.utime = xmp_utime,
|
||||
.create = xmp_create,
|
||||
.open = xmp_open,
|
||||
|
@ -63,9 +63,9 @@ typedef int (*fuse_dirfil_t) (fuse_dirh_t h, const char *name, int type,
|
||||
*
|
||||
* All methods are optional, but some are essential for a useful
|
||||
* filesystem (e.g. getattr). Open, flush, release, fsync, opendir,
|
||||
* releasedir, fsyncdir, access, create, init and destroy are special
|
||||
* purpose methods, without which a full featured filesystem can still
|
||||
* be implemented.
|
||||
* releasedir, fsyncdir, access, create, ftruncate, init and destroy
|
||||
* are special purpose methods, without which a full featured
|
||||
* filesystem can still be implemented.
|
||||
*/
|
||||
struct fuse_operations {
|
||||
/** Get file attributes.
|
||||
@ -324,6 +324,20 @@ struct fuse_operations {
|
||||
* Introduced in version 2.5
|
||||
*/
|
||||
int (*create) (const char *, mode_t, struct fuse_file_info *);
|
||||
|
||||
/**
|
||||
* Change the size of an open file
|
||||
*
|
||||
* This method is called instead of the truncate() method if the
|
||||
* truncation was invoked from an ftruncate() system call.
|
||||
*
|
||||
* If this method is not implemented or under Linux kernel
|
||||
* versions earlier than 2.6.15, the truncate() method will be
|
||||
* called instead.
|
||||
*
|
||||
* Introduced in version 2.5
|
||||
*/
|
||||
int (*ftruncate) (const char *, off_t, struct fuse_file_info *);
|
||||
};
|
||||
|
||||
/** Extra context that may be needed by some filesystems
|
||||
|
@ -198,6 +198,13 @@ struct fuse_lowlevel_ops {
|
||||
* bitmask contain valid values. Other members contain undefined
|
||||
* values.
|
||||
*
|
||||
* If the setattr was invoked from the ftruncate() system call
|
||||
* under Linux kernel versions 2.6.15 or later, the fi->fh will
|
||||
* contain the value set by the open method or will be undefined
|
||||
* if the open method didn't set any value. Otherwise (not
|
||||
* ftruncate call, or kernel version earlier than 2.6.15) the fi
|
||||
* parameter will be NULL.
|
||||
*
|
||||
* Valid replies:
|
||||
* fuse_reply_attr()
|
||||
* fuse_reply_err()
|
||||
@ -206,7 +213,10 @@ struct fuse_lowlevel_ops {
|
||||
* @param ino the inode number
|
||||
* @param attr the attributes
|
||||
* @param to_set bit mask of attributes which should be set
|
||||
* @param fi for future use, currently always NULL
|
||||
* @param fi file information, or NULL
|
||||
*
|
||||
* Changed in version 2.5:
|
||||
* file information filled in for ftruncate
|
||||
*/
|
||||
void (*setattr) (fuse_req_t req, fuse_ino_t ino, struct stat *attr,
|
||||
int to_set, struct fuse_file_info *fi);
|
||||
|
34
kernel/dir.c
34
kernel/dir.c
@ -838,34 +838,36 @@ static int fuse_dir_fsync(struct file *file, struct dentry *de, int datasync)
|
||||
return file ? fuse_fsync_common(file, de, datasync, 1) : 0;
|
||||
}
|
||||
|
||||
static unsigned iattr_to_fattr(struct iattr *iattr, struct fuse_attr *fattr)
|
||||
static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
|
||||
{
|
||||
unsigned ivalid = iattr->ia_valid;
|
||||
unsigned fvalid = 0;
|
||||
|
||||
memset(fattr, 0, sizeof(*fattr));
|
||||
|
||||
if (ivalid & ATTR_MODE)
|
||||
fvalid |= FATTR_MODE, fattr->mode = iattr->ia_mode;
|
||||
arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode;
|
||||
if (ivalid & ATTR_UID)
|
||||
fvalid |= FATTR_UID, fattr->uid = iattr->ia_uid;
|
||||
arg->valid |= FATTR_UID, arg->uid = iattr->ia_uid;
|
||||
if (ivalid & ATTR_GID)
|
||||
fvalid |= FATTR_GID, fattr->gid = iattr->ia_gid;
|
||||
arg->valid |= FATTR_GID, arg->gid = iattr->ia_gid;
|
||||
if (ivalid & ATTR_SIZE)
|
||||
fvalid |= FATTR_SIZE, fattr->size = iattr->ia_size;
|
||||
arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size;
|
||||
/* You can only _set_ these together (they may change by themselves) */
|
||||
if ((ivalid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME)) {
|
||||
fvalid |= FATTR_ATIME | FATTR_MTIME;
|
||||
arg->valid |= FATTR_ATIME | FATTR_MTIME;
|
||||
#ifdef KERNEL_2_6
|
||||
fattr->atime = iattr->ia_atime.tv_sec;
|
||||
fattr->mtime = iattr->ia_mtime.tv_sec;
|
||||
arg->atime = iattr->ia_atime.tv_sec;
|
||||
arg->mtime = iattr->ia_mtime.tv_sec;
|
||||
#else
|
||||
fattr->atime = iattr->ia_atime;
|
||||
fattr->mtime = iattr->ia_mtime;
|
||||
arg->atime = iattr->ia_atime;
|
||||
arg->mtime = iattr->ia_mtime;
|
||||
#endif
|
||||
}
|
||||
|
||||
return fvalid;
|
||||
#ifdef ATTR_FILE
|
||||
if (ivalid & ATTR_FILE) {
|
||||
struct fuse_file *ff = iattr->ia_file->private_data;
|
||||
arg->valid |= FATTR_FH;
|
||||
arg->fh = ff->fh;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static int fuse_setattr(struct dentry *entry, struct iattr *attr)
|
||||
@ -904,7 +906,7 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr)
|
||||
return -EINTR;
|
||||
|
||||
memset(&inarg, 0, sizeof(inarg));
|
||||
inarg.valid = iattr_to_fattr(attr, &inarg.attr);
|
||||
iattr_to_fattr(attr, &inarg);
|
||||
req->in.h.opcode = FUSE_SETATTR;
|
||||
req->in.h.nodeid = get_node_id(inode);
|
||||
req->inode = inode;
|
||||
|
@ -42,7 +42,7 @@
|
||||
#define FUSE_KERNEL_VERSION 7
|
||||
|
||||
/** Minor version number of this interface */
|
||||
#define FUSE_KERNEL_MINOR_VERSION 2
|
||||
#define FUSE_KERNEL_MINOR_VERSION 3
|
||||
|
||||
/** The node ID of the root inode */
|
||||
#define FUSE_ROOT_ID 1
|
||||
@ -89,6 +89,7 @@ struct fuse_kstatfs {
|
||||
#define FATTR_SIZE (1 << 3)
|
||||
#define FATTR_ATIME (1 << 4)
|
||||
#define FATTR_MTIME (1 << 5)
|
||||
#define FATTR_FH (1 << 6)
|
||||
|
||||
/**
|
||||
* Flags returned by the OPEN request
|
||||
@ -182,7 +183,20 @@ struct fuse_link_in {
|
||||
struct fuse_setattr_in {
|
||||
__u32 valid;
|
||||
__u32 padding;
|
||||
struct fuse_attr attr;
|
||||
__u64 fh;
|
||||
__u64 size;
|
||||
__u64 unused1;
|
||||
__u64 atime;
|
||||
__u64 mtime;
|
||||
__u64 unused2;
|
||||
__u32 atimensec;
|
||||
__u32 mtimensec;
|
||||
__u32 unused3;
|
||||
__u32 mode;
|
||||
__u32 unused4;
|
||||
__u32 uid;
|
||||
__u32 gid;
|
||||
__u32 unused5;
|
||||
};
|
||||
|
||||
struct fuse_open_in {
|
||||
|
11
lib/fuse.c
11
lib/fuse.c
@ -674,12 +674,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;
|
||||
@ -706,8 +709,6 @@ static void fuse_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
|
||||
char *path;
|
||||
int err;
|
||||
|
||||
(void) fi;
|
||||
|
||||
err = -ENOENT;
|
||||
pthread_rwlock_rdlock(&f->tree_lock);
|
||||
path = get_path(f, ino);
|
||||
@ -720,7 +721,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)
|
||||
|
@ -95,7 +95,7 @@ static void convert_stat(const struct stat *stbuf, struct fuse_attr *attr)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void convert_attr(const struct fuse_attr *attr, struct stat *stbuf)
|
||||
static void convert_attr(const struct fuse_setattr_in *attr, struct stat *stbuf)
|
||||
{
|
||||
stbuf->st_mode = attr->mode;
|
||||
stbuf->st_uid = attr->uid;
|
||||
@ -103,11 +103,9 @@ static void convert_attr(const struct fuse_attr *attr, struct stat *stbuf)
|
||||
stbuf->st_size = attr->size;
|
||||
stbuf->st_atime = attr->atime;
|
||||
stbuf->st_mtime = attr->mtime;
|
||||
stbuf->st_ctime = attr->ctime;
|
||||
#ifdef HAVE_STRUCT_STAT_ST_ATIM
|
||||
stbuf->st_atim.tv_nsec = attr->atimensec;
|
||||
stbuf->st_mtim.tv_nsec = attr->mtimensec;
|
||||
stbuf->st_ctim.tv_nsec = attr->ctimensec;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -366,12 +364,20 @@ static void do_getattr(fuse_req_t req, fuse_ino_t nodeid)
|
||||
}
|
||||
|
||||
static void do_setattr(fuse_req_t req, fuse_ino_t nodeid,
|
||||
struct fuse_setattr_in *arg, struct fuse_file_info *fi)
|
||||
struct fuse_setattr_in *arg)
|
||||
{
|
||||
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->attr, &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;
|
||||
}
|
||||
req->f->op.setattr(req, nodeid, &stbuf, arg->valid, fi);
|
||||
} else
|
||||
fuse_reply_err(req, ENOSYS);
|
||||
@ -754,7 +760,7 @@ 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, NULL);
|
||||
do_setattr(req, in->nodeid, (struct fuse_setattr_in *) inarg);
|
||||
break;
|
||||
|
||||
case FUSE_READLINK:
|
||||
|
Loading…
Reference in New Issue
Block a user