aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.am14
-rw-r--r--lib/cuse_lowlevel.c10
-rw-r--r--lib/fuse.c495
-rw-r--r--lib/fuse_i.h76
-rw-r--r--lib/fuse_kern_chan.c98
-rw-r--r--lib/fuse_loop.c24
-rwxr-xr-x[-rw-r--r--]lib/fuse_loop_mt.c31
-rwxr-xr-x[-rw-r--r--]lib/fuse_lowlevel.c469
-rw-r--r--lib/fuse_misc.h12
-rw-r--r--lib/fuse_mt.c101
-rw-r--r--lib/fuse_opt.c15
-rw-r--r--lib/fuse_session.c156
-rwxr-xr-x[-rw-r--r--]lib/fuse_signals.c3
-rw-r--r--lib/fuse_versionscript84
-rw-r--r--lib/helper.c210
-rw-r--r--lib/modules/iconv.c7
-rw-r--r--lib/modules/subdir.c7
-rw-r--r--lib/mount.c36
-rw-r--r--lib/mount_bsd.c7
-rw-r--r--lib/mount_util.c1
-rw-r--r--lib/ulockmgr.c444
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;
diff --git a/lib/fuse.c b/lib/fuse.c
index cfac238..7508c54 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -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;
-}