]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dlfcn-util: invert function naming and add helper that does the whole job
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 22 Jun 2021 06:48:41 +0000 (08:48 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 24 Jun 2021 08:16:43 +0000 (10:16 +0200)
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().

src/journal/pcre2-dlopen.c
src/shared/bpf-dlopen.c
src/shared/cryptsetup-util.c
src/shared/dlfcn-util.c
src/shared/dlfcn-util.h
src/shared/idn-util.c
src/shared/libfido2-util.c
src/shared/pwquality-util.c
src/shared/qrcode-util.c
src/shared/tpm2-util.c

index 5f78f76672a888ab9583a81dfab846da802610ff..210e39a0aed0e23e9a36a6085c5eb8ef91c3c889 100644 (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),
index 055614845877ef4a2f6e4e62d22f3f72e3988d1e..0d222ae19e93a04298f6f046c014af2136c81fd3 100644 (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),
index 9deae39dea0c4ba0cf5b5ab9e850d73bb63ca56b..99c78f68588a8f1e579aa4d818b09577b41eb4d7 100644 (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),
index 2dbff0e3589c387d7aefeb62429e7f659cee66e8..c027e3396b0d0bc8d5371c09e164b59d36275a8d 100644 (file)
@@ -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;
+}
index aa713d328bc66592676d1a7e62480e5e4f74a276..87585b406acd9ccbb8771e08a10cf16efdef0ec3 100644 (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) \
index 1c4472dc6694fca6a0b85b27302485e4909af6b0..63a9ebf99dd61bc229433f29b9fe549e67bd0d4c 100644 (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),
index ec09937d8388e92d56d2f2310ab679efa0a232fc..c69943262df7e21ebd7c8ce00b8820dceedca6a1 100644 (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),
index 5bd33eee4c44fb705c53b317c711722f79eff2cc..d7776e7eff207e9f191e4f47fbc39b12cc356ddc 100644 (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),
index 79ac640672563291d9f9f644afdb7763c3f25b36..5345b7288bc8aa33bae876b3b6126e8bac8896ff 100644 (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),
index b2540c62fef38170e0b3d72b6ec0d0a0b4711fe6..da78e1f406f08fbdb3fa5855d94efd60ec3b6baf 100644 (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),