* 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),
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),
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),
#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;
+}
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) \
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),
"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),
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),
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),
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),
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),
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),
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),