66 lines
2.7 KiB
C
66 lines
2.7 KiB
C
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
|
|
|
#include "alloc-util.h"
|
|
#include "dlfcn-util.h"
|
|
#include "pcre2-dlopen.h"
|
|
|
|
#if HAVE_PCRE2
|
|
static void *pcre2_dl = NULL;
|
|
|
|
pcre2_match_data* (*sym_pcre2_match_data_create)(uint32_t, pcre2_general_context *);
|
|
void (*sym_pcre2_match_data_free)(pcre2_match_data *);
|
|
void (*sym_pcre2_code_free)(pcre2_code *);
|
|
pcre2_code* (*sym_pcre2_compile)(PCRE2_SPTR, PCRE2_SIZE, uint32_t, int *, PCRE2_SIZE *, pcre2_compile_context *);
|
|
int (*sym_pcre2_get_error_message)(int, PCRE2_UCHAR *, PCRE2_SIZE);
|
|
int (*sym_pcre2_match)(const pcre2_code *, PCRE2_SPTR, PCRE2_SIZE, PCRE2_SIZE, uint32_t, pcre2_match_data *, pcre2_match_context *);
|
|
PCRE2_SIZE* (*sym_pcre2_get_ovector_pointer)(pcre2_match_data *);
|
|
|
|
int dlopen_pcre2(void) {
|
|
_cleanup_(dlclosep) void *dl = NULL;
|
|
int r;
|
|
|
|
if (pcre2_dl)
|
|
return 0; /* Already loaded */
|
|
|
|
dl = dlopen("libpcre2-8.so.0", RTLD_LAZY);
|
|
if (!dl)
|
|
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
|
"PCRE2 support is not installed: %s", dlerror());
|
|
|
|
/* So here's something weird: PCRE2 actually renames the symbols exported by the library via C
|
|
* macros, so that the exported symbols carry a suffix "_8" but when used from C the suffix is
|
|
* gone. In the argument list below we ignore this mangling. Surprisingly (at least to me), we
|
|
* actually get away with that. That's because DLSYM_ARG() useses STRINGIFY() to generate a string
|
|
* version of the symbol name, and that resolves the macro mapping implicitly already, so that the
|
|
* 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(
|
|
dl,
|
|
LOG_ERR,
|
|
DLSYM_ARG(pcre2_match_data_create),
|
|
DLSYM_ARG(pcre2_match_data_free),
|
|
DLSYM_ARG(pcre2_code_free),
|
|
DLSYM_ARG(pcre2_compile),
|
|
DLSYM_ARG(pcre2_get_error_message),
|
|
DLSYM_ARG(pcre2_match),
|
|
DLSYM_ARG(pcre2_get_ovector_pointer),
|
|
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. */
|
|
pcre2_dl = TAKE_PTR(dl);
|
|
|
|
return 1;
|
|
}
|
|
|
|
#else
|
|
|
|
int dlopen_pcre2(void) {
|
|
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
|
"PCRE2 support is not compiled in.");
|
|
}
|
|
#endif
|