mirror of
https://github.com/systemd/systemd.git
synced 2025-02-24 17:57:34 +03:00
journalctl: make pcre2 a dlopen() dependency
Let's make use of the library if it is installed, but otherwise just generate a nice error and provide all other functionality.
This commit is contained in:
parent
046c91314a
commit
9200bb30d0
@ -1798,8 +1798,8 @@ public_programs += executable(
|
|||||||
libqrencode,
|
libqrencode,
|
||||||
libxz,
|
libxz,
|
||||||
liblz4,
|
liblz4,
|
||||||
libpcre2,
|
libzstd,
|
||||||
libzstd],
|
libdl],
|
||||||
install_rpath : rootlibexecdir,
|
install_rpath : rootlibexecdir,
|
||||||
install : true,
|
install : true,
|
||||||
install_dir : rootbindir)
|
install_dir : rootbindir)
|
||||||
|
@ -56,6 +56,7 @@
|
|||||||
#include "pager.h"
|
#include "pager.h"
|
||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
|
#include "pcre2-dlopen.h"
|
||||||
#include "pretty-print.h"
|
#include "pretty-print.h"
|
||||||
#include "rlimit-util.h"
|
#include "rlimit-util.h"
|
||||||
#include "set.h"
|
#include "set.h"
|
||||||
@ -160,20 +161,20 @@ typedef struct BootId {
|
|||||||
} BootId;
|
} BootId;
|
||||||
|
|
||||||
#if HAVE_PCRE2
|
#if HAVE_PCRE2
|
||||||
DEFINE_TRIVIAL_CLEANUP_FUNC(pcre2_match_data*, pcre2_match_data_free);
|
DEFINE_TRIVIAL_CLEANUP_FUNC(pcre2_match_data*, sym_pcre2_match_data_free);
|
||||||
DEFINE_TRIVIAL_CLEANUP_FUNC(pcre2_code*, pcre2_code_free);
|
DEFINE_TRIVIAL_CLEANUP_FUNC(pcre2_code*, sym_pcre2_code_free);
|
||||||
|
|
||||||
static int pattern_compile(const char *pattern, unsigned flags, pcre2_code **out) {
|
static int pattern_compile(const char *pattern, unsigned flags, pcre2_code **out) {
|
||||||
int errorcode, r;
|
int errorcode, r;
|
||||||
PCRE2_SIZE erroroffset;
|
PCRE2_SIZE erroroffset;
|
||||||
pcre2_code *p;
|
pcre2_code *p;
|
||||||
|
|
||||||
p = pcre2_compile((PCRE2_SPTR8) pattern,
|
p = sym_pcre2_compile((PCRE2_SPTR8) pattern,
|
||||||
PCRE2_ZERO_TERMINATED, flags, &errorcode, &erroroffset, NULL);
|
PCRE2_ZERO_TERMINATED, flags, &errorcode, &erroroffset, NULL);
|
||||||
if (!p) {
|
if (!p) {
|
||||||
unsigned char buf[LINE_MAX];
|
unsigned char buf[LINE_MAX];
|
||||||
|
|
||||||
r = pcre2_get_error_message(errorcode, buf, sizeof buf);
|
r = sym_pcre2_get_error_message(errorcode, buf, sizeof buf);
|
||||||
|
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||||
"Bad pattern \"%s\": %s", pattern,
|
"Bad pattern \"%s\": %s", pattern,
|
||||||
@ -183,7 +184,6 @@ static int pattern_compile(const char *pattern, unsigned flags, pcre2_code **out
|
|||||||
*out = p;
|
*out = p;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int add_matches_for_device(sd_journal *j, const char *devpath) {
|
static int add_matches_for_device(sd_journal *j, const char *devpath) {
|
||||||
@ -1087,14 +1087,18 @@ static int parse_argv(int argc, char *argv[]) {
|
|||||||
if (arg_pattern) {
|
if (arg_pattern) {
|
||||||
unsigned flags;
|
unsigned flags;
|
||||||
|
|
||||||
|
r = dlopen_pcre2();
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
if (arg_case_sensitive >= 0)
|
if (arg_case_sensitive >= 0)
|
||||||
flags = !arg_case_sensitive * PCRE2_CASELESS;
|
flags = !arg_case_sensitive * PCRE2_CASELESS;
|
||||||
else {
|
else {
|
||||||
_cleanup_(pcre2_match_data_freep) pcre2_match_data *md = NULL;
|
_cleanup_(sym_pcre2_match_data_freep) pcre2_match_data *md = NULL;
|
||||||
bool has_case;
|
bool has_case;
|
||||||
_cleanup_(pcre2_code_freep) pcre2_code *cs = NULL;
|
_cleanup_(sym_pcre2_code_freep) pcre2_code *cs = NULL;
|
||||||
|
|
||||||
md = pcre2_match_data_create(1, NULL);
|
md = sym_pcre2_match_data_create(1, NULL);
|
||||||
if (!md)
|
if (!md)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
@ -1102,7 +1106,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = pcre2_match(cs, (PCRE2_SPTR8) arg_pattern, PCRE2_ZERO_TERMINATED, 0, 0, md, NULL);
|
r = sym_pcre2_match(cs, (PCRE2_SPTR8) arg_pattern, PCRE2_ZERO_TERMINATED, 0, 0, md, NULL);
|
||||||
has_case = r >= 0;
|
has_case = r >= 0;
|
||||||
|
|
||||||
flags = !has_case * PCRE2_CASELESS;
|
flags = !has_case * PCRE2_CASELESS;
|
||||||
@ -2630,12 +2634,12 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
#if HAVE_PCRE2
|
#if HAVE_PCRE2
|
||||||
if (arg_compiled_pattern) {
|
if (arg_compiled_pattern) {
|
||||||
_cleanup_(pcre2_match_data_freep) pcre2_match_data *md = NULL;
|
_cleanup_(sym_pcre2_match_data_freep) pcre2_match_data *md = NULL;
|
||||||
const void *message;
|
const void *message;
|
||||||
size_t len;
|
size_t len;
|
||||||
PCRE2_SIZE *ovec;
|
PCRE2_SIZE *ovec;
|
||||||
|
|
||||||
md = pcre2_match_data_create(1, NULL);
|
md = sym_pcre2_match_data_create(1, NULL);
|
||||||
if (!md)
|
if (!md)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
@ -2652,7 +2656,7 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
assert_se(message = startswith(message, "MESSAGE="));
|
assert_se(message = startswith(message, "MESSAGE="));
|
||||||
|
|
||||||
r = pcre2_match(arg_compiled_pattern,
|
r = sym_pcre2_match(arg_compiled_pattern,
|
||||||
message,
|
message,
|
||||||
len - strlen("MESSAGE="),
|
len - strlen("MESSAGE="),
|
||||||
0, /* start at offset 0 in the subject */
|
0, /* start at offset 0 in the subject */
|
||||||
@ -2667,14 +2671,14 @@ int main(int argc, char *argv[]) {
|
|||||||
unsigned char buf[LINE_MAX];
|
unsigned char buf[LINE_MAX];
|
||||||
int r2;
|
int r2;
|
||||||
|
|
||||||
r2 = pcre2_get_error_message(r, buf, sizeof buf);
|
r2 = sym_pcre2_get_error_message(r, buf, sizeof buf);
|
||||||
log_error("Pattern matching failed: %s",
|
log_error("Pattern matching failed: %s",
|
||||||
r2 < 0 ? "unknown error" : (char*) buf);
|
r2 < 0 ? "unknown error" : (char*) buf);
|
||||||
r = -EINVAL;
|
r = -EINVAL;
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
ovec = pcre2_get_ovector_pointer(md);
|
ovec = sym_pcre2_get_ovector_pointer(md);
|
||||||
highlight[0] = ovec[0];
|
highlight[0] = ovec[0];
|
||||||
highlight[1] = ovec[1];
|
highlight[1] = ovec[1];
|
||||||
}
|
}
|
||||||
@ -2766,7 +2770,7 @@ finish:
|
|||||||
|
|
||||||
#if HAVE_PCRE2
|
#if HAVE_PCRE2
|
||||||
if (arg_compiled_pattern) {
|
if (arg_compiled_pattern) {
|
||||||
pcre2_code_free(arg_compiled_pattern);
|
sym_pcre2_code_free(arg_compiled_pattern);
|
||||||
|
|
||||||
/* --grep was used, no error was thrown, but the pattern didn't
|
/* --grep was used, no error was thrown, but the pattern didn't
|
||||||
* match anything. Let's mimic grep's behavior here and return
|
* match anything. Let's mimic grep's behavior here and return
|
||||||
|
@ -101,7 +101,11 @@ journald_gperf_c = custom_target(
|
|||||||
|
|
||||||
systemd_cat_sources = files('cat.c')
|
systemd_cat_sources = files('cat.c')
|
||||||
|
|
||||||
journalctl_sources = files('journalctl.c')
|
journalctl_sources = files('''
|
||||||
|
journalctl.c
|
||||||
|
pcre2-dlopen.c
|
||||||
|
pcre2-dlopen.h
|
||||||
|
'''.split())
|
||||||
|
|
||||||
if conf.get('HAVE_QRENCODE') == 1
|
if conf.get('HAVE_QRENCODE') == 1
|
||||||
journalctl_sources += files('journal-qrcode.c',
|
journalctl_sources += files('journal-qrcode.c',
|
||||||
|
57
src/journal/pcre2-dlopen.c
Normal file
57
src/journal/pcre2-dlopen.c
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||||
|
|
||||||
|
#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());
|
||||||
|
|
||||||
|
r = dlsym_many_and_warn(
|
||||||
|
dl,
|
||||||
|
LOG_ERR,
|
||||||
|
&sym_pcre2_match_data_create, "pcre2_match_data_create_8",
|
||||||
|
&sym_pcre2_match_data_free, "pcre2_match_data_free_8",
|
||||||
|
&sym_pcre2_code_free, "pcre2_code_free_8",
|
||||||
|
&sym_pcre2_compile, "pcre2_compile_8",
|
||||||
|
&sym_pcre2_get_error_message, "pcre2_get_error_message_8",
|
||||||
|
&sym_pcre2_match, "pcre2_match_8",
|
||||||
|
&sym_pcre2_get_ovector_pointer, "pcre2_get_ovector_pointer_8",
|
||||||
|
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
|
18
src/journal/pcre2-dlopen.h
Normal file
18
src/journal/pcre2-dlopen.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if HAVE_PCRE2
|
||||||
|
|
||||||
|
#define PCRE2_CODE_UNIT_WIDTH 8
|
||||||
|
#include <pcre2.h>
|
||||||
|
|
||||||
|
extern pcre2_match_data* (*sym_pcre2_match_data_create)(uint32_t, pcre2_general_context *);
|
||||||
|
extern void (*sym_pcre2_match_data_free)(pcre2_match_data *);
|
||||||
|
extern void (*sym_pcre2_code_free)(pcre2_code *);
|
||||||
|
extern pcre2_code* (*sym_pcre2_compile)(PCRE2_SPTR, PCRE2_SIZE, uint32_t, int *, PCRE2_SIZE *, pcre2_compile_context *);
|
||||||
|
extern int (*sym_pcre2_get_error_message)(int, PCRE2_UCHAR *, PCRE2_SIZE);
|
||||||
|
extern int (*sym_pcre2_match)(const pcre2_code *, PCRE2_SPTR, PCRE2_SIZE, PCRE2_SIZE, uint32_t, pcre2_match_data *, pcre2_match_context *);
|
||||||
|
extern PCRE2_SIZE* (*sym_pcre2_get_ovector_pointer)(pcre2_match_data *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int dlopen_pcre2(void);
|
Loading…
x
Reference in New Issue
Block a user