From: Miklos Szeredi Date: Thu, 25 Aug 2005 15:19:06 +0000 (+0000) Subject: fix X-Git-Tag: fuse_2_4_0_pre2~12 X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=ecce1bf2ff73eb37048a784df0fa97ad041c6bdd;p=qemu-gpiodev%2Flibfuse.git fix --- diff --git a/ChangeLog b/ChangeLog index faf3559..c44e8ff 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2005-08-25 Miklos Szeredi + + * lib: add userspace side of ftruncate() method for experimentation + 2005-08-23 Miklos Szeredi * lib: add userspace side of create() method for experimentation diff --git a/example/fusexmp_fh.c b/example/fusexmp_fh.c index a1d2283..17bd77e 100644 --- a/example/fusexmp_fh.c +++ b/example/fusexmp_fh.c @@ -193,6 +193,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; @@ -353,6 +367,7 @@ static struct fuse_operations xmp_oper = { .chmod = xmp_chmod, .chown = xmp_chown, .truncate = xmp_truncate, + .ftruncate = xmp_ftruncate, .utime = xmp_utime, .open = xmp_open, .read = xmp_read, diff --git a/example/hello_ll.c b/example/hello_ll.c index f5a2baf..882f2cd 100644 --- a/example/hello_ll.c +++ b/example/hello_ll.c @@ -40,10 +40,13 @@ static int hello_stat(fuse_ino_t ino, struct stat *stbuf) return 0; } -static void hello_ll_getattr(fuse_req_t req, fuse_ino_t ino) +static void hello_ll_getattr(fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi) { struct stat stbuf; + (void) fi; + memset(&stbuf, 0, sizeof(stbuf)); if (hello_stat(ino, &stbuf) == -1) fuse_reply_err(req, ENOENT); diff --git a/include/fuse.h b/include/fuse.h index 6251158..39982dc 100644 --- a/include/fuse.h +++ b/include/fuse.h @@ -313,6 +313,8 @@ struct fuse_operations { int (*access) (const char *, int); int (*create) (const char *, mode_t, struct fuse_file_info *); + + int (*ftruncate) (const char *, off_t, struct fuse_file_info *); }; /** Extra context that may be needed by some filesystems diff --git a/include/fuse_lowlevel.h b/include/fuse_lowlevel.h index a8e3e3e..a1c475e 100644 --- a/include/fuse_lowlevel.h +++ b/include/fuse_lowlevel.h @@ -78,9 +78,9 @@ struct fuse_lowlevel_ops { void (*lookup) (fuse_req_t req, fuse_ino_t parent, const char *name); void (*forget) (fuse_req_t req, fuse_ino_t ino, unsigned long nlookup); - void (*getattr)(fuse_req_t req, fuse_ino_t ino); + void (*getattr)(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi); void (*setattr)(fuse_req_t req, fuse_ino_t ino, struct stat *attr, - int to_set); + int to_set, struct fuse_file_info *fi); void (*access) (fuse_req_t req, fuse_ino_t ino, int mask); void (*readlink)(fuse_req_t req, fuse_ino_t ino); void (*mknod) (fuse_req_t req, fuse_ino_t parent, const char *name, diff --git a/kernel/fuse_kernel.h b/kernel/fuse_kernel.h index aa6b298..e1d8a0c 100644 --- a/kernel/fuse_kernel.h +++ b/kernel/fuse_kernel.h @@ -107,7 +107,8 @@ enum fuse_opcode { FUSE_SETLK = 32, FUSE_SETLKW = 33, FUSE_ACCESS = 34, - FUSE_CREATE = 35 + FUSE_CREATE = 35, + FUSE_FSETATTR = 36 }; /* Conservative buffer size for the client */ @@ -163,6 +164,11 @@ struct fuse_setattr_in { struct fuse_attr attr; }; +struct fuse_fsetattr_in { + __u64 fh; + struct fuse_setattr_in setattr; +}; + struct fuse_open_in { __u32 flags; __u32 mode; diff --git a/lib/fuse.c b/lib/fuse.c index 237dee1..7f8ed3d 100644 --- a/lib/fuse.c +++ b/lib/fuse.c @@ -612,13 +612,16 @@ static void fuse_forget(fuse_req_t req, fuse_ino_t ino, unsigned long nlookup) fuse_reply_none(req); } -static void fuse_getattr(fuse_req_t req, fuse_ino_t ino) +static void fuse_getattr(fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi) { struct fuse *f = req_fuse_prepare(req); struct stat buf; char *path; int err; + (void) fi; + err = -ENOENT; pthread_rwlock_rdlock(&f->tree_lock); path = get_path(f, ino); @@ -661,12 +664,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; @@ -686,7 +692,7 @@ static int do_utime(struct fuse *f, const char *path, struct stat *attr) } static void fuse_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, - int valid) + int valid, struct fuse_file_info *fi) { struct fuse *f = req_fuse_prepare(req); struct stat buf; @@ -705,7 +711,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) diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c index 893f723..3bbc296 100644 --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -74,6 +74,7 @@ static const char *opname(enum fuse_opcode opcode) case FUSE_SETLKW: return "SETLKW"; case FUSE_ACCESS: return "ACCESS"; case FUSE_CREATE: return "CREATE"; + case FUSE_FSETATTR: return "FSETATTR"; default: return "???"; } } @@ -394,23 +395,33 @@ static void do_forget(fuse_req_t req, fuse_ino_t nodeid, static void do_getattr(fuse_req_t req, fuse_ino_t nodeid) { if (req->f->op.getattr) - req->f->op.getattr(req, nodeid); + req->f->op.getattr(req, nodeid, NULL); else fuse_reply_err(req, ENOSYS); } static void do_setattr(fuse_req_t req, fuse_ino_t nodeid, - struct fuse_setattr_in *arg) + struct fuse_setattr_in *arg, struct fuse_file_info *fi) { if (req->f->op.setattr) { struct stat stbuf; memset(&stbuf, 0, sizeof(stbuf)); convert_attr(&arg->attr, &stbuf); - req->f->op.setattr(req, nodeid, &stbuf, arg->valid); + req->f->op.setattr(req, nodeid, &stbuf, arg->valid, fi); } else fuse_reply_err(req, ENOSYS); } +static void do_fsetattr(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_fsetattr_in *arg) +{ + struct fuse_file_info fi; + + memset(&fi, 0, sizeof(fi)); + fi.fh = arg->fh; + do_setattr(req, nodeid, &arg->setattr, &fi); +} + static void do_access(fuse_req_t req, fuse_ino_t nodeid, struct fuse_access_in *arg) { @@ -813,7 +824,11 @@ 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); + do_setattr(req, in->nodeid, (struct fuse_setattr_in *) inarg, NULL); + break; + + case FUSE_FSETATTR: + do_fsetattr(req, in->nodeid, (struct fuse_fsetattr_in *) inarg); break; case FUSE_READLINK: diff --git a/test/test.c b/test/test.c index 0f409ad..3fba745 100644 --- a/test/test.c +++ b/test/test.c @@ -364,7 +364,6 @@ static int create_dir(const char *path, const char **dir_files) return 0; } - int test_truncate(int len) { const char *data = testdata; @@ -412,6 +411,73 @@ int test_truncate(int len) return 0; } +int test_ftruncate(int len, int mode) +{ + const char *data = testdata; + int datalen = testdatalen; + int res; + int fd; + + start_test("ftruncate(%u) mode: 0%03o", len, mode); + res = create_file(testfile, data, datalen); + if (res == -1) + return -1; + + fd = open(testfile, O_WRONLY); + if (fd == -1) { + PERROR("open"); + return -1; + } + + res = fchmod(fd, mode); + if (res == -1) { + PERROR("fchmod"); + close(fd); + return -1; + } + res = check_mode(testfile, mode); + if (res == -1) { + close(fd); + return -1; + } + res = ftruncate(fd, len); + if (res == -1) { + PERROR("ftruncate"); + close(fd); + return -1; + } + close(fd); + res = check_size(testfile, len); + if (res == -1) + return -1; + + if (len > 0) { + if (len <= datalen) { + res = check_data(testfile, data, 0, len); + if (res == -1) + return -1; + } else { + res = check_data(testfile, data, 0, datalen); + if (res == -1) + return -1; + res = check_data(testfile, zerodata, datalen, len - datalen); + if (res == -1) + return -1; + } + } + res = unlink(testfile); + if (res == -1) { + PERROR("unlink"); + return -1; + } + res = check_nonexist(testfile2); + if (res == -1) + return -1; + + success(); + return 0; +} + static int test_create(void) { const char *data = testdata; @@ -612,6 +678,49 @@ static int do_test_open(int exist, int flags, const char *flags_str, int mode) return 0; } +#define test_open_acc(flags, mode, err) do_test_open_acc(flags, #flags, mode, err) + +static int do_test_open_acc(int flags, const char *flags_str, int mode, int err) +{ + const char *data = testdata; + int datalen = testdatalen; + int res; + int fd; + + start_test("open_acc(%s) mode: 0%03o error: '%s'", flags_str, mode, + strerror(err)); + unlink(testfile); + res = create_file(testfile, data, datalen); + if (res == -1) + return -1; + + res = chmod(testfile, mode); + if (res == -1) { + PERROR("chmod"); + return -1; + } + + res = check_mode(testfile, mode); + if (res == -1) + return -1; + + fd = open(testfile, flags); + if (fd == -1) { + if (err != errno) { + PERROR("open"); + return -1; + } + } else { + if (err) { + ERROR("open should have failed"); + close(fd); + return -1; + } + close(fd); + } + success(); + return 0; +} static int test_symlink(void) { @@ -849,6 +958,13 @@ int main(int argc, char *argv[]) err += test_truncate(testdatalen / 2); err += test_truncate(testdatalen); err += test_truncate(testdatalen + 100); + err += test_ftruncate(0, 0600); + err += test_ftruncate(testdatalen / 2, 0600); + err += test_ftruncate(testdatalen, 0600); + err += test_ftruncate(testdatalen + 100, 0600); + err += test_ftruncate(0, 0400); + err += test_ftruncate(0, 0200); + err += test_ftruncate(0, 0000); err += test_open(0, O_RDONLY, 0); err += test_open(1, O_RDONLY, 0); err += test_open(1, O_RDWR, 0); @@ -872,6 +988,19 @@ int main(int argc, char *argv[]) err += test_open(1, O_RDWR | O_CREAT | O_EXCL, 0600); err += test_open(0, O_RDWR | O_CREAT | O_EXCL, 0000); err += test_open(1, O_RDWR | O_CREAT | O_EXCL, 0000); + err += test_open_acc(O_RDONLY, 0600, 0); + err += test_open_acc(O_WRONLY, 0600, 0); + err += test_open_acc(O_RDWR, 0600, 0); + err += test_open_acc(O_RDONLY, 0400, 0); + err += test_open_acc(O_RDONLY | O_TRUNC, 0400, EACCES); + err += test_open_acc(O_WRONLY, 0400, EACCES); + err += test_open_acc(O_RDWR, 0400, EACCES); + err += test_open_acc(O_RDONLY, 0200, EACCES); + err += test_open_acc(O_WRONLY, 0200, 0); + err += test_open_acc(O_RDWR, 0200, EACCES); + err += test_open_acc(O_RDONLY, 0000, EACCES); + err += test_open_acc(O_WRONLY, 0000, EACCES); + err += test_open_acc(O_RDWR, 0000, EACCES); unlink(testfile); unlink(testfile2);