summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/journal/pcre2-dlopen.c2
-rw-r--r--src/shared/bpf-dlopen.c2
-rw-r--r--src/shared/cryptsetup-util.c2
-rw-r--r--src/shared/dlfcn-util.c70
-rw-r--r--src/shared/dlfcn-util.h8
-rw-r--r--src/shared/idn-util.c4
-rw-r--r--src/shared/libfido2-util.c2
-rw-r--r--src/shared/pwquality-util.c2
-rw-r--r--src/shared/qrcode-util.c2
-rw-r--r--src/shared/tpm2-util.c6
10 files changed, 64 insertions, 36 deletions
diff --git a/src/journal/pcre2-dlopen.c b/src/journal/pcre2-dlopen.c
index 5f78f76672..210e39a0ae 100644
--- a/src/journal/pcre2-dlopen.c
+++ b/src/journal/pcre2-dlopen.c
@@ -35,7 +35,7 @@ int dlopen_pcre2(void) {
* string actually contains the "_8" suffix already due to that and we don't have to append it
* manually anymore. C is weird. 🤯 */
- r = dlsym_many_and_warn(
+ r = dlsym_many_or_warn(
dl,
LOG_ERR,
DLSYM_ARG(pcre2_match_data_create),
diff --git a/src/shared/bpf-dlopen.c b/src/shared/bpf-dlopen.c
index 0556148458..0d222ae19e 100644
--- a/src/shared/bpf-dlopen.c
+++ b/src/shared/bpf-dlopen.c
@@ -35,7 +35,7 @@ int dlopen_bpf(void) {
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"libbpf is not installed: %s", dlerror());
- r = dlsym_many_and_warn(
+ r = dlsym_many_or_warn(
dl,
LOG_DEBUG,
DLSYM_ARG(bpf_link__destroy),
diff --git a/src/shared/cryptsetup-util.c b/src/shared/cryptsetup-util.c
index 9deae39dea..99c78f6858 100644
--- a/src/shared/cryptsetup-util.c
+++ b/src/shared/cryptsetup-util.c
@@ -62,7 +62,7 @@ int dlopen_cryptsetup(void) {
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"libcryptsetup support is not installed: %s", dlerror());
- r = dlsym_many_and_warn(
+ r = dlsym_many_or_warn(
dl,
LOG_DEBUG,
DLSYM_ARG(crypt_activate_by_passphrase),
diff --git a/src/shared/dlfcn-util.c b/src/shared/dlfcn-util.c
index 2dbff0e358..c027e3396b 100644
--- a/src/shared/dlfcn-util.c
+++ b/src/shared/dlfcn-util.c
@@ -2,39 +2,63 @@
#include "dlfcn-util.h"
-int dlsym_many_and_warn(void *dl, int level, ...) {
- va_list ap;
- int r;
-
- /* Tries to resolve a bunch of function symbols, and logs errors about the ones it cannot
- * resolve. Note that this function possibly modifies the supplied function pointers if the whole
- * operation fails */
+static int dlsym_many_or_warnv(void *dl, int log_level, va_list ap) {
+ void (**fn)(void);
- va_start(ap, level);
+ /* Tries to resolve a bunch of function symbols, and logs an error about if it cannot resolve one of
+ * them. Note that this function possibly modifies the supplied function pointers if the whole
+ * operation fails. */
- for (;;) {
- void (**fn)(void);
+ while ((fn = va_arg(ap, typeof(fn)))) {
void (*tfn)(void);
const char *symbol;
- fn = va_arg(ap, typeof(fn));
- if (!fn)
- break;
-
symbol = va_arg(ap, typeof(symbol));
tfn = (typeof(tfn)) dlsym(dl, symbol);
- if (!tfn) {
- r = log_full_errno(level,
- SYNTHETIC_ERRNO(ELIBBAD),
- "Can't find symbol %s: %s", symbol, dlerror());
- va_end(ap);
- return r;
- }
-
+ if (!tfn)
+ return log_full_errno(log_level,
+ SYNTHETIC_ERRNO(ELIBBAD),
+ "Can't find symbol %s: %s", symbol, dlerror());
*fn = tfn;
}
- va_end(ap);
return 0;
}
+
+int dlsym_many_or_warn(void *dl, int log_level, ...) {
+ va_list ap;
+ int r;
+
+ va_start(ap, log_level);
+ r = dlsym_many_or_warnv(dl, log_level, ap);
+ va_end(ap);
+
+ return r;
+}
+
+int dlopen_many_sym_or_warn_sentinel(void **dlp, const char *filename, int log_level, ...) {
+ _cleanup_(dlclosep) void *dl = NULL;
+ int r;
+
+ if (*dlp)
+ return 0; /* Already loaded */
+
+ dl = dlopen(filename, RTLD_LAZY);
+ if (!dl)
+ return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "%s is not installed: %s", filename, dlerror());
+
+ va_list ap;
+ va_start(ap, log_level);
+ r = dlsym_many_or_warnv(dl, log_level, ap);
+ va_end(ap);
+
+ if (r < 0)
+ return r;
+
+ /* Note that we never release the reference here, because there's no real reason to. After all this
+ * was traditionally a regular shared library dependency which lives forever too. */
+ *dlp = TAKE_PTR(dl);
+ return 1;
+}
diff --git a/src/shared/dlfcn-util.h b/src/shared/dlfcn-util.h
index aa713d328b..87585b406a 100644
--- a/src/shared/dlfcn-util.h
+++ b/src/shared/dlfcn-util.h
@@ -7,9 +7,13 @@
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(void*, dlclose, NULL);
-int dlsym_many_and_warn(void *dl, int level, ...);
+int dlsym_many_or_warn(void *dl, int log_level, ...) _sentinel_;
+int dlopen_many_sym_or_warn_sentinel(void **dlp, const char *filename, int log_level, ...) _sentinel_;
-/* Macro useful for putting together variable/symbol name pairs when calling dlsym_many_and_warn(). Assumes
+#define dlopen_many_sym_or_warn(dlp, filename, log_level, ...) \
+ dlopen_many_sym_or_warn_sentinel(dlp, filename, log_level, __VA_ARGS__, NULL)
+
+/* Macro useful for putting together variable/symbol name pairs when calling dlsym_many_or_warn(). Assumes
* that each library symbol to resolve will be placed in a variable with the "sym_" prefix, i.e. a symbol
* "foobar" is loaded into a variable "sym_foobar". */
#define DLSYM_ARG(arg) \
diff --git a/src/shared/idn-util.c b/src/shared/idn-util.c
index 1c4472dc66..63a9ebf99d 100644
--- a/src/shared/idn-util.c
+++ b/src/shared/idn-util.c
@@ -32,7 +32,7 @@ int dlopen_idn(void) {
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"libidn2 support is not installed: %s", dlerror());
- r = dlsym_many_and_warn(
+ r = dlsym_many_or_warn(
dl,
LOG_DEBUG,
DLSYM_ARG(idn2_lookup_u8),
@@ -73,7 +73,7 @@ int dlopen_idn(void) {
"libidn support is not installed: %s", dlerror());
}
- r = dlsym_many_and_warn(
+ r = dlsym_many_or_warn(
dl,
LOG_DEBUG,
DLSYM_ARG(idna_to_ascii_4i),
diff --git a/src/shared/libfido2-util.c b/src/shared/libfido2-util.c
index ec09937d83..c69943262d 100644
--- a/src/shared/libfido2-util.c
+++ b/src/shared/libfido2-util.c
@@ -72,7 +72,7 @@ int dlopen_libfido2(void) {
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"libfido2 support is not installed: %s", dlerror());
- r = dlsym_many_and_warn(
+ r = dlsym_many_or_warn(
dl,
LOG_DEBUG,
DLSYM_ARG(fido_assert_allow_cred),
diff --git a/src/shared/pwquality-util.c b/src/shared/pwquality-util.c
index 5bd33eee4c..d7776e7eff 100644
--- a/src/shared/pwquality-util.c
+++ b/src/shared/pwquality-util.c
@@ -35,7 +35,7 @@ int dlopen_pwquality(void) {
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"libpwquality support is not installed: %s", dlerror());
- r = dlsym_many_and_warn(
+ r = dlsym_many_or_warn(
dl,
LOG_DEBUG,
DLSYM_ARG(pwquality_check),
diff --git a/src/shared/qrcode-util.c b/src/shared/qrcode-util.c
index 79ac640672..5345b7288b 100644
--- a/src/shared/qrcode-util.c
+++ b/src/shared/qrcode-util.c
@@ -29,7 +29,7 @@ int dlopen_qrencode(void) {
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"libqrcode support is not installed: %s", dlerror());
- r = dlsym_many_and_warn(
+ r = dlsym_many_or_warn(
dl,
LOG_DEBUG,
DLSYM_ARG(QRcode_encodeString),
diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c
index b2540c62fe..da78e1f406 100644
--- a/src/shared/tpm2-util.c
+++ b/src/shared/tpm2-util.c
@@ -52,7 +52,7 @@ int dlopen_tpm2(void) {
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"TPM2 support is not installed: %s", dlerror());
- r = dlsym_many_and_warn(
+ r = dlsym_many_or_warn(
dl,
LOG_DEBUG,
DLSYM_ARG(Esys_Create),
@@ -84,7 +84,7 @@ int dlopen_tpm2(void) {
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"TPM2 support is not installed: %s", dlerror());
- r = dlsym_many_and_warn(
+ r = dlsym_many_or_warn(
dl,
LOG_DEBUG,
DLSYM_ARG(Tss2_RC_Decode),
@@ -104,7 +104,7 @@ int dlopen_tpm2(void) {
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"TPM2 support is not installed: %s", dlerror());
- r = dlsym_many_and_warn(
+ r = dlsym_many_or_warn(
dl,
LOG_DEBUG,
DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Marshal),