1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "dlfcn-util.h"
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 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. */
while ((fn = va_arg(ap, typeof(fn)))) {
void (*tfn)(void);
const char *symbol;
symbol = va_arg(ap, typeof(symbol));
tfn = (typeof(tfn)) dlsym(dl, symbol);
if (!tfn)
return log_full_errno(log_level,
SYNTHETIC_ERRNO(ELIBBAD),
"Can't find symbol %s: %s", symbol, dlerror());
*fn = tfn;
}
return 0;
}
int dlsym_many_or_warn_sentinel(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());
log_debug("Loaded '%s' via dlopen()", filename);
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;
}
|