diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Makefile.am | 14 | ||||
-rw-r--r-- | lib/cuse_lowlevel.c | 10 | ||||
-rw-r--r-- | lib/fuse.c | 495 | ||||
-rw-r--r-- | lib/fuse_i.h | 76 | ||||
-rw-r--r-- | lib/fuse_kern_chan.c | 98 | ||||
-rw-r--r-- | lib/fuse_loop.c | 24 | ||||
-rwxr-xr-x[-rw-r--r--] | lib/fuse_loop_mt.c | 31 | ||||
-rwxr-xr-x[-rw-r--r--] | lib/fuse_lowlevel.c | 469 | ||||
-rw-r--r-- | lib/fuse_misc.h | 12 | ||||
-rw-r--r-- | lib/fuse_mt.c | 101 | ||||
-rw-r--r-- | lib/fuse_opt.c | 15 | ||||
-rw-r--r-- | lib/fuse_session.c | 156 | ||||
-rwxr-xr-x[-rw-r--r--] | lib/fuse_signals.c | 3 | ||||
-rw-r--r-- | lib/fuse_versionscript | 84 | ||||
-rw-r--r-- | lib/helper.c | 210 | ||||
-rw-r--r-- | lib/modules/iconv.c | 7 | ||||
-rw-r--r-- | lib/modules/subdir.c | 7 | ||||
-rw-r--r-- | lib/mount.c | 36 | ||||
-rw-r--r-- | lib/mount_bsd.c | 7 | ||||
-rw-r--r-- | lib/mount_util.c | 1 | ||||
-rw-r--r-- | lib/ulockmgr.c | 444 |
21 files changed, 433 insertions, 1867 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am index 87c0522..2ad0f15 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,9 +1,9 @@ ## Process this file with automake to produce Makefile.in AM_CPPFLAGS = -I$(top_srcdir)/include -DFUSERMOUNT_DIR=\"$(bindir)\" \ - -D_FILE_OFFSET_BITS=64 -D_REENTRANT -DFUSE_USE_VERSION=26 + -D_REENTRANT -DFUSE_USE_VERSION=30 -lib_LTLIBRARIES = libfuse.la libulockmgr.la +lib_LTLIBRARIES = libfuse3.la if BSD mount_source = mount_bsd.c @@ -17,10 +17,9 @@ else iconv_source = endif -libfuse_la_SOURCES = \ +libfuse3_la_SOURCES = \ fuse.c \ fuse_i.h \ - fuse_kern_chan.c \ fuse_loop.c \ fuse_loop_mt.c \ fuse_lowlevel.c \ @@ -36,14 +35,11 @@ libfuse_la_SOURCES = \ $(iconv_source) \ $(mount_source) -libfuse_la_LDFLAGS = -pthread @libfuse_libs@ -version-number 2:9:3 \ +libfuse3_la_LDFLAGS = -pthread @libfuse_libs@ -version-number 0:0:0 \ -Wl,--version-script,$(srcdir)/fuse_versionscript if NETBSD -libfuse_la_LIBADD = -lperfuse -lpuffs +libfuse3_la_LIBADD = -lperfuse -lpuffs endif -libulockmgr_la_SOURCES = ulockmgr.c -libulockmgr_la_LDFLAGS = -pthread -version-number 1:0:1 - EXTRA_DIST = fuse_versionscript diff --git a/lib/cuse_lowlevel.c b/lib/cuse_lowlevel.c index 402cf4b..fbaa873 100644 --- a/lib/cuse_lowlevel.c +++ b/lib/cuse_lowlevel.c @@ -7,11 +7,11 @@ See the file COPYING.LIB. */ +#include "config.h" #include "cuse_lowlevel.h" #include "fuse_kernel.h" #include "fuse_i.h" #include "fuse_opt.h" -#include "fuse_misc.h" #include <stdio.h> #include <string.h> @@ -170,12 +170,12 @@ struct fuse_session *cuse_lowlevel_new(struct fuse_args *args, lop.ioctl = clop->ioctl ? cuse_fll_ioctl : NULL; lop.poll = clop->poll ? cuse_fll_poll : NULL; - se = fuse_lowlevel_new_common(args, &lop, sizeof(lop), userdata); + se = fuse_lowlevel_new(args, &lop, sizeof(lop), userdata); if (!se) { free(cd); return NULL; } - ll = se->data; + ll = se->f; ll->cuse_data = cd; return se; @@ -200,7 +200,7 @@ void cuse_lowlevel_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) struct cuse_init_out outarg; struct fuse_ll *f = req->f; struct cuse_data *cd = f->cuse_data; - size_t bufsize = fuse_chan_bufsize(req->ch); + size_t bufsize = f->bufsize; struct cuse_lowlevel_ops *clop = req_clop(req); (void) nodeid; @@ -313,7 +313,7 @@ struct fuse_session *cuse_lowlevel_setup(int argc, char *argv[], goto err_se; } - ch = fuse_kern_chan_new(fd); + ch = fuse_chan_new(fd); if (!ch) { close(fd); goto err_se; @@ -15,8 +15,6 @@ #include "fuse_lowlevel.h" #include "fuse_opt.h" #include "fuse_misc.h" -#include "fuse_common_compat.h" -#include "fuse_compat.h" #include "fuse_kernel.h" #include <stdio.h> @@ -83,7 +81,6 @@ struct fuse_fs { struct fuse_operations op; struct fuse_module *m; void *user_data; - int compat; int debug; }; @@ -146,8 +143,6 @@ struct fuse { struct fuse_config conf; int intr_installed; struct fuse_fs *fs; - int nullpath_ok; - int utime_omit_ok; struct lock_queue_element *lockq; int pagesize; struct list_head partial_slabs; @@ -208,12 +203,6 @@ struct fuse_dh { fuse_ino_t nodeid; }; -/* old dir handle */ -struct fuse_dirhandle { - fuse_fill_dir_t filler; - void *buf; -}; - struct fuse_context_i { struct fuse_context ctx; fuse_req_t req; @@ -1104,10 +1093,13 @@ static void debug_path(struct fuse *f, const char *msg, fuse_ino_t nodeid, if (wr) wnode = lookup_node(f, nodeid, name); - if (wnode) - fprintf(stderr, "%s %li (w)\n", msg, wnode->nodeid); - else - fprintf(stderr, "%s %li\n", msg, nodeid); + if (wnode) { + fprintf(stderr, "%s %llu (w)\n", + msg, (unsigned long long) wnode->nodeid); + } else { + fprintf(stderr, "%s %llu\n", + msg, (unsigned long long) nodeid); + } } } @@ -1182,7 +1174,7 @@ static int get_path_nullok(struct fuse *f, fuse_ino_t nodeid, char **path) *path = NULL; } else { err = get_path_common(f, nodeid, NULL, path, NULL); - if (err == -ENOENT && f->nullpath_ok) + if (err == -ENOENT) err = 0; } @@ -1464,129 +1456,6 @@ static inline void fuse_prepare_interrupt(struct fuse *f, fuse_req_t req, fuse_do_prepare_interrupt(req, d); } -#if !defined(__FreeBSD__) && !defined(__NetBSD__) - -static int fuse_compat_open(struct fuse_fs *fs, const char *path, - struct fuse_file_info *fi) -{ - int err; - if (!fs->compat || fs->compat >= 25) - err = fs->op.open(path, fi); - else if (fs->compat == 22) { - struct fuse_file_info_compat tmp; - memcpy(&tmp, fi, sizeof(tmp)); - err = ((struct fuse_operations_compat22 *) &fs->op)->open(path, - &tmp); - memcpy(fi, &tmp, sizeof(tmp)); - fi->fh = tmp.fh; - } else - err = ((struct fuse_operations_compat2 *) &fs->op) - ->open(path, fi->flags); - return err; -} - -static int fuse_compat_release(struct fuse_fs *fs, const char *path, - struct fuse_file_info *fi) -{ - if (!fs->compat || fs->compat >= 22) - return fs->op.release(path, fi); - else - return ((struct fuse_operations_compat2 *) &fs->op) - ->release(path, fi->flags); -} - -static int fuse_compat_opendir(struct fuse_fs *fs, const char *path, - struct fuse_file_info *fi) -{ - if (!fs->compat || fs->compat >= 25) - return fs->op.opendir(path, fi); - else { - int err; - struct fuse_file_info_compat tmp; - memcpy(&tmp, fi, sizeof(tmp)); - err = ((struct fuse_operations_compat22 *) &fs->op) - ->opendir(path, &tmp); - memcpy(fi, &tmp, sizeof(tmp)); - fi->fh = tmp.fh; - return err; - } -} - -static void convert_statfs_compat(struct fuse_statfs_compat1 *compatbuf, - struct statvfs *stbuf) -{ - stbuf->f_bsize = compatbuf->block_size; - stbuf->f_blocks = compatbuf->blocks; - stbuf->f_bfree = compatbuf->blocks_free; - stbuf->f_bavail = compatbuf->blocks_free; - stbuf->f_files = compatbuf->files; - stbuf->f_ffree = compatbuf->files_free; - stbuf->f_namemax = compatbuf->namelen; -} - -static void convert_statfs_old(struct statfs *oldbuf, struct statvfs *stbuf) -{ - stbuf->f_bsize = oldbuf->f_bsize; - stbuf->f_blocks = oldbuf->f_blocks; - stbuf->f_bfree = oldbuf->f_bfree; - stbuf->f_bavail = oldbuf->f_bavail; - stbuf->f_files = oldbuf->f_files; - stbuf->f_ffree = oldbuf->f_ffree; - stbuf->f_namemax = oldbuf->f_namelen; -} - -static int fuse_compat_statfs(struct fuse_fs *fs, const char *path, - struct statvfs *buf) -{ - int err; - - if (!fs->compat || fs->compat >= 25) { - err = fs->op.statfs(fs->compat == 25 ? "/" : path, buf); - } else if (fs->compat > 11) { - struct statfs oldbuf; - err = ((struct fuse_operations_compat22 *) &fs->op) - ->statfs("/", &oldbuf); - if (!err) - convert_statfs_old(&oldbuf, buf); - } else { - struct fuse_statfs_compat1 compatbuf; - memset(&compatbuf, 0, sizeof(struct fuse_statfs_compat1)); - err = ((struct fuse_operations_compat1 *) &fs->op) - ->statfs(&compatbuf); - if (!err) - convert_statfs_compat(&compatbuf, buf); - } - return err; -} - -#else /* __FreeBSD__ || __NetBSD__ */ - -static inline int fuse_compat_open(struct fuse_fs *fs, char *path, - struct fuse_file_info *fi) -{ - return fs->op.open(path, fi); -} - -static inline int fuse_compat_release(struct fuse_fs *fs, const char *path, - struct fuse_file_info *fi) -{ - return fs->op.release(path, fi); -} - -static inline int fuse_compat_opendir(struct fuse_fs *fs, const char *path, - struct fuse_file_info *fi) -{ - return fs->op.opendir(path, fi); -} - -static inline int fuse_compat_statfs(struct fuse_fs *fs, const char *path, - struct statvfs *buf) -{ - return fs->op.statfs(fs->compat == 25 ? "/" : path, buf); -} - -#endif /* __FreeBSD__ || __NetBSD__ */ - int fuse_fs_getattr(struct fuse_fs *fs, const char *path, struct stat *buf) { fuse_get_context()->private_data = fs->user_data; @@ -1696,7 +1565,7 @@ int fuse_fs_release(struct fuse_fs *fs, const char *path, fi->flush ? "+flush" : "", (unsigned long long) fi->fh, fi->flags); - return fuse_compat_release(fs, path, fi); + return fs->op.release(path, fi); } else { return 0; } @@ -1713,10 +1582,10 @@ int fuse_fs_opendir(struct fuse_fs *fs, const char *path, fprintf(stderr, "opendir flags: 0x%x %s\n", fi->flags, path); - err = fuse_compat_opendir(fs, path, fi); + err = fs->op.opendir(path, fi); if (fs->debug && !err) - fprintf(stderr, " opendir[%lli] flags: 0x%x %s\n", + fprintf(stderr, " opendir[%llu] flags: 0x%x %s\n", (unsigned long long) fi->fh, fi->flags, path); return err; @@ -1736,10 +1605,10 @@ int fuse_fs_open(struct fuse_fs *fs, const char *path, fprintf(stderr, "open flags: 0x%x %s\n", fi->flags, path); - err = fuse_compat_open(fs, path, fi); + err = fs->op.open(path, fi); if (fs->debug && !err) - fprintf(stderr, " open[%lli] flags: 0x%x %s\n", + fprintf(stderr, " open[%llu] flags: 0x%x %s\n", (unsigned long long) fi->fh, fi->flags, path); return err; @@ -1958,7 +1827,7 @@ int fuse_fs_statfs(struct fuse_fs *fs, const char *path, struct statvfs *buf) if (fs->debug) fprintf(stderr, "statfs %s\n", path); - return fuse_compat_statfs(fs, path, buf); + return fs->op.statfs(path, buf); } else { buf->f_namemax = 255; buf->f_bsize = 512; @@ -1981,20 +1850,6 @@ int fuse_fs_releasedir(struct fuse_fs *fs, const char *path, } } -static int fill_dir_old(struct fuse_dirhandle *dh, const char *name, int type, - ino_t ino) -{ - int res; - struct stat stbuf; - - memset(&stbuf, 0, sizeof(stbuf)); - stbuf.st_mode = type << 12; - stbuf.st_ino = ino; - - res = dh->filler(dh->buf, name, &stbuf, 0); - return res ? -ENOMEM : 0; -} - int fuse_fs_readdir(struct fuse_fs *fs, const char *path, void *buf, fuse_fill_dir_t filler, off_t off, struct fuse_file_info *fi) @@ -2007,16 +1862,6 @@ int fuse_fs_readdir(struct fuse_fs *fs, const char *path, void *buf, (unsigned long long) off); return fs->op.readdir(path, buf, filler, off, fi); - } else if (fs->op.getdir) { - struct fuse_dirhandle dh; - - if (fs->debug) - fprintf(stderr, "getdir[%llu]\n", - (unsigned long long) fi->fh); - - dh.filler = filler; - dh.buf = buf; - return fs->op.getdir(path, &dh, fill_dir_old); } else { return -ENOSYS; } @@ -2154,16 +1999,6 @@ int fuse_fs_utimens(struct fuse_fs *fs, const char *path, tv[1].tv_sec, tv[1].tv_nsec); return fs->op.utimens(path, tv); - } else if(fs->op.utime) { - struct utimbuf buf; - - if (fs->debug) - fprintf(stderr, "utime %s %li %li\n", path, - tv[0].tv_sec, tv[1].tv_sec); - - buf.actime = tv[0].tv_sec; - buf.modtime = tv[1].tv_sec; - return fs->op.utime(path, &buf); } else { return -ENOSYS; } @@ -2324,8 +2159,9 @@ int fuse_fs_poll(struct fuse_fs *fs, const char *path, int res; if (fs->debug) - fprintf(stderr, "poll[%llu] ph: %p\n", - (unsigned long long) fi->fh, ph); + fprintf(stderr, "poll[%llu] ph: %p, events 0x%x\n", + (unsigned long long) fi->fh, ph, + fi->poll_events); res = fs->op.poll(path, fi, ph, reventsp); @@ -2487,8 +2323,8 @@ static int lookup_path(struct fuse *f, fuse_ino_t nodeid, } set_stat(f, e->ino, &e->attr); if (f->conf.debug) - fprintf(stderr, " NODEID: %lu\n", - (unsigned long) e->ino); + fprintf(stderr, " NODEID: %llu\n", + (unsigned long long) e->ino); } } return res; @@ -2496,9 +2332,12 @@ static int lookup_path(struct fuse *f, fuse_ino_t nodeid, static struct fuse_context_i *fuse_get_context_internal(void) { - struct fuse_context_i *c; + return (struct fuse_context_i *) pthread_getspecific(fuse_context_key); +} - c = (struct fuse_context_i *) pthread_getspecific(fuse_context_key); +static struct fuse_context_i *fuse_create_context(struct fuse *f) +{ + struct fuse_context_i *c = fuse_get_context_internal(); if (c == NULL) { c = (struct fuse_context_i *) calloc(1, sizeof(struct fuse_context_i)); @@ -2511,7 +2350,11 @@ static struct fuse_context_i *fuse_get_context_internal(void) abort(); } pthread_setspecific(fuse_context_key, c); + } else { + memset(c, 0, sizeof(*c)); } + c->ctx.fuse = f; + return c; } @@ -2551,10 +2394,9 @@ static void fuse_delete_context_key(void) static struct fuse *req_fuse_prepare(fuse_req_t req) { - struct fuse_context_i *c = fuse_get_context_internal(); + struct fuse_context_i *c = fuse_create_context(req_fuse(req)); const struct fuse_ctx *ctx = fuse_req_ctx(req); c->req = req; - c->ctx.fuse = req_fuse(req); c->ctx.uid = ctx->uid; c->ctx.gid = ctx->gid; c->ctx.pid = ctx->pid; @@ -2598,10 +2440,8 @@ void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn) static void fuse_lib_init(void *data, struct fuse_conn_info *conn) { struct fuse *f = (struct fuse *) data; - struct fuse_context_i *c = fuse_get_context_internal(); - memset(c, 0, sizeof(*c)); - c->ctx.fuse = f; + fuse_create_context(f); conn->want |= FUSE_CAP_EXPORT_SUPPORT; fuse_fs_init(f->fs, conn); } @@ -2619,10 +2459,8 @@ void fuse_fs_destroy(struct fuse_fs *fs) static void fuse_lib_destroy(void *data) { struct fuse *f = (struct fuse *) data; - struct fuse_context_i *c = fuse_get_context_internal(); - memset(c, 0, sizeof(*c)); - c->ctx.fuse = f; + fuse_create_context(f); fuse_fs_destroy(f->fs); f->fs = NULL; } @@ -2692,8 +2530,7 @@ static void do_forget(struct fuse *f, fuse_ino_t ino, uint64_t nlookup) forget_node(f, ino, nlookup); } -static void fuse_lib_forget(fuse_req_t req, fuse_ino_t ino, - unsigned long nlookup) +static void fuse_lib_forget(fuse_req_t req, fuse_ino_t ino, uint64_t nlookup) { do_forget(req_fuse(req), ino, nlookup); fuse_reply_none(req); @@ -2796,7 +2633,7 @@ static void fuse_lib_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, attr->st_size); } #ifdef HAVE_UTIMENSAT - if (!err && f->utime_omit_ok && + if (!err && (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME))) { struct timespec tv[2]; @@ -3079,14 +2916,8 @@ static void fuse_do_release(struct fuse *f, fuse_ino_t ino, const char *path, { struct node *node; int unlink_hidden = 0; - const char *compatpath; - if (path != NULL || f->nullpath_ok || f->conf.nopath) - compatpath = path; - else - compatpath = "-"; - - fuse_fs_release(f->fs, compatpath, fi); + fuse_fs_release(f->fs, path, fi); pthread_mutex_lock(&f->lock); node = get_node(f, ino); @@ -3312,7 +3143,6 @@ static struct fuse_dh *get_dirhandle(const struct fuse_file_info *llfi, struct fuse_dh *dh = (struct fuse_dh *) (uintptr_t) llfi->fh; memset(fi, 0, sizeof(struct fuse_file_info)); fi->fh = dh->fh; - fi->fh_old = dh->fh; return dh; } @@ -3517,16 +3347,11 @@ static void fuse_lib_releasedir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info fi; struct fuse_dh *dh = get_dirhandle(llfi, &fi); char *path; - const char *compatpath; get_path_nullok(f, ino, &path); - if (path != NULL || f->nullpath_ok || f->conf.nopath) - compatpath = path; - else - compatpath = "-"; fuse_prepare_interrupt(f, req, &d); - fuse_fs_releasedir(f->fs, compatpath, &fi); + fuse_fs_releasedir(f->fs, path, &fi); fuse_finish_interrupt(f, req, &d); free_path(f, ino, path); @@ -4184,90 +4009,29 @@ int fuse_notify_poll(struct fuse_pollhandle *ph) return fuse_lowlevel_notify_poll(ph); } -static void free_cmd(struct fuse_cmd *cmd) -{ - free(cmd->buf); - free(cmd); -} - -void fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd) -{ - fuse_session_process(f->se, cmd->buf, cmd->buflen, cmd->ch); - free_cmd(cmd); -} - -int fuse_exited(struct fuse *f) -{ - return fuse_session_exited(f->se); -} - struct fuse_session *fuse_get_session(struct fuse *f) { return f->se; } -static struct fuse_cmd *fuse_alloc_cmd(size_t bufsize) -{ - struct fuse_cmd *cmd = (struct fuse_cmd *) malloc(sizeof(*cmd)); - if (cmd == NULL) { - fprintf(stderr, "fuse: failed to allocate cmd\n"); - return NULL; - } - cmd->buf = (char *) malloc(bufsize); - if (cmd->buf == NULL) { - fprintf(stderr, "fuse: failed to allocate read buffer\n"); - free(cmd); - return NULL; - } - return cmd; -} - -struct fuse_cmd *fuse_read_cmd(struct fuse *f) -{ - struct fuse_chan *ch = fuse_session_next_chan(f->se, NULL); - size_t bufsize = fuse_chan_bufsize(ch); - struct fuse_cmd *cmd = fuse_alloc_cmd(bufsize); - if (cmd != NULL) { - int res = fuse_chan_recv(&ch, cmd->buf, bufsize); - if (res <= 0) { - free_cmd(cmd); - if (res < 0 && res != -EINTR && res != -EAGAIN) - fuse_exit(f); - return NULL; - } - cmd->buflen = res; - cmd->ch = ch; - } - return cmd; -} - static int fuse_session_loop_remember(struct fuse *f) { struct fuse_session *se = f->se; int res = 0; struct timespec now; time_t next_clean; - struct fuse_chan *ch = fuse_session_next_chan(se, NULL); - size_t bufsize = fuse_chan_bufsize(ch); - char *buf = (char *) malloc(bufsize); + struct fuse_chan *ch = fuse_session_chan(se); struct pollfd fds = { .fd = fuse_chan_fd(ch), .events = POLLIN }; - - if (!buf) { - fprintf(stderr, "fuse: failed to allocate read buffer\n"); - return -1; - } + struct fuse_buf fbuf = { + .mem = NULL, + }; curr_time(&now); next_clean = now.tv_sec; while (!fuse_session_exited(se)) { - struct fuse_chan *tmpch = ch; - struct fuse_buf fbuf = { - .mem = buf, - .size = bufsize, - }; unsigned timeout; curr_time(&now); @@ -4283,14 +4047,14 @@ static int fuse_session_loop_remember(struct fuse *f) else break; } else if (res > 0) { - res = fuse_session_receive_buf(se, &fbuf, &tmpch); + res = fuse_session_receive_buf(se, &fbuf, ch); if (res == -EINTR) continue; if (res <= 0) break; - fuse_session_process_buf(se, &fbuf, tmpch); + fuse_session_process_buf(se, &fbuf, ch); } else { timeout = fuse_clean_cache(f); curr_time(&now); @@ -4298,7 +4062,7 @@ static int fuse_session_loop_remember(struct fuse *f) } } - free(buf); + free(fbuf.mem); fuse_session_reset(se); return res < 0 ? -1 : 0; } @@ -4314,13 +4078,6 @@ int fuse_loop(struct fuse *f) return fuse_session_loop(f->se); } -int fuse_invalidate(struct fuse *f, const char *path) -{ - (void) f; - (void) path; - return -EINVAL; -} - void fuse_exit(struct fuse *f) { fuse_session_exit(f->se); @@ -4328,36 +4085,31 @@ void fuse_exit(struct fuse *f) struct fuse_context *fuse_get_context(void) { - return &fuse_get_context_internal()->ctx; -} + struct fuse_context_i *c = fuse_get_context_internal(); -/* - * The size of fuse_context got extended, so need to be careful about - * incompatibility (i.e. a new binary cannot work with an old - * library). - */ -struct fuse_context *fuse_get_context_compat22(void); -struct fuse_context *fuse_get_context_compat22(void) -{ - return &fuse_get_context_internal()->ctx; + if (c) + return &c->ctx; + else + return NULL; } -FUSE_SYMVER(".symver fuse_get_context_compat22,fuse_get_context@FUSE_2.2"); int fuse_getgroups(int size, gid_t list[]) { - fuse_req_t req = fuse_get_context_internal()->req; - return fuse_req_getgroups(req, size, list); + struct fuse_context_i *c = fuse_get_context_internal(); + if (!c) + return -EINVAL; + + return fuse_req_getgroups(c->req, size, list); } int fuse_interrupted(void) { - return fuse_req_interrupted(fuse_get_context_internal()->req); -} + struct fuse_context_i *c = fuse_get_context_internal(); -void fuse_set_getcontext_func(struct fuse_context *(*func)(void)) -{ - (void) func; - /* no-op */ + if (c) + return fuse_req_interrupted(c->req); + else + return 0; } enum { @@ -4402,7 +4154,7 @@ static const struct fuse_opt fuse_lib_opts[] = { static void fuse_lib_help(void) { - fprintf(stderr, + printf( " -o hard_remove immediate removal (don't hide files)\n" " -o use_ino let filesystem set inode numbers\n" " -o readdir_ino try to fill in d_ino in readdir\n" @@ -4428,7 +4180,7 @@ static void fuse_lib_help(void) static void fuse_lib_help_modules(void) { struct fuse_module *m; - fprintf(stderr, "\nModule options:\n"); + printf("\nModule options:\n"); pthread_mutex_lock(&fuse_context_lock); for (m = fuse_modules; m; m = m->next) { struct fuse_fs *fs = NULL; @@ -4436,7 +4188,7 @@ static void fuse_lib_help_modules(void) struct fuse_args args = FUSE_ARGS_INIT(0, NULL); if (fuse_opt_add_arg(&args, "") != -1 && fuse_opt_add_arg(&args, "-h") != -1) { - fprintf(stderr, "\n[%s]\n", m->name); + printf("\n[%s]\n", m->name); newfs = m->factory(&args, &fs); assert(newfs == NULL); } @@ -4459,12 +4211,6 @@ static int fuse_lib_opt_proc(void *data, const char *arg, int key, return 1; } -int fuse_is_lib_option(const char *opt) -{ - return fuse_lowlevel_is_lib_option(opt) || - fuse_opt_match(fuse_lib_opts, opt); -} - static int fuse_init_intr_signal(int signum, int *installed) { struct sigaction old_sa; @@ -4517,9 +4263,7 @@ static int fuse_push_module(struct fuse *f, const char *module, } newfs->m = m; 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; } @@ -4589,9 +4333,9 @@ void fuse_stop_cleanup_thread(struct fuse *f) } } -struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args, - const struct fuse_operations *op, - size_t op_size, void *user_data, int compat) +struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args, + const struct fuse_operations *op, + size_t op_size, void *user_data) { struct fuse *f; struct node *root; @@ -4611,11 +4355,8 @@ struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args, if (!fs) goto out_free; - fs->compat = compat; 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) { @@ -4663,12 +4404,7 @@ struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args, f->conf.readdir_ino = 1; #endif - if (compat && compat <= 25) { - if (fuse_sync_compat_args(args) == -1) - goto out_free_fs; - } - - f->se = fuse_lowlevel_new_common(args, &llop, sizeof(llop), f); + f->se = fuse_lowlevel_new(args, &llop, sizeof(llop), f); if (f->se == NULL) { if (f->conf.help) fuse_lib_help_modules(); @@ -4678,9 +4414,7 @@ struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args, fuse_session_add_chan(f->se, ch); 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 */ @@ -4729,10 +4463,9 @@ out_free_name_table: out_free_session: fuse_session_destroy(f->se); out_free_fs: - /* Horrible compatibility hack to stop the destructor from being - called on the filesystem without init being called first */ - fs->op.destroy = NULL; - fuse_fs_destroy(f->fs); + if (f->fs->m) + fuse_put_module(f->fs->m); + free(f->fs); free(f->conf.modules); out_free: free(f); @@ -4742,13 +4475,6 @@ out: return NULL; } -struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args, - const struct fuse_operations *op, size_t op_size, - void *user_data) -{ - return fuse_new_common(ch, args, op, op_size, user_data, 0); -} - void fuse_destroy(struct fuse *f) { size_t i; @@ -4757,10 +4483,7 @@ void fuse_destroy(struct fuse *f) fuse_restore_intr_signal(f->conf.intr_signal); if (f->fs) { - struct fuse_context_i *c = fuse_get_context_internal(); - - memset(c, 0, sizeof(*c)); - c->ctx.fuse = f; + fuse_create_context(f); for (i = 0; i < f->id_table.size; i++) { struct node *node; @@ -4799,19 +4522,6 @@ void fuse_destroy(struct fuse *f) fuse_delete_context_key(); } -static struct fuse *fuse_new_common_compat25(int fd, struct fuse_args *args, - const struct fuse_operations *op, - size_t op_size, int compat) -{ - struct fuse *f = NULL; - struct fuse_chan *ch = fuse_kern_chan_new(fd); - - if (ch) - f = fuse_new_common(ch, args, op, op_size, NULL, compat); - - return f; -} - /* called with fuse_context_lock held or during initialization (before main() has been called) */ void fuse_register_module(struct fuse_module *mod) @@ -4823,72 +4533,3 @@ void fuse_register_module(struct fuse_module *mod) mod->next = fuse_modules; fuse_modules = mod; } - -#if !defined(__FreeBSD__) && !defined(__NetBSD__) - -static struct fuse *fuse_new_common_compat(int fd, const char *opts, - const struct fuse_operations *op, - size_t op_size, int compat) -{ - struct fuse *f; - struct fuse_args args = FUSE_ARGS_INIT(0, NULL); - - if (fuse_opt_add_arg(&args, "") == -1) - return NULL; - if (opts && - (fuse_opt_add_arg(&args, "-o") == -1 || - fuse_opt_add_arg(&args, opts) == -1)) { - fuse_opt_free_args(&args); - return NULL; - } - f = fuse_new_common_compat25(fd, &args, op, op_size, compat); - fuse_opt_free_args(&args); - - return f; -} - -struct fuse *fuse_new_compat22(int fd, const char *opts, - const struct fuse_operations_compat22 *op, - size_t op_size) -{ - return fuse_new_common_compat(fd, opts, (struct fuse_operations *) op, - op_size, 22); -} - -struct fuse *fuse_new_compat2(int fd, const char *opts, - const struct fuse_operations_compat2 *op) -{ - return fuse_new_common_compat(fd, opts, (struct fuse_operations *) op, - sizeof(struct fuse_operations_compat2), - 21); -} - -struct fuse *fuse_new_compat1(int fd, int flags, - const struct fuse_operations_compat1 *op) -{ - const char *opts = NULL; - if (flags & FUSE_DEBUG_COMPAT1) - opts = "debug"; - return fuse_new_common_compat(fd, opts, (struct fuse_operations *) op, - sizeof(struct fuse_operations_compat1), - 11); -} - -FUSE_SYMVER(".symver fuse_exited,__fuse_exited@"); -FUSE_SYMVER(".symver fuse_process_cmd,__fuse_process_cmd@"); -FUSE_SYMVER(".symver fuse_read_cmd,__fuse_read_cmd@"); -FUSE_SYMVER(".symver fuse_set_getcontext_func,__fuse_set_getcontext_func@"); -FUSE_SYMVER(".symver fuse_new_compat2,fuse_new@"); -FUSE_SYMVER(".symver fuse_new_compat22,fuse_new@FUSE_2.2"); - -#endif /* __FreeBSD__ || __NetBSD__ */ - -struct fuse *fuse_new_compat25(int fd, struct fuse_args *args, - const struct fuse_operations_compat25 *op, - size_t op_size) -{ - return fuse_new_common_compat25(fd, args, (struct fuse_operations *) op, - op_size, 25); -} - -FUSE_SYMVER(".symver fuse_new_compat25,fuse_new@FUSE_2.5"); diff --git a/lib/fuse_i.h b/lib/fuse_i.h index fa37156..5823743 100644 --- a/lib/fuse_i.h +++ b/lib/fuse_i.h @@ -13,21 +13,20 @@ struct fuse_chan; struct fuse_ll; struct fuse_session { - struct fuse_session_ops op; - - int (*receive_buf)(struct fuse_session *se, struct fuse_buf *buf, - struct fuse_chan **chp); - - void (*process_buf)(void *data, const struct fuse_buf *buf, - struct fuse_chan *ch); - - void *data; + struct fuse_ll *f; volatile int exited; struct fuse_chan *ch; }; +struct fuse_chan { + struct fuse_session *se; + + int fd; +}; + + struct fuse_req { struct fuse_ll *f; uint64_t unique; @@ -71,6 +70,10 @@ struct fuse_ll { int no_splice_write; int no_splice_move; int no_splice_read; + int auto_inval_data; + int no_auto_inval_data; + int no_readdirplus; + int no_readdirplus_auto; struct fuse_lowlevel_ops op; int got_init; struct cuse_data *cuse_data; @@ -85,28 +88,35 @@ struct fuse_ll { int broken_splice_nonblock; uint64_t notify_ctr; struct fuse_notify_req notify_list; + size_t bufsize; }; -struct fuse_cmd { - char *buf; - size_t buflen; - struct fuse_chan *ch; -}; - -struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args, - const struct fuse_operations *op, - size_t op_size, void *user_data, int compat); - -int fuse_sync_compat_args(struct fuse_args *args); - -struct fuse_chan *fuse_kern_chan_new(int fd); - -struct fuse_session *fuse_lowlevel_new_common(struct fuse_args *args, - const struct fuse_lowlevel_ops *op, - size_t op_size, void *userdata); - -void fuse_kern_unmount_compat22(const char *mountpoint); int fuse_chan_clearfd(struct fuse_chan *ch); +void fuse_chan_close(struct fuse_chan *ch); + +/** + * Create a new session + * + * @return new session object, or NULL on failure + */ +struct fuse_session *fuse_session_new(void); + +/** + * Create a new channel + * + * @param op channel operations + * @param fd file descriptor of the channel + * @return the new channel object, or NULL on failure + */ +struct fuse_chan *fuse_chan_new(int fd); + +/** + * Query the session to which this channel is assigned + * + * @param ch the channel + * @return the session, or NULL if the channel is not assigned + */ +struct fuse_session *fuse_chan_session(struct fuse_chan *ch); void fuse_kern_unmount(const char *mountpoint, int fd); int fuse_kern_mount(const char *mountpoint, struct fuse_args *args); @@ -115,16 +125,6 @@ int fuse_send_reply_iov_nofree(fuse_req_t req, int error, struct iovec *iov, int count); void fuse_free_req(fuse_req_t req); - -struct fuse *fuse_setup_common(int argc, char *argv[], - const struct fuse_operations *op, - size_t op_size, - char **mountpoint, - int *multithreaded, - int *fd, - void *user_data, - int compat); - void cuse_lowlevel_init(fuse_req_t req, fuse_ino_t nodeide, const void *inarg); int fuse_start_thread(pthread_t *thread_id, void *(*func)(void *), void *arg); diff --git a/lib/fuse_kern_chan.c b/lib/fuse_kern_chan.c deleted file mode 100644 index 4a9beb8..0000000 --- a/lib/fuse_kern_chan.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - FUSE: Filesystem in Userspace - Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu> - - This program can be distributed under the terms of the GNU LGPLv2. - See the file COPYING.LIB -*/ - -#include "fuse_lowlevel.h" -#include "fuse_kernel.h" -#include "fuse_i.h" - -#include <stdio.h> -#include <errno.h> -#include <unistd.h> -#include <assert.h> - -static int fuse_kern_chan_receive(struct fuse_chan **chp, char *buf, - size_t size) -{ - struct fuse_chan *ch = *chp; - int err; - ssize_t res; - struct fuse_session *se = fuse_chan_session(ch); - assert(se != NULL); - -restart: - res = read(fuse_chan_fd(ch), buf, size); - err = errno; - - if (fuse_session_exited(se)) - return 0; - if (res == -1) { - /* ENOENT means the operation was interrupted, it's safe - to restart */ - if (err == ENOENT) - goto restart; - - if (err == ENODEV) { - fuse_session_exit(se); - return 0; - } - /* Errors occurring during normal operation: EINTR (read - interrupted), EAGAIN (nonblocking I/O), ENODEV (filesystem - umounted) */ - if (err != EINTR && err != EAGAIN) - perror("fuse: reading device"); - return -err; - } - if ((size_t) res < sizeof(struct fuse_in_header)) { - fprintf(stderr, "short read on fuse device\n"); - return -EIO; - } - return res; -} - -static int fuse_kern_chan_send(struct fuse_chan *ch, const struct iovec iov[], - size_t count) -{ - if (iov) { - ssize_t res = writev(fuse_chan_fd(ch), iov, count); - int err = errno; - - if (res == -1) { - struct fuse_session *se = fuse_chan_session(ch); - - assert(se != NULL); - - /* ENOENT means the operation was interrupted */ - if (!fuse_session_exited(se) && err != ENOENT) - perror("fuse: writing device"); - return -err; - } - } - return 0; -} - -static void fuse_kern_chan_destroy(struct fuse_chan *ch) -{ - int fd = fuse_chan_fd(ch); - - if (fd != -1) - close(fd); -} - -#define MIN_BUFSIZE 0x21000 - -struct fuse_chan *fuse_kern_chan_new(int fd) -{ - struct fuse_chan_ops op = { - .receive = fuse_kern_chan_receive, - .send = fuse_kern_chan_send, - .destroy = fuse_kern_chan_destroy, - }; - size_t bufsize = getpagesize() + 0x1000; - bufsize = bufsize < MIN_BUFSIZE ? MIN_BUFSIZE : bufsize; - return fuse_chan_new(&op, fd, bufsize, NULL); -} diff --git a/lib/fuse_loop.c b/lib/fuse_loop.c index b7b4ca4..fb6d8a6 100644 --- a/lib/fuse_loop.c +++ b/lib/fuse_loop.c @@ -6,6 +6,7 @@ See the file COPYING.LIB */ +#include "config.h" #include "fuse_lowlevel.h" #include <stdio.h> @@ -15,32 +16,23 @@ int fuse_session_loop(struct fuse_session *se) { int res = 0; - struct fuse_chan *ch = fuse_session_next_chan(se, NULL); - size_t bufsize = fuse_chan_bufsize(ch); - char *buf = (char *) malloc(bufsize); - if (!buf) { - fprintf(stderr, "fuse: failed to allocate read buffer\n"); - return -1; - } + struct fuse_chan *ch = fuse_session_chan(se); + struct fuse_buf fbuf = { + .mem = NULL, + }; while (!fuse_session_exited(se)) { - struct fuse_chan *tmpch = ch; - struct fuse_buf fbuf = { - .mem = buf, - .size = bufsize, - }; - - res = fuse_session_receive_buf(se, &fbuf, &tmpch); + res = fuse_session_receive_buf(se, &fbuf, ch); if (res == -EINTR) continue; if (res <= 0) break; - fuse_session_process_buf(se, &fbuf, tmpch); + fuse_session_process_buf(se, &fbuf, ch); } - free(buf); + free(fbuf.mem); fuse_session_reset(se); return res < 0 ? -1 : 0; } diff --git a/lib/fuse_loop_mt.c b/lib/fuse_loop_mt.c index 82e3001..8f4dceb 100644..100755 --- a/lib/fuse_loop_mt.c +++ b/lib/fuse_loop_mt.c @@ -6,6 +6,7 @@ See the file COPYING.LIB. */ +#include "config.h" #include "fuse_lowlevel.h" #include "fuse_misc.h" #include "fuse_kernel.h" @@ -28,7 +29,7 @@ struct fuse_worker { struct fuse_worker *next; pthread_t thread_id; size_t bufsize; - char *buf; + struct fuse_buf fbuf; struct fuse_mt *mt; }; @@ -70,15 +71,10 @@ static void *fuse_do_work(void *data) while (!fuse_session_exited(mt->se)) { int isforget = 0; - struct fuse_chan *ch = mt->prevch; - struct fuse_buf fbuf = { - .mem = w->buf, - .size = w->bufsize, - }; int res; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); - res = fuse_session_receive_buf(mt->se, &fbuf, &ch); + res = fuse_session_receive_buf(mt->se, &w->fbuf, mt->prevch); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); if (res == -EINTR) continue; @@ -100,8 +96,8 @@ static void *fuse_do_work(void *data) * This disgusting hack is needed so that zillions of threads * are not created on a burst of FORGET messages */ - if (!(fbuf.flags & FUSE_BUF_IS_FD)) { - struct fuse_in_header *in = fbuf.mem; + if (!(w->fbuf.flags & FUSE_BUF_IS_FD)) { + struct fuse_in_header *in = w->fbuf.mem; if (in->opcode == FUSE_FORGET || in->opcode == FUSE_BATCH_FORGET) @@ -114,7 +110,7 @@ static void *fuse_do_work(void *data) fuse_loop_start_thread(mt); pthread_mutex_unlock(&mt->lock); - fuse_session_process_buf(mt->se, &fbuf, ch); + fuse_session_process_buf(mt->se, &w->fbuf, mt->prevch); pthread_mutex_lock(&mt->lock); if (!isforget) @@ -130,7 +126,7 @@ static void *fuse_do_work(void *data) pthread_mutex_unlock(&mt->lock); pthread_detach(w->thread_id); - free(w->buf); + free(w->fbuf.mem); free(w); return NULL; } @@ -184,18 +180,11 @@ static int fuse_loop_start_thread(struct fuse_mt *mt) return -1; } memset(w, 0, sizeof(struct fuse_worker)); - w->bufsize = fuse_chan_bufsize(mt->prevch); - w->buf = malloc(w->bufsize); + w->fbuf.mem = NULL; w->mt = mt; - if (!w->buf) { - fprintf(stderr, "fuse: failed to allocate read buffer\n"); - free(w); - return -1; - } res = fuse_start_thread(&w->thread_id, fuse_do_work, w); if (res == -1) { - free(w->buf); free(w); return -1; } @@ -212,7 +201,7 @@ static void fuse_join_worker(struct fuse_mt *mt, struct fuse_worker *w) pthread_mutex_lock(&mt->lock); list_del_worker(w); pthread_mutex_unlock(&mt->lock); - free(w->buf); + free(w->fbuf.mem); free(w); } @@ -224,7 +213,7 @@ int fuse_session_loop_mt(struct fuse_session *se) memset(&mt, 0, sizeof(struct fuse_mt)); mt.se = se; - mt.prevch = fuse_session_next_chan(se, NULL); + mt.prevch = fuse_session_chan(se); mt.error = 0; mt.numworker = 0; mt.numavail = 0; diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c index 8853346..2b8df06 100644..100755 --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -13,8 +13,6 @@ #include "fuse_kernel.h" #include "fuse_opt.h" #include "fuse_misc.h" -#include "fuse_common_compat.h" -#include "fuse_lowlevel_compat.h" #include <stdio.h> #include <stdlib.h> @@ -156,6 +154,82 @@ static struct fuse_req *fuse_ll_alloc_req(struct fuse_ll *f) return req; } +static int fuse_chan_recv(struct fuse_session *se, struct fuse_buf *buf, + struct fuse_chan *ch) +{ + struct fuse_ll *f = se->f; + int err; + ssize_t res; + + if (!buf->mem) { + buf->mem = malloc(f->bufsize); + if (!buf->mem) { + fprintf(stderr, + "fuse: failed to allocate read buffer\n"); + return -ENOMEM; + } + } + +restart: + res = read(fuse_chan_fd(ch), buf->mem, f->bufsize); + err = errno; + + if (fuse_session_exited(se)) + return 0; + if (res == -1) { + /* ENOENT means the operation was interrupted, it's safe + to restart */ + if (err == ENOENT) + goto restart; + + if (err == ENODEV) { + fuse_session_exit(se); + return 0; + } + /* Errors occurring during normal operation: EINTR (read + interrupted), EAGAIN (nonblocking I/O), ENODEV (filesystem + umounted) */ + if (err != EINTR && err != EAGAIN) + perror("fuse: reading device"); + return -err; + } + if ((size_t) res < sizeof(struct fuse_in_header)) { + fprintf(stderr, "short read on fuse device\n"); + return -EIO; + } + + buf->size = res; + + return res; +} + +static int fuse_chan_send(struct fuse_chan *ch, const struct iovec iov[], + size_t count) +{ + ssize_t res = writev(fuse_chan_fd(ch), iov, count); + int err = errno; + + if (res == -1) { + struct fuse_session *se = fuse_chan_session(ch); + + assert(se != NULL); + + /* ENOENT means the operation was interrupted */ + if (!fuse_session_exited(se) && err != ENOENT) + perror("fuse: writing device"); + return -err; + } + + return 0; +} + +void fuse_chan_close(struct fuse_chan *ch) +{ + int fd = fuse_chan_fd(ch); + if (fd != -1) + close(fd); +} + static int fuse_send_msg(struct fuse_ll *f, struct fuse_chan *ch, struct iovec *iov, int count) @@ -242,13 +316,13 @@ int fuse_reply_iov(fuse_req_t req, const struct iovec *iov, int count) return res; } -size_t fuse_dirent_size(size_t namelen) +static size_t fuse_dirent_size(size_t namelen) { return FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + namelen); } -char *fuse_add_dirent(char *buf, const char *name, const struct stat *stbuf, - off_t off) +static char *fuse_add_dirent(char *buf, const char *name, + const struct stat *stbuf, off_t off) { unsigned namelen = strlen(name); unsigned entlen = FUSE_NAME_OFFSET + namelen; @@ -304,8 +378,6 @@ int fuse_reply_err(fuse_req_t req, int err) void fuse_reply_none(fuse_req_t req) { - if (req->ch) - fuse_chan_send(req->ch, NULL, 0); fuse_free_req(req); } @@ -342,6 +414,25 @@ static void fill_entry(struct fuse_entry_out *arg, convert_stat(&e->attr, &arg->attr); } +size_t fuse_add_direntry_plus(fuse_req_t req, char *buf, size_t bufsize, + const char *name, + const struct fuse_entry_param *e, off_t off) +{ + struct fuse_entry_out *argp; + size_t entsize; + + (void) req; + entsize = FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET_DIRENTPLUS + + fuse_dirent_size(strlen(name))); + if (entsize <= bufsize && buf){ + argp = (struct fuse_entry_out *)buf; + memset(argp, 0, sizeof(*argp)); + fill_entry(argp, e); + fuse_add_dirent(buf + sizeof(*argp), name, &(e->attr), off); + } + return entsize; +} + static void fill_open(struct fuse_open_out *arg, const struct fuse_file_info *f) { @@ -486,6 +577,31 @@ static void fuse_ll_pipe_free(struct fuse_ll_pipe *llp) } #ifdef HAVE_SPLICE +#if !defined(HAVE_PIPE2) || !defined(O_CLOEXEC) +static int fuse_pipe(int fds[2]) +{ + int rv = pipe(fds); + + if (rv == -1) + return rv; + + if (fcntl(fds[0], F_SETFL, O_NONBLOCK) == -1 || + fcntl(fds[1], F_SETFL, O_NONBLOCK) == -1 || + fcntl(fds[0], F_SETFD, FD_CLOEXEC) == -1 || + fcntl(fds[1], F_SETFD, FD_CLOEXEC) == -1) { + close(fds[0]); + close(fds[1]); + rv = -1; + } + return rv; +} +#else +static int fuse_pipe(int fds[2]) +{ + return pipe2(fds, O_CLOEXEC | O_NONBLOCK); +} +#endif + static struct fuse_ll_pipe *fuse_ll_get_pipe(struct fuse_ll *f) { struct fuse_ll_pipe *llp = pthread_getspecific(f->pipe_key); @@ -496,20 +612,12 @@ static struct fuse_ll_pipe *fuse_ll_get_pipe(struct fuse_ll *f) if (llp == NULL) return NULL; - res = pipe(llp->pipe); + res = fuse_pipe(llp->pipe); if (res == -1) { free(llp); return NULL; } - if (fcntl(llp->pipe[0], F_SETFL, O_NONBLOCK) == -1 || - fcntl(llp->pipe[1], F_SETFL, O_NONBLOCK) == -1) { - close(llp->pipe[0]); - close(llp->pipe[1]); - free(llp); - return NULL; - } - /* *the default size is 16 pages on linux */ @@ -1036,7 +1144,6 @@ static void do_getattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) if (arg->getattr_flags & FUSE_GETATTR_FH) { memset(&fi, 0, sizeof(fi)); fi.fh = arg->fh; - fi.fh_old = fi.fh; fip = &fi; } } @@ -1062,7 +1169,6 @@ static void do_setattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) memset(&fi_store, 0, sizeof(fi_store)); fi = &fi_store; fi->fh = arg->fh; - fi->fh_old = fi->fh; } arg->valid &= FUSE_SET_ATTR_MODE | @@ -1225,7 +1331,6 @@ static void do_read(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) memset(&fi, 0, sizeof(fi)); fi.fh = arg->fh; - fi.fh_old = fi.fh; if (req->f->conn.proto_minor >= 9) { fi.lock_owner = arg->lock_owner; fi.flags = arg->flags; @@ -1243,8 +1348,7 @@ static void do_write(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) memset(&fi, 0, sizeof(fi)); fi.fh = arg->fh; - fi.fh_old = fi.fh; - fi.writepage = arg->write_flags & 1; + fi.writepage = (arg->write_flags & 1) != 0; if (req->f->conn.proto_minor < 9) { param = ((char *) arg) + FUSE_COMPAT_WRITE_IN_SIZE; @@ -1274,7 +1378,6 @@ static void do_write_buf(fuse_req_t req, fuse_ino_t nodeid, const void *inarg, memset(&fi, 0, sizeof(fi)); fi.fh = arg->fh; - fi.fh_old = fi.fh; fi.writepage = arg->write_flags & 1; if (req->f->conn.proto_minor < 9) { @@ -1313,7 +1416,6 @@ static void do_flush(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) memset(&fi, 0, sizeof(fi)); fi.fh = arg->fh; - fi.fh_old = fi.fh; fi.flush = 1; if (req->f->conn.proto_minor >= 7) fi.lock_owner = arg->lock_owner; @@ -1332,7 +1434,6 @@ static void do_release(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) memset(&fi, 0, sizeof(fi)); fi.flags = arg->flags; fi.fh = arg->fh; - fi.fh_old = fi.fh; if (req->f->conn.proto_minor >= 8) { fi.flush = (arg->release_flags & FUSE_RELEASE_FLUSH) ? 1 : 0; fi.lock_owner = arg->lock_owner; @@ -1355,7 +1456,6 @@ static void do_fsync(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) memset(&fi, 0, sizeof(fi)); fi.fh = arg->fh; - fi.fh_old = fi.fh; if (req->f->op.fsync) req->f->op.fsync(req, nodeid, arg->fsync_flags & 1, &fi); @@ -1384,7 +1484,6 @@ static void do_readdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) memset(&fi, 0, sizeof(fi)); fi.fh = arg->fh; - fi.fh_old = fi.fh; if (req->f->op.readdir) req->f->op.readdir(req, nodeid, arg->size, arg->offset, &fi); @@ -1392,6 +1491,20 @@ static void do_readdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) fuse_reply_err(req, ENOSYS); } +static void do_readdirplus(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_read_in *arg = (struct fuse_read_in *) inarg; + struct fuse_file_info fi; + + memset(&fi, 0, sizeof(fi)); + fi.fh = arg->fh; + + if (req->f->op.readdirplus) + req->f->op.readdirplus(req, nodeid, arg->size, arg->offset, &fi); + else + fuse_reply_err(req, ENOSYS); +} + static void do_releasedir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { struct fuse_release_in *arg = (struct fuse_release_in *) inarg; @@ -1400,7 +1513,6 @@ static void do_releasedir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) memset(&fi, 0, sizeof(fi)); fi.flags = arg->flags; fi.fh = arg->fh; - fi.fh_old = fi.fh; if (req->f->op.releasedir) req->f->op.releasedir(req, nodeid, &fi); @@ -1415,7 +1527,6 @@ static void do_fsyncdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) memset(&fi, 0, sizeof(fi)); fi.fh = arg->fh; - fi.fh_old = fi.fh; if (req->f->op.fsyncdir) req->f->op.fsyncdir(req, nodeid, arg->fsync_flags & 1, &fi); @@ -1670,7 +1781,6 @@ static void do_ioctl(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) memset(&fi, 0, sizeof(fi)); fi.fh = arg->fh; - fi.fh_old = fi.fh; if (sizeof(void *) == 4 && req->f->conn.proto_minor >= 16 && !(flags & FUSE_IOCTL_32BIT)) { @@ -1697,7 +1807,7 @@ static void do_poll(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) memset(&fi, 0, sizeof(fi)); fi.fh = arg->fh; - fi.fh_old = fi.fh; + fi.poll_events = arg->events; if (req->f->op.poll) { struct fuse_pollhandle *ph = NULL; @@ -1738,7 +1848,7 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) struct fuse_init_in *arg = (struct fuse_init_in *) inarg; struct fuse_init_out outarg; struct fuse_ll *f = req->f; - size_t bufsize = fuse_chan_bufsize(req->ch); + size_t bufsize = f->bufsize; (void) nodeid; if (f->debug) { @@ -1790,6 +1900,12 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) f->conn.capable |= FUSE_CAP_DONT_MASK; if (arg->flags & FUSE_FLOCK_LOCKS) f->conn.capable |= FUSE_CAP_FLOCK_LOCKS; + if (arg->flags & FUSE_AUTO_INVAL_DATA) + f->conn.capable |= FUSE_CAP_AUTO_INVAL_DATA; + if (arg->flags & FUSE_DO_READDIRPLUS) + f->conn.capable |= FUSE_CAP_READDIRPLUS; + if (arg->flags & FUSE_READDIRPLUS_AUTO) + f->conn.capable |= FUSE_CAP_READDIRPLUS_AUTO; } else { f->conn.async_read = 0; f->conn.max_readahead = 0; @@ -1820,6 +1936,13 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) f->conn.want |= FUSE_CAP_FLOCK_LOCKS; if (f->big_writes) f->conn.want |= FUSE_CAP_BIG_WRITES; + if (f->auto_inval_data) + f->conn.want |= FUSE_CAP_AUTO_INVAL_DATA; + if (f->op.readdirplus && !f->no_readdirplus) { + f->conn.want |= FUSE_CAP_READDIRPLUS; + if (!f->no_readdirplus_auto) + f->conn.want |= FUSE_CAP_READDIRPLUS_AUTO; + } if (bufsize < FUSE_MIN_READ_BUFFER) { fprintf(stderr, "fuse: warning: buffer size too small: %zu\n", @@ -1841,7 +1964,12 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) f->conn.want &= ~FUSE_CAP_SPLICE_WRITE; if (f->no_splice_move) f->conn.want &= ~FUSE_CAP_SPLICE_MOVE; - + if (f->no_auto_inval_data) + f->conn.want &= ~FUSE_CAP_AUTO_INVAL_DATA; + if (f->no_readdirplus) + f->conn.want &= ~FUSE_CAP_READDIRPLUS; + if (f->no_readdirplus_auto) + f->conn.want &= ~FUSE_CAP_READDIRPLUS_AUTO; if (f->conn.async_read || (f->conn.want & FUSE_CAP_ASYNC_READ)) outarg.flags |= FUSE_ASYNC_READ; if (f->conn.want & FUSE_CAP_POSIX_LOCKS) @@ -1856,6 +1984,12 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) outarg.flags |= FUSE_DONT_MASK; if (f->conn.want & FUSE_CAP_FLOCK_LOCKS) outarg.flags |= FUSE_FLOCK_LOCKS; + if (f->conn.want & FUSE_CAP_AUTO_INVAL_DATA) + outarg.flags |= FUSE_AUTO_INVAL_DATA; + if (f->conn.want & FUSE_CAP_READDIRPLUS) + outarg.flags |= FUSE_DO_READDIRPLUS; + if (f->conn.want & FUSE_CAP_READDIRPLUS_AUTO) + outarg.flags |= FUSE_READDIRPLUS_AUTO; outarg.max_readahead = f->conn.max_readahead; outarg.max_write = f->conn.max_write; if (f->conn.proto_minor >= 13) { @@ -1989,7 +2123,7 @@ int fuse_lowlevel_notify_inval_inode(struct fuse_chan *ch, fuse_ino_t ino, if (!ch) return -EINVAL; - f = (struct fuse_ll *)fuse_session_data(fuse_chan_session(ch)); + f = fuse_chan_session(ch)->f; if (!f) return -ENODEV; @@ -2013,7 +2147,7 @@ int fuse_lowlevel_notify_inval_entry(struct fuse_chan *ch, fuse_ino_t parent, if (!ch) return -EINVAL; - f = (struct fuse_ll *)fuse_session_data(fuse_chan_session(ch)); + f = fuse_chan_session(ch)->f; if (!f) return -ENODEV; @@ -2040,7 +2174,7 @@ int fuse_lowlevel_notify_delete(struct fuse_chan *ch, if (!ch) return -EINVAL; - f = (struct fuse_ll *)fuse_session_data(fuse_chan_session(ch)); + f = fuse_chan_session(ch)->f; if (!f) return -ENODEV; @@ -2074,7 +2208,7 @@ int fuse_lowlevel_notify_store(struct fuse_chan *ch, fuse_ino_t ino, if (!ch) return -EINVAL; - f = (struct fuse_ll *)fuse_session_data(fuse_chan_session(ch)); + f = fuse_chan_session(ch)->f; if (!f) return -ENODEV; @@ -2156,7 +2290,7 @@ int fuse_lowlevel_notify_retrieve(struct fuse_chan *ch, fuse_ino_t ino, if (!ch) return -EINVAL; - f = (struct fuse_ll *)fuse_session_data(fuse_chan_session(ch)); + f = fuse_chan_session(ch)->f; if (!f) return -ENODEV; @@ -2203,21 +2337,6 @@ const struct fuse_ctx *fuse_req_ctx(fuse_req_t req) return &req->ctx; } -/* - * The size of fuse_ctx got extended, so need to be careful about - * incompatibility (i.e. a new binary cannot work with an old - * library). - */ -const struct fuse_ctx *fuse_req_ctx_compat24(fuse_req_t req); -const struct fuse_ctx *fuse_req_ctx_compat24(fuse_req_t req) -{ - return fuse_req_ctx(req); -} -#ifndef __NetBSD__ -FUSE_SYMVER(".symver fuse_req_ctx_compat24,fuse_req_ctx@FUSE_2.4"); -#endif - - void fuse_req_interrupt_func(fuse_req_t req, fuse_interrupt_func_t func, void *data) { @@ -2287,6 +2406,7 @@ static struct { [FUSE_DESTROY] = { do_destroy, "DESTROY" }, [FUSE_NOTIFY_REPLY] = { (void *) 1, "NOTIFY_REPLY" }, [FUSE_BATCH_FORGET] = { do_batch_forget, "BATCH_FORGET" }, + [FUSE_READDIRPLUS] = { do_readdirplus, "READDIRPLUS"}, [CUSE_INIT] = { cuse_lowlevel_init, "CUSE_INIT" }, }; @@ -2315,10 +2435,10 @@ static int fuse_ll_copy_from_pipe(struct fuse_bufvec *dst, return 0; } -static void fuse_ll_process_buf(void *data, const struct fuse_buf *buf, - struct fuse_chan *ch) +void fuse_session_process_buf(struct fuse_session *se, + const struct fuse_buf *buf, struct fuse_chan *ch) { - struct fuse_ll *f = (struct fuse_ll *) data; + struct fuse_ll *f = se->f; const size_t write_header_size = sizeof(struct fuse_in_header) + sizeof(struct fuse_write_in); struct fuse_bufvec bufv = { .buf[0] = *buf, .count = 1 }; @@ -2352,10 +2472,10 @@ static void fuse_ll_process_buf(void *data, const struct fuse_buf *buf, if (f->debug) { fprintf(stderr, - "unique: %llu, opcode: %s (%i), nodeid: %lu, insize: %zu, pid: %u\n", + "unique: %llu, opcode: %s (%i), nodeid: %llu, insize: %zu, pid: %u\n", (unsigned long long) in->unique, opname((enum fuse_opcode) in->opcode), in->opcode, - (unsigned long) in->nodeid, buf->size, in->pid); + (unsigned long long) in->nodeid, buf->size, in->pid); } req = fuse_ll_alloc_req(f); @@ -2395,7 +2515,8 @@ static void fuse_ll_process_buf(void *data, const struct fuse_buf *buf, in->opcode != FUSE_WRITE && in->opcode != FUSE_FSYNC && in->opcode != FUSE_RELEASE && in->opcode != FUSE_READDIR && in->opcode != FUSE_FSYNCDIR && in->opcode != FUSE_RELEASEDIR && - in->opcode != FUSE_NOTIFY_REPLY) + in->opcode != FUSE_NOTIFY_REPLY && + in->opcode != FUSE_READDIRPLUS) goto reply_err; err = ENOSYS; @@ -2453,17 +2574,6 @@ clear_pipe: goto out_free; } -static void fuse_ll_process(void *data, const char *buf, size_t len, - struct fuse_chan *ch) -{ - struct fuse_buf fbuf = { - .mem = (void *) buf, - .size = len, - }; - - fuse_ll_process_buf(data, &fbuf, ch); -} - enum { KEY_HELP, KEY_VERSION, @@ -2492,6 +2602,13 @@ static const struct fuse_opt fuse_ll_opts[] = { { "no_splice_move", offsetof(struct fuse_ll, no_splice_move), 1}, { "splice_read", offsetof(struct fuse_ll, splice_read), 1}, { "no_splice_read", offsetof(struct fuse_ll, no_splice_read), 1}, + { "auto_inval_data", offsetof(struct fuse_ll, auto_inval_data), 1}, + { "no_auto_inval_data", offsetof(struct fuse_ll, no_auto_inval_data), 1}, + { "readdirplus=no", offsetof(struct fuse_ll, no_readdirplus), 1}, + { "readdirplus=yes", offsetof(struct fuse_ll, no_readdirplus), 0}, + { "readdirplus=yes", offsetof(struct fuse_ll, no_readdirplus_auto), 1}, + { "readdirplus=auto", offsetof(struct fuse_ll, no_readdirplus), 0}, + { "readdirplus=auto", offsetof(struct fuse_ll, no_readdirplus_auto), 0}, FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_DISCARD), FUSE_OPT_KEY("-h", KEY_HELP), FUSE_OPT_KEY("--help", KEY_HELP), @@ -2502,13 +2619,13 @@ static const struct fuse_opt fuse_ll_opts[] = { static void fuse_ll_version(void) { - fprintf(stderr, "using FUSE kernel interface version %i.%i\n", - FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION); + printf("using FUSE kernel interface version %i.%i\n", + FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION); } static void fuse_ll_help(void) { - fprintf(stderr, + printf( " -o max_write=N set maximum size of write requests\n" " -o max_readahead=N set maximum readahead\n" " -o max_background=N set number of maximum background requests\n" @@ -2523,6 +2640,8 @@ static void fuse_ll_help(void) " -o [no_]splice_write use splice to write to the fuse device\n" " -o [no_]splice_move move data while splicing to the fuse device\n" " -o [no_]splice_read use splice to read from the fuse device\n" +" -o [no_]auto_inval_data use automatic kernel cache invalidation logic\n" +" -o readdirplus=S control readdirplus use (yes|no|auto)\n" ); } @@ -2547,14 +2666,8 @@ static int fuse_ll_opt_proc(void *data, const char *arg, int key, return -1; } -int fuse_lowlevel_is_lib_option(const char *opt) -{ - return fuse_opt_match(fuse_ll_opts, opt); -} - -static void fuse_ll_destroy(void *data) +static void fuse_ll_destroy(struct fuse_ll *f) { - struct fuse_ll *f = (struct fuse_ll *) data; struct fuse_ll_pipe *llp; if (f->got_init && !f->got_destroy) { @@ -2570,6 +2683,15 @@ static void fuse_ll_destroy(void *data) free(f); } +void fuse_session_destroy(struct fuse_session *se) +{ + fuse_ll_destroy(se->f); + if (se->ch != NULL) + fuse_chan_destroy(se->ch); + free(se); +} + + static void fuse_ll_pipe_destructor(void *data) { struct fuse_ll_pipe *llp = data; @@ -2577,12 +2699,11 @@ static void fuse_ll_pipe_destructor(void *data) } #ifdef HAVE_SPLICE -static int fuse_ll_receive_buf(struct fuse_session *se, struct fuse_buf *buf, - struct fuse_chan **chp) +int fuse_session_receive_buf(struct fuse_session *se, struct fuse_buf *buf, + struct fuse_chan *ch) { - struct fuse_chan *ch = *chp; - struct fuse_ll *f = fuse_session_data(se); - size_t bufsize = buf->size; + struct fuse_ll *f = se->f; + size_t bufsize = buf->size = f->bufsize; struct fuse_ll_pipe *llp; struct fuse_buf tmpbuf; int err; @@ -2666,47 +2787,25 @@ static int fuse_ll_receive_buf(struct fuse_session *se, struct fuse_buf *buf, return res; fallback: - res = fuse_chan_recv(chp, buf->mem, bufsize); - if (res <= 0) - return res; - - buf->size = res; - - return res; + return fuse_chan_recv(se, buf, ch); } #else -static int fuse_ll_receive_buf(struct fuse_session *se, struct fuse_buf *buf, - struct fuse_chan **chp) +int fuse_session_receive_buf(struct fuse_session *se, struct fuse_buf *buf, + struct fuse_chan *ch) { - (void) se; - - int res = fuse_chan_recv(chp, buf->mem, buf->size); - if (res <= 0) - return res; - - buf->size = res; - - return res; + return fuse_chan_recv(se, buf, ch); } #endif +#define MIN_BUFSIZE 0x21000 -/* - * always call fuse_lowlevel_new_common() internally, to work around a - * misfeature in the FreeBSD runtime linker, which links the old - * version of a symbol to internal references. - */ -struct fuse_session *fuse_lowlevel_new_common(struct fuse_args *args, - const struct fuse_lowlevel_ops *op, - size_t op_size, void *userdata) +struct fuse_session *fuse_lowlevel_new(struct fuse_args *args, + const struct fuse_lowlevel_ops *op, + size_t op_size, void *userdata) { int err; struct fuse_ll *f; struct fuse_session *se; - struct fuse_session_ops sop = { - .process = fuse_ll_process, - .destroy = fuse_ll_destroy, - }; if (sizeof(struct fuse_lowlevel_ops) < op_size) { fprintf(stderr, "fuse: warning: library too old, some operations may not work\n"); @@ -2723,6 +2822,9 @@ struct fuse_session *fuse_lowlevel_new_common(struct fuse_args *args, f->conn.max_write = UINT_MAX; f->conn.max_readahead = UINT_MAX; f->atomic_o_trunc = 0; + f->bufsize = getpagesize() + 0x1000; + f->bufsize = f->bufsize < MIN_BUFSIZE ? MIN_BUFSIZE : f->bufsize; + list_init_req(&f->list); list_init_req(&f->interrupts); list_init_nreq(&f->notify_list); @@ -2746,12 +2848,11 @@ struct fuse_session *fuse_lowlevel_new_common(struct fuse_args *args, f->owner = getuid(); f->userdata = userdata; - se = fuse_session_new(&sop, f); + se = fuse_session_new(); if (!se) goto out_key_destroy; - se->receive_buf = fuse_ll_receive_buf; - se->process_buf = fuse_ll_process_buf; + se->f = f; return se; @@ -2764,14 +2865,6 @@ out: return NULL; } - -struct fuse_session *fuse_lowlevel_new(struct fuse_args *args, - const struct fuse_lowlevel_ops *op, - size_t op_size, void *userdata) -{ - return fuse_lowlevel_new_common(args, op, op_size, userdata); -} - #ifdef linux int fuse_req_getgroups(fuse_req_t req, int size, gid_t list[]) { @@ -2840,129 +2933,3 @@ int fuse_req_getgroups(fuse_req_t req, int size, gid_t list[]) return -ENOSYS; } #endif - -#if !defined(__FreeBSD__) && !defined(__NetBSD__) - -static void fill_open_compat(struct fuse_open_out *arg, - const struct fuse_file_info_compat *f) -{ - arg->fh = f->fh; - if (f->direct_io) - arg->open_flags |= FOPEN_DIRECT_IO; - if (f->keep_cache) - arg->open_flags |= FOPEN_KEEP_CACHE; -} - -static void convert_statfs_compat(const struct statfs *compatbuf, - struct statvfs *buf) -{ - buf->f_bsize = compatbuf->f_bsize; - buf->f_blocks = compatbuf->f_blocks; - buf->f_bfree = compatbuf->f_bfree; - buf->f_bavail = compatbuf->f_bavail; - buf->f_files = compatbuf->f_files; - buf->f_ffree = compatbuf->f_ffree; - buf->f_namemax = compatbuf->f_namelen; -} - -int fuse_reply_open_compat(fuse_req_t req, - const struct fuse_file_info_compat *f) -{ - struct fuse_open_out arg; - - memset(&arg, 0, sizeof(arg)); - fill_open_compat(&arg, f); - return send_reply_ok(req, &arg, sizeof(arg)); -} - -int fuse_reply_statfs_compat(fuse_req_t req, const struct statfs *stbuf) -{ - struct statvfs newbuf; - - memset(&newbuf, 0, sizeof(newbuf)); - convert_statfs_compat(stbuf, &newbuf); - - return fuse_reply_statfs(req, &newbuf); -} - -struct fuse_session *fuse_lowlevel_new_compat(const char *opts, - const struct fuse_lowlevel_ops_compat *op, - size_t op_size, void *userdata) -{ - struct fuse_session *se; - struct fuse_args args = FUSE_ARGS_INIT(0, NULL); - - if (opts && - (fuse_opt_add_arg(&args, "") == -1 || - fuse_opt_add_arg(&args, "-o") == -1 || - fuse_opt_add_arg(&args, opts) == -1)) { - fuse_opt_free_args(&args); - return NULL; - } - se = fuse_lowlevel_new(&args, (const struct fuse_lowlevel_ops *) op, - op_size, userdata); - fuse_opt_free_args(&args); - - return se; -} - -struct fuse_ll_compat_conf { - unsigned max_read; - int set_max_read; -}; - -static const struct fuse_opt fuse_ll_opts_compat[] = { - { "max_read=", offsetof(struct fuse_ll_compat_conf, set_max_read), 1 }, - { "max_read=%u", offsetof(struct fuse_ll_compat_conf, max_read), 0 }, - FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_KEEP), - FUSE_OPT_END -}; - -int fuse_sync_compat_args(struct fuse_args *args) -{ - struct fuse_ll_compat_conf conf; - - memset(&conf, 0, sizeof(conf)); - if (fuse_opt_parse(args, &conf, fuse_ll_opts_compat, NULL) == -1) - return -1; - - if (fuse_opt_insert_arg(args, 1, "-osync_read")) - return -1; - - if (conf.set_max_read) { - char tmpbuf[64]; - - sprintf(tmpbuf, "-omax_readahead=%u", conf.max_read); - if (fuse_opt_insert_arg(args, 1, tmpbuf) == -1) - return -1; - } - return 0; -} - -FUSE_SYMVER(".symver fuse_reply_statfs_compat,fuse_reply_statfs@FUSE_2.4"); -FUSE_SYMVER(".symver fuse_reply_open_compat,fuse_reply_open@FUSE_2.4"); -FUSE_SYMVER(".symver fuse_lowlevel_new_compat,fuse_lowlevel_new@FUSE_2.4"); - -#else /* __FreeBSD__ || __NetBSD__ */ - -int fuse_sync_compat_args(struct fuse_args *args) -{ - (void) args; - return 0; -} - -#endif /* __FreeBSD__ || __NetBSD__ */ - -struct fuse_session *fuse_lowlevel_new_compat25(struct fuse_args *args, - const struct fuse_lowlevel_ops_compat25 *op, - size_t op_size, void *userdata) -{ - if (fuse_sync_compat_args(args) == -1) - return NULL; - - return fuse_lowlevel_new_common(args, - (const struct fuse_lowlevel_ops *) op, - op_size, userdata); -} - -FUSE_SYMVER(".symver fuse_lowlevel_new_compat25,fuse_lowlevel_new@FUSE_2.5"); diff --git a/lib/fuse_misc.h b/lib/fuse_misc.h index eedf0e0..8b76775 100644 --- a/lib/fuse_misc.h +++ b/lib/fuse_misc.h @@ -6,20 +6,8 @@ See the file COPYING.LIB */ -#include "config.h" #include <pthread.h> -/* - Versioned symbols cannot be used in some cases because it - - confuse the dynamic linker in uClibc - - not supported on MacOSX (in MachO binary format) -*/ -#if (!defined(__UCLIBC__) && !defined(__APPLE__)) -#define FUSE_SYMVER(x) __asm__(x) -#else -#define FUSE_SYMVER(x) -#endif - #ifndef USE_UCLIBC #define fuse_mutex_init(mut) pthread_mutex_init(mut, NULL) #else diff --git a/lib/fuse_mt.c b/lib/fuse_mt.c index f6dbe71..be5d644 100644 --- a/lib/fuse_mt.c +++ b/lib/fuse_mt.c @@ -6,105 +6,10 @@ See the file COPYING.LIB. */ -#include "fuse_i.h" -#include "fuse_misc.h" +#include "config.h" +#include "fuse.h" #include "fuse_lowlevel.h" -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <pthread.h> -#include <assert.h> - -struct procdata { - struct fuse *f; - struct fuse_chan *prevch; - struct fuse_session *prevse; - fuse_processor_t proc; - void *data; -}; - -static void mt_session_proc(void *data, const char *buf, size_t len, - struct fuse_chan *ch) -{ - struct procdata *pd = (struct procdata *) data; - struct fuse_cmd *cmd = *(struct fuse_cmd **) buf; - - (void) len; - (void) ch; - pd->proc(pd->f, cmd, pd->data); -} - -static void mt_session_exit(void *data, int val) -{ - struct procdata *pd = (struct procdata *) data; - if (val) - fuse_session_exit(pd->prevse); - else - fuse_session_reset(pd->prevse); -} - -static int mt_session_exited(void *data) -{ - struct procdata *pd = (struct procdata *) data; - return fuse_session_exited(pd->prevse); -} - -static int mt_chan_receive(struct fuse_chan **chp, char *buf, size_t size) -{ - struct fuse_cmd *cmd; - struct procdata *pd = (struct procdata *) fuse_chan_data(*chp); - - assert(size >= sizeof(cmd)); - - cmd = fuse_read_cmd(pd->f); - if (cmd == NULL) - return 0; - - *(struct fuse_cmd **) buf = cmd; - - return sizeof(cmd); -} - -int fuse_loop_mt_proc(struct fuse *f, fuse_processor_t proc, void *data) -{ - int res; - struct procdata pd; - struct fuse_session *prevse = fuse_get_session(f); - struct fuse_session *se; - struct fuse_chan *prevch = fuse_session_next_chan(prevse, NULL); - struct fuse_chan *ch; - struct fuse_session_ops sop = { - .exit = mt_session_exit, - .exited = mt_session_exited, - .process = mt_session_proc, - }; - struct fuse_chan_ops cop = { - .receive = mt_chan_receive, - }; - - pd.f = f; - pd.prevch = prevch; - pd.prevse = prevse; - pd.proc = proc; - pd.data = data; - - se = fuse_session_new(&sop, &pd); - if (se == NULL) - return -1; - - ch = fuse_chan_new(&cop, fuse_chan_fd(prevch), - sizeof(struct fuse_cmd *), &pd); - if (ch == NULL) { - fuse_session_destroy(se); - return -1; - } - fuse_session_add_chan(se, ch); - res = fuse_session_loop_mt(se); - fuse_session_destroy(se); - return res; -} - int fuse_loop_mt(struct fuse *f) { if (f == NULL) @@ -118,5 +23,3 @@ int fuse_loop_mt(struct fuse *f) fuse_stop_cleanup_thread(f); return res; } - -FUSE_SYMVER(".symver fuse_loop_mt_proc,__fuse_loop_mt@"); diff --git a/lib/fuse_opt.c b/lib/fuse_opt.c index a2118ce..bd7a6ee 100644 --- a/lib/fuse_opt.c +++ b/lib/fuse_opt.c @@ -6,6 +6,7 @@ See the file COPYING.LIB */ +#include "config.h" #include "fuse_opt.h" #include "fuse_misc.h" @@ -92,13 +93,6 @@ int fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg) return fuse_opt_insert_arg_common(args, pos, arg); } -int fuse_opt_insert_arg_compat(struct fuse_args *args, int pos, - const char *arg); -int fuse_opt_insert_arg_compat(struct fuse_args *args, int pos, const char *arg) -{ - return fuse_opt_insert_arg_common(args, pos, arg); -} - static int next_arg(struct fuse_opt_context *ctx, const char *opt) { if (ctx->argctr + 1 >= ctx->argc) { @@ -211,11 +205,13 @@ static int process_opt_param(void *var, const char *format, const char *param, { assert(format[0] == '%'); if (format[1] == 's') { + char **s = var; char *copy = strdup(param); if (!copy) return alloc_failed(); - *(char **) var = copy; + free(*s); + *s = copy; } else { if (sscanf(param, format, var) != 1) { fprintf(stderr, "fuse: invalid parameter in option `%s'\n", arg); @@ -421,6 +417,3 @@ int fuse_opt_parse(struct fuse_args *args, void *data, fuse_opt_free_args(&ctx.outargs); return res; } - -/* This symbol version was mistakenly added to the version script */ -FUSE_SYMVER(".symver fuse_opt_insert_arg_compat,fuse_opt_insert_arg@FUSE_2.5"); diff --git a/lib/fuse_session.c b/lib/fuse_session.c index 6e11068..e919e73 100644 --- a/lib/fuse_session.c +++ b/lib/fuse_session.c @@ -6,10 +6,9 @@ See the file COPYING.LIB */ +#include "config.h" #include "fuse_i.h" #include "fuse_misc.h" -#include "fuse_common_compat.h" -#include "fuse_lowlevel_compat.h" #include <stdio.h> #include <stdlib.h> @@ -17,31 +16,15 @@ #include <assert.h> #include <errno.h> -struct fuse_chan { - struct fuse_chan_ops op; - struct fuse_session *se; - - int fd; - - size_t bufsize; - - void *data; - - int compat; -}; - -struct fuse_session *fuse_session_new(struct fuse_session_ops *op, void *data) +struct fuse_session *fuse_session_new(void) { struct fuse_session *se = (struct fuse_session *) malloc(sizeof(*se)); if (se == NULL) { fprintf(stderr, "fuse: failed to allocate session\n"); return NULL; } - memset(se, 0, sizeof(*se)); - se->op = *op; - se->data = data; return se; } @@ -64,89 +47,34 @@ void fuse_session_remove_chan(struct fuse_chan *ch) } } -struct fuse_chan *fuse_session_next_chan(struct fuse_session *se, - struct fuse_chan *ch) -{ - assert(ch == NULL || ch == se->ch); - if (ch == NULL) - return se->ch; - else - return NULL; -} - -void fuse_session_process(struct fuse_session *se, const char *buf, size_t len, - struct fuse_chan *ch) -{ - se->op.process(se->data, buf, len, ch); -} - -void fuse_session_process_buf(struct fuse_session *se, - const struct fuse_buf *buf, struct fuse_chan *ch) -{ - if (se->process_buf) { - se->process_buf(se->data, buf, ch); - } else { - assert(!(buf->flags & FUSE_BUF_IS_FD)); - fuse_session_process(se->data, buf->mem, buf->size, ch); - } -} - -int fuse_session_receive_buf(struct fuse_session *se, struct fuse_buf *buf, - struct fuse_chan **chp) +struct fuse_chan *fuse_session_chan(struct fuse_session *se) { - int res; - - if (se->receive_buf) { - res = se->receive_buf(se, buf, chp); - } else { - res = fuse_chan_recv(chp, buf->mem, buf->size); - if (res > 0) - buf->size = res; - } - - return res; + return se->ch; } - -void fuse_session_destroy(struct fuse_session *se) +int fuse_chan_clearfd(struct fuse_chan *ch) { - if (se->op.destroy) - se->op.destroy(se->data); - if (se->ch != NULL) - fuse_chan_destroy(se->ch); - free(se); + int fd = ch->fd; + ch->fd = -1; + return fd; } void fuse_session_exit(struct fuse_session *se) { - if (se->op.exit) - se->op.exit(se->data, 1); se->exited = 1; } void fuse_session_reset(struct fuse_session *se) { - if (se->op.exit) - se->op.exit(se->data, 0); se->exited = 0; } int fuse_session_exited(struct fuse_session *se) { - if (se->op.exited) - return se->op.exited(se->data); - else - return se->exited; -} - -void *fuse_session_data(struct fuse_session *se) -{ - return se->data; + return se->exited; } -static struct fuse_chan *fuse_chan_new_common(struct fuse_chan_ops *op, int fd, - size_t bufsize, void *data, - int compat) +struct fuse_chan *fuse_chan_new(int fd) { struct fuse_chan *ch = (struct fuse_chan *) malloc(sizeof(*ch)); if (ch == NULL) { @@ -155,86 +83,24 @@ static struct fuse_chan *fuse_chan_new_common(struct fuse_chan_ops *op, int fd, } memset(ch, 0, sizeof(*ch)); - ch->op = *op; ch->fd = fd; - ch->bufsize = bufsize; - ch->data = data; - ch->compat = compat; return ch; } -struct fuse_chan *fuse_chan_new(struct fuse_chan_ops *op, int fd, - size_t bufsize, void *data) -{ - return fuse_chan_new_common(op, fd, bufsize, data, 0); -} - -struct fuse_chan *fuse_chan_new_compat24(struct fuse_chan_ops_compat24 *op, - int fd, size_t bufsize, void *data) -{ - return fuse_chan_new_common((struct fuse_chan_ops *) op, fd, bufsize, - data, 24); -} - int fuse_chan_fd(struct fuse_chan *ch) { return ch->fd; } -int fuse_chan_clearfd(struct fuse_chan *ch) -{ - int fd = ch->fd; - ch->fd = -1; - return fd; -} - -size_t fuse_chan_bufsize(struct fuse_chan *ch) -{ - return ch->bufsize; -} - -void *fuse_chan_data(struct fuse_chan *ch) -{ - return ch->data; -} - struct fuse_session *fuse_chan_session(struct fuse_chan *ch) { return ch->se; } -int fuse_chan_recv(struct fuse_chan **chp, char *buf, size_t size) -{ - struct fuse_chan *ch = *chp; - if (ch->compat) - return ((struct fuse_chan_ops_compat24 *) &ch->op) - ->receive(ch, buf, size); - else - return ch->op.receive(chp, buf, size); -} - -int fuse_chan_receive(struct fuse_chan *ch, char *buf, size_t size) -{ - int res; - - res = fuse_chan_recv(&ch, buf, size); - return res >= 0 ? res : (res != -EINTR && res != -EAGAIN) ? -1 : 0; -} - -int fuse_chan_send(struct fuse_chan *ch, const struct iovec iov[], size_t count) -{ - return ch->op.send(ch, iov, count); -} - void fuse_chan_destroy(struct fuse_chan *ch) { fuse_session_remove_chan(ch); - if (ch->op.destroy) - ch->op.destroy(ch); + fuse_chan_close(ch); free(ch); } - -#ifndef __FreeBSD__ -FUSE_SYMVER(".symver fuse_chan_new_compat24,fuse_chan_new@FUSE_2.4"); -#endif diff --git a/lib/fuse_signals.c b/lib/fuse_signals.c index 88ac39e..c78c62d 100644..100755 --- a/lib/fuse_signals.c +++ b/lib/fuse_signals.c @@ -6,6 +6,7 @@ See the file COPYING.LIB */ +#include "config.h" #include "fuse_lowlevel.h" #include <stdio.h> @@ -14,12 +15,14 @@ static struct fuse_session *fuse_instance; +/*! [doxygen_exit_handler] */ static void exit_handler(int sig) { (void) sig; if (fuse_instance) fuse_session_exit(fuse_instance); } +/*! [doxygen_exit_handler] */ static int set_one_signal_handler(int sig, void (*handler)(int)) { diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript index 8d91887..08dafbd 100644 --- a/lib/fuse_versionscript +++ b/lib/fuse_versionscript @@ -1,38 +1,11 @@ -FUSE_2.2 { +FUSE_3.0 { global: fuse_destroy; fuse_exit; - fuse_exited; - fuse_invalidate; - fuse_is_lib_option; fuse_loop; fuse_loop_mt; - fuse_loop_mt_proc; - fuse_main; - fuse_main_compat1; - fuse_main_compat2; - fuse_mount_compat1; - fuse_new_compat1; - fuse_new_compat2; - fuse_process_cmd; - fuse_read_cmd; - fuse_set_getcontext_func; - fuse_setup_compat2; -}; - -FUSE_2.4 { - global: - fuse_add_dirent; - fuse_chan_bufsize; - fuse_chan_data; fuse_chan_destroy; fuse_chan_fd; - fuse_chan_receive; - fuse_chan_send; - fuse_chan_session; - fuse_dirent_size; - fuse_kern_chan_new; - fuse_lowlevel_is_lib_option; fuse_reply_attr; fuse_reply_buf; fuse_reply_entry; @@ -48,18 +21,8 @@ FUSE_2.4 { fuse_session_exited; fuse_session_loop; fuse_session_loop_mt; - fuse_session_new; - fuse_session_next_chan; - fuse_session_process; + fuse_session_chan; fuse_session_reset; -} FUSE_2.2; - -FUSE_2.5 { - global: - fuse_lowlevel_new_compat; - fuse_main_real_compat22; - fuse_mount_compat22; - fuse_new_compat22; fuse_opt_parse; fuse_opt_add_opt; fuse_opt_add_arg; @@ -69,45 +32,23 @@ FUSE_2.5 { fuse_remove_signal_handlers; fuse_reply_create; fuse_reply_open; - fuse_reply_open_compat; fuse_reply_statfs; - fuse_reply_statfs_compat; - fuse_setup_compat22; fuse_set_signal_handlers; -} FUSE_2.4; - -FUSE_2.6 { - global: fuse_add_direntry; - fuse_chan_new; - fuse_chan_new_compat24; - fuse_chan_recv; + fuse_add_direntry_plus; fuse_daemonize; fuse_get_session; fuse_interrupted; fuse_lowlevel_new; - fuse_lowlevel_new_compat25; fuse_main_real; - fuse_main_real_compat25; fuse_mount; - fuse_mount_compat25; fuse_new; - fuse_new_compat25; fuse_opt_insert_arg; fuse_reply_lock; fuse_req_interrupt_func; fuse_req_interrupted; fuse_session_remove_chan; - fuse_setup; - fuse_setup_compat25; - fuse_teardown; - fuse_teardown_compat22; fuse_unmount; - fuse_unmount_compat22; -} FUSE_2.5; - -FUSE_2.7 { - global: fuse_fs_access; fuse_fs_bmap; fuse_fs_chmod; @@ -148,15 +89,7 @@ FUSE_2.7 { fuse_register_module; fuse_reply_iov; fuse_version; -} FUSE_2.6; - -FUSE_2.7.5 { - global: fuse_reply_bmap; -} FUSE_2.7; - -FUSE_2.8 { - global: cuse_lowlevel_new; cuse_lowlevel_main; cuse_lowlevel_setup; @@ -177,11 +110,6 @@ FUSE_2.8 { fuse_reply_poll; fuse_req_ctx; fuse_req_getgroups; - fuse_session_data; -} FUSE_2.7.5; - -FUSE_2.9 { - global: fuse_buf_copy; fuse_buf_size; fuse_fs_read_buf; @@ -196,12 +124,8 @@ FUSE_2.9 { fuse_clean_cache; fuse_lowlevel_notify_delete; fuse_fs_flock; -} FUSE_2.8; - -FUSE_2.9.1 { - global: fuse_fs_fallocate; local: *; -} FUSE_2.9; +}; diff --git a/lib/helper.c b/lib/helper.c index b644012..e5550c9 100644 --- a/lib/helper.c +++ b/lib/helper.c @@ -11,7 +11,6 @@ #include "fuse_misc.h" #include "fuse_opt.h" #include "fuse_lowlevel.h" -#include "fuse_common_compat.h" #include <stdio.h> #include <stdlib.h> @@ -59,30 +58,26 @@ static const struct fuse_opt fuse_helper_opts[] = { static void usage(const char *progname) { - fprintf(stderr, - "usage: %s mountpoint [options]\n\n", progname); - fprintf(stderr, - "general options:\n" - " -o opt,[opt...] mount options\n" - " -h --help print help\n" - " -V --version print version\n" - "\n"); + printf("usage: %s mountpoint [options]\n\n", progname); + printf("general options:\n" + " -o opt,[opt...] mount options\n" + " -h --help print help\n" + " -V --version print version\n" + "\n"); } static void helper_help(void) { - fprintf(stderr, - "FUSE options:\n" - " -d -o debug enable debug output (implies -f)\n" - " -f foreground operation\n" - " -s disable multi-threaded operation\n" - "\n" - ); + printf("FUSE options:\n" + " -d -o debug enable debug output (implies -f)\n" + " -f foreground operation\n" + " -s disable multi-threaded operation\n" + "\n"); } static void helper_version(void) { - fprintf(stderr, "FUSE library version: %s\n", PACKAGE_VERSION); + printf("FUSE library version: %s\n", PACKAGE_VERSION); } static int fuse_helper_opt_proc(void *data, const char *arg, int key, @@ -211,12 +206,13 @@ int fuse_daemonize(int foreground) if (nullfd > 2) close(nullfd); } + } else { + (void) chdir("/"); } return 0; } -static struct fuse_chan *fuse_mount_common(const char *mountpoint, - struct fuse_args *args) +struct fuse_chan *fuse_mount(const char *mountpoint, struct fuse_args *args) { struct fuse_chan *ch; int fd; @@ -231,23 +227,18 @@ static struct fuse_chan *fuse_mount_common(const char *mountpoint, close(fd); } while (fd >= 0 && fd <= 2); - fd = fuse_mount_compat25(mountpoint, args); + fd = fuse_kern_mount(mountpoint, args); if (fd == -1) return NULL; - ch = fuse_kern_chan_new(fd); + ch = fuse_chan_new(fd); if (!ch) fuse_kern_unmount(mountpoint, fd); return ch; } -struct fuse_chan *fuse_mount(const char *mountpoint, struct fuse_args *args) -{ - return fuse_mount_common(mountpoint, args); -} - -static void fuse_unmount_common(const char *mountpoint, struct fuse_chan *ch) +void fuse_unmount(const char *mountpoint, struct fuse_chan *ch) { if (mountpoint) { int fd = ch ? fuse_chan_clearfd(ch) : -1; @@ -257,19 +248,9 @@ static void fuse_unmount_common(const char *mountpoint, struct fuse_chan *ch) } } -void fuse_unmount(const char *mountpoint, struct fuse_chan *ch) -{ - fuse_unmount_common(mountpoint, ch); -} - -struct fuse *fuse_setup_common(int argc, char *argv[], - const struct fuse_operations *op, - size_t op_size, - char **mountpoint, - int *multithreaded, - int *fd, - void *user_data, - int compat) +static struct fuse *fuse_setup(int argc, char *argv[], + const struct fuse_operations *op, size_t op_size, + char **mountpoint, int *multithreaded, void *user_data) { struct fuse_args args = FUSE_ARGS_INIT(argc, argv); struct fuse_chan *ch; @@ -281,13 +262,13 @@ struct fuse *fuse_setup_common(int argc, char *argv[], if (res == -1) return NULL; - ch = fuse_mount_common(*mountpoint, &args); + ch = fuse_mount(*mountpoint, &args); if (!ch) { fuse_opt_free_args(&args); goto err_free; } - fuse = fuse_new_common(ch, &args, op, op_size, user_data, compat); + fuse = fuse_new(ch, &args, op, op_size, user_data); fuse_opt_free_args(&args); if (fuse == NULL) goto err_unmount; @@ -300,13 +281,10 @@ struct fuse *fuse_setup_common(int argc, char *argv[], if (res == -1) goto err_unmount; - if (fd) - *fd = fuse_chan_fd(ch); - return fuse; err_unmount: - fuse_unmount_common(*mountpoint, ch); + fuse_unmount(*mountpoint, ch); if (fuse) fuse_destroy(fuse); err_free: @@ -314,40 +292,26 @@ err_free: return NULL; } -struct fuse *fuse_setup(int argc, char *argv[], - const struct fuse_operations *op, size_t op_size, - char **mountpoint, int *multithreaded, void *user_data) -{ - return fuse_setup_common(argc, argv, op, op_size, mountpoint, - multithreaded, NULL, user_data, 0); -} - -static void fuse_teardown_common(struct fuse *fuse, char *mountpoint) +static void fuse_teardown(struct fuse *fuse, char *mountpoint) { struct fuse_session *se = fuse_get_session(fuse); - struct fuse_chan *ch = fuse_session_next_chan(se, NULL); + struct fuse_chan *ch = fuse_session_chan(se); fuse_remove_signal_handlers(se); - fuse_unmount_common(mountpoint, ch); + fuse_unmount(mountpoint, ch); fuse_destroy(fuse); free(mountpoint); } -void fuse_teardown(struct fuse *fuse, char *mountpoint) -{ - fuse_teardown_common(fuse, mountpoint); -} - -static int fuse_main_common(int argc, char *argv[], - const struct fuse_operations *op, size_t op_size, - void *user_data, int compat) +int fuse_main_real(int argc, char *argv[], const struct fuse_operations *op, + size_t op_size, void *user_data) { struct fuse *fuse; char *mountpoint; int multithreaded; int res; - fuse = fuse_setup_common(argc, argv, op, op_size, &mountpoint, - &multithreaded, NULL, user_data, compat); + fuse = fuse_setup(argc, argv, op, op_size, &mountpoint, + &multithreaded, user_data); if (fuse == NULL) return 1; @@ -356,125 +320,15 @@ static int fuse_main_common(int argc, char *argv[], else res = fuse_loop(fuse); - fuse_teardown_common(fuse, mountpoint); + fuse_teardown(fuse, mountpoint); if (res == -1) return 1; return 0; } -int fuse_main_real(int argc, char *argv[], const struct fuse_operations *op, - size_t op_size, void *user_data) -{ - return fuse_main_common(argc, argv, op, op_size, user_data, 0); -} - -#undef fuse_main -int fuse_main(void); -int fuse_main(void) -{ - fprintf(stderr, "fuse_main(): This function does not exist\n"); - return -1; -} - int fuse_version(void) { return FUSE_VERSION; } -#include "fuse_compat.h" - -#if !defined(__FreeBSD__) && !defined(__NetBSD__) - -struct fuse *fuse_setup_compat22(int argc, char *argv[], - const struct fuse_operations_compat22 *op, - size_t op_size, char **mountpoint, - int *multithreaded, int *fd) -{ - return fuse_setup_common(argc, argv, (struct fuse_operations *) op, - op_size, mountpoint, multithreaded, fd, NULL, - 22); -} - -struct fuse *fuse_setup_compat2(int argc, char *argv[], - const struct fuse_operations_compat2 *op, - char **mountpoint, int *multithreaded, - int *fd) -{ - return fuse_setup_common(argc, argv, (struct fuse_operations *) op, - sizeof(struct fuse_operations_compat2), - mountpoint, multithreaded, fd, NULL, 21); -} - -int fuse_main_real_compat22(int argc, char *argv[], - const struct fuse_operations_compat22 *op, - size_t op_size) -{ - return fuse_main_common(argc, argv, (struct fuse_operations *) op, - op_size, NULL, 22); -} - -void fuse_main_compat1(int argc, char *argv[], - const struct fuse_operations_compat1 *op) -{ - fuse_main_common(argc, argv, (struct fuse_operations *) op, - sizeof(struct fuse_operations_compat1), NULL, 11); -} - -int fuse_main_compat2(int argc, char *argv[], - const struct fuse_operations_compat2 *op) -{ - return fuse_main_common(argc, argv, (struct fuse_operations *) op, - sizeof(struct fuse_operations_compat2), NULL, - 21); -} - -int fuse_mount_compat1(const char *mountpoint, const char *args[]) -{ - /* just ignore mount args for now */ - (void) args; - return fuse_mount_compat22(mountpoint, NULL); -} - -FUSE_SYMVER(".symver fuse_setup_compat2,__fuse_setup@"); -FUSE_SYMVER(".symver fuse_setup_compat22,fuse_setup@FUSE_2.2"); -FUSE_SYMVER(".symver fuse_teardown,__fuse_teardown@"); -FUSE_SYMVER(".symver fuse_main_compat2,fuse_main@"); -FUSE_SYMVER(".symver fuse_main_real_compat22,fuse_main_real@FUSE_2.2"); - -#endif /* __FreeBSD__ || __NetBSD__ */ - - -struct fuse *fuse_setup_compat25(int argc, char *argv[], - const struct fuse_operations_compat25 *op, - size_t op_size, char **mountpoint, - int *multithreaded, int *fd) -{ - return fuse_setup_common(argc, argv, (struct fuse_operations *) op, - op_size, mountpoint, multithreaded, fd, NULL, - 25); -} - -int fuse_main_real_compat25(int argc, char *argv[], - const struct fuse_operations_compat25 *op, - size_t op_size) -{ - return fuse_main_common(argc, argv, (struct fuse_operations *) op, - op_size, NULL, 25); -} - -void fuse_teardown_compat22(struct fuse *fuse, int fd, char *mountpoint) -{ - (void) fd; - fuse_teardown_common(fuse, mountpoint); -} - -int fuse_mount_compat25(const char *mountpoint, struct fuse_args *args) -{ - return fuse_kern_mount(mountpoint, args); -} - -FUSE_SYMVER(".symver fuse_setup_compat25,fuse_setup@FUSE_2.5"); -FUSE_SYMVER(".symver fuse_teardown_compat22,fuse_teardown@FUSE_2.2"); -FUSE_SYMVER(".symver fuse_main_real_compat25,fuse_main_real@FUSE_2.5"); -FUSE_SYMVER(".symver fuse_mount_compat25,fuse_mount@FUSE_2.5"); diff --git a/lib/modules/iconv.c b/lib/modules/iconv.c index 89b22e4..7438ecb 100644 --- a/lib/modules/iconv.c +++ b/lib/modules/iconv.c @@ -6,7 +6,9 @@ See the file COPYING.LIB */ -#define FUSE_USE_VERSION 26 +#define FUSE_USE_VERSION 30 + +#include <config.h> #include <fuse.h> #include <stdio.h> @@ -631,7 +633,6 @@ static const struct fuse_operations iconv_oper = { .flock = iconv_flock, .bmap = iconv_bmap, - .flag_nullpath_ok = 1, .flag_nopath = 1, }; @@ -649,7 +650,7 @@ static void iconv_help(void) char *charmap = strdup(nl_langinfo(CODESET)); setlocale(LC_CTYPE, old); free(old); - fprintf(stderr, + printf( " -o from_code=CHARSET original encoding of file names (default: UTF-8)\n" " -o to_code=CHARSET new encoding of the file names (default: %s)\n", charmap); diff --git a/lib/modules/subdir.c b/lib/modules/subdir.c index 76a53fa..eb56d36 100644 --- a/lib/modules/subdir.c +++ b/lib/modules/subdir.c @@ -6,7 +6,9 @@ See the file COPYING.LIB */ -#define FUSE_USE_VERSION 26 +#define FUSE_USE_VERSION 30 + +#include <config.h> #include <fuse.h> #include <stdio.h> @@ -614,7 +616,6 @@ static const struct fuse_operations subdir_oper = { .flock = subdir_flock, .bmap = subdir_bmap, - .flag_nullpath_ok = 1, .flag_nopath = 1, }; @@ -629,7 +630,7 @@ static const struct fuse_opt subdir_opts[] = { static void subdir_help(void) { - fprintf(stderr, + printf( " -o subdir=DIR prepend this directory to all paths (mandatory)\n" " -o [no]rellinks transform absolute symlinks to relative\n"); } diff --git a/lib/mount.c b/lib/mount.c index 0f767c8..fb9231a 100644 --- a/lib/mount.c +++ b/lib/mount.c @@ -10,7 +10,6 @@ #include "fuse_i.h" #include "fuse_misc.h" #include "fuse_opt.h" -#include "fuse_common_compat.h" #include "mount_util.h" #include <stdio.h> @@ -98,6 +97,10 @@ static const struct fuse_opt fuse_mount_opts[] = { FUSE_OPT_KEY("large_read", KEY_KERN_OPT), FUSE_OPT_KEY("blksize=", KEY_KERN_OPT), FUSE_OPT_KEY("default_permissions", KEY_KERN_OPT), + FUSE_OPT_KEY("context=", KEY_KERN_OPT), + FUSE_OPT_KEY("fscontext=", KEY_KERN_OPT), + FUSE_OPT_KEY("defcontext=", KEY_KERN_OPT), + FUSE_OPT_KEY("rootcontext=", KEY_KERN_OPT), FUSE_OPT_KEY("max_read=", KEY_KERN_OPT), FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_KEEP), FUSE_OPT_KEY("user=", KEY_MTAB_OPT), @@ -124,7 +127,7 @@ static const struct fuse_opt fuse_mount_opts[] = { static void mount_help(void) { - fprintf(stderr, + printf( " -o allow_other allow access to other users\n" " -o allow_root allow access to root\n" " -o auto_unmount auto unmount on process termination\n" @@ -291,9 +294,6 @@ void fuse_kern_unmount(const char *mountpoint, int fd) int res; int pid; - if (!mountpoint) - return; - if (fd != -1) { struct pollfd pfd; @@ -337,11 +337,6 @@ void fuse_kern_unmount(const char *mountpoint, int fd) waitpid(pid, NULL, 0); } -void fuse_unmount_compat22(const char *mountpoint) -{ - fuse_kern_unmount(mountpoint, -1); -} - static int fuse_mount_fusermount(const char *mountpoint, struct mount_opts *mo, const char *opts, int quiet) { @@ -409,17 +404,15 @@ static int fuse_mount_fusermount(const char *mountpoint, struct mount_opts *mo, waitpid(pid, NULL, 0); /* bury zombie */ } + if (rv >= 0) + fcntl(rv, F_SETFD, FD_CLOEXEC); + return rv; } -int fuse_mount_compat22(const char *mountpoint, const char *opts) -{ - struct mount_opts mo; - memset(&mo, 0, sizeof(mo)); - mo.flags = MS_NOSUID | MS_NODEV; - - return fuse_mount_fusermount(mountpoint, &mo, opts, 0); -} +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif static int fuse_mount_sys(const char *mnt, struct mount_opts *mo, const char *mnt_opts) @@ -457,7 +450,7 @@ static int fuse_mount_sys(const char *mnt, struct mount_opts *mo, return -2; } - fd = open(devname, O_RDWR); + fd = open(devname, O_RDWR | O_CLOEXEC); if (fd == -1) { if (errno == ENODEV || errno == ENOENT) fprintf(stderr, "fuse: device not found, try 'modprobe fuse' first\n"); @@ -466,6 +459,8 @@ static int fuse_mount_sys(const char *mnt, struct mount_opts *mo, devname, strerror(errno)); return -1; } + if (!O_CLOEXEC) + fcntl(fd, F_SETFD, FD_CLOEXEC); snprintf(tmp, sizeof(tmp), "fd=%i,rootmode=%o,user_id=%i,group_id=%i", fd, stbuf.st_mode & S_IFMT, getuid(), getgid()); @@ -635,6 +630,3 @@ out: free(mo.mtab_opts); return res; } - -FUSE_SYMVER(".symver fuse_mount_compat22,fuse_mount@FUSE_2.2"); -FUSE_SYMVER(".symver fuse_unmount_compat22,fuse_unmount@FUSE_2.2"); diff --git a/lib/mount_bsd.c b/lib/mount_bsd.c index 3aec3e3..8f3acf0 100644 --- a/lib/mount_bsd.c +++ b/lib/mount_bsd.c @@ -6,6 +6,7 @@ See the file COPYING.LIB. */ +#include "config.h" #include "fuse_i.h" #include "fuse_misc.h" #include "fuse_opt.h" @@ -101,9 +102,7 @@ static const struct fuse_opt fuse_mount_opts[] = { static void mount_help(void) { - fprintf(stderr, - " -o allow_root allow access to root\n" - ); + printf(" -o allow_root allow access to root\n"); system(FUSERMOUNT_PROG " --help"); fputc('\n', stderr); } @@ -387,5 +386,3 @@ out: free(mo.kernel_opts); return res; } - -FUSE_SYMVER(".symver fuse_unmount_compat22,fuse_unmount@FUSE_2.2"); diff --git a/lib/mount_util.c b/lib/mount_util.c index 3cad2e6..87e3888 100644 --- a/lib/mount_util.c +++ b/lib/mount_util.c @@ -6,6 +6,7 @@ See the file COPYING.LIB. */ +#include "config.h" #include "mount_util.h" #include <stdio.h> #include <unistd.h> diff --git a/lib/ulockmgr.c b/lib/ulockmgr.c deleted file mode 100644 index b875c50..0000000 --- a/lib/ulockmgr.c +++ /dev/null @@ -1,444 +0,0 @@ -/* - libulockmgr: Userspace Lock Manager Library - Copyright (C) 2006 Miklos Szeredi <miklos@szeredi.hu> - - This program can be distributed under the terms of the GNU LGPLv2. - See the file COPYING.LIB -*/ - -/* #define DEBUG 1 */ - -#include "ulockmgr.h" -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <pthread.h> -#include <errno.h> -#include <assert.h> -#include <signal.h> -#include <sys/stat.h> -#include <sys/socket.h> -#include <sys/wait.h> - -struct message { - unsigned intr : 1; - unsigned nofd : 1; - pthread_t thr; - int cmd; - int fd; - struct flock lock; - int error; -}; - -struct fd_store { - struct fd_store *next; - int fd; - int inuse; -}; - -struct owner { - struct owner *next; - struct owner *prev; - struct fd_store *fds; - void *id; - size_t id_len; - int cfd; -}; - -static pthread_mutex_t ulockmgr_lock; -static int ulockmgr_cfd = -1; -static struct owner owner_list = { .next = &owner_list, .prev = &owner_list }; - -#define MAX_SEND_FDS 2 - -static void list_del_owner(struct owner *owner) -{ - struct owner *prev = owner->prev; - struct owner *next = owner->next; - prev->next = next; - next->prev = prev; -} - -static void list_add_owner(struct owner *owner, struct owner *next) -{ - struct owner *prev = next->prev; - owner->next = next; - owner->prev = prev; - prev->next = owner; - next->prev = owner; -} - -/* - * There's a bug in the linux kernel (< 2.6.22) recv() implementation - * on AF_UNIX, SOCK_STREAM sockets, that could cause it to return - * zero, even if data was available. Retrying the recv will return - * the data in this case. - */ -static int do_recv(int sock, void *buf, size_t len, int flags) -{ - int res = recv(sock, buf, len, flags); - if (res == 0) - res = recv(sock, buf, len, flags); - - return res; -} - -static int ulockmgr_send_message(int sock, void *buf, size_t buflen, - int *fdp, int numfds) -{ - struct msghdr msg; - struct cmsghdr *p_cmsg; - struct iovec vec; - size_t cmsgbuf[CMSG_SPACE(sizeof(int) * MAX_SEND_FDS) / sizeof(size_t)]; - int res; - - assert(numfds <= MAX_SEND_FDS); - msg.msg_control = cmsgbuf; - msg.msg_controllen = sizeof(cmsgbuf); - p_cmsg = CMSG_FIRSTHDR(&msg); - p_cmsg->cmsg_level = SOL_SOCKET; - p_cmsg->cmsg_type = SCM_RIGHTS; - p_cmsg->cmsg_len = CMSG_LEN(sizeof(int) * numfds); - memcpy(CMSG_DATA(p_cmsg), fdp, sizeof(int) * numfds); - msg.msg_controllen = p_cmsg->cmsg_len; - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_iov = &vec; - msg.msg_iovlen = 1; - msg.msg_flags = 0; - vec.iov_base = buf; - vec.iov_len = buflen; - res = sendmsg(sock, &msg, MSG_NOSIGNAL); - if (res == -1) { - perror("libulockmgr: sendmsg"); - return -1; - } - if ((size_t) res != buflen) { - fprintf(stderr, "libulockmgr: sendmsg short\n"); - return -1; - } - return 0; -} - -static int ulockmgr_start_daemon(void) -{ - int sv[2]; - int res; - char tmp[64]; - - res = socketpair(AF_UNIX, SOCK_STREAM, 0, sv); - if (res == -1) { - perror("libulockmgr: socketpair"); - return -1; - } - snprintf(tmp, sizeof(tmp), "exec ulockmgr_server %i", sv[0]); - res = system(tmp); - close(sv[0]); - if (res == -1 || !WIFEXITED(res) || WEXITSTATUS(res) != 0) { - close(sv[1]); - return -1; - } - ulockmgr_cfd = sv[1]; - return 0; -} - -static struct owner *ulockmgr_new_owner(const void *id, size_t id_len) -{ - int sv[2]; - int res; - char c = 'm'; - struct owner *o; - - if (ulockmgr_cfd == -1 && ulockmgr_start_daemon() == -1) - return NULL; - - o = calloc(1, sizeof(struct owner) + id_len); - if (!o) { - fprintf(stderr, "libulockmgr: failed to allocate memory\n"); - return NULL; - } - o->id = o + 1; - o->id_len = id_len; - res = socketpair(AF_UNIX, SOCK_STREAM, 0, sv); - if (res == -1) { - perror("libulockmgr: socketpair"); - goto out_free; - } - res = ulockmgr_send_message(ulockmgr_cfd, &c, sizeof(c), &sv[0], 1); - close(sv[0]); - if (res == -1) { - close(ulockmgr_cfd); - ulockmgr_cfd = -1; - goto out_close; - } - - o->cfd = sv[1]; - memcpy(o->id, id, id_len); - list_add_owner(o, &owner_list); - - return o; - -out_close: - close(sv[1]); -out_free: - free(o); - return NULL; -} - -static int ulockmgr_send_request(struct message *msg, const void *id, - size_t id_len) -{ - int sv[2]; - int cfd; - struct owner *o; - struct fd_store *f = NULL; - struct fd_store *newf = NULL; - struct fd_store **fp; - int fd = msg->fd; - int cmd = msg->cmd; - int res; - int unlockall = (cmd == F_SETLK && msg->lock.l_type == F_UNLCK && - msg->lock.l_start == 0 && msg->lock.l_len == 0); - - for (o = owner_list.next; o != &owner_list; o = o->next) - if (o->id_len == id_len && memcmp(o->id, id, id_len) == 0) - break; - - if (o == &owner_list) - o = NULL; - - if (!o && cmd != F_GETLK && msg->lock.l_type != F_UNLCK) - o = ulockmgr_new_owner(id, id_len); - - if (!o) { - if (cmd == F_GETLK) { - res = fcntl(msg->fd, F_GETLK, &msg->lock); - return (res == -1) ? -errno : 0; - } else if (msg->lock.l_type == F_UNLCK) - return 0; - else - return -ENOLCK; - } - - if (unlockall) - msg->nofd = 1; - else { - for (fp = &o->fds; *fp; fp = &(*fp)->next) { - f = *fp; - if (f->fd == fd) { - msg->nofd = 1; - break; - } - } - } - - if (!msg->nofd) { - newf = f = calloc(1, sizeof(struct fd_store)); - if (!f) { - fprintf(stderr, "libulockmgr: failed to allocate memory\n"); - return -ENOLCK; - } - } - - res = socketpair(AF_UNIX, SOCK_STREAM, 0, sv); - if (res == -1) { - perror("libulockmgr: socketpair"); - free(newf); - return -ENOLCK; - } - - cfd = sv[1]; - sv[1] = msg->fd; - res = ulockmgr_send_message(o->cfd, msg, sizeof(struct message), sv, - msg->nofd ? 1 : 2); - close(sv[0]); - if (res == -1) { - free(newf); - close(cfd); - return -EIO; - } - - if (newf) { - newf->fd = msg->fd; - newf->next = o->fds; - o->fds = newf; - } - if (f) - f->inuse++; - - res = do_recv(cfd, msg, sizeof(struct message), MSG_WAITALL); - if (res == -1) { - perror("libulockmgr: recv"); - msg->error = EIO; - } else if (res != sizeof(struct message)) { - fprintf(stderr, "libulockmgr: recv short\n"); - msg->error = EIO; - } else if (cmd == F_SETLKW && msg->error == EAGAIN) { - pthread_mutex_unlock(&ulockmgr_lock); - while (1) { - sigset_t old; - sigset_t unblock; - int errno_save; - - sigemptyset(&unblock); - sigaddset(&unblock, SIGUSR1); - pthread_sigmask(SIG_UNBLOCK, &unblock, &old); - res = do_recv(cfd, msg, sizeof(struct message), - MSG_WAITALL); - errno_save = errno; - pthread_sigmask(SIG_SETMASK, &old, NULL); - if (res == sizeof(struct message)) - break; - else if (res >= 0) { - fprintf(stderr, "libulockmgr: recv short\n"); - msg->error = EIO; - break; - } else if (errno_save != EINTR) { - errno = errno_save; - perror("libulockmgr: recv"); - msg->error = EIO; - break; - } - msg->intr = 1; - res = send(o->cfd, msg, sizeof(struct message), - MSG_NOSIGNAL); - if (res == -1) { - perror("libulockmgr: send"); - msg->error = EIO; - break; - } - if (res != sizeof(struct message)) { - fprintf(stderr, "libulockmgr: send short\n"); - msg->error = EIO; - break; - } - } - pthread_mutex_lock(&ulockmgr_lock); - - } - if (f) - f->inuse--; - close(cfd); - if (unlockall) { - for (fp = &o->fds; *fp;) { - f = *fp; - if (f->fd == fd && !f->inuse) { - *fp = f->next; - free(f); - } else - fp = &f->next; - } - if (!o->fds) { - list_del_owner(o); - close(o->cfd); - free(o); - } - /* Force OK on unlock-all, since it _will_ succeed once the - owner is deleted */ - msg->error = 0; - } - - return -msg->error; -} - -#ifdef DEBUG -static uint32_t owner_hash(const unsigned char *id, size_t id_len) -{ - uint32_t h = 0; - size_t i; - for (i = 0; i < id_len; i++) - h = ((h << 8) | (h >> 24)) ^ id[i]; - - return h; -} -#endif - -static int ulockmgr_canonicalize(int fd, struct flock *lock) -{ - off_t offset; - if (lock->l_whence == SEEK_CUR) { - offset = lseek(fd, 0, SEEK_CUR); - if (offset == (off_t) -1) - return -errno; - } else if (lock->l_whence == SEEK_END) { - struct stat stbuf; - int res = fstat(fd, &stbuf); - if (res == -1) - return -errno; - - offset = stbuf.st_size; - } else - offset = 0; - - lock->l_whence = SEEK_SET; - lock->l_start += offset; - - if (lock->l_start < 0) - return -EINVAL; - - if (lock->l_len < 0) { - lock->l_start += lock->l_len; - if (lock->l_start < 0) - return -EINVAL; - lock->l_len = -lock->l_len; - } - if (lock->l_len && lock->l_start + lock->l_len - 1 < 0) - return -EINVAL; - - return 0; -} - -int ulockmgr_op(int fd, int cmd, struct flock *lock, const void *owner, - size_t owner_len) -{ - int err; - struct message msg; - sigset_t old; - sigset_t block; - - if (cmd != F_GETLK && cmd != F_SETLK && cmd != F_SETLKW) - return -EINVAL; - - if (lock->l_type != F_RDLCK && lock->l_type != F_WRLCK && - lock->l_type != F_UNLCK) - return -EINVAL; - - if (lock->l_whence != SEEK_SET && lock->l_whence != SEEK_CUR && - lock->l_whence != SEEK_END) - return -EINVAL; - -#ifdef DEBUG - fprintf(stderr, "libulockmgr: %i %i %i %lli %lli own: 0x%08x\n", - cmd, lock->l_type, lock->l_whence, lock->l_start, lock->l_len, - owner_hash(owner, owner_len)); -#endif - - /* Unlock should never block anyway */ - if (cmd == F_SETLKW && lock->l_type == F_UNLCK) - cmd = F_SETLK; - - memset(&msg, 0, sizeof(struct message)); - msg.cmd = cmd; - msg.fd = fd; - msg.lock = *lock; - err = ulockmgr_canonicalize(fd, &msg.lock); - if (err) - return err; - - sigemptyset(&block); - sigaddset(&block, SIGUSR1); - pthread_sigmask(SIG_BLOCK, &block, &old); - pthread_mutex_lock(&ulockmgr_lock); - err = ulockmgr_send_request(&msg, owner, owner_len); - pthread_mutex_unlock(&ulockmgr_lock); - pthread_sigmask(SIG_SETMASK, &old, NULL); - if (!err && cmd == F_GETLK) { - if (msg.lock.l_type == F_UNLCK) - lock->l_type = F_UNLCK; - else - *lock = msg.lock; - } - - return err; -} |