aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorBernd Schubert <bernd.schubert@fastmail.fm>2024-05-13 12:32:06 +0200
committerGitHub <noreply@github.com>2024-05-13 12:32:06 +0200
commit58f85bfa9b7dca9a216cd0bb4e38e9cdf4b661da (patch)
tree6b731982629b96315c70bca87280141e3240fcd7 /lib
parent2bdec0bc22ce39b307e299ee9ec19d1c58b640de (diff)
downloadlibfuse-58f85bfa9b7dca9a216cd0bb4e38e9cdf4b661da.tar.gz
Add in the libfuse version a program was compiled with (#942)
The API stays the same, the libfuse version comes from inlined functions, which are defined fuse_lowlevel.h and fuse.h. As these inlined functions are defined in the header files they get added into the application, similar as if these were preprocessor macros. Macro vs inlined function is then just a style issue - I personally prefer the latter. fuse_session_new() -> static inlinei, in the application _fuse_session_new -> inside of libfuse fuse_new() -> static inline, in the application _fuse_new() -> inside of libfuse Note: Entirely untested is the fuse 30 api - we need a test for it. And we do not have any ABI tests at all. Signed-off-by: Bernd Schubert <bernd.schubert@fastmail.fm>
Diffstat (limited to 'lib')
-rw-r--r--lib/fuse.c75
-rw-r--r--lib/fuse_i.h5
-rw-r--r--lib/fuse_lowlevel.c33
-rw-r--r--lib/fuse_versionscript9
-rw-r--r--lib/helper.c20
5 files changed, 125 insertions, 17 deletions
diff --git a/lib/fuse.c b/lib/fuse.c
index f619c00..8617168 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -4890,11 +4890,19 @@ void fuse_stop_cleanup_thread(struct fuse *f)
}
}
-
-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)
+/*
+ * Not supposed to be called directly, but supposed to be called
+ * through the fuse_new macro
+ */
+struct fuse *_fuse_new_317(struct fuse_args *args,
+ const struct fuse_operations *op,
+ size_t op_size, struct libfuse_version *version,
+ void *user_data);
+FUSE_SYMVER("_fuse_new_317", "_fuse_new@@FUSE_3.17")
+struct fuse *_fuse_new_317(struct fuse_args *args,
+ const struct fuse_operations *op,
+ size_t op_size, struct libfuse_version *version,
+ void *user_data)
{
struct fuse *f;
struct node *root;
@@ -4976,7 +4984,7 @@ struct fuse *fuse_new_31(struct fuse_args *args,
f->conf.readdir_ino = 1;
#endif
- f->se = fuse_session_new(args, &llop, sizeof(llop), f);
+ f->se = _fuse_session_new(args, &llop, sizeof(llop), version, f);
if (f->se == NULL)
goto out_free_fs;
@@ -5041,16 +5049,62 @@ 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,
+ struct libfuse_version *version,
+ void *user_data);
+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,
+ struct libfuse_version *version,
+ void *user_data)
+{
+ struct fuse_config conf = {0};
+
+ const struct fuse_opt opts[] = {
+ FUSE_LIB_OPT("-h", show_help, 1),
+ FUSE_LIB_OPT("--help", show_help, 1),
+ FUSE_OPT_END
+ };
+
+ if (fuse_opt_parse(args, &conf, opts,
+ fuse_lib_opt_proc) == -1)
+ return NULL;
+
+ if (conf.show_help) {
+ fuse_lib_help(args);
+ return NULL;
+ } else
+ return _fuse_new_317(args, op, op_size, version, user_data);
+}
+
+/* ABI compat version */
+struct fuse *fuse_new_31(struct fuse_args *args, const struct fuse_operations *op,
+ size_t op_size, void *user_data);
+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)
+{
+ /* unknown version */
+ struct libfuse_version version = { 0 };
+
+ return _fuse_new_317(args, op, op_size, &version, user_data);
+}
+
+/*
+ * ABI compat version
+ * 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);
+ size_t op_size, void *user_data);
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)
{
- struct fuse_config conf;
-
- memset(&conf, 0, sizeof(conf));
+ struct fuse_config conf = {0};
const struct fuse_opt opts[] = {
FUSE_LIB_OPT("-h", show_help, 1),
@@ -5069,6 +5123,7 @@ struct fuse *fuse_new_30(struct fuse_args *args,
return fuse_new_31(args, op, op_size, user_data);
}
+
void fuse_destroy(struct fuse *f)
{
size_t i;
diff --git a/lib/fuse_i.h b/lib/fuse_i.h
index 74cfe36..7a2ae04 100644
--- a/lib/fuse_i.h
+++ b/lib/fuse_i.h
@@ -65,6 +65,11 @@ struct fuse_session {
struct fuse_notify_req notify_list;
size_t bufsize;
int error;
+
+ /* This is useful if any kind of ABI incompatibility is found at
+ * a later version, to 'fix' it at run time.
+ */
+ struct libfuse_version version;
};
struct fuse_chan {
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index 46aef98..c08c99c 100644
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -3024,9 +3024,12 @@ restart:
return res;
}
-struct fuse_session *fuse_session_new(struct fuse_args *args,
- const struct fuse_lowlevel_ops *op,
- size_t op_size, void *userdata)
+FUSE_SYMVER("_fuse_session_new_317", "_fuse_session_new@@FUSE_3.17")
+struct fuse_session *_fuse_session_new_317(struct fuse_args *args,
+ const struct fuse_lowlevel_ops *op,
+ size_t op_size,
+ struct libfuse_version *version,
+ void *userdata)
{
int err;
struct fuse_session *se;
@@ -3105,6 +3108,14 @@ struct fuse_session *fuse_session_new(struct fuse_args *args,
se->userdata = userdata;
se->mo = mo;
+
+ /* Fuse server application should pass the version it was compiled
+ * against and pass it. If a libfuse version accidentally introduces an
+ * ABI incompatibility, it might be possible to 'fix' that at run time,
+ * by checking the version numbers.
+ */
+ se->version = *version;
+
return se;
out5:
@@ -3120,6 +3131,22 @@ out1:
return NULL;
}
+struct fuse_session *fuse_session_new_30(struct fuse_args *args,
+ const struct fuse_lowlevel_ops *op,
+ size_t op_size,
+ void *userdata);
+FUSE_SYMVER("fuse_session_new_30", "fuse_session_new@FUSE_3.0")
+struct fuse_session *fuse_session_new_30(struct fuse_args *args,
+ const struct fuse_lowlevel_ops *op,
+ size_t op_size,
+ void *userdata)
+{
+ /* unknown version */
+ struct libfuse_version version = { 0 };
+
+ return _fuse_session_new_317(args, op, op_size, &version, userdata);
+}
+
int fuse_session_custom_io(struct fuse_session *se, const struct fuse_custom_io *io,
int fd)
{
diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript
index c0d58bf..22782bc 100644
--- a/lib/fuse_versionscript
+++ b/lib/fuse_versionscript
@@ -187,6 +187,15 @@ FUSE_3.12 {
fuse_lowlevel_notify_expire_entry;
} FUSE_3.4;
+FUSE_3.17 {
+ global:
+ _fuse_session_new_317;
+ _fuse_new;
+ _fuse_new_30;
+ _fuse_new_317;
+ fuse_main_real_317;
+} FUSE_3.12;
+
# Local Variables:
# indent-tabs-mode: t
# End:
diff --git a/lib/helper.c b/lib/helper.c
index 14a0df3..e84c857 100644
--- a/lib/helper.c
+++ b/lib/helper.c
@@ -304,8 +304,11 @@ int fuse_daemonize(int foreground)
return 0;
}
-int fuse_main_real(int argc, char *argv[], const struct fuse_operations *op,
- size_t op_size, void *user_data)
+int fuse_main_real_317(int argc, char *argv[], const struct fuse_operations *op,
+ size_t op_size, struct libfuse_version *version, void *user_data);
+FUSE_SYMVER("fuse_main_real_317", "fuse_main_real@@FUSE_3.17")
+int fuse_main_real_317(int argc, char *argv[], const struct fuse_operations *op,
+ size_t op_size, struct libfuse_version *version, void *user_data)
{
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
struct fuse *fuse;
@@ -341,8 +344,7 @@ int fuse_main_real(int argc, char *argv[], const struct fuse_operations *op,
goto out1;
}
-
- fuse = fuse_new_31(&args, op, op_size, user_data);
+ fuse = _fuse_new(&args, op, op_size, version, user_data);
if (fuse == NULL) {
res = 3;
goto out1;
@@ -394,6 +396,16 @@ out1:
return res;
}
+int fuse_main_real_30(int argc, char *argv[], const struct fuse_operations *op,
+ size_t op_size, void *user_data);
+FUSE_SYMVER("fuse_main_real_30", "fuse_main_real@FUSE_3.0")
+int fuse_main_real_30(int argc, char *argv[], const struct fuse_operations *op,
+ size_t op_size, void *user_data)
+{
+ struct libfuse_version version = { 0 };
+
+ return fuse_main_real_317(argc, argv, op, op_size, &version, user_data);
+}
void fuse_apply_conn_info_opts(struct fuse_conn_info_opts *opts,
struct fuse_conn_info *conn)