diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/buffer.c | 3 | ||||
-rw-r--r-- | lib/cuse_lowlevel.c | 1 | ||||
-rw-r--r--[-rwxr-xr-x] | lib/fuse.c | 21 | ||||
-rw-r--r-- | lib/fuse_loop_mt.c | 9 | ||||
-rw-r--r-- | lib/fuse_lowlevel.c | 53 | ||||
-rw-r--r-- | lib/fuse_misc.h | 25 | ||||
-rw-r--r-- | lib/fuse_versionscript | 1 | ||||
-rw-r--r-- | lib/meson.build | 2 | ||||
-rw-r--r-- | lib/modules/iconv.c | 22 | ||||
-rw-r--r-- | lib/mount_util.c | 2 |
10 files changed, 78 insertions, 61 deletions
diff --git a/lib/buffer.c b/lib/buffer.c index 5ab9b87..757807a 100644 --- a/lib/buffer.c +++ b/lib/buffer.c @@ -266,6 +266,9 @@ static int fuse_bufvec_advance(struct fuse_bufvec *bufv, size_t len) { const struct fuse_buf *buf = fuse_bufvec_current(bufv); + if (!buf) + return 0; + bufv->off += len; assert(bufv->off <= buf->size); if (bufv->off == buf->size) { diff --git a/lib/cuse_lowlevel.c b/lib/cuse_lowlevel.c index 9917b64..b70947e 100644 --- a/lib/cuse_lowlevel.c +++ b/lib/cuse_lowlevel.c @@ -319,6 +319,7 @@ struct fuse_session *cuse_lowlevel_setup(int argc, char *argv[], if (res == -1) goto err_sig; + fuse_opt_free_args(&args); return se; err_sig: diff --git a/lib/fuse.c b/lib/fuse.c index b0f5b30..a95d7c1 100755..100644 --- a/lib/fuse.c +++ b/lib/fuse.c @@ -3390,7 +3390,7 @@ static void fuse_lib_opendir(fuse_req_t req, fuse_ino_t ino, dh->len = 0; dh->filled = 0; dh->nodeid = ino; - fuse_mutex_init(&dh->lock); + pthread_mutex_init(&dh->lock, NULL); llfi->fh = (uintptr_t) dh; @@ -3566,7 +3566,7 @@ static int fill_dir_plus(void *dh_, const char *name, const struct stat *statp, return 1; } - if (off && statp && (flags & FUSE_FILL_DIR_PLUS)) { + if (statp && (flags & FUSE_FILL_DIR_PLUS)) { e.attr = *statp; if (!is_dot_or_dotdot(name)) { @@ -3578,6 +3578,11 @@ static int fill_dir_plus(void *dh_, const char *name, const struct stat *statp, } } else { e.attr.st_ino = FUSE_UNKNOWN_INO; + if (statp) { + e.attr.st_mode = statp->st_mode; + if (f->conf.use_ino) + e.attr.st_ino = statp->st_ino; + } if (!f->conf.use_ino && f->conf.readdir_ino) { e.attr.st_ino = (ino_t) lookup_nodeid(f, dh->nodeid, name); @@ -4533,7 +4538,7 @@ static int fuse_session_loop_remember(struct fuse *f) res = poll(&fds, 1, timeout * 1000); if (res == -1) { - if (errno == -EINTR) + if (errno == EINTR) continue; else break; @@ -4569,7 +4574,7 @@ int fuse_loop(struct fuse *f) return fuse_session_loop(f->se); } -FUSE_SYMVER(".symver fuse_loop_mt_32,fuse_loop_mt@@FUSE_3.2"); +FUSE_SYMVER("fuse_loop_mt_32", "fuse_loop_mt@@FUSE_3.2") int fuse_loop_mt_32(struct fuse *f, struct fuse_loop_config *config) { if (f == NULL) @@ -4585,7 +4590,7 @@ int fuse_loop_mt_32(struct fuse *f, struct fuse_loop_config *config) } int fuse_loop_mt_31(struct fuse *f, int clone_fd); -FUSE_SYMVER(".symver fuse_loop_mt_31,fuse_loop_mt@FUSE_3.0"); +FUSE_SYMVER("fuse_loop_mt_31", "fuse_loop_mt@FUSE_3.0") int fuse_loop_mt_31(struct fuse *f, int clone_fd) { struct fuse_loop_config config; @@ -4870,7 +4875,7 @@ void fuse_stop_cleanup_thread(struct fuse *f) } -FUSE_SYMVER(".symver fuse_new_31,fuse_new@@FUSE_3.1"); +FUSE_SYMVER("fuse_new_31", "fuse_new@@FUSE_3.1") struct fuse *fuse_new_31(struct fuse_args *args, const struct fuse_operations *op, size_t op_size, void *user_data) @@ -4973,7 +4978,7 @@ struct fuse *fuse_new_31(struct fuse_args *args, if (node_table_init(&f->id_table) == -1) goto out_free_name_table; - fuse_mutex_init(&f->lock); + pthread_mutex_init(&f->lock, NULL); root = alloc_node(f); if (root == NULL) { @@ -5024,7 +5029,7 @@ out: /* Emulates 3.0-style fuse_new(), which processes --help */ struct fuse *fuse_new_30(struct fuse_args *args, const struct fuse_operations *op, size_t op_size, void *private_data); -FUSE_SYMVER(".symver fuse_new_30,fuse_new@FUSE_3.0"); +FUSE_SYMVER("fuse_new_30", "fuse_new@FUSE_3.0") struct fuse *fuse_new_30(struct fuse_args *args, const struct fuse_operations *op, size_t op_size, void *user_data) diff --git a/lib/fuse_loop_mt.c b/lib/fuse_loop_mt.c index 445e9a0..8fcc46c 100644 --- a/lib/fuse_loop_mt.c +++ b/lib/fuse_loop_mt.c @@ -32,7 +32,6 @@ struct fuse_worker { struct fuse_worker *prev; struct fuse_worker *next; pthread_t thread_id; - size_t bufsize; // We need to include fuse_buf so that we can properly free // it when a thread is terminated by pthread_cancel(). @@ -65,7 +64,7 @@ static struct fuse_chan *fuse_chan_new(int fd) memset(ch, 0, sizeof(*ch)); ch->fd = fd; ch->ctr = 1; - fuse_mutex_init(&ch->lock); + pthread_mutex_init(&ch->lock, NULL); return ch; } @@ -304,7 +303,7 @@ static void fuse_join_worker(struct fuse_mt *mt, struct fuse_worker *w) free(w); } -FUSE_SYMVER(".symver fuse_session_loop_mt_32,fuse_session_loop_mt@@FUSE_3.2"); +FUSE_SYMVER("fuse_session_loop_mt_32", "fuse_session_loop_mt@@FUSE_3.2") int fuse_session_loop_mt_32(struct fuse_session *se, struct fuse_loop_config *config) { int err; @@ -321,7 +320,7 @@ int fuse_session_loop_mt_32(struct fuse_session *se, struct fuse_loop_config *co mt.main.thread_id = pthread_self(); mt.main.prev = mt.main.next = &mt.main; sem_init(&mt.finish, 0, 0); - fuse_mutex_init(&mt.lock); + pthread_mutex_init(&mt.lock, NULL); pthread_mutex_lock(&mt.lock); err = fuse_loop_start_thread(&mt); @@ -352,7 +351,7 @@ int fuse_session_loop_mt_32(struct fuse_session *se, struct fuse_loop_config *co } int fuse_session_loop_mt_31(struct fuse_session *se, int clone_fd); -FUSE_SYMVER(".symver fuse_session_loop_mt_31,fuse_session_loop_mt@FUSE_3.0"); +FUSE_SYMVER("fuse_session_loop_mt_31", "fuse_session_loop_mt@FUSE_3.0") int fuse_session_loop_mt_31(struct fuse_session *se, int clone_fd) { struct fuse_loop_config config; diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c index 459fca5..aee22b4 100644 --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -156,7 +156,7 @@ static struct fuse_req *fuse_ll_alloc_req(struct fuse_session *se) req->se = se; req->ctr = 1; list_init_req(req); - fuse_mutex_init(&req->lock); + pthread_mutex_init(&req->lock, NULL); } return req; @@ -168,6 +168,7 @@ static int fuse_send_msg(struct fuse_session *se, struct fuse_chan *ch, { struct fuse_out_header *out = iov[0].iov_base; + assert(se != NULL); out->len = iov_length(iov, count); if (se->debug) { if (out->unique == 0) { @@ -190,8 +191,6 @@ static int fuse_send_msg(struct fuse_session *se, struct fuse_chan *ch, int err = errno; if (res == -1) { - assert(se != NULL); - /* ENOENT means the operation was interrupted */ if (!fuse_session_exited(se) && err != ENOENT) perror("fuse: writing device"); @@ -755,7 +754,7 @@ static int fuse_send_data_iov(struct fuse_session *se, struct fuse_chan *ch, struct fuse_ll_pipe *llp; int splice_flags; size_t pipesize; - size_t total_fd_size; + size_t total_buf_size; size_t idx; size_t headerlen; struct fuse_bufvec pipe_buf = FUSE_BUFVEC_INIT(len); @@ -766,15 +765,13 @@ static int fuse_send_data_iov(struct fuse_session *se, struct fuse_chan *ch, if (flags & FUSE_BUF_NO_SPLICE) goto fallback; - total_fd_size = 0; + total_buf_size = 0; for (idx = buf->idx; idx < buf->count; idx++) { - if (buf->buf[idx].flags & FUSE_BUF_IS_FD) { - total_fd_size = buf->buf[idx].size; - if (idx == buf->idx) - total_fd_size -= buf->off; - } + total_buf_size += buf->buf[idx].size; + if (idx == buf->idx) + total_buf_size -= buf->off; } - if (total_fd_size < 2 * pagesize) + if (total_buf_size < 2 * pagesize) goto fallback; if (se->conn.proto_minor < 14 || @@ -2006,7 +2003,10 @@ static void do_lseek(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) fuse_reply_err(req, ENOSYS); } -static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +/* Prevent bogus data races (bogus since "init" is called before + * multi-threading becomes relevant */ +static __attribute__((no_sanitize("thread"))) +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; @@ -2078,8 +2078,12 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) se->conn.capable |= FUSE_CAP_POSIX_ACL; if (arg->flags & FUSE_HANDLE_KILLPRIV) se->conn.capable |= FUSE_CAP_HANDLE_KILLPRIV; + if (arg->flags & FUSE_CACHE_SYMLINKS) + se->conn.capable |= FUSE_CAP_CACHE_SYMLINKS; if (arg->flags & FUSE_NO_OPENDIR_SUPPORT) se->conn.capable |= FUSE_CAP_NO_OPENDIR_SUPPORT; + if (arg->flags & FUSE_EXPLICIT_INVAL_DATA) + se->conn.capable |= FUSE_CAP_EXPLICIT_INVAL_DATA; if (!(arg->flags & FUSE_MAX_PAGES)) { size_t max_bufsize = FUSE_DEFAULT_MAX_PAGES_PER_REQ * getpagesize() @@ -2204,6 +2208,10 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) outarg.flags |= FUSE_POSIX_ACL; if (se->conn.want & FUSE_CAP_PASSTHROUGH) outarg.flags |= FUSE_PASSTHROUGH; + if (se->conn.want & FUSE_CAP_CACHE_SYMLINKS) + outarg.flags |= FUSE_CACHE_SYMLINKS; + if (se->conn.want & FUSE_CAP_EXPLICIT_INVAL_DATA) + outarg.flags |= FUSE_EXPLICIT_INVAL_DATA; outarg.max_readahead = se->conn.max_readahead; outarg.max_write = se->conn.max_write; if (se->conn.proto_minor >= 13) { @@ -2344,7 +2352,7 @@ int fuse_lowlevel_notify_inval_inode(struct fuse_session *se, fuse_ino_t ino, if (!se) return -EINVAL; - if (se->conn.proto_major < 6 || se->conn.proto_minor < 12) + if (se->conn.proto_minor < 12) return -ENOSYS; outarg.ino = ino; @@ -2366,7 +2374,7 @@ int fuse_lowlevel_notify_inval_entry(struct fuse_session *se, fuse_ino_t parent, if (!se) return -EINVAL; - if (se->conn.proto_major < 6 || se->conn.proto_minor < 12) + if (se->conn.proto_minor < 12) return -ENOSYS; outarg.parent = parent; @@ -2391,7 +2399,7 @@ int fuse_lowlevel_notify_delete(struct fuse_session *se, if (!se) return -EINVAL; - if (se->conn.proto_major < 6 || se->conn.proto_minor < 18) + if (se->conn.proto_minor < 18) return -ENOSYS; outarg.parent = parent; @@ -2420,7 +2428,7 @@ int fuse_lowlevel_notify_store(struct fuse_session *se, fuse_ino_t ino, if (!se) return -EINVAL; - if (se->conn.proto_major < 6 || se->conn.proto_minor < 15) + if (se->conn.proto_minor < 15) return -ENOSYS; out.unique = 0; @@ -2498,7 +2506,7 @@ int fuse_lowlevel_notify_retrieve(struct fuse_session *se, fuse_ino_t ino, if (!se) return -EINVAL; - if (se->conn.proto_major < 6 || se->conn.proto_minor < 15) + if (se->conn.proto_minor < 15) return -ENOSYS; rreq = malloc(sizeof(*rreq)); @@ -3092,7 +3100,7 @@ struct fuse_session *fuse_session_new(struct fuse_args *args, list_init_req(&se->interrupts); list_init_nreq(&se->notify_list); se->notify_ctr = 1; - fuse_mutex_init(&se->lock); + pthread_mutex_init(&se->lock, NULL); err = pthread_key_create(&se->pipe_key, fuse_ll_pipe_destructor); if (err) { @@ -3113,7 +3121,8 @@ out5: out4: fuse_opt_free_args(args); out3: - free(mo); + if (mo != NULL) + destroy_mount_opts(mo); out2: free(se); out1: @@ -3179,6 +3188,7 @@ void fuse_session_unmount(struct fuse_session *se) { if (se->mountpoint != NULL) { fuse_kern_unmount(se->mountpoint, se->fd); + se->fd = -1; free(se->mountpoint); se->mountpoint = NULL; } @@ -3254,17 +3264,22 @@ int fuse_req_getgroups(fuse_req_t req, int size, gid_t list[]) } #endif +/* Prevent spurious data race warning - we don't care + * about races for this flag */ +__attribute__((no_sanitize_thread)) void fuse_session_exit(struct fuse_session *se) { se->exited = 1; } +__attribute__((no_sanitize_thread)) void fuse_session_reset(struct fuse_session *se) { se->exited = 0; se->error = 0; } +__attribute__((no_sanitize_thread)) int fuse_session_exited(struct fuse_session *se) { return se->exited; diff --git a/lib/fuse_misc.h b/lib/fuse_misc.h index 2f6663e..f956ab7 100644 --- a/lib/fuse_misc.h +++ b/lib/fuse_misc.h @@ -10,27 +10,16 @@ /* 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) +#ifndef __APPLE__ +# if HAVE_SYMVER_ATTRIBUTE +# define FUSE_SYMVER(sym1, sym2) __attribute__ ((symver (sym2))) +# else +# define FUSE_SYMVER(sym1, sym2) __asm__("\t.symver " sym1 "," sym2); +# endif #else -#define FUSE_SYMVER(x) -#endif - -#ifndef USE_UCLIBC -#define fuse_mutex_init(mut) pthread_mutex_init(mut, NULL) -#else -/* Is this hack still needed? */ -static inline void fuse_mutex_init(pthread_mutex_t *mut) -{ - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP); - pthread_mutex_init(mut, &attr); - pthread_mutexattr_destroy(&attr); -} +#define FUSE_SYMVER(sym1, sym2) #endif #ifdef HAVE_STRUCT_STAT_ST_ATIM diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript index b01699a..35964f3 100644 --- a/lib/fuse_versionscript +++ b/lib/fuse_versionscript @@ -145,6 +145,7 @@ FUSE_3.2 { global: fuse_session_loop_mt; fuse_session_loop_mt_31; + fuse_session_loop_mt_32; fuse_loop_mt; fuse_loop_mt_31; } FUSE_3.1; diff --git a/lib/meson.build b/lib/meson.build index 28f0aee..98461d8 100644 --- a/lib/meson.build +++ b/lib/meson.build @@ -37,7 +37,7 @@ libfuse = library('fuse3', libfuse_sources, version: meson.project_version(), soversion: '3', include_directories: include_dirs, dependencies: deps, install: true, link_depends: 'fuse_versionscript', - c_args: [ '-DFUSE_USE_VERSION=34', + c_args: [ '-DFUSE_USE_VERSION=35', '-DFUSERMOUNT_DIR="@0@"'.format(fusermount_path) ], link_args: ['-Wl,--version-script,' + meson.current_source_dir() + '/fuse_versionscript' ]) diff --git a/lib/modules/iconv.c b/lib/modules/iconv.c index eb5edd8..0ec3c2b 100644 --- a/lib/modules/iconv.c +++ b/lib/modules/iconv.c @@ -638,13 +638,18 @@ static const struct fuse_opt iconv_opts[] = { static void iconv_help(void) { - char *old = strdup(setlocale(LC_CTYPE, "")); - char *charmap = strdup(nl_langinfo(CODESET)); - setlocale(LC_CTYPE, old); - free(old); + char *charmap; + const char *old = setlocale(LC_CTYPE, ""); + + charmap = strdup(nl_langinfo(CODESET)); + if (old) + setlocale(LC_CTYPE, old); + else + perror("setlocale"); + 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", +" -o to_code=CHARSET new encoding of the file names (default: %s)\n", charmap); free(charmap); } @@ -667,7 +672,7 @@ static struct fuse_fs *iconv_new(struct fuse_args *args, { struct fuse_fs *fs; struct iconv *ic; - char *old = NULL; + const char *old = NULL; const char *from; const char *to; @@ -689,7 +694,7 @@ static struct fuse_fs *iconv_new(struct fuse_args *args, to = ic->to_code ? ic->to_code : ""; /* FIXME: detect charset equivalence? */ if (!to[0]) - old = strdup(setlocale(LC_CTYPE, "")); + old = setlocale(LC_CTYPE, ""); ic->tofs = iconv_open(from, to); if (ic->tofs == (iconv_t) -1) { fuse_log(FUSE_LOG_ERR, "fuse-iconv: cannot convert from %s to %s\n", @@ -704,7 +709,7 @@ static struct fuse_fs *iconv_new(struct fuse_args *args, } if (old) { setlocale(LC_CTYPE, old); - free(old); + old = NULL; } ic->next = next[0]; @@ -724,7 +729,6 @@ out_free: free(ic); if (old) { setlocale(LC_CTYPE, old); - free(old); } return NULL; } diff --git a/lib/mount_util.c b/lib/mount_util.c index f1d2325..35e9948 100644 --- a/lib/mount_util.c +++ b/lib/mount_util.c @@ -30,7 +30,7 @@ #include <sys/mount.h> #include <sys/param.h> -#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) +#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) #define umount2(mnt, flags) unmount(mnt, ((flags) == 2) ? MNT_FORCE : 0) #endif |