summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2020-12-09 21:09:33 +0100
committerGitHub <noreply@github.com>2020-12-09 21:09:33 +0100
commit733558adef7787f1a66c301bc36c4740218d16aa (patch)
treec8256cccf67289876560df746489fa4bb08bb0a8
parent4e1db59274c4b31ba5369270a489420245616eb4 (diff)
parenta6c7811f0d3888e2fa545cd80d7815049b5cb084 (diff)
downloadsystemd-733558adef7787f1a66c301bc36c4740218d16aa.tar.gz
Merge pull request #17884 from poettering/test-dlopen
tests: add test that dlopen()s our weak shared library deps once
-rw-r--r--meson.build1
-rw-r--r--src/shared/qrcode-util.c48
-rw-r--r--src/shared/qrcode-util.h2
-rw-r--r--src/test/meson.build4
-rw-r--r--src/test/test-dlopen-so.c40
-rw-r--r--test/test-functions13
6 files changed, 94 insertions, 14 deletions
diff --git a/meson.build b/meson.build
index 5d9413a5bb..513b841ac5 100644
--- a/meson.build
+++ b/meson.build
@@ -1117,6 +1117,7 @@ conf.set10('HAVE_LIBIPTC', have)
want_qrencode = get_option('qrencode')
if want_qrencode != 'false' and not skip_deps
libqrencode = dependency('libqrencode',
+ version : '>= 4',
required : want_qrencode == 'true')
have = libqrencode.found()
else
diff --git a/src/shared/qrcode-util.c b/src/shared/qrcode-util.c
index f7d2d984c9..6b9ff8531b 100644
--- a/src/shared/qrcode-util.c
+++ b/src/shared/qrcode-util.c
@@ -5,12 +5,45 @@
#if HAVE_QRENCODE
#include <qrencode.h>
+#include "alloc-util.h"
#include "dlfcn-util.h"
#include "locale-util.h"
#include "terminal-util.h"
#define ANSI_WHITE_ON_BLACK "\033[40;37;1m"
+static void *qrcode_dl = NULL;
+
+static QRcode* (*sym_QRcode_encodeString)(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive) = NULL;
+static void (*sym_QRcode_free)(QRcode *qrcode) = NULL;
+
+int dlopen_qrencode(void) {
+ _cleanup_(dlclosep) void *dl = NULL;
+ int r;
+
+ if (qrcode_dl)
+ return 0; /* Already loaded */
+
+ dl = dlopen("libqrencode.so.4", RTLD_LAZY);
+ if (!dl)
+ return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "libqrcode support is not installed: %s", dlerror());
+
+ r = dlsym_many_and_warn(
+ dl,
+ LOG_DEBUG,
+ DLSYM_ARG(QRcode_encodeString),
+ DLSYM_ARG(QRcode_free),
+ NULL);
+ 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. */
+ qrcode_dl = TAKE_PTR(dl);
+ return 1;
+}
+
static void print_border(FILE *output, unsigned width) {
/* Four rows of border */
for (unsigned y = 0; y < 4; y += 2) {
@@ -65,9 +98,6 @@ static void write_qrcode(FILE *output, QRcode *qr) {
}
int print_qrcode(FILE *out, const char *header, const char *string) {
- QRcode* (*sym_QRcode_encodeString)(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive);
- void (*sym_QRcode_free)(QRcode *qrcode);
- _cleanup_(dlclosep) void *dl = NULL;
QRcode* qr;
int r;
@@ -76,17 +106,7 @@ int print_qrcode(FILE *out, const char *header, const char *string) {
if (!is_locale_utf8() || !colors_enabled())
return -EOPNOTSUPP;
- dl = dlopen("libqrencode.so.4", RTLD_LAZY);
- if (!dl)
- return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
- "QRCODE support is not installed: %s", dlerror());
-
- r = dlsym_many_and_warn(
- dl,
- LOG_DEBUG,
- DLSYM_ARG(QRcode_encodeString),
- DLSYM_ARG(QRcode_free),
- NULL);
+ r = dlopen_qrencode();
if (r < 0)
return r;
diff --git a/src/shared/qrcode-util.h b/src/shared/qrcode-util.h
index 6fc45c93d1..b64ecce80a 100644
--- a/src/shared/qrcode-util.h
+++ b/src/shared/qrcode-util.h
@@ -5,6 +5,8 @@
#include <errno.h>
#if HAVE_QRENCODE
+int dlopen_qrencode(void);
+
int print_qrcode(FILE *out, const char *header, const char *string);
#else
static inline int print_qrcode(FILE *out, const char *header, const char *string) {
diff --git a/src/test/meson.build b/src/test/meson.build
index 9e781f88dc..3afe5d58cb 100644
--- a/src/test/meson.build
+++ b/src/test/meson.build
@@ -71,6 +71,10 @@ tests += [
libshared],
[]],
+ [['src/test/test-dlopen-so.c'],
+ [libshared],
+ []],
+
[['src/test/test-job-type.c'],
[libcore,
libshared],
diff --git a/src/test/test-dlopen-so.c b/src/test/test-dlopen-so.c
new file mode 100644
index 0000000000..6436dc600f
--- /dev/null
+++ b/src/test/test-dlopen-so.c
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <dlfcn.h>
+#include <stdlib.h>
+
+#include "cryptsetup-util.h"
+#include "idn-util.h"
+#include "macro.h"
+#include "main-func.h"
+#include "pwquality-util.h"
+#include "qrcode-util.h"
+#include "tests.h"
+
+static int run(int argc, char **argv) {
+ test_setup_logging(LOG_DEBUG);
+
+ /* Try to load each of our weak library dependencies once. This is supposed to help finding cases
+ * where .so versions change and distributions update, but systemd doesn't have the new so names
+ * around yet. */
+
+#if HAVE_LIBIDN2 || HAVE_LIBIDN
+ assert_se(dlopen_idn() >= 0);
+#endif
+
+#if HAVE_LIBCRYPTSETUP
+ assert_se(dlopen_cryptsetup() >= 0);
+#endif
+
+#if HAVE_PWQUALITY
+ assert_se(dlopen_pwquality() >= 0);
+#endif
+
+#if HAVE_QRENCODE
+ assert_se(dlopen_qrencode() >= 0);
+#endif
+
+ return 0;
+}
+
+DEFINE_MAIN_FUNCTION(run);
diff --git a/test/test-functions b/test/test-functions
index d5da8e0ea5..91cd7312d6 100644
--- a/test/test-functions
+++ b/test/test-functions
@@ -676,6 +676,19 @@ install_missing_libraries() {
for i in $initdir{,/usr}/{sbin,bin}/* $initdir{,/usr}/lib/systemd/{,tests/{,manual/,unsafe/}}*; do
LD_LIBRARY_PATH="${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$(get_ldpath $i):$(get_ldpath $i)/src/udev" inst_libs $i
done
+
+ # A number of dependencies is now optional via dlopen, so the install
+ # script will not pick them up, since it looks at linkage.
+ for lib in libcryptsetup libidn libidn2 pwquality libqrencode; do
+ if pkg-config --exists ${lib}; then
+ path=$(pkg-config --variable=libdir ${lib})
+ if ! [[ ${lib} =~ ^lib ]]; then
+ lib="lib${lib}"
+ fi
+ inst_libs "${path}/${lib}.so"
+ inst_library "${path}/${lib}.so"
+ fi
+ done
}
cleanup_loopdev() {