diff options
author | Bernd Schubert <bschubert@ddn.com> | 2025-04-16 00:24:42 +0200 |
---|---|---|
committer | Bernd Schubert <bernd@bsbernd.com> | 2025-04-16 13:48:42 +0200 |
commit | 3863da58b1f7904675ca050434d8219bc410f34a (patch) | |
tree | a10b16ccda64e72fd4eeff0a69066c8436a9374f /test/test_want_conversion.c | |
parent | d66ca89e86a72fa5ad48d88ef5570062a79397be (diff) | |
download | libfuse-3863da58b1f7904675ca050434d8219bc410f34a.tar.gz |
conn: prevent duplicate flag conversion in high-level interface
The high-level interface triggers flag conversion twice: once in the
high-level init and once in the low-level init. This caused false
"both 'want' and 'want_ext' are set" errors when using
fuse_set_feature_flag() or fuse_unset_feature_flag().
The existing check for duplicate conversion only worked when 32-bit
flags were set directly. When using the preferred flag manipulation
functions, conn->want and the lower 32 bits of conn->want_ext
would differ, triggering the error.
Fix this by synchronizing conn->want with the lower 32 bits of
conn->want_ext after conversion, ensuring consistent state for
subsequent calls.
Closes: https://github.com/libfuse/libfuse/issues/1171
Signed-off-by: Bernd Schubert <bschubert@ddn.com>
Diffstat (limited to 'test/test_want_conversion.c')
-rw-r--r-- | test/test_want_conversion.c | 30 |
1 files changed, 21 insertions, 9 deletions
diff --git a/test/test_want_conversion.c b/test/test_want_conversion.c index 935b58d..bee23cc 100644 --- a/test/test_want_conversion.c +++ b/test/test_want_conversion.c @@ -1,11 +1,11 @@ #include "util.h" -#include <string.h> #define FUSE_USE_VERSION FUSE_MAKE_VERSION(3, 17) #include "fuse_i.h" #include <stdio.h> #include <assert.h> #include <inttypes.h> +#include <stdbool.h> static void print_conn_info(const char *prefix, struct fuse_conn_info *conn) { @@ -13,14 +13,21 @@ static void print_conn_info(const char *prefix, struct fuse_conn_info *conn) conn->want, conn->want_ext); } -static void application_init(struct fuse_conn_info *conn) +static void application_init_old_style(struct fuse_conn_info *conn) { - /* Simulate application init */ + /* Simulate application init the old style */ conn->want |= FUSE_CAP_ASYNC_READ; conn->want &= ~FUSE_CAP_SPLICE_READ; } -static void test_fuse_fs_init(struct fuse_conn_info *conn) +static void application_init_new_style(struct fuse_conn_info *conn) +{ + /* Simulate application init the new style */ + fuse_set_feature_flag(conn, FUSE_CAP_ASYNC_READ); + fuse_unset_feature_flag(conn, FUSE_CAP_SPLICE_READ); +} + +static void test_fuse_fs_init(struct fuse_conn_info *conn, bool new_style) { uint64_t want_ext_default = conn->want_ext; uint32_t want_default = fuse_lower_32_bits(conn->want_ext); @@ -31,18 +38,22 @@ static void test_fuse_fs_init(struct fuse_conn_info *conn) conn->want = want_default; - application_init(conn); + if (new_style) + application_init_new_style(conn); + else + application_init_old_style(conn); rc = convert_to_conn_want_ext(conn, want_ext_default, want_default); assert(rc == 0); } -static void test_do_init(struct fuse_conn_info *conn) +static void test_do_init(struct fuse_conn_info *conn, bool new_style) { /* Initial setup */ conn->capable_ext = FUSE_CAP_SPLICE_READ | FUSE_CAP_SPLICE_WRITE | FUSE_CAP_SPLICE_MOVE | FUSE_CAP_POSIX_LOCKS | - FUSE_CAP_FLOCK_LOCKS | FUSE_CAP_EXPORT_SUPPORT; + FUSE_CAP_FLOCK_LOCKS | FUSE_CAP_EXPORT_SUPPORT | + FUSE_CAP_ASYNC_READ; conn->capable = fuse_lower_32_bits(conn->capable_ext); conn->want_ext = conn->capable_ext; @@ -55,7 +66,7 @@ static void test_do_init(struct fuse_conn_info *conn) conn->want = want_default; conn->capable = fuse_lower_32_bits(conn->capable_ext); - test_fuse_fs_init(conn); + test_fuse_fs_init(conn, new_style); rc = convert_to_conn_want_ext(conn, want_ext_default, want_default); assert(rc == 0); @@ -82,7 +93,8 @@ static void test_want_conversion_basic(void) struct fuse_conn_info conn = { 0 }; printf("\nTesting basic want conversion:\n"); - test_do_init(&conn); + test_do_init(&conn, false); + test_do_init(&conn, true); print_conn_info("After init", &conn); } |