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:
Zbigniew Jędrzejewski-Szmek
2021-06-24 10:16:43 +02:00
parent 87501ac0eb
commit fff25ab22e
10 changed files with 64 additions and 36 deletions
+1 -1
View File
@@ -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),
+1 -1
View File
@@ -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),
+1 -1
View File
@@ -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
View File
@@ -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;
}
+6 -2
View File
@@ -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) \
+2 -2
View File
@@ -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),
+1 -1
View File
@@ -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),
+1 -1
View File
@@ -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),
+1 -1
View File
@@ -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),
+3 -3
View File
@@ -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),