diff --git a/Makefile b/Makefile index 24fd2120..83e25ab6 100644 --- a/Makefile +++ b/Makefile @@ -34,6 +34,7 @@ TOUCH ?= touch BUILDDIR := build GITHUB_REPO ?= "https://github.com/trapexit/mergerfs" +RELEASE_SAMPLE ?= "debian:13.amd64" ifndef GIT_REPO ifneq ($(shell $(GIT) --version 2> /dev/null),) @@ -49,7 +50,22 @@ UGID_USE_RWLOCK ?= 0 ifdef NDEBUG OPT_FLAGS := -O2 -DNDEBUG else -OPT_FLAGS := -O0 -g -fno-omit-frame-pointer -DDEBUG +ifdef SANITIZE +ifeq ($(SANITIZE),1) + override SANITIZE := -fsanitize=address,undefined,leak +else + override SANITIZE := -fsanitize=$(SANITIZE) +endif +endif +OPT_FLAGS := -O0 \ + -g \ + -fno-omit-frame-pointer \ + $(SANITIZE) \ + -fstack-protector-strong \ + -Wextra \ + -Werror \ + -Wno-unused-parameter \ + -DDEBUG endif ifdef STATIC @@ -332,7 +348,7 @@ endef release: $(call build_release,"all") release-sample: - $(call build_release,"debian:13.amd64") + $(call build_release,$(RELEASE_SAMPLE)) release-amd64: $(call build_release,"amd64") release-arm64: diff --git a/libfuse/Makefile b/libfuse/Makefile index 45e198b1..e1e6f222 100644 --- a/libfuse/Makefile +++ b/libfuse/Makefile @@ -33,7 +33,22 @@ endif ifeq ($(NDEBUG),1) OPT_FLAGS := -O2 -DNDEBUG else -OPT_FLAGS := -O0 -g -DDEBUG -fno-omit-frame-pointer +ifdef SANITIZE +ifeq ($(SANITIZE),1) + override SANITIZE := -fsanitize=address,undefined,leak +else + override SANITIZE := -fsanitize=$(SANITIZE) +endif +endif +OPT_FLAGS := -O0 \ + -g \ + -fno-omit-frame-pointer \ + $(SANITIZE) \ + -fstack-protector-strong \ + -Wextra \ + -Werror \ + -Wno-unused-parameter \ + -DDEBUG endif ifeq ($(LTO),1) @@ -60,7 +75,6 @@ INSTALLMAN1DIR ?= $(DESTDIR)$(MAN1DIR) BUILDDIR := build SRC_C = \ - lib/buffer.c \ lib/crc32b.c \ lib/fuse_opt.c \ lib/fuse_session.c \ diff --git a/libfuse/include/fuse_common.h b/libfuse/include/fuse_common.h index 78cbbce1..97ff00f6 100644 --- a/libfuse/include/fuse_common.h +++ b/libfuse/include/fuse_common.h @@ -330,70 +330,6 @@ struct fuse_buf { off_t pos; }; -/** - * Data buffer vector - * - * An array of data buffers, each containing a memory pointer or a - * file descriptor. - * - * Allocate dynamically to add more than one buffer. - */ -struct fuse_bufvec { - /** - * Number of buffers in the array - */ - size_t count; - - /** - * Index of current buffer within the array - */ - size_t idx; - - /** - * Current offset within the current buffer - */ - size_t off; - - /** - * Array of buffers - */ - struct fuse_buf buf[1]; -}; - -/* Initialize bufvec with a single buffer of given size */ -#define FUSE_BUFVEC_INIT(size__) \ - ((struct fuse_bufvec) { \ - /* .count= */ 1, \ - /* .idx = */ 0, \ - /* .off = */ 0, \ - /* .buf = */ { /* [0] = */ { \ - /* .size = */ (size__), \ - /* .flags = */ (enum fuse_buf_flags) 0, \ - /* .mem = */ NULL, \ - /* .fd = */ -1, \ - /* .pos = */ 0, \ - } } \ - } ) - -/** - * Get total size of data in a fuse buffer vector - * - * @param bufv buffer vector - * @return size of data - */ -size_t fuse_buf_size(const struct fuse_bufvec *bufv); - -/** - * Copy data from one buffer vector to another - * - * @param dst destination buffer vector - * @param src source buffer vector - * @param flags flags controlling the copy - * @return actual number of bytes copied or -errno on error - */ -ssize_t fuse_buf_copy(struct fuse_bufvec *dst, struct fuse_bufvec *src, - enum fuse_buf_copy_flags flags); - /* ----------------------------------------------------------- * * Signal handling * * ----------------------------------------------------------- */ diff --git a/libfuse/include/fuse_lowlevel.h b/libfuse/include/fuse_lowlevel.h index 40250096..801dc74f 100644 --- a/libfuse/include/fuse_lowlevel.h +++ b/libfuse/include/fuse_lowlevel.h @@ -472,30 +472,6 @@ int fuse_lowlevel_notify_delete(struct fuse_chan *ch, uint64_t parent, uint64_t child, const char *name, size_t namelen); -/** - * Store data to the kernel buffers - * - * Synchronously store data in the kernel buffers belonging to the - * given inode. The stored data is marked up-to-date (no read will be - * performed against it, unless it's invalidated or evicted from the - * cache). - * - * If the stored data overflows the current file size, then the size - * is extended, similarly to a write(2) on the filesystem. - * - * If this function returns an error, then the store wasn't fully - * completed, but it may have been partially completed. - * - * @param ch the channel through which to send the invalidation - * @param ino the inode number - * @param offset the starting offset into the file to store to - * @param bufv buffer vector - * @param flags flags controlling the copy - * @return zero for success, -errno for failure - */ -int fuse_lowlevel_notify_store(struct fuse_chan *ch, uint64_t ino, - off_t offset, struct fuse_bufvec *bufv, - enum fuse_buf_copy_flags flags); /** * Retrieve data from the kernel buffers * diff --git a/libfuse/lib/buffer.c b/libfuse/lib/buffer.c deleted file mode 100644 index fea1bde4..00000000 --- a/libfuse/lib/buffer.c +++ /dev/null @@ -1,316 +0,0 @@ -/* - FUSE: Filesystem in Userspace - Copyright (C) 2010 Miklos Szeredi - - This program can be distributed under the terms of the GNU LGPLv2. - See the file COPYING.LIB -*/ - -#define _GNU_SOURCE - -#include "fuse_i.h" -#include "fuse_lowlevel.h" -#include -#include -#include -#include - -size_t fuse_buf_size(const struct fuse_bufvec *bufv) -{ - size_t i; - size_t size = 0; - - for (i = 0; i < bufv->count; i++) { - if (bufv->buf[i].size == SIZE_MAX) - size = SIZE_MAX; - else - size += bufv->buf[i].size; - } - - return size; -} - -static size_t min_size(size_t s1, size_t s2) -{ - return s1 < s2 ? s1 : s2; -} - -static ssize_t fuse_buf_write(const struct fuse_buf *dst, size_t dst_off, - const struct fuse_buf *src, size_t src_off, - size_t len) -{ - ssize_t res = 0; - size_t copied = 0; - - while (len) { - if (dst->flags & FUSE_BUF_FD_SEEK) { - res = pwrite(dst->fd, src->mem + src_off, len, - dst->pos + dst_off); - } else { - res = write(dst->fd, src->mem + src_off, len); - } - if (res == -1) { - if (!copied) - return -errno; - break; - } - if (res == 0) - break; - - copied += res; - if (!(dst->flags & FUSE_BUF_FD_RETRY)) - break; - - src_off += res; - dst_off += res; - len -= res; - } - - return copied; -} - -static ssize_t fuse_buf_read(const struct fuse_buf *dst, size_t dst_off, - const struct fuse_buf *src, size_t src_off, - size_t len) -{ - ssize_t res = 0; - size_t copied = 0; - - while (len) { - if (src->flags & FUSE_BUF_FD_SEEK) { - res = pread(src->fd, dst->mem + dst_off, len, - src->pos + src_off); - } else { - res = read(src->fd, dst->mem + dst_off, len); - } - if (res == -1) { - if (!copied) - return -errno; - break; - } - if (res == 0) - break; - - copied += res; - if (!(src->flags & FUSE_BUF_FD_RETRY)) - break; - - dst_off += res; - src_off += res; - len -= res; - } - - return copied; -} - -static ssize_t fuse_buf_fd_to_fd(const struct fuse_buf *dst, size_t dst_off, - const struct fuse_buf *src, size_t src_off, - size_t len) -{ - char buf[4096]; - struct fuse_buf tmp = { - .size = sizeof(buf), - .flags = 0, - }; - ssize_t res; - size_t copied = 0; - - tmp.mem = buf; - - while (len) { - size_t this_len = min_size(tmp.size, len); - size_t read_len; - - res = fuse_buf_read(&tmp, 0, src, src_off, this_len); - if (res < 0) { - if (!copied) - return res; - break; - } - if (res == 0) - break; - - read_len = res; - res = fuse_buf_write(dst, dst_off, &tmp, 0, read_len); - if (res < 0) { - if (!copied) - return res; - break; - } - if (res == 0) - break; - - copied += res; - - if (res < this_len) - break; - - dst_off += res; - src_off += res; - len -= res; - } - - return copied; -} - -#ifdef HAVE_SPLICE -static ssize_t fuse_buf_splice(const struct fuse_buf *dst, size_t dst_off, - const struct fuse_buf *src, size_t src_off, - size_t len, enum fuse_buf_copy_flags flags) -{ - int splice_flags = 0; - off_t *srcpos = NULL; - off_t *dstpos = NULL; - off_t srcpos_val; - off_t dstpos_val; - ssize_t res; - size_t copied = 0; - - if (flags & FUSE_BUF_SPLICE_MOVE) - splice_flags |= SPLICE_F_MOVE; - if (flags & FUSE_BUF_SPLICE_NONBLOCK) - splice_flags |= SPLICE_F_NONBLOCK; - - if (src->flags & FUSE_BUF_FD_SEEK) { - srcpos_val = src->pos + src_off; - srcpos = &srcpos_val; - } - if (dst->flags & FUSE_BUF_FD_SEEK) { - dstpos_val = dst->pos + dst_off; - dstpos = &dstpos_val; - } - - while (len) { - res = splice(src->fd, srcpos, dst->fd, dstpos, len, splice_flags); - if (res == -1) { - if (copied) - break; - - if (errno != EINVAL || (flags & FUSE_BUF_FORCE_SPLICE)) - return -errno; - - /* Maybe splice is not supported for this combination */ - return fuse_buf_fd_to_fd(dst, dst_off, src, src_off, - len); - } - if (res == 0) - break; - - copied += res; - if (!(src->flags & FUSE_BUF_FD_RETRY) && - !(dst->flags & FUSE_BUF_FD_RETRY)) { - break; - } - - len -= res; - } - - return copied; -} -#else -static ssize_t fuse_buf_splice(const struct fuse_buf *dst, size_t dst_off, - const struct fuse_buf *src, size_t src_off, - size_t len, enum fuse_buf_copy_flags flags) -{ - (void) flags; - - return fuse_buf_fd_to_fd(dst, dst_off, src, src_off, len); -} -#endif - - -static ssize_t fuse_buf_copy_one(const struct fuse_buf *dst, size_t dst_off, - const struct fuse_buf *src, size_t src_off, - size_t len, enum fuse_buf_copy_flags flags) -{ - int src_is_fd = src->flags & FUSE_BUF_IS_FD; - int dst_is_fd = dst->flags & FUSE_BUF_IS_FD; - - if (!src_is_fd && !dst_is_fd) { - char *dstmem = dst->mem + dst_off; - char *srcmem = src->mem + src_off; - - if (dstmem != srcmem) { - if (dstmem + len <= srcmem || srcmem + len <= dstmem) - memcpy(dstmem, srcmem, len); - else - memmove(dstmem, srcmem, len); - } - - return len; - } else if (!src_is_fd) { - return fuse_buf_write(dst, dst_off, src, src_off, len); - } else if (!dst_is_fd) { - return fuse_buf_read(dst, dst_off, src, src_off, len); - } else if (flags & FUSE_BUF_NO_SPLICE) { - return fuse_buf_fd_to_fd(dst, dst_off, src, src_off, len); - } else { - return fuse_buf_splice(dst, dst_off, src, src_off, len, flags); - } -} - -static const struct fuse_buf *fuse_bufvec_current(struct fuse_bufvec *bufv) -{ - if (bufv->idx < bufv->count) - return &bufv->buf[bufv->idx]; - else - return NULL; -} - -static int fuse_bufvec_advance(struct fuse_bufvec *bufv, size_t len) -{ - const struct fuse_buf *buf = fuse_bufvec_current(bufv); - - bufv->off += len; - assert(bufv->off <= buf->size); - if (bufv->off == buf->size) { - assert(bufv->idx < bufv->count); - bufv->idx++; - if (bufv->idx == bufv->count) - return 0; - bufv->off = 0; - } - return 1; -} - -ssize_t fuse_buf_copy(struct fuse_bufvec *dstv, struct fuse_bufvec *srcv, - enum fuse_buf_copy_flags flags) -{ - size_t copied = 0; - - if (dstv == srcv) - return fuse_buf_size(dstv); - - for (;;) { - const struct fuse_buf *src = fuse_bufvec_current(srcv); - const struct fuse_buf *dst = fuse_bufvec_current(dstv); - size_t src_len; - size_t dst_len; - size_t len; - ssize_t res; - - if (src == NULL || dst == NULL) - break; - - src_len = src->size - srcv->off; - dst_len = dst->size - dstv->off; - len = min_size(src_len, dst_len); - - res = fuse_buf_copy_one(dst, dstv->off, src, srcv->off, len, flags); - if (res < 0) { - if (!copied) - return res; - break; - } - copied += res; - - if (!fuse_bufvec_advance(srcv, res) || - !fuse_bufvec_advance(dstv, res)) - break; - - if (res < len) - break; - } - - return copied; -} diff --git a/libfuse/lib/crc32b.c b/libfuse/lib/crc32b.c index 39453422..f51605a9 100644 --- a/libfuse/lib/crc32b.c +++ b/libfuse/lib/crc32b.c @@ -78,8 +78,8 @@ crc32b_continue(const void *buf_, const crc32b_t len_, const crc32b_t crc_) { - int i; char *buf; + crc32b_t i; crc32b_t crc; crc = crc_; diff --git a/libfuse/lib/fuse.cpp b/libfuse/lib/fuse.cpp index 554e7b9e..1c5b15b8 100644 --- a/libfuse/lib/fuse.cpp +++ b/libfuse/lib/fuse.cpp @@ -152,7 +152,7 @@ struct fuse_dh fuse_dirents_t d; }; -static struct fuse f = {0}; +static struct fuse f = {}; /* Why was the nodeid:generation logic simplified? @@ -1020,7 +1020,7 @@ get_path_common(uint64_t nodeid, err = try_get_path(nodeid,name,path,wnode,true); if(err == -EAGAIN) { - struct lock_queue_element qe = {0}; + struct lock_queue_element qe = {}; qe.nodeid1 = nodeid; qe.name1 = name; @@ -1079,7 +1079,7 @@ get_path2(uint64_t nodeid1, path1,path2,wnode1,wnode2); if(err == -EAGAIN) { - struct lock_queue_element qe = {0}; + struct lock_queue_element qe = {}; qe.nodeid1 = nodeid1; qe.name1 = name1; @@ -1157,7 +1157,7 @@ forget_node(const uint64_t nodeid, */ while(node->nlookup == nlookup && node->treelock) { - struct lock_queue_element qe = {0}; + struct lock_queue_element qe = {}; qe.nodeid1 = nodeid; @@ -1389,7 +1389,7 @@ fuse_lib_lookup(fuse_req_t *req_, char *fusepath; const char *name; node_t *dot = NULL; - struct fuse_entry_param e = {0}; + struct fuse_entry_param e = {}; name = (const char*)fuse_hdr_arg(hdr_); nodeid = hdr_->nodeid; @@ -1622,7 +1622,7 @@ fuse_lib_setattr(fuse_req_t *req_, struct fuse_in_header *hdr_) { uint64_t fh; - struct stat stbuf = {0}; + struct stat stbuf = {}; char *fusepath; int err; fuse_timeouts_t timeout; @@ -1927,7 +1927,7 @@ fuse_lib_symlink(fuse_req_t *req_, char *fusepath; const char *name; const char *linkname; - struct fuse_entry_param e = {0}; + struct fuse_entry_param e = {}; name = (const char*)fuse_hdr_arg(hdr_); linkname = (name + strlen(name) + 1); @@ -2017,7 +2017,7 @@ fuse_lib_link(fuse_req_t *req_, char *newpath; const char *newname; struct fuse_link_in *arg; - struct fuse_entry_param e = {0}; + struct fuse_entry_param e = {}; arg = (fuse_link_in*)fuse_hdr_arg(hdr_); newname = (const char*)PARAM(arg); @@ -2074,7 +2074,7 @@ fuse_lib_create(fuse_req_t *req_, char *fusepath; const char *name; uint64_t new_nodeid; - fuse_file_info_t ffi = {0}; + fuse_file_info_t ffi = {}; struct fuse_entry_param e; struct fuse_create_in *arg; @@ -2188,7 +2188,7 @@ fuse_lib_open(fuse_req_t *req_, { int err; char *fusepath; - fuse_file_info_t ffi = {0}; + fuse_file_info_t ffi = {}; struct fuse_open_in *arg; arg = (fuse_open_in*)fuse_hdr_arg(hdr_); @@ -2231,7 +2231,7 @@ fuse_lib_read(fuse_req_t *req_, struct fuse_in_header *hdr_) { int res; - fuse_file_info_t ffi = {0}; + fuse_file_info_t ffi = {}; struct fuse_read_in *arg; fuse_msgbuf_t *msgbuf; @@ -2266,7 +2266,7 @@ fuse_lib_write(fuse_req_t *req_, { int res; char *data; - fuse_file_info_t ffi = {0}; + fuse_file_info_t ffi = {}; struct fuse_write_in *arg; arg = (fuse_write_in*)fuse_hdr_arg(hdr_); @@ -2335,8 +2335,8 @@ fuse_lib_opendir(fuse_req_t *req_, int err; char *fusepath; struct fuse_dh *dh; - fuse_file_info_t llffi = {0}; - fuse_file_info_t ffi = {0}; + fuse_file_info_t llffi = {}; + fuse_file_info_t ffi = {}; struct fuse_open_in *arg; arg = (fuse_open_in*)fuse_hdr_arg(hdr_); @@ -2422,8 +2422,8 @@ fuse_lib_readdir(fuse_req_t *req_, size_t size; fuse_dirents_t *d; struct fuse_dh *dh; - fuse_file_info_t ffi = {0}; - fuse_file_info_t llffi = {0}; + fuse_file_info_t ffi = {}; + fuse_file_info_t llffi = {}; struct fuse_read_in *arg; arg = (fuse_read_in*)fuse_hdr_arg(hdr_); @@ -2466,8 +2466,8 @@ fuse_lib_readdir_plus(fuse_req_t *req_, size_t size; fuse_dirents_t *d; struct fuse_dh *dh; - fuse_file_info_t ffi = {0}; - fuse_file_info_t llffi = {0}; + fuse_file_info_t ffi = {}; + fuse_file_info_t llffi = {}; struct fuse_read_in *arg; arg = (fuse_read_in*)fuse_hdr_arg(hdr_); @@ -2508,7 +2508,7 @@ fuse_lib_releasedir(fuse_req_t *req_, { struct fuse_dh *dh; fuse_file_info_t ffi; - fuse_file_info_t llffi = {0}; + fuse_file_info_t llffi = {}; struct fuse_release_in *arg; arg = (fuse_release_in*)fuse_hdr_arg(hdr_); @@ -2537,7 +2537,7 @@ fuse_lib_fsyncdir(fuse_req_t *req_, int err; int is_datasync; fuse_file_info_t ffi; - fuse_file_info_t llffi = {0}; + fuse_file_info_t llffi = {}; struct fuse_fsync_in *arg; arg = (fuse_fsync_in*)fuse_hdr_arg(hdr_); @@ -2560,7 +2560,7 @@ fuse_lib_statfs(fuse_req_t *req_, { int err = 0; char *fusepath; - struct statvfs buf = {0}; + struct statvfs buf = {}; fusepath = NULL; if(hdr_->nodeid) @@ -2767,8 +2767,8 @@ fuse_lib_copy_file_range(fuse_req_t *req_, const struct fuse_in_header *hdr_) { ssize_t rv; - fuse_file_info_t ffi_in = {0}; - fuse_file_info_t ffi_out = {0}; + fuse_file_info_t ffi_in = {}; + fuse_file_info_t ffi_out = {}; const struct fuse_copy_file_range_in *arg; arg = (fuse_copy_file_range_in*)fuse_hdr_arg(hdr_); @@ -2825,7 +2825,7 @@ fuse_lib_tmpfile(fuse_req_t *req_, int err; char *fusepath; const char *name; - fuse_file_info_t ffi = {0}; + fuse_file_info_t ffi = {}; struct fuse_entry_param e; struct fuse_create_in *arg; @@ -3072,7 +3072,7 @@ fuse_lib_release(fuse_req_t *req_, struct fuse_in_header *hdr_) { int err = 0; - fuse_file_info_t ffi = {0}; + fuse_file_info_t ffi = {}; struct fuse_release_in *arg; arg = (fuse_release_in*)fuse_hdr_arg(hdr_); @@ -3109,7 +3109,7 @@ fuse_lib_flush(fuse_req_t *req_, struct fuse_in_header *hdr_) { int err; - fuse_file_info_t ffi = {0}; + fuse_file_info_t ffi = {}; struct fuse_flush_in *arg; arg = (fuse_flush_in*)fuse_hdr_arg(hdr_); @@ -3167,7 +3167,7 @@ fuse_lib_getlk(fuse_req_t *req_, lock_t lk; struct flock flk; lock_t *conflict; - fuse_file_info_t ffi = {0}; + fuse_file_info_t ffi = {}; const struct fuse_lk_in *arg; arg = (fuse_lk_in*)fuse_hdr_arg(hdr_); @@ -3270,7 +3270,7 @@ fuse_lib_ioctl(fuse_req_t *req_, int err; char *out_buf = NULL; fuse_file_info_t ffi; - fuse_file_info_t llffi = {0}; + fuse_file_info_t llffi = {}; const void *in_buf; uint32_t out_size; const struct fuse_ioctl_in *arg; @@ -3339,7 +3339,7 @@ fuse_lib_poll(fuse_req_t *req_, { int err; unsigned revents = 0; - fuse_file_info_t ffi = {0}; + fuse_file_info_t ffi = {}; fuse_pollhandle_t *ph = NULL; const struct fuse_poll_in *arg; @@ -3428,7 +3428,7 @@ fuse_prune_some_remembered_nodes(int *offset_) pruned = 0; checked = 0; now = current_time(); - while(*offset_ < kv_size(f.remembered_nodes)) + while(*offset_ < (int)kv_size(f.remembered_nodes)) { time_t age; remembered_node_t *fn = &kv_A(f.remembered_nodes,*offset_); @@ -3913,7 +3913,7 @@ fuse_passthrough_open(const int fd_) { int rv; int dev_fuse_fd; - struct fuse_backing_map bm = {0}; + struct fuse_backing_map bm = {}; dev_fuse_fd = fuse_chan_fd(f.se->ch); bm.fd = fd_; diff --git a/libfuse/lib/fuse_lowlevel.cpp b/libfuse/lib/fuse_lowlevel.cpp index 43cddfe4..c82e95a5 100644 --- a/libfuse/lib/fuse_lowlevel.cpp +++ b/libfuse/lib/fuse_lowlevel.cpp @@ -292,7 +292,7 @@ int fuse_reply_entry(fuse_req_t *req, const struct fuse_entry_param *e) { - struct fuse_entry_out arg = {0}; + struct fuse_entry_out arg = {}; size_t size = req->f->conn.proto_minor < 9 ? FUSE_COMPAT_ENTRY_OUT_SIZE : sizeof(arg); @@ -322,7 +322,7 @@ fuse_reply_create(fuse_req_t *req, const struct fuse_entry_param *e, const fuse_file_info_t *f) { - struct fuse_create_out buf = {0}; + struct fuse_create_out buf = {}; size_t entrysize = req->f->conn.proto_minor < 9 ? FUSE_COMPAT_ENTRY_OUT_SIZE : sizeof(struct fuse_entry_out); struct fuse_entry_out *earg = (struct fuse_entry_out*)&buf.e; @@ -339,7 +339,7 @@ fuse_reply_attr(fuse_req_t *req, const struct stat *attr, const uint64_t timeout) { - struct fuse_attr_out arg = {0}; + struct fuse_attr_out arg = {}; size_t size = req->f->conn.proto_minor < 9 ? FUSE_COMPAT_ATTR_OUT_SIZE : sizeof(arg); @@ -377,7 +377,7 @@ int fuse_reply_open(fuse_req_t *req, const fuse_file_info_t *f) { - struct fuse_open_out arg = {0}; + struct fuse_open_out arg = {}; fill_open(&arg, f); @@ -388,7 +388,7 @@ int fuse_reply_write(fuse_req_t *req, size_t count) { - struct fuse_write_out arg = {0}; + struct fuse_write_out arg = {}; arg.size = count; @@ -403,55 +403,6 @@ fuse_reply_buf(fuse_req_t *req, return send_reply_ok(req, buf, size); } -static -int -fuse_send_data_iov_fallback(struct fuse_ll *f, - struct fuse_chan *ch, - struct iovec *iov, - int iov_count, - struct fuse_bufvec *buf, - size_t len) -{ - int res; - struct fuse_bufvec mem_buf = FUSE_BUFVEC_INIT(len); - - /* Optimize common case */ - if(buf->count == 1 && buf->idx == 0 && buf->off == 0 && - !(buf->buf[0].flags & FUSE_BUF_IS_FD)) - { - /* FIXME: also avoid memory copy if there are multiple buffers - but none of them contain an fd */ - - iov[iov_count].iov_base = buf->buf[0].mem; - iov[iov_count].iov_len = len; - iov_count++; - - return fuse_send_msg(f, ch, iov, iov_count); - } - - fuse_msgbuf_t *msgbuf; - msgbuf = msgbuf_alloc(); - if(msgbuf == NULL) - return -ENOMEM; - - mem_buf.buf[0].mem = msgbuf->mem; - res = fuse_buf_copy(&mem_buf, buf, (fuse_buf_copy_flags)0); - if(res < 0) - { - msgbuf_free(msgbuf); - return -res; - } - len = res; - - iov[iov_count].iov_base = msgbuf->mem; - iov[iov_count].iov_len = len; - iov_count++; - res = fuse_send_msg(f, ch, iov, iov_count); - msgbuf_free(msgbuf); - - return res; -} - struct fuse_ll_pipe { size_t size; @@ -468,21 +419,6 @@ fuse_ll_pipe_free(struct fuse_ll_pipe *llp) free(llp); } -static -int -fuse_send_data_iov(struct fuse_ll *f, - struct fuse_chan *ch, - struct iovec *iov, - int iov_count, - struct fuse_bufvec *buf, - unsigned int flags) -{ - size_t len = fuse_buf_size(buf); - (void) flags; - - return fuse_send_data_iov_fallback(f, ch, iov, iov_count, buf, len); -} - int fuse_reply_data(fuse_req_t *req, char *buf_, @@ -516,7 +452,7 @@ int fuse_reply_statfs(fuse_req_t *req, const struct statvfs *stbuf) { - struct fuse_statfs_out arg = {0}; + struct fuse_statfs_out arg = {}; size_t size = req->f->conn.proto_minor < 4 ? FUSE_COMPAT_STATFS_SIZE : sizeof(arg); @@ -529,7 +465,7 @@ int fuse_reply_xattr(fuse_req_t *req, size_t count) { - struct fuse_getxattr_out arg = {0}; + struct fuse_getxattr_out arg = {}; arg.size = count; @@ -540,7 +476,7 @@ int fuse_reply_lock(fuse_req_t *req, const struct flock *lock) { - struct fuse_lk_out arg = {0}; + struct fuse_lk_out arg = {}; arg.lk.type = lock->l_type; if(lock->l_type != F_UNLCK) @@ -560,7 +496,7 @@ int fuse_reply_bmap(fuse_req_t *req, uint64_t idx) { - struct fuse_bmap_out arg = {0}; + struct fuse_bmap_out arg = {}; arg.block = idx; @@ -595,7 +531,7 @@ fuse_reply_ioctl_retry(fuse_req_t *req, const struct iovec *out_iov, size_t out_count) { - struct fuse_ioctl_out arg = {0}; + struct fuse_ioctl_out arg = {}; struct fuse_ioctl_iovec *in_fiov = NULL; struct fuse_ioctl_iovec *out_fiov = NULL; struct iovec iov[4]; @@ -705,7 +641,7 @@ fuse_reply_ioctl_iov(fuse_req_t *req, int count) { struct iovec *padded_iov; - struct fuse_ioctl_out arg = {0}; + struct fuse_ioctl_out arg = {}; int res; padded_iov = (iovec*)malloc((count + 2) * sizeof(struct iovec)); @@ -728,7 +664,7 @@ int fuse_reply_poll(fuse_req_t *req, unsigned revents) { - struct fuse_poll_out arg = {0}; + struct fuse_poll_out arg = {}; arg.revents = revents; @@ -1015,7 +951,7 @@ do_setlk_common(fuse_req_t *req, int sleep) { struct flock flock; - fuse_file_info_t fi = {0}; + fuse_file_info_t fi = {}; struct fuse_lk_in *arg = (struct fuse_lk_in*)inarg; fi.fh = arg->fh; @@ -1118,7 +1054,7 @@ void do_init(fuse_req_t *req, struct fuse_in_header *hdr_) { - struct fuse_init_out outarg = {0}; + struct fuse_init_out outarg = {}; struct fuse_init_in *arg = (struct fuse_init_in *)&hdr_[1]; struct fuse_ll *f = req->f; size_t bufsize; @@ -1604,50 +1540,6 @@ fuse_lowlevel_notify_delete(struct fuse_chan *ch, return send_notify_iov(f, ch, FUSE_NOTIFY_DELETE, iov, 3); } -int -fuse_lowlevel_notify_store(struct fuse_chan *ch, - uint64_t ino, - off_t offset, - struct fuse_bufvec *bufv, - enum fuse_buf_copy_flags flags) -{ - struct fuse_out_header out; - struct fuse_notify_store_out outarg; - struct fuse_ll *f; - struct iovec iov[3]; - size_t size = fuse_buf_size(bufv); - int res; - - if(!ch) - return -EINVAL; - - f = (struct fuse_ll*)fuse_session_data(fuse_chan_session(ch)); - if(!f) - return -ENODEV; - - if(f->conn.proto_minor < 15) - return -ENOSYS; - - out.unique = 0; - out.error = FUSE_NOTIFY_STORE; - - outarg.nodeid = ino; - outarg.offset = offset; - outarg.size = size; - outarg.padding = 0; - - iov[0].iov_base = &out; - iov[0].iov_len = sizeof(out); - iov[1].iov_base = &outarg; - iov[1].iov_len = sizeof(outarg); - - res = fuse_send_data_iov(f, ch, iov, 2, bufv, flags); - if(res > 0) - res = -res; - - return res; -} - struct fuse_retrieve_req { struct fuse_notify_req nreq; @@ -1825,8 +1717,8 @@ fuse_send_errno(struct fuse_ll *f_, const int errno_, const uint64_t unique_id_) { - struct fuse_out_header out = {0}; - struct iovec iov = {0}; + struct fuse_out_header out = {}; + struct iovec iov = {}; out.unique = unique_id_; out.error = -errno_; diff --git a/libfuse/util/fusermount.c b/libfuse/util/fusermount.c index f60b7af7..982d3345 100644 --- a/libfuse/util/fusermount.c +++ b/libfuse/util/fusermount.c @@ -65,13 +65,13 @@ static int auto_unmount = 0; static const char *get_user_name(void) { - struct passwd *pw = getpwuid(getuid()); - if (pw != NULL && pw->pw_name != NULL) - return pw->pw_name; - else { - fprintf(stderr, "%s: could not determine username\n", progname); - return NULL; - } + struct passwd *pw = getpwuid(getuid()); + if (pw != NULL && pw->pw_name != NULL) + return pw->pw_name; + else { + fprintf(stderr, "%s: could not determine username\n", progname); + return NULL; + } } static uid_t oldfsuid; @@ -79,18 +79,18 @@ static gid_t oldfsgid; static void drop_privs(void) { - if (getuid() != 0) { - oldfsuid = setfsuid(getuid()); - oldfsgid = setfsgid(getgid()); - } + if (getuid() != 0) { + oldfsuid = setfsuid(getuid()); + oldfsgid = setfsgid(getgid()); + } } static void restore_privs(void) { - if (getuid() != 0) { - setfsuid(oldfsuid); - setfsgid(oldfsgid); - } + if (getuid() != 0) { + setfsuid(oldfsuid); + setfsgid(oldfsgid); + } } #ifndef IGNORE_MTAB @@ -99,114 +99,114 @@ static void restore_privs(void) */ static int lock_umount(void) { - const char *mtab_lock = _PATH_MOUNTED ".fuselock"; - int mtablock; - int res; - struct stat mtab_stat; - - /* /etc/mtab could be a symlink to /proc/mounts */ - if (lstat(_PATH_MOUNTED, &mtab_stat) == 0 && S_ISLNK(mtab_stat.st_mode)) - return -1; - - mtablock = open(mtab_lock, O_RDWR | O_CREAT, 0600); - if (mtablock == -1) { - fprintf(stderr, "%s: unable to open fuse lock file: %s\n", - progname, strerror(errno)); - return -1; - } - res = lockf(mtablock, F_LOCK, 0); - if (res < 0) { - fprintf(stderr, "%s: error getting lock: %s\n", progname, - strerror(errno)); - close(mtablock); - return -1; - } - - return mtablock; + const char *mtab_lock = _PATH_MOUNTED ".fuselock"; + int mtablock; + int res; + struct stat mtab_stat; + + /* /etc/mtab could be a symlink to /proc/mounts */ + if (lstat(_PATH_MOUNTED, &mtab_stat) == 0 && S_ISLNK(mtab_stat.st_mode)) + return -1; + + mtablock = open(mtab_lock, O_RDWR | O_CREAT, 0600); + if (mtablock == -1) { + fprintf(stderr, "%s: unable to open fuse lock file: %s\n", + progname, strerror(errno)); + return -1; + } + res = lockf(mtablock, F_LOCK, 0); + if (res < 0) { + fprintf(stderr, "%s: error getting lock: %s\n", progname, + strerror(errno)); + close(mtablock); + return -1; + } + + return mtablock; } static void unlock_umount(int mtablock) { - if (mtablock >= 0) { - int res; - - res = lockf(mtablock, F_ULOCK, 0); - if (res < 0) { - fprintf(stderr, "%s: error releasing lock: %s\n", - progname, strerror(errno)); - } - close(mtablock); - } + if (mtablock >= 0) { + int res; + + res = lockf(mtablock, F_ULOCK, 0); + if (res < 0) { + fprintf(stderr, "%s: error releasing lock: %s\n", + progname, strerror(errno)); + } + close(mtablock); + } } static int add_mount(const char *source, const char *mnt, const char *type, const char *opts) { - return fuse_mnt_add_mount(progname, source, mnt, type, opts); + return fuse_mnt_add_mount(progname, source, mnt, type, opts); } static int may_unmount(const char *mnt, int quiet) { - struct mntent *entp; - FILE *fp; - const char *user = NULL; - char uidstr[32]; - unsigned uidlen = 0; - int found; - const char *mtab = _PATH_MOUNTED; - - user = get_user_name(); - if (user == NULL) - return -1; - - fp = setmntent(mtab, "r"); - if (fp == NULL) { - fprintf(stderr, "%s: failed to open %s: %s\n", progname, mtab, - strerror(errno)); - return -1; - } - - uidlen = sprintf(uidstr, "%u", getuid()); - - found = 0; - while ((entp = getmntent(fp)) != NULL) { - if (!found && strcmp(entp->mnt_dir, mnt) == 0 && - (strcmp(entp->mnt_type, "fuse") == 0 || - strcmp(entp->mnt_type, "fuseblk") == 0 || - strncmp(entp->mnt_type, "fuse.", 5) == 0 || - strncmp(entp->mnt_type, "fuseblk.", 8) == 0)) { - char *p = strstr(entp->mnt_opts, "user="); - if (p && - (p == entp->mnt_opts || *(p-1) == ',') && - strcmp(p + 5, user) == 0) { - found = 1; - break; - } - /* /etc/mtab is a link pointing to - /proc/mounts: */ - else if ((p = - strstr(entp->mnt_opts, "user_id=")) && - (p == entp->mnt_opts || - *(p-1) == ',') && - strncmp(p + 8, uidstr, uidlen) == 0 && - (*(p+8+uidlen) == ',' || - *(p+8+uidlen) == '\0')) { - found = 1; - break; - } - } - } - endmntent(fp); - - if (!found) { - if (!quiet) - fprintf(stderr, - "%s: entry for %s not found in %s\n", - progname, mnt, mtab); - return -1; - } - - return 0; + struct mntent *entp; + FILE *fp; + const char *user = NULL; + char uidstr[32]; + unsigned uidlen = 0; + int found; + const char *mtab = _PATH_MOUNTED; + + user = get_user_name(); + if (user == NULL) + return -1; + + fp = setmntent(mtab, "r"); + if (fp == NULL) { + fprintf(stderr, "%s: failed to open %s: %s\n", progname, mtab, + strerror(errno)); + return -1; + } + + uidlen = sprintf(uidstr, "%u", getuid()); + + found = 0; + while ((entp = getmntent(fp)) != NULL) { + if (!found && strcmp(entp->mnt_dir, mnt) == 0 && + (strcmp(entp->mnt_type, "fuse") == 0 || + strcmp(entp->mnt_type, "fuseblk") == 0 || + strncmp(entp->mnt_type, "fuse.", 5) == 0 || + strncmp(entp->mnt_type, "fuseblk.", 8) == 0)) { + char *p = strstr(entp->mnt_opts, "user="); + if (p && + (p == entp->mnt_opts || *(p-1) == ',') && + strcmp(p + 5, user) == 0) { + found = 1; + break; + } + /* /etc/mtab is a link pointing to + /proc/mounts: */ + else if ((p = + strstr(entp->mnt_opts, "user_id=")) && + (p == entp->mnt_opts || + *(p-1) == ',') && + strncmp(p + 8, uidstr, uidlen) == 0 && + (*(p+8+uidlen) == ',' || + *(p+8+uidlen) == '\0')) { + found = 1; + break; + } + } + } + endmntent(fp); + + if (!found) { + if (!quiet) + fprintf(stderr, + "%s: entry for %s not found in %s\n", + progname, mnt, mtab); + return -1; + } + + return 0; } /* @@ -234,349 +234,349 @@ static int may_unmount(const char *mnt, int quiet) */ static int check_is_mount_child(void *p) { - const char **a = p; - const char *last = a[0]; - const char *mnt = a[1]; - int res; - const char *procmounts = "/proc/mounts"; - int found; - FILE *fp; - struct mntent *entp; - int count; - - res = mount("", "/", "", MS_PRIVATE | MS_REC, NULL); - if (res == -1) { - fprintf(stderr, "%s: failed to mark mounts private: %s\n", - progname, strerror(errno)); - return 1; - } - - fp = setmntent(procmounts, "r"); - if (fp == NULL) { - fprintf(stderr, "%s: failed to open %s: %s\n", progname, - procmounts, strerror(errno)); - return 1; - } - - count = 0; - while (getmntent(fp) != NULL) - count++; - endmntent(fp); - - fp = setmntent(procmounts, "r"); - if (fp == NULL) { - fprintf(stderr, "%s: failed to open %s: %s\n", progname, - procmounts, strerror(errno)); - return 1; - } - - res = mount(".", "/", "", MS_BIND | MS_REC, NULL); - if (res == -1) { - fprintf(stderr, "%s: failed to bind parent to /: %s\n", - progname, strerror(errno)); - return 1; - } - - found = 0; - while ((entp = getmntent(fp)) != NULL) { - if (count > 0) { - count--; - continue; - } - if (entp->mnt_dir[0] == '/' && - strcmp(entp->mnt_dir + 1, last) == 0) { - found = 1; - break; - } - } - endmntent(fp); - - if (!found) { - fprintf(stderr, "%s: %s not mounted\n", progname, mnt); - return 1; - } - - return 0; + const char **a = p; + const char *last = a[0]; + const char *mnt = a[1]; + int res; + const char *procmounts = "/proc/mounts"; + int found; + FILE *fp; + struct mntent *entp; + int count; + + res = mount("", "/", "", MS_PRIVATE | MS_REC, NULL); + if (res == -1) { + fprintf(stderr, "%s: failed to mark mounts private: %s\n", + progname, strerror(errno)); + return 1; + } + + fp = setmntent(procmounts, "r"); + if (fp == NULL) { + fprintf(stderr, "%s: failed to open %s: %s\n", progname, + procmounts, strerror(errno)); + return 1; + } + + count = 0; + while (getmntent(fp) != NULL) + count++; + endmntent(fp); + + fp = setmntent(procmounts, "r"); + if (fp == NULL) { + fprintf(stderr, "%s: failed to open %s: %s\n", progname, + procmounts, strerror(errno)); + return 1; + } + + res = mount(".", "/", "", MS_BIND | MS_REC, NULL); + if (res == -1) { + fprintf(stderr, "%s: failed to bind parent to /: %s\n", + progname, strerror(errno)); + return 1; + } + + found = 0; + while ((entp = getmntent(fp)) != NULL) { + if (count > 0) { + count--; + continue; + } + if (entp->mnt_dir[0] == '/' && + strcmp(entp->mnt_dir + 1, last) == 0) { + found = 1; + break; + } + } + endmntent(fp); + + if (!found) { + fprintf(stderr, "%s: %s not mounted\n", progname, mnt); + return 1; + } + + return 0; } static pid_t clone_newns(void *a) { - char buf[131072]; - char *stack = buf + (sizeof(buf) / 2 - ((size_t) buf & 15)); + char buf[131072]; + char *stack = buf + (sizeof(buf) / 2 - ((size_t) buf & 15)); #ifdef __ia64__ - extern int __clone2(int (*fn)(void *), - void *child_stack_base, size_t stack_size, - int flags, void *arg, pid_t *ptid, - void *tls, pid_t *ctid); + extern int __clone2(int (*fn)(void *), + void *child_stack_base, size_t stack_size, + int flags, void *arg, pid_t *ptid, + void *tls, pid_t *ctid); - return __clone2(check_is_mount_child, stack, sizeof(buf) / 2, - CLONE_NEWNS, a, NULL, NULL, NULL); + return __clone2(check_is_mount_child, stack, sizeof(buf) / 2, + CLONE_NEWNS, a, NULL, NULL, NULL); #else - return clone(check_is_mount_child, stack, CLONE_NEWNS, a); + return clone(check_is_mount_child, stack, CLONE_NEWNS, a); #endif } static int check_is_mount(const char *last, const char *mnt) { - pid_t pid, p; - int status; - const char *a[2] = { last, mnt }; - - pid = clone_newns((void *) a); - if (pid == (pid_t) -1) { - fprintf(stderr, "%s: failed to clone namespace: %s\n", - progname, strerror(errno)); - return -1; - } - p = waitpid(pid, &status, __WCLONE); - if (p == (pid_t) -1) { - fprintf(stderr, "%s: waitpid failed: %s\n", - progname, strerror(errno)); - return -1; - } - if (!WIFEXITED(status)) { - fprintf(stderr, "%s: child terminated abnormally (status %i)\n", - progname, status); - return -1; - } - if (WEXITSTATUS(status) != 0) - return -1; - - return 0; + pid_t pid, p; + int status; + const char *a[2] = { last, mnt }; + + pid = clone_newns((void *) a); + if (pid == (pid_t) -1) { + fprintf(stderr, "%s: failed to clone namespace: %s\n", + progname, strerror(errno)); + return -1; + } + p = waitpid(pid, &status, __WCLONE); + if (p == (pid_t) -1) { + fprintf(stderr, "%s: waitpid failed: %s\n", + progname, strerror(errno)); + return -1; + } + if (!WIFEXITED(status)) { + fprintf(stderr, "%s: child terminated abnormally (status %i)\n", + progname, status); + return -1; + } + if (WEXITSTATUS(status) != 0) + return -1; + + return 0; } static int chdir_to_parent(char *copy, const char **lastp) { - char *tmp; - const char *parent; - char buf[65536]; - int res; - - tmp = strrchr(copy, '/'); - if (tmp == NULL || tmp[1] == '\0') { - fprintf(stderr, "%s: internal error: invalid abs path: <%s>\n", - progname, copy); - return -1; - } - if (tmp != copy) { - *tmp = '\0'; - parent = copy; - *lastp = tmp + 1; - } else if (tmp[1] != '\0') { - *lastp = tmp + 1; - parent = "/"; - } else { - *lastp = "."; - parent = "/"; - } - - res = chdir(parent); - if (res == -1) { - fprintf(stderr, "%s: failed to chdir to %s: %s\n", - progname, parent, strerror(errno)); - return -1; - } - - if (getcwd(buf, sizeof(buf)) == NULL) { - fprintf(stderr, "%s: failed to obtain current directory: %s\n", - progname, strerror(errno)); - return -1; - } - if (strcmp(buf, parent) != 0) { - fprintf(stderr, "%s: mountpoint moved (%s -> %s)\n", progname, - parent, buf); - return -1; - - } - - return 0; + char *tmp; + const char *parent; + char buf[65536]; + int res; + + tmp = strrchr(copy, '/'); + if (tmp == NULL || tmp[1] == '\0') { + fprintf(stderr, "%s: internal error: invalid abs path: <%s>\n", + progname, copy); + return -1; + } + if (tmp != copy) { + *tmp = '\0'; + parent = copy; + *lastp = tmp + 1; + } else if (tmp[1] != '\0') { + *lastp = tmp + 1; + parent = "/"; + } else { + *lastp = "."; + parent = "/"; + } + + res = chdir(parent); + if (res == -1) { + fprintf(stderr, "%s: failed to chdir to %s: %s\n", + progname, parent, strerror(errno)); + return -1; + } + + if (getcwd(buf, sizeof(buf)) == NULL) { + fprintf(stderr, "%s: failed to obtain current directory: %s\n", + progname, strerror(errno)); + return -1; + } + if (strcmp(buf, parent) != 0) { + fprintf(stderr, "%s: mountpoint moved (%s -> %s)\n", progname, + parent, buf); + return -1; + + } + + return 0; } /* Check whether the kernel supports UMOUNT_NOFOLLOW flag */ static int umount_nofollow_support(void) { - int res = umount2("", UMOUNT_UNUSED); - if (res != -1 || errno != EINVAL) - return 0; + int res = umount2("", UMOUNT_UNUSED); + if (res != -1 || errno != EINVAL) + return 0; - res = umount2("", UMOUNT_NOFOLLOW); - if (res != -1 || errno != ENOENT) - return 0; + res = umount2("", UMOUNT_NOFOLLOW); + if (res != -1 || errno != ENOENT) + return 0; - return 1; + return 1; } static int unmount_fuse_locked(const char *mnt, int quiet, int lazy) { - int res; - char *copy; - const char *last; - int umount_flags = lazy ? UMOUNT_DETACH : 0; - - if (getuid() != 0) { - res = may_unmount(mnt, quiet); - if (res == -1) - return -1; - } - - copy = strdup(mnt); - if (copy == NULL) { - fprintf(stderr, "%s: failed to allocate memory\n", progname); - return -1; - } - - res = chdir_to_parent(copy, &last); - if (res == -1) - goto out; - - if (umount_nofollow_support()) { - umount_flags |= UMOUNT_NOFOLLOW; - } else { - res = check_is_mount(last, mnt); - if (res == -1) - goto out; - } - - res = umount2(last, umount_flags); - if (res == -1 && !quiet) { - fprintf(stderr, "%s: failed to unmount %s: %s\n", - progname, mnt, strerror(errno)); - } - -out: - if (res == -1) - return -1; - - res = chdir("/"); - if (res == -1) { - fprintf(stderr, "%s: failed to chdir to '/'\n", progname); - return -1; - } - - return fuse_mnt_remove_mount(progname, mnt); + int res; + char *copy; + const char *last; + int umount_flags = lazy ? UMOUNT_DETACH : 0; + + if (getuid() != 0) { + res = may_unmount(mnt, quiet); + if (res == -1) + return -1; + } + + copy = strdup(mnt); + if (copy == NULL) { + fprintf(stderr, "%s: failed to allocate memory\n", progname); + return -1; + } + + res = chdir_to_parent(copy, &last); + if (res == -1) + goto out; + + if (umount_nofollow_support()) { + umount_flags |= UMOUNT_NOFOLLOW; + } else { + res = check_is_mount(last, mnt); + if (res == -1) + goto out; + } + + res = umount2(last, umount_flags); + if (res == -1 && !quiet) { + fprintf(stderr, "%s: failed to unmount %s: %s\n", + progname, mnt, strerror(errno)); + } + + out: + if (res == -1) + return -1; + + res = chdir("/"); + if (res == -1) { + fprintf(stderr, "%s: failed to chdir to '/'\n", progname); + return -1; + } + + return fuse_mnt_remove_mount(progname, mnt); } static int unmount_fuse(const char *mnt, int quiet, int lazy) { - int res; - int mtablock = lock_umount(); + int res; + int mtablock = lock_umount(); - res = unmount_fuse_locked(mnt, quiet, lazy); - unlock_umount(mtablock); + res = unmount_fuse_locked(mnt, quiet, lazy); + unlock_umount(mtablock); - return res; + return res; } static int count_fuse_fs(void) { - struct mntent *entp; - int count = 0; - const char *mtab = _PATH_MOUNTED; - FILE *fp = setmntent(mtab, "r"); - if (fp == NULL) { - fprintf(stderr, "%s: failed to open %s: %s\n", progname, mtab, - strerror(errno)); - return -1; - } - while ((entp = getmntent(fp)) != NULL) { - if (strcmp(entp->mnt_type, "fuse") == 0 || - strncmp(entp->mnt_type, "fuse.", 5) == 0) - count ++; - } - endmntent(fp); - return count; + struct mntent *entp; + int count = 0; + const char *mtab = _PATH_MOUNTED; + FILE *fp = setmntent(mtab, "r"); + if (fp == NULL) { + fprintf(stderr, "%s: failed to open %s: %s\n", progname, mtab, + strerror(errno)); + return -1; + } + while ((entp = getmntent(fp)) != NULL) { + if (strcmp(entp->mnt_type, "fuse") == 0 || + strncmp(entp->mnt_type, "fuse.", 5) == 0) + count ++; + } + endmntent(fp); + return count; } #else /* IGNORE_MTAB */ static int count_fuse_fs() { - return 0; + return 0; } static int add_mount(const char *source, const char *mnt, const char *type, const char *opts) { - (void) source; - (void) mnt; - (void) type; - (void) opts; - return 0; + (void) source; + (void) mnt; + (void) type; + (void) opts; + return 0; } static int unmount_fuse(const char *mnt, int quiet, int lazy) { - return fuse_mnt_umount(progname, mnt, mnt, lazy); + return fuse_mnt_umount(progname, mnt, mnt, lazy); } #endif /* IGNORE_MTAB */ static void strip_line(char *line) { - char *s = strchr(line, '#'); - if (s != NULL) - s[0] = '\0'; - for (s = line + strlen(line) - 1; - s >= line && isspace((unsigned char) *s); s--); - s[1] = '\0'; - for (s = line; isspace((unsigned char) *s); s++); - if (s != line) - memmove(line, s, strlen(s)+1); + char *s = strchr(line, '#'); + if (s != NULL) + s[0] = '\0'; + for (s = line + strlen(line) - 1; + s >= line && isspace((unsigned char) *s); s--); + s[1] = '\0'; + for (s = line; isspace((unsigned char) *s); s++); + if (s != line) + memmove(line, s, strlen(s)+1); } static void parse_line(char *line, int linenum) { - int tmp; - if (strcmp(line, "user_allow_other") == 0) - user_allow_other = 1; - else if (sscanf(line, "mount_max = %i", &tmp) == 1) - mount_max = tmp; - else if(line[0]) - fprintf(stderr, - "%s: unknown parameter in %s at line %i: '%s'\n", - progname, FUSE_CONF, linenum, line); + int tmp; + if (strcmp(line, "user_allow_other") == 0) + user_allow_other = 1; + else if (sscanf(line, "mount_max = %i", &tmp) == 1) + mount_max = tmp; + else if(line[0]) + fprintf(stderr, + "%s: unknown parameter in %s at line %i: '%s'\n", + progname, FUSE_CONF, linenum, line); } static void read_conf(void) { - FILE *fp = fopen(FUSE_CONF, "r"); - if (fp != NULL) { - int linenum = 1; - char line[256]; - int isnewline = 1; - while (fgets(line, sizeof(line), fp) != NULL) { - if (isnewline) { - if (line[strlen(line)-1] == '\n') { - strip_line(line); - parse_line(line, linenum); - } else { - isnewline = 0; - } - } else if(line[strlen(line)-1] == '\n') { - fprintf(stderr, "%s: reading %s: line %i too long\n", progname, FUSE_CONF, linenum); - - isnewline = 1; - } - if (isnewline) - linenum ++; - } - if (!isnewline) { - fprintf(stderr, "%s: reading %s: missing newline at end of file\n", progname, FUSE_CONF); - - } - fclose(fp); - } else if (errno != ENOENT) { - fprintf(stderr, "%s: failed to open %s: %s\n", - progname, FUSE_CONF, strerror(errno)); - } + FILE *fp = fopen(FUSE_CONF, "r"); + if (fp != NULL) { + int linenum = 1; + char line[256]; + int isnewline = 1; + while (fgets(line, sizeof(line), fp) != NULL) { + if (isnewline) { + if (line[strlen(line)-1] == '\n') { + strip_line(line); + parse_line(line, linenum); + } else { + isnewline = 0; + } + } else if(line[strlen(line)-1] == '\n') { + fprintf(stderr, "%s: reading %s: line %i too long\n", progname, FUSE_CONF, linenum); + + isnewline = 1; + } + if (isnewline) + linenum ++; + } + if (!isnewline) { + fprintf(stderr, "%s: reading %s: missing newline at end of file\n", progname, FUSE_CONF); + + } + fclose(fp); + } else if (errno != ENOENT) { + fprintf(stderr, "%s: failed to open %s: %s\n", + progname, FUSE_CONF, strerror(errno)); + } } static int begins_with(const char *s, const char *beg) { - if (strncmp(s, beg, strlen(beg)) == 0) - return 1; - else - return 0; + if (strncmp(s, beg, strlen(beg)) == 0) + return 1; + else + return 0; } struct mount_flags @@ -643,540 +643,543 @@ find_mount_flag(const char *s, unsigned len, int *on, int *flag) static int add_option(char **optsp, const char *opt, unsigned expand) { - char *newopts; - if (*optsp == NULL) - newopts = strdup(opt); - else { - unsigned oldsize = strlen(*optsp); - unsigned newsize = oldsize + 1 + strlen(opt) + expand + 1; - newopts = (char *) realloc(*optsp, newsize); - if (newopts) - sprintf(newopts + oldsize, ",%s", opt); - } - if (newopts == NULL) { - fprintf(stderr, "%s: failed to allocate memory\n", progname); - return -1; - } - *optsp = newopts; - return 0; + char *newopts; + if (*optsp == NULL) + newopts = strdup(opt); + else { + unsigned oldsize = strlen(*optsp); + unsigned newsize = oldsize + 1 + strlen(opt) + expand + 1; + newopts = (char *) realloc(*optsp, newsize); + if (newopts) + sprintf(newopts + oldsize, ",%s", opt); + } + if (newopts == NULL) { + fprintf(stderr, "%s: failed to allocate memory\n", progname); + return -1; + } + *optsp = newopts; + return 0; } static int get_mnt_opts(int flags, char *opts, char **mnt_optsp) { - int i; - int l; - - if (!(flags & MS_RDONLY) && add_option(mnt_optsp, "rw", 0) == -1) - return -1; - - for (i = 0; mount_flags[i].opt != NULL; i++) { - if (mount_flags[i].on && (flags & mount_flags[i].flag) && - add_option(mnt_optsp, mount_flags[i].opt, 0) == -1) - return -1; - } - - if (add_option(mnt_optsp, opts, 0) == -1) - return -1; - /* remove comma from end of opts*/ - l = strlen(*mnt_optsp); - if ((*mnt_optsp)[l-1] == ',') - (*mnt_optsp)[l-1] = '\0'; - if (getuid() != 0) { - const char *user = get_user_name(); - if (user == NULL) - return -1; - - if (add_option(mnt_optsp, "user=", strlen(user)) == -1) - return -1; - strcat(*mnt_optsp, user); - } - return 0; + int i; + int l; + + if (!(flags & MS_RDONLY) && add_option(mnt_optsp, "rw", 0) == -1) + return -1; + + for (i = 0; mount_flags[i].opt != NULL; i++) { + if (mount_flags[i].on && (flags & mount_flags[i].flag) && + add_option(mnt_optsp, mount_flags[i].opt, 0) == -1) + return -1; + } + + if (add_option(mnt_optsp, opts, 0) == -1) + return -1; + /* remove comma from end of opts*/ + l = strlen(*mnt_optsp); + if ((*mnt_optsp)[l-1] == ',') + (*mnt_optsp)[l-1] = '\0'; + if (getuid() != 0) { + const char *user = get_user_name(); + if (user == NULL) + return -1; + + if (add_option(mnt_optsp, "user=", strlen(user)) == -1) + return -1; + strcat(*mnt_optsp, user); + } + return 0; } static int opt_eq(const char *s, unsigned len, const char *opt) { - if(strlen(opt) == len && strncmp(s, opt, len) == 0) - return 1; - else - return 0; + if(strlen(opt) == len && strncmp(s, opt, len) == 0) + return 1; + else + return 0; } -static int get_string_opt(const char *s, unsigned len, const char *opt, - char **val) +static +int +get_string_opt(const char *s, + unsigned len, + const char *opt, + char **val) { - int i; - unsigned opt_len = strlen(opt); - char *d; - - if (*val) - free(*val); - *val = (char *) malloc(len - opt_len + 1); - if (!*val) { - fprintf(stderr, "%s: failed to allocate memory\n", progname); - return 0; - } - - d = *val; - s += opt_len; - len -= opt_len; - for (i = 0; i < len; i++) { - if (s[i] == '\\' && i + 1 < len) - i++; - *d++ = s[i]; - } - *d = '\0'; - return 1; + unsigned opt_len = strlen(opt); + char *d; + + if (*val) + free(*val); + *val = (char *) malloc(len - opt_len + 1); + if (!*val) { + fprintf(stderr, "%s: failed to allocate memory\n", progname); + return 0; + } + + d = *val; + s += opt_len; + len -= opt_len; + for (unsigned i = 0; i < len; i++) { + if (s[i] == '\\' && i + 1 < len) + i++; + *d++ = s[i]; + } + *d = '\0'; + return 1; } static int do_mount(const char *mnt, char **typep, mode_t rootmode, int fd, const char *opts, const char *dev, char **sourcep, char **mnt_optsp, off_t rootsize) { - int res; - int flags = MS_NOSUID | MS_NODEV; - char *optbuf; - char *mnt_opts = NULL; - const char *s; - char *d; - char *fsname = NULL; - char *subtype = NULL; - char *source = NULL; - char *type = NULL; - int blkdev = 0; - - optbuf = (char *) malloc(strlen(opts) + 128); - if (!optbuf) { - fprintf(stderr, "%s: failed to allocate memory\n", progname); - return -1; - } - - for (s = opts, d = optbuf; *s;) { - unsigned len; - const char *fsname_str = "fsname="; - const char *subtype_str = "subtype="; - for (len = 0; s[len]; len++) { - if (s[len] == '\\' && s[len + 1]) - len++; - else if (s[len] == ',') - break; - } - if (begins_with(s, fsname_str)) { - if (!get_string_opt(s, len, fsname_str, &fsname)) - goto err; - } else if (begins_with(s, subtype_str)) { - if (!get_string_opt(s, len, subtype_str, &subtype)) - goto err; - } else if (opt_eq(s, len, "blkdev")) { - if (getuid() != 0) { - fprintf(stderr, - "%s: option blkdev is privileged\n", - progname); - goto err; - } - blkdev = 1; - } else if (opt_eq(s, len, "auto_unmount")) { - auto_unmount = 1; - } else if (!begins_with(s, "fd=") && - !begins_with(s, "rootmode=") && - !begins_with(s, "user_id=") && - !begins_with(s, "group_id=")) { - int on; - int flag; - int skip_option = 0; - if (opt_eq(s, len, "large_read")) { - struct utsname utsname; - unsigned kmaj, kmin; - res = uname(&utsname); - if (res == 0 && - sscanf(utsname.release, "%u.%u", - &kmaj, &kmin) == 2 && - (kmaj > 2 || (kmaj == 2 && kmin > 4))) { - fprintf(stderr, "%s: note: 'large_read' mount option is deprecated for %i.%i kernels\n", progname, kmaj, kmin); - skip_option = 1; - } - } - if (getuid() != 0 && !user_allow_other && opt_eq(s, len, "allow_other")) { - fprintf(stderr, "%s: option %.*s only allowed if 'user_allow_other' is set in /etc/fuse.conf\n", progname, len, s); - goto err; - } - if (!skip_option) { - if (find_mount_flag(s, len, &on, &flag)) { - if (on) - flags |= flag; - else - flags &= ~flag; - } else { - memcpy(d, s, len); - d += len; - *d++ = ','; - } - } - } - s += len; - if (*s) - s++; - } - *d = '\0'; - res = get_mnt_opts(flags, optbuf, &mnt_opts); - if (res == -1) - goto err; - - sprintf(d, "fd=%i,rootmode=%o,user_id=%u,group_id=%u", - fd, rootmode, getuid(), getgid()); - - source = malloc((fsname ? strlen(fsname) : 0) + - (subtype ? strlen(subtype) : 0) + strlen(dev) + 32); - - type = malloc((subtype ? strlen(subtype) : 0) + 32); - if (!type || !source) { - fprintf(stderr, "%s: failed to allocate memory\n", progname); - goto err; - } - - if (subtype) - sprintf(type, "%s.%s", blkdev ? "fuseblk" : "fuse", subtype); - else - strcpy(type, blkdev ? "fuseblk" : "fuse"); - - if (fsname) - strcpy(source, fsname); - else - strcpy(source, subtype ? subtype : dev); - - res = mount(source, mnt, type, flags, optbuf); - if (res == -1 && errno == ENODEV && subtype) { - /* Probably missing subtype support */ - strcpy(type, blkdev ? "fuseblk" : "fuse"); - if (fsname) { - if (!blkdev) - sprintf(source, "%s#%s", subtype, fsname); - } else { - strcpy(source, type); - } - - res = mount(source, mnt, type, flags, optbuf); - } - if (res == -1 && errno == EINVAL) { - /* It could be an old version not supporting group_id */ - sprintf(d, "fd=%i,rootmode=%o,user_id=%u", - fd, rootmode, getuid()); - res = mount(source, mnt, type, flags, optbuf); - } - if (res == -1) { - int errno_save = errno; - if (blkdev && errno == ENODEV && !fuse_mnt_check_fuseblk()) - fprintf(stderr, "%s: 'fuseblk' support missing\n", - progname); - else - fprintf(stderr, "%s: mount failed: %s\n", progname, - strerror(errno_save)); - goto err; - } - *sourcep = source; - *typep = type; - *mnt_optsp = mnt_opts; - free(fsname); - free(optbuf); - - return 0; - -err: - free(fsname); - free(subtype); - free(source); - free(type); - free(mnt_opts); - free(optbuf); - return -1; + int res; + int flags = MS_NOSUID | MS_NODEV; + char *optbuf; + char *mnt_opts = NULL; + const char *s; + char *d; + char *fsname = NULL; + char *subtype = NULL; + char *source = NULL; + char *type = NULL; + int blkdev = 0; + + optbuf = (char *) malloc(strlen(opts) + 128); + if (!optbuf) { + fprintf(stderr, "%s: failed to allocate memory\n", progname); + return -1; + } + + for (s = opts, d = optbuf; *s;) { + unsigned len; + const char *fsname_str = "fsname="; + const char *subtype_str = "subtype="; + for (len = 0; s[len]; len++) { + if (s[len] == '\\' && s[len + 1]) + len++; + else if (s[len] == ',') + break; + } + if (begins_with(s, fsname_str)) { + if (!get_string_opt(s, len, fsname_str, &fsname)) + goto err; + } else if (begins_with(s, subtype_str)) { + if (!get_string_opt(s, len, subtype_str, &subtype)) + goto err; + } else if (opt_eq(s, len, "blkdev")) { + if (getuid() != 0) { + fprintf(stderr, + "%s: option blkdev is privileged\n", + progname); + goto err; + } + blkdev = 1; + } else if (opt_eq(s, len, "auto_unmount")) { + auto_unmount = 1; + } else if (!begins_with(s, "fd=") && + !begins_with(s, "rootmode=") && + !begins_with(s, "user_id=") && + !begins_with(s, "group_id=")) { + int on; + int flag; + int skip_option = 0; + if (opt_eq(s, len, "large_read")) { + struct utsname utsname; + unsigned kmaj, kmin; + res = uname(&utsname); + if (res == 0 && + sscanf(utsname.release, "%u.%u", + &kmaj, &kmin) == 2 && + (kmaj > 2 || (kmaj == 2 && kmin > 4))) { + fprintf(stderr, "%s: note: 'large_read' mount option is deprecated for %i.%i kernels\n", progname, kmaj, kmin); + skip_option = 1; + } + } + if (getuid() != 0 && !user_allow_other && opt_eq(s, len, "allow_other")) { + fprintf(stderr, "%s: option %.*s only allowed if 'user_allow_other' is set in /etc/fuse.conf\n", progname, len, s); + goto err; + } + if (!skip_option) { + if (find_mount_flag(s, len, &on, &flag)) { + if (on) + flags |= flag; + else + flags &= ~flag; + } else { + memcpy(d, s, len); + d += len; + *d++ = ','; + } + } + } + s += len; + if (*s) + s++; + } + *d = '\0'; + res = get_mnt_opts(flags, optbuf, &mnt_opts); + if (res == -1) + goto err; + + sprintf(d, "fd=%i,rootmode=%o,user_id=%u,group_id=%u", + fd, rootmode, getuid(), getgid()); + + source = malloc((fsname ? strlen(fsname) : 0) + + (subtype ? strlen(subtype) : 0) + strlen(dev) + 32); + + type = malloc((subtype ? strlen(subtype) : 0) + 32); + if (!type || !source) { + fprintf(stderr, "%s: failed to allocate memory\n", progname); + goto err; + } + + if (subtype) + sprintf(type, "%s.%s", blkdev ? "fuseblk" : "fuse", subtype); + else + strcpy(type, blkdev ? "fuseblk" : "fuse"); + + if (fsname) + strcpy(source, fsname); + else + strcpy(source, subtype ? subtype : dev); + + res = mount(source, mnt, type, flags, optbuf); + if (res == -1 && errno == ENODEV && subtype) { + /* Probably missing subtype support */ + strcpy(type, blkdev ? "fuseblk" : "fuse"); + if (fsname) { + if (!blkdev) + sprintf(source, "%s#%s", subtype, fsname); + } else { + strcpy(source, type); + } + + res = mount(source, mnt, type, flags, optbuf); + } + if (res == -1 && errno == EINVAL) { + /* It could be an old version not supporting group_id */ + sprintf(d, "fd=%i,rootmode=%o,user_id=%u", + fd, rootmode, getuid()); + res = mount(source, mnt, type, flags, optbuf); + } + if (res == -1) { + int errno_save = errno; + if (blkdev && errno == ENODEV && !fuse_mnt_check_fuseblk()) + fprintf(stderr, "%s: 'fuseblk' support missing\n", + progname); + else + fprintf(stderr, "%s: mount failed: %s\n", progname, + strerror(errno_save)); + goto err; + } + *sourcep = source; + *typep = type; + *mnt_optsp = mnt_opts; + free(fsname); + free(optbuf); + + return 0; + + err: + free(fsname); + free(subtype); + free(source); + free(type); + free(mnt_opts); + free(optbuf); + return -1; } static int check_version(const char *dev) { - int res; - int majorver; - int minorver; - const char *version_file; - FILE *vf; - - if (strcmp(dev, FUSE_DEV_OLD) != 0) - return 0; - - version_file = FUSE_VERSION_FILE_OLD; - vf = fopen(version_file, "r"); - if (vf == NULL) { - fprintf(stderr, "%s: kernel interface too old\n", progname); - return -1; - } - res = fscanf(vf, "%i.%i", &majorver, &minorver); - fclose(vf); - if (res != 2) { - fprintf(stderr, "%s: error reading %s\n", progname, - version_file); - return -1; - } - if (majorver < 3) { - fprintf(stderr, "%s: kernel interface too old\n", progname); - return -1; - } - return 0; + int res; + int majorver; + int minorver; + const char *version_file; + FILE *vf; + + if (strcmp(dev, FUSE_DEV_OLD) != 0) + return 0; + + version_file = FUSE_VERSION_FILE_OLD; + vf = fopen(version_file, "r"); + if (vf == NULL) { + fprintf(stderr, "%s: kernel interface too old\n", progname); + return -1; + } + res = fscanf(vf, "%i.%i", &majorver, &minorver); + fclose(vf); + if (res != 2) { + fprintf(stderr, "%s: error reading %s\n", progname, + version_file); + return -1; + } + if (majorver < 3) { + fprintf(stderr, "%s: kernel interface too old\n", progname); + return -1; + } + return 0; } static int check_perm(const char **mntp, struct stat *stbuf, int *mountpoint_fd) { - int res; - const char *mnt = *mntp; - const char *origmnt = mnt; - - res = lstat(mnt, stbuf); - if (res == -1) { - fprintf(stderr, "%s: failed to access mountpoint %s: %s\n", - progname, mnt, strerror(errno)); - return -1; - } - - /* No permission checking is done for root */ - if (getuid() == 0) - return 0; - - if (S_ISDIR(stbuf->st_mode)) { - res = chdir(mnt); - if (res == -1) { - fprintf(stderr, - "%s: failed to chdir to mountpoint: %s\n", - progname, strerror(errno)); - return -1; - } - mnt = *mntp = "."; - res = lstat(mnt, stbuf); - if (res == -1) { - fprintf(stderr, - "%s: failed to access mountpoint %s: %s\n", - progname, origmnt, strerror(errno)); - return -1; - } - - if ((stbuf->st_mode & S_ISVTX) && stbuf->st_uid != getuid()) { - fprintf(stderr, "%s: mountpoint %s not owned by user\n", - progname, origmnt); - return -1; - } - - res = access(mnt, W_OK); - if (res == -1) { - fprintf(stderr, "%s: user has no write access to mountpoint %s\n", - progname, origmnt); - return -1; - } - } else if (S_ISREG(stbuf->st_mode)) { - static char procfile[256]; - *mountpoint_fd = open(mnt, O_WRONLY); - if (*mountpoint_fd == -1) { - fprintf(stderr, "%s: failed to open %s: %s\n", - progname, mnt, strerror(errno)); - return -1; - } - res = fstat(*mountpoint_fd, stbuf); - if (res == -1) { - fprintf(stderr, - "%s: failed to access mountpoint %s: %s\n", - progname, mnt, strerror(errno)); - return -1; - } - if (!S_ISREG(stbuf->st_mode)) { - fprintf(stderr, - "%s: mountpoint %s is no longer a regular file\n", - progname, mnt); - return -1; - } - - sprintf(procfile, "/proc/self/fd/%i", *mountpoint_fd); - *mntp = procfile; - } else { - fprintf(stderr, - "%s: mountpoint %s is not a directory or a regular file\n", - progname, mnt); - return -1; - } - - - return 0; + int res; + const char *mnt = *mntp; + const char *origmnt = mnt; + + res = lstat(mnt, stbuf); + if (res == -1) { + fprintf(stderr, "%s: failed to access mountpoint %s: %s\n", + progname, mnt, strerror(errno)); + return -1; + } + + /* No permission checking is done for root */ + if (getuid() == 0) + return 0; + + if (S_ISDIR(stbuf->st_mode)) { + res = chdir(mnt); + if (res == -1) { + fprintf(stderr, + "%s: failed to chdir to mountpoint: %s\n", + progname, strerror(errno)); + return -1; + } + mnt = *mntp = "."; + res = lstat(mnt, stbuf); + if (res == -1) { + fprintf(stderr, + "%s: failed to access mountpoint %s: %s\n", + progname, origmnt, strerror(errno)); + return -1; + } + + if ((stbuf->st_mode & S_ISVTX) && stbuf->st_uid != getuid()) { + fprintf(stderr, "%s: mountpoint %s not owned by user\n", + progname, origmnt); + return -1; + } + + res = access(mnt, W_OK); + if (res == -1) { + fprintf(stderr, "%s: user has no write access to mountpoint %s\n", + progname, origmnt); + return -1; + } + } else if (S_ISREG(stbuf->st_mode)) { + static char procfile[256]; + *mountpoint_fd = open(mnt, O_WRONLY); + if (*mountpoint_fd == -1) { + fprintf(stderr, "%s: failed to open %s: %s\n", + progname, mnt, strerror(errno)); + return -1; + } + res = fstat(*mountpoint_fd, stbuf); + if (res == -1) { + fprintf(stderr, + "%s: failed to access mountpoint %s: %s\n", + progname, mnt, strerror(errno)); + return -1; + } + if (!S_ISREG(stbuf->st_mode)) { + fprintf(stderr, + "%s: mountpoint %s is no longer a regular file\n", + progname, mnt); + return -1; + } + + sprintf(procfile, "/proc/self/fd/%i", *mountpoint_fd); + *mntp = procfile; + } else { + fprintf(stderr, + "%s: mountpoint %s is not a directory or a regular file\n", + progname, mnt); + return -1; + } + + + return 0; } static int try_open(const char *dev, char **devp, int silent) { - int fd = open(dev, O_RDWR); - if (fd != -1) { - *devp = strdup(dev); - if (*devp == NULL) { - fprintf(stderr, "%s: failed to allocate memory\n", - progname); - close(fd); - fd = -1; - } - } else if (errno == ENODEV || - errno == ENOENT)/* check for ENOENT too, for the udev case */ - return -2; - else if (!silent) { - fprintf(stderr, "%s: failed to open %s: %s\n", progname, dev, - strerror(errno)); - } - return fd; + int fd = open(dev, O_RDWR); + if (fd != -1) { + *devp = strdup(dev); + if (*devp == NULL) { + fprintf(stderr, "%s: failed to allocate memory\n", + progname); + close(fd); + fd = -1; + } + } else if (errno == ENODEV || + errno == ENOENT)/* check for ENOENT too, for the udev case */ + return -2; + else if (!silent) { + fprintf(stderr, "%s: failed to open %s: %s\n", progname, dev, + strerror(errno)); + } + return fd; } static int try_open_fuse_device(char **devp) { - int fd; - int err; + int fd; + int err; - drop_privs(); - fd = try_open(FUSE_DEV_NEW, devp, 0); - restore_privs(); - if (fd >= 0) - return fd; + drop_privs(); + fd = try_open(FUSE_DEV_NEW, devp, 0); + restore_privs(); + if (fd >= 0) + return fd; - err = fd; - fd = try_open(FUSE_DEV_OLD, devp, 1); - if (fd >= 0) - return fd; + err = fd; + fd = try_open(FUSE_DEV_OLD, devp, 1); + if (fd >= 0) + return fd; - return err; + return err; } static int open_fuse_device(char **devp) { - int fd = try_open_fuse_device(devp); - if (fd >= -1) - return fd; + int fd = try_open_fuse_device(devp); + if (fd >= -1) + return fd; - fprintf(stderr, - "%s: fuse device not found, try 'modprobe fuse' first\n", - progname); + fprintf(stderr, + "%s: fuse device not found, try 'modprobe fuse' first\n", + progname); - return -1; + return -1; } static int mount_fuse(const char *mnt, const char *opts) { - int res; - int fd; - char *dev; - struct stat stbuf; - char *type = NULL; - char *source = NULL; - char *mnt_opts = NULL; - const char *real_mnt = mnt; - int mountpoint_fd = -1; - - fd = open_fuse_device(&dev); - if (fd == -1) - return -1; - - drop_privs(); - read_conf(); - - if (getuid() != 0 && mount_max != -1) { - int mount_count = count_fuse_fs(); - if (mount_count >= mount_max) { - fprintf(stderr, "%s: too many FUSE filesystems mounted; mount_max=N can be set in /etc/fuse.conf\n", progname); - goto fail_close_fd; - } - } - - res = check_version(dev); - if (res != -1) { - res = check_perm(&real_mnt, &stbuf, &mountpoint_fd); - restore_privs(); - if (res != -1) - res = do_mount(real_mnt, &type, stbuf.st_mode & S_IFMT, - fd, opts, dev, &source, &mnt_opts, - stbuf.st_size); - } else - restore_privs(); - - if (mountpoint_fd != -1) - close(mountpoint_fd); - - if (res == -1) - goto fail_close_fd; - - res = chdir("/"); - if (res == -1) { - fprintf(stderr, "%s: failed to chdir to '/'\n", progname); - goto fail_close_fd; - } - - if (geteuid() == 0) { - res = add_mount(source, mnt, type, mnt_opts); - if (res == -1) { - /* Can't clean up mount in a non-racy way */ - goto fail_close_fd; - } - } - -out_free: - free(source); - free(type); - free(mnt_opts); - free(dev); - - return fd; - -fail_close_fd: - close(fd); - fd = -1; - goto out_free; + int res; + int fd; + char *dev; + struct stat stbuf; + char *type = NULL; + char *source = NULL; + char *mnt_opts = NULL; + const char *real_mnt = mnt; + int mountpoint_fd = -1; + + fd = open_fuse_device(&dev); + if (fd == -1) + return -1; + + drop_privs(); + read_conf(); + + if (getuid() != 0 && mount_max != -1) { + int mount_count = count_fuse_fs(); + if (mount_count >= mount_max) { + fprintf(stderr, "%s: too many FUSE filesystems mounted; mount_max=N can be set in /etc/fuse.conf\n", progname); + goto fail_close_fd; + } + } + + res = check_version(dev); + if (res != -1) { + res = check_perm(&real_mnt, &stbuf, &mountpoint_fd); + restore_privs(); + if (res != -1) + res = do_mount(real_mnt, &type, stbuf.st_mode & S_IFMT, + fd, opts, dev, &source, &mnt_opts, + stbuf.st_size); + } else + restore_privs(); + + if (mountpoint_fd != -1) + close(mountpoint_fd); + + if (res == -1) + goto fail_close_fd; + + res = chdir("/"); + if (res == -1) { + fprintf(stderr, "%s: failed to chdir to '/'\n", progname); + goto fail_close_fd; + } + + if (geteuid() == 0) { + res = add_mount(source, mnt, type, mnt_opts); + if (res == -1) { + /* Can't clean up mount in a non-racy way */ + goto fail_close_fd; + } + } + + out_free: + free(source); + free(type); + free(mnt_opts); + free(dev); + + return fd; + + fail_close_fd: + close(fd); + fd = -1; + goto out_free; } static int send_fd(int sock_fd, int fd) { - int retval; - struct msghdr msg; - struct cmsghdr *p_cmsg; - struct iovec vec; - size_t cmsgbuf[CMSG_SPACE(sizeof(fd)) / sizeof(size_t)]; - int *p_fds; - char sendchar = 0; - - 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(fd)); - p_fds = (int *) CMSG_DATA(p_cmsg); - *p_fds = fd; - 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; - /* "To pass file descriptors or credentials you need to send/read at - * least one byte" (man 7 unix) */ - vec.iov_base = &sendchar; - vec.iov_len = sizeof(sendchar); - while ((retval = sendmsg(sock_fd, &msg, 0)) == -1 && errno == EINTR); - if (retval != 1) { - perror("sending file descriptor"); - return -1; - } - return 0; + int retval; + struct msghdr msg; + struct cmsghdr *p_cmsg; + struct iovec vec; + size_t cmsgbuf[CMSG_SPACE(sizeof(fd)) / sizeof(size_t)]; + int *p_fds; + char sendchar = 0; + + 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(fd)); + p_fds = (int *) CMSG_DATA(p_cmsg); + *p_fds = fd; + 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; + /* "To pass file descriptors or credentials you need to send/read at + * least one byte" (man 7 unix) */ + vec.iov_base = &sendchar; + vec.iov_len = sizeof(sendchar); + while ((retval = sendmsg(sock_fd, &msg, 0)) == -1 && errno == EINTR); + if (retval != 1) { + perror("sending file descriptor"); + return -1; + } + return 0; } static void usage(void) { - fprintf(stderr, - "%s: [options] mountpoint\n" - "Options:\n" - " -h print help\n" - " -V print version\n" - " -o opt[,opt...] mount options\n" - " -u unmount\n" - " -q quiet\n" - " -z lazy unmount\n", - progname); - exit(1); + fprintf(stderr, + "%s: [options] mountpoint\n" + "Options:\n" + " -h print help\n" + " -V print version\n" + " -o opt[,opt...] mount options\n" + " -u unmount\n" + " -q quiet\n" + " -z lazy unmount\n", + progname); + exit(1); } static void show_version(void) @@ -1186,159 +1189,159 @@ static void show_version(void) int main(int argc, char *argv[]) { - sigset_t sigset; - int ch; - int fd; - int res; - char *origmnt; - char *mnt; - static int unmount = 0; - static int lazy = 0; - static int quiet = 0; - char *commfd; - int cfd; - const char *opts = ""; - - static const struct option long_opts[] = { - {"unmount", no_argument, NULL, 'u'}, - {"lazy", no_argument, NULL, 'z'}, - {"quiet", no_argument, NULL, 'q'}, - {"help", no_argument, NULL, 'h'}, - {"version", no_argument, NULL, 'V'}, - {0, 0, 0, 0}}; - - progname = strdup(argv[0]); - if (progname == NULL) { - fprintf(stderr, "%s: failed to allocate memory\n", argv[0]); - exit(1); - } - - while ((ch = getopt_long(argc, argv, "hVo:uzq", long_opts, - NULL)) != -1) { - switch (ch) { - case 'h': - usage(); - break; - - case 'V': - show_version(); - break; - - case 'o': - opts = optarg; - break; - - case 'u': - unmount = 1; - break; - - case 'z': - lazy = 1; - break; - - case 'q': - quiet = 1; - break; - - default: - exit(1); - } - } - - if (lazy && !unmount) { - fprintf(stderr, "%s: -z can only be used with -u\n", progname); - exit(1); - } - - if (optind >= argc) { - fprintf(stderr, "%s: missing mountpoint argument\n", progname); - exit(1); - } else if (argc > optind + 1) { - fprintf(stderr, "%s: extra arguments after the mountpoint\n", - progname); - exit(1); - } - - origmnt = argv[optind]; - - drop_privs(); - mnt = fuse_mnt_resolve_path(progname, origmnt); - if (mnt != NULL) { - res = chdir("/"); - if (res == -1) { - fprintf(stderr, "%s: failed to chdir to '/'\n", progname); - exit(1); - } - } - restore_privs(); - if (mnt == NULL) - exit(1); - - umask(033); - if (unmount) - goto do_unmount; - - commfd = getenv(FUSE_COMMFD_ENV); - if (commfd == NULL) { - fprintf(stderr, "%s: old style mounting not supported\n", - progname); - exit(1); - } - - fd = mount_fuse(mnt, opts); - if (fd == -1) - exit(1); - - cfd = atoi(commfd); - res = send_fd(cfd, fd); - if (res == -1) - exit(1); - close(fd); - - if (!auto_unmount) - return 0; - - /* Become a daemon and wait for the parent to exit or die. - ie For the control socket to get closed. - btw We don't want to use daemon() function here because - it forks and messes with the file descriptors. */ - setsid(); - res = chdir("/"); - if (res == -1) { - fprintf(stderr, "%s: failed to chdir to '/'\n", progname); - exit(1); - } - - sigfillset(&sigset); - sigprocmask(SIG_BLOCK, &sigset, NULL); - - lazy = 1; - quiet = 1; - - while (1) { - unsigned char buf[16]; - int n = recv(cfd, buf, sizeof(buf), 0); - if (!n) - break; - - if (n < 0) { - if (errno == EINTR) - continue; - break; - } - } - -do_unmount: - if (geteuid() == 0) - res = unmount_fuse(mnt, quiet, lazy); - else { - res = umount2(mnt, lazy ? UMOUNT_DETACH : 0); - if (res == -1 && !quiet) - fprintf(stderr, - "%s: failed to unmount %s: %s\n", - progname, mnt, strerror(errno)); - } - if (res == -1) - exit(1); - return 0; + sigset_t sigset; + int ch; + int fd; + int res; + char *origmnt; + char *mnt; + static int unmount = 0; + static int lazy = 0; + static int quiet = 0; + char *commfd; + int cfd; + const char *opts = ""; + + static const struct option long_opts[] = { + {"unmount", no_argument, NULL, 'u'}, + {"lazy", no_argument, NULL, 'z'}, + {"quiet", no_argument, NULL, 'q'}, + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'V'}, + {0, 0, 0, 0}}; + + progname = strdup(argv[0]); + if (progname == NULL) { + fprintf(stderr, "%s: failed to allocate memory\n", argv[0]); + exit(1); + } + + while ((ch = getopt_long(argc, argv, "hVo:uzq", long_opts, + NULL)) != -1) { + switch (ch) { + case 'h': + usage(); + break; + + case 'V': + show_version(); + break; + + case 'o': + opts = optarg; + break; + + case 'u': + unmount = 1; + break; + + case 'z': + lazy = 1; + break; + + case 'q': + quiet = 1; + break; + + default: + exit(1); + } + } + + if (lazy && !unmount) { + fprintf(stderr, "%s: -z can only be used with -u\n", progname); + exit(1); + } + + if (optind >= argc) { + fprintf(stderr, "%s: missing mountpoint argument\n", progname); + exit(1); + } else if (argc > optind + 1) { + fprintf(stderr, "%s: extra arguments after the mountpoint\n", + progname); + exit(1); + } + + origmnt = argv[optind]; + + drop_privs(); + mnt = fuse_mnt_resolve_path(progname, origmnt); + if (mnt != NULL) { + res = chdir("/"); + if (res == -1) { + fprintf(stderr, "%s: failed to chdir to '/'\n", progname); + exit(1); + } + } + restore_privs(); + if (mnt == NULL) + exit(1); + + umask(033); + if (unmount) + goto do_unmount; + + commfd = getenv(FUSE_COMMFD_ENV); + if (commfd == NULL) { + fprintf(stderr, "%s: old style mounting not supported\n", + progname); + exit(1); + } + + fd = mount_fuse(mnt, opts); + if (fd == -1) + exit(1); + + cfd = atoi(commfd); + res = send_fd(cfd, fd); + if (res == -1) + exit(1); + close(fd); + + if (!auto_unmount) + return 0; + + /* Become a daemon and wait for the parent to exit or die. + ie For the control socket to get closed. + btw We don't want to use daemon() function here because + it forks and messes with the file descriptors. */ + setsid(); + res = chdir("/"); + if (res == -1) { + fprintf(stderr, "%s: failed to chdir to '/'\n", progname); + exit(1); + } + + sigfillset(&sigset); + sigprocmask(SIG_BLOCK, &sigset, NULL); + + lazy = 1; + quiet = 1; + + while (1) { + unsigned char buf[16]; + int n = recv(cfd, buf, sizeof(buf), 0); + if (!n) + break; + + if (n < 0) { + if (errno == EINTR) + continue; + break; + } + } + + do_unmount: + if (geteuid() == 0) + res = unmount_fuse(mnt, quiet, lazy); + else { + res = umount2(mnt, lazy ? UMOUNT_DETACH : 0); + if (res == -1 && !quiet) + fprintf(stderr, + "%s: failed to unmount %s: %s\n", + progname, mnt, strerror(errno)); + } + if (res == -1) + exit(1); + return 0; } diff --git a/src/branches.cpp b/src/branches.cpp index 43080c70..d1f781b6 100644 --- a/src/branches.cpp +++ b/src/branches.cpp @@ -154,6 +154,7 @@ namespace l rv = l::parse_minfreespace(v[1],minfreespace_); if(rv < 0) return rv; + [[fallthrough]]; case 1: rv = l::parse_mode(v[0],mode_); if(rv < 0) diff --git a/src/branches.hpp b/src/branches.hpp index e8fc50ff..2ed87258 100644 --- a/src/branches.hpp +++ b/src/branches.hpp @@ -63,13 +63,16 @@ public: public: using Ptr = Branches::Impl::Ptr; +public: + u64 minfreespace; + private: mutable std::mutex _mutex; Ptr _impl; public: - Branches(const u64 &default_minfreespace_) - : _impl(std::make_shared(default_minfreespace_)) + Branches() + : _impl(std::make_shared(minfreespace)) {} public: diff --git a/src/config.cpp b/src/config.cpp index ceeefda6..ac0fc901 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -81,7 +81,7 @@ Config::Config() : allow_idmap(false), async_read(true), - branches(minfreespace), + branches(), branches_mount_timeout(0), branches_mount_timeout_fail(false), cache_attr(1), @@ -118,7 +118,7 @@ Config::Config() link_exdev(LinkEXDEV::ENUM::PASSTHROUGH), log_metrics(false), max_background(fuse_cfg.max_background,0), - minfreespace(MINFREESPACE_DEFAULT), + minfreespace(branches.minfreespace,MINFREESPACE_DEFAULT), mountpoint(), _mount(mountpoint), _mountpoint(mountpoint), diff --git a/src/config.hpp b/src/config.hpp index 046c805a..75824325 100644 --- a/src/config.hpp +++ b/src/config.hpp @@ -148,7 +148,7 @@ public: LinkEXDEV link_exdev; LogMetrics log_metrics; TFSRef max_background; - ConfigUINT64 minfreespace; + TFSRef minfreespace; fs::path mountpoint; TFSRef _mount; TFSRef _mountpoint; diff --git a/src/config_pagesize.hpp b/src/config_pagesize.hpp index 22a7c6bf..e3000b77 100644 --- a/src/config_pagesize.hpp +++ b/src/config_pagesize.hpp @@ -44,7 +44,7 @@ public: return *this; } - operator const uint64_t() const + operator uint64_t() const { return _v; } diff --git a/src/fs_copyfile.cpp b/src/fs_copyfile.cpp index 1a27bf48..cc5bc88f 100644 --- a/src/fs_copyfile.cpp +++ b/src/fs_copyfile.cpp @@ -103,7 +103,7 @@ fs::copyfile(const int src_fd_, { s64 rv; int dst_fd; - struct stat src_st = {0}; + struct stat src_st = {}; std::string dst_tmppath; struct sigaction old_act; struct sigaction new_act; diff --git a/src/fs_glob.cpp b/src/fs_glob.cpp index 43d96895..09b99a45 100644 --- a/src/fs_glob.cpp +++ b/src/fs_glob.cpp @@ -38,7 +38,7 @@ fs::glob(const string &pattern_, vector *strs_) { int flags; - glob_t gbuf = {0}; + glob_t gbuf = {}; flags = (GLOB_BRACE|GLOB_ONLYDIR); ::glob(pattern_.c_str(),flags,NULL,&gbuf); diff --git a/src/fs_wait_for_mount.cpp b/src/fs_wait_for_mount.cpp index f5c933af..96da1c0c 100644 --- a/src/fs_wait_for_mount.cpp +++ b/src/fs_wait_for_mount.cpp @@ -146,7 +146,7 @@ fs::wait_for_mount(const fs::path &src_path_, const std::chrono::milliseconds &timeout_) { int rv; - struct stat src_st = {0}; + struct stat src_st = {}; rv = fs::stat(src_path_,&src_st); if(rv < 0) diff --git a/src/fuse_create.cpp b/src/fuse_create.cpp index 32be9c54..253c3dc6 100644 --- a/src/fuse_create.cpp +++ b/src/fuse_create.cpp @@ -208,7 +208,6 @@ _create(const Policy::Search &searchFunc_, } constexpr -const uint64_t _(const PassthroughIOEnum e_, const uint64_t m_) diff --git a/src/fuse_open.cpp b/src/fuse_open.cpp index 60789739..6723380a 100644 --- a/src/fuse_open.cpp +++ b/src/fuse_open.cpp @@ -265,7 +265,6 @@ _open(const Policy::Search &searchFunc_, } constexpr -const uint64_t _(const PassthroughIOEnum e_, const uint64_t m_) diff --git a/src/fuse_readdir.cpp b/src/fuse_readdir.cpp index 8c0f8d26..21cc1acb 100644 --- a/src/fuse_readdir.cpp +++ b/src/fuse_readdir.cpp @@ -86,7 +86,7 @@ _handle_ENOENT(const fuse_file_info_t *ffi_, if(!di->fusepath.empty()) return -ENOENT; - de = {0}; + de = {}; de.d_ino = 0; de.d_off = 0;