dlfcn-util: invert function naming and add helper that does the whole job
We warn when the operation fails, not when it succeeds. Hence this should be "<do>_or_<handle failure>", not "<do>_and_<handle failure>". We *could* use whatever convention we want, but rust and perl are rather consistent in using the logical convention. We don't care about perl that much, but having a naming convention inverted wrt. rust would be rather confusing. Also, pretty much every implementation does similar steps, so add a nice wrapper which combines opening of the library and loading of the symbols. Also add missing sentinel attribute in dlopen_or_warn().
This commit is contained in:
@@ -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),
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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),
|
||||
|
||||
+47
-23
@@ -2,39 +2,63 @@
|
||||
|
||||
#include "dlfcn-util.h"
|
||||
|
||||
int dlsym_many_and_warn(void *dl, int level, ...) {
|
||||
va_list ap;
|
||||
int r;
|
||||
static int dlsym_many_or_warnv(void *dl, int log_level, va_list ap) {
|
||||
void (**fn)(void);
|
||||
|
||||
/* 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 */
|
||||
/* 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. */
|
||||
|
||||
va_start(ap, level);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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) \
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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),
|
||||
|
||||
Reference in New Issue
Block a user