static void sfs_init(void *userdata, fuse_conn_info *conn) {
(void)userdata;
- if (fs.passthrough && conn->capable & FUSE_CAP_PASSTHROUGH)
- conn->want |= FUSE_CAP_PASSTHROUGH;
- else
+ if (!fuse_set_feature_flag(conn, FUSE_CAP_PASSTHROUGH))
fs.passthrough = false;
/* Passthrough and writeback cache are conflicting modes */
- if (fs.timeout && !fs.passthrough &&
- conn->capable & FUSE_CAP_WRITEBACK_CACHE)
- conn->want |= FUSE_CAP_WRITEBACK_CACHE;
+ if (fs.timeout && !fs.passthrough)
+ fuse_set_feature_flag(conn, FUSE_CAP_WRITEBACK_CACHE);
- if (conn->capable & FUSE_CAP_FLOCK_LOCKS)
- conn->want |= FUSE_CAP_FLOCK_LOCKS;
+ fuse_set_feature_flag(conn, FUSE_CAP_FLOCK_LOCKS);
if (fs.nosplice) {
// FUSE_CAP_SPLICE_READ is enabled in libfuse3 by default,
// see do_init() in in fuse_lowlevel.c
// Just unset both, in case FUSE_CAP_SPLICE_WRITE would also get enabled
// by default.
- conn->want &= ~FUSE_CAP_SPLICE_READ;
- conn->want &= ~FUSE_CAP_SPLICE_WRITE;
+ fuse_unset_feature_flag(conn, FUSE_CAP_SPLICE_READ);
+ fuse_unset_feature_flag(conn, FUSE_CAP_SPLICE_WRITE);
} else {
- if (conn->capable & FUSE_CAP_SPLICE_WRITE)
- conn->want |= FUSE_CAP_SPLICE_WRITE;
- if (conn->capable & FUSE_CAP_SPLICE_READ)
- conn->want |= FUSE_CAP_SPLICE_READ;
+ fuse_set_feature_flag(conn, FUSE_CAP_SPLICE_WRITE);
+ fuse_set_feature_flag(conn, FUSE_CAP_SPLICE_READ);
}
/* This is a local file system - no network coherency needed */
- if (conn->capable & FUSE_CAP_DIRECT_IO_ALLOW_MMAP)
- conn->want |= FUSE_CAP_DIRECT_IO_ALLOW_MMAP;
+ fuse_set_feature_flag(conn, FUSE_CAP_DIRECT_IO_ALLOW_MMAP);
/* Disable the receiving and processing of FUSE_INTERRUPT requests */
conn->no_interrupt = 1;
/** @file */
+#include <stdbool.h>
#if !defined(FUSE_H_) && !defined(FUSE_LOWLEVEL_H_)
#error "Never include <fuse_common.h> directly; use <fuse.h> or <fuse_lowlevel.h> instead."
#endif
struct fuse_loop_config_v1 *v1_conf);
#endif
+
+static inline bool fuse_set_feature_flag(struct fuse_conn_info *conn,
+ uint64_t flag)
+{
+ if (conn->capable & flag) {
+ conn->want |= flag;
+ return true;
+ }
+ return false;
+}
+
+static inline void fuse_unset_feature_flag(struct fuse_conn_info *conn,
+ uint64_t flag)
+{
+ conn->want &= ~flag;
+}
+
/* ----------------------------------------------------------- *
* Compatibility stuff *
* ----------------------------------------------------------- */
See the file COPYING.LIB
*/
+#include <stdbool.h>
#define _GNU_SOURCE
#include "fuse_config.h"
fuse_reply_err(req, ENOSYS);
}
+static bool want_flags_valid(uint64_t capable, uint64_t want)
+{
+ uint64_t unknown_flags = want & (~capable);
+ if (unknown_flags != 0) {
+ fuse_log(FUSE_LOG_ERR,
+ "fuse: unknown connection 'want' flags: 0x%08lx\n",
+ unknown_flags);
+ return false;
+ }
+ return true;
+}
+
/* Prevent bogus data races (bogus since "init" is called before
* multi-threading becomes relevant */
static __attribute__((no_sanitize("thread")))
if (se->op.init)
se->op.init(se->userdata, &se->conn);
- if (se->conn.want & (~se->conn.capable)) {
- fuse_log(FUSE_LOG_ERR, "fuse: error: filesystem requested capabilities "
- "0x%x that are not supported by kernel, aborting.\n",
- se->conn.want & (~se->conn.capable));
+ if (!want_flags_valid(se->conn.capable, se->conn.want)) {
fuse_reply_err(req, EPROTO);
se->error = -EPROTO;
fuse_session_exit(se);