Compare commits

..

21 Commits

Author SHA1 Message Date
Zbigniew Jędrzejewski-Szmek fea4ac42e3
Merge pull request #16652 from eliroca/adapt-tests-for-SUSE
Adapt tests to work on SUSE
2020-08-04 17:13:28 +02:00
Lennart Poettering f01da474d1 update TODO 2020-08-04 16:47:40 +02:00
Zbigniew Jędrzejewski-Szmek d06bd2e785 Merge pull request #16596 from poettering/event-time-rel
Conflict in src/libsystemd-network/test-ndisc-rs.c fixed manually.
2020-08-04 16:07:03 +02:00
Zbigniew Jędrzejewski-Szmek 1472b58835
Merge pull request #16260 from poettering/pcre2-dlopen
turn pcre2 dependency into dlopen() dependency
2020-08-04 15:37:48 +02:00
Zbigniew Jędrzejewski-Szmek 3a4378cb9e
Merge pull request #16145 from poettering/qrcode-dlopen
journalctl: make libqrencode a weak (dlopen() style) dependency
2020-08-04 15:25:50 +02:00
Lennart Poettering 11579a956d home: use ID128_UUID_STRING_MAX where appropriate 2020-08-04 12:40:34 +02:00
Joerg Behrmann c90b6abc91 docs: spelling fixes 2020-08-04 12:39:03 +02:00
Elisei Roca 491b736a49 test: adapt TEST-13-NSPAWN-SMOKE for SUSE 2020-08-03 17:41:29 +02:00
Elisei Roca ef8b52c657 test: adapt TEST-21-SYSUSERS for SUSE 2020-08-03 16:32:14 +02:00
Lennart Poettering f6ad6248e8 update TODO 2020-07-28 11:25:08 +02:00
Lennart Poettering 39cf0351c5 tree-wide: make use of new relative time events in sd-event.h 2020-07-28 11:24:55 +02:00
Lennart Poettering 4c5e74f71b man: document new relative time APIs in sd-event 2020-07-28 11:24:37 +02:00
Lennart Poettering d6a83dc48a sd-event: add relative timer calls
We frequently want to set a timer relative to the current time. Let's
add an explicit API for this. This not only saves us a few lines of code
everywhere and simplifies things, but also allows us to do correct
overflow checking.
2020-07-28 11:23:41 +02:00
Lennart Poettering 43663e2254 update TODO 2020-07-21 10:38:04 +02:00
Lennart Poettering 9200bb30d0 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.
2020-07-21 10:37:54 +02:00
Lennart Poettering 046c91314a dlfcn-util: add dlsym_many_and_warn() helper
When we dlopen() some library we most likely will resolve more than a
few symbols, hence add a helper that makes it easy.
2020-07-21 10:36:38 +02:00
Lennart Poettering e44b500484 journalctl: make libqrencode a weak dependency
This way journalctl can make use of libqrencode if it's there, but will
quietly not use it if it isn't.

This means libqrencode remains a build-time dep, but not a strict
runtime dependency.

I figure we should do something similar for a bunch of other "leaf"
libraries we only use few symbols of. Specifically the following are
probably good candidates:

* pcre2
* libpwquality
* p11kit
* elfutils

and possibly:

* libcryptsetup (only in some parts. i.e. building systemd-cryptsetup
  without it makes no sense. However building the dissect option with
  libcryptsetup as optional dep does make sense)
* possibly the compression libraries (at least the ones we never use for
  compression, but only as alternative ones for decompression)

Already covered like this is:

* libxkcommon
2020-06-25 09:28:27 +02:00
Lennart Poettering a4df1f0b9d journalctl: set and log about all fss file flags individually
Also, don#t complain about unsupported chattr support on backing fs
beyond LOG_DEBUG.
2020-06-25 09:28:22 +02:00
Lennart Poettering 0523022d5b journalctl: don't print QR codes if we can't/shan't use colors
We need them to display things properly, hence treat color-less
terminals the same way as UTF-8-less systems: avoid the QR code.
2020-06-25 09:28:18 +02:00
Lennart Poettering 9bff141052 qrcode: modernize code a bit 2020-06-25 09:28:12 +02:00
Lennart Poettering 49b19567d6 dlfcn-util: add dlsym_many_and_warn() helper
When we dlopen() some library we most likely will resolve more than a
few symbols, hence add a helper that makes it easy.
2020-06-25 09:27:11 +02:00
41 changed files with 479 additions and 276 deletions

9
TODO
View File

@ -20,6 +20,9 @@ Features:
* make use of the new statx mountid and rootmount fields in path_get_mnt_id() * make use of the new statx mountid and rootmount fields in path_get_mnt_id()
and fd_is_mount_point() and fd_is_mount_point()
* make use of new loopback setup ioctl to setup loopback devices in one atomic
ioctl
* nspawn: move "incoming mount" directory to /run/host, move "inaccessible" * nspawn: move "incoming mount" directory to /run/host, move "inaccessible"
nodes to /run/host, move notify socket (for sd_notify() between payload and nodes to /run/host, move notify socket (for sd_notify() between payload and
container manager) container manager)
@ -83,8 +86,6 @@ Features:
* make us use dynamically fewer deps for containers in general purpose distros: * make us use dynamically fewer deps for containers in general purpose distros:
o turn into dlopen() deps: o turn into dlopen() deps:
- pcre2 (always) — irrelevant on Fedora, since dep by
libselinux, but should benefit Debian
- libpwquality (always) - only relevant for homed, and maybe soon - libpwquality (always) - only relevant for homed, and maybe soon
firstboot firstboot
- elfutils (always) - elfutils (always)
@ -936,6 +937,10 @@ Features:
- allow multiple signal handlers per signal? - allow multiple signal handlers per signal?
- document chaining of signal handler for SIGCHLD and child handlers - document chaining of signal handler for SIGCHLD and child handlers
- define more intervals where we will shift wakeup intervals around in, 1h, 6h, 24h, ... - define more intervals where we will shift wakeup intervals around in, 1h, 6h, 24h, ...
- maybe support iouring as backend, so that we allow hooking read and write
operations instead of IO ready events into event loops. See considerations
here:
http://blog.vmsplice.net/2020/07/rethinking-event-loop-integration-for.html
* investigate endianness issues of UUID vs. GUID * investigate endianness issues of UUID vs. GUID

View File

@ -372,7 +372,7 @@ layout: default
broken on Linux). broken on Linux).
- When applying C-style unescaping as well as specifier expansion on the same - When applying C-style unescaping as well as specifier expansion on the same
string, always apply the C-style unescaping fist, followed by the specifier string, always apply the C-style unescaping first, followed by the specifier
expansion. When doing the reverse, make sure to escape `%` in specifier-style expansion. When doing the reverse, make sure to escape `%` in specifier-style
first (i.e. `%``%%`), and then do C-style escaping where necessary. first (i.e. `%``%%`), and then do C-style escaping where necessary.
@ -529,7 +529,7 @@ layout: default
- Don't use `fgets()`, it's too hard to properly handle errors such as overly - Don't use `fgets()`, it's too hard to properly handle errors such as overly
long lines. Use `read_line()` instead, which is our own function that handles long lines. Use `read_line()` instead, which is our own function that handles
this much nicer. this much more nicely.
- Don't invoke `exit()`, ever. It is not replacement for proper error - Don't invoke `exit()`, ever. It is not replacement for proper error
handling. Please escalate errors up your call chain, and use normal `return` handling. Please escalate errors up your call chain, and use normal `return`

View File

@ -51,6 +51,17 @@
<paramdef>void *<parameter>userdata</parameter></paramdef> <paramdef>void *<parameter>userdata</parameter></paramdef>
</funcprototype> </funcprototype>
<funcprototype>
<funcdef>int <function>sd_event_add_time_relative</function></funcdef>
<paramdef>sd_event *<parameter>event</parameter></paramdef>
<paramdef>sd_event_source **<parameter>source</parameter></paramdef>
<paramdef>clockid_t <parameter>clock</parameter></paramdef>
<paramdef>uint64_t <parameter>usec</parameter></paramdef>
<paramdef>uint64_t <parameter>accuracy</parameter></paramdef>
<paramdef>sd_event_time_handler_t <parameter>handler</parameter></paramdef>
<paramdef>void *<parameter>userdata</parameter></paramdef>
</funcprototype>
<funcprototype> <funcprototype>
<funcdef>int <function>sd_event_source_get_time</function></funcdef> <funcdef>int <function>sd_event_source_get_time</function></funcdef>
<paramdef>sd_event_source *<parameter>source</parameter></paramdef> <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
@ -63,6 +74,12 @@
<paramdef>uint64_t <parameter>usec</parameter></paramdef> <paramdef>uint64_t <parameter>usec</parameter></paramdef>
</funcprototype> </funcprototype>
<funcprototype>
<funcdef>int <function>sd_event_source_set_time_relative</function></funcdef>
<paramdef>sd_event_source *<parameter>source</parameter></paramdef>
<paramdef>uint64_t <parameter>usec</parameter></paramdef>
</funcprototype>
<funcprototype> <funcprototype>
<funcdef>int <function>sd_event_source_get_time_accuracy</function></funcdef> <funcdef>int <function>sd_event_source_get_time_accuracy</function></funcdef>
<paramdef>sd_event_source *<parameter>source</parameter></paramdef> <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
@ -123,6 +140,11 @@
<function>sd_event_source_set_time()</function>. <function>sd_event_source_set_time()</function>.
</para> </para>
<para><function>sd_event_add_time_relative()</function> is like <function>sd_event_add_time()</function>,
but takes a relative time specification. It's relative to the current time of the event loop iteration,
as returned by
<citerefentry><refentrytitle>sd_event_now</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
<para>To destroy an event source object use <para>To destroy an event source object use
<citerefentry><refentrytitle>sd_event_source_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>, <citerefentry><refentrytitle>sd_event_source_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
but note that the event source is only removed from the event loop but note that the event source is only removed from the event loop
@ -173,17 +195,21 @@
events will be regular, while in the latter case the scheduling events will be regular, while in the latter case the scheduling
latency will keep accumulating on the timer.</para> latency will keep accumulating on the timer.</para>
<para><function>sd_event_source_get_time()</function> retrieves <para><function>sd_event_source_get_time()</function> retrieves the configured time value of an event
the configured time value of an event source created source created previously with <function>sd_event_add_time()</function> or
previously with <function>sd_event_add_time()</function>. It takes <function>sd_event_add_time_relative()</function>. It takes the event source object and a pointer to a
the event source object and a pointer to a variable to store the variable to store the time in, relative to the selected clock's epoch, in µs. The returned value is
time in, relative to the selected clock's epoch, in µs.</para> relative to the epoch, even if the event source was created with a relative time via
<function>sd_event_add_time_relative()</function>.</para>
<para><function>sd_event_source_set_time()</function> changes the <para><function>sd_event_source_set_time()</function> changes the time of an event source created
time of an event source created previously with previously with <function>sd_event_add_time()</function> or
<function>sd_event_add_time()</function>. It takes the event <function>sd_event_add_time_relative()</function>. It takes the event source object and a time relative
source object and a time relative to the selected clock's epoch, to the selected clock's epoch, in µs.</para>
in µs.</para>
<para><function>sd_event_source_set_time_relative()</function> is similar to
<function>sd_event_source_set_time()</function>, but takes a time relative to the current time of the
event loop iteration, as returned by <function>sd_event_now()</function>.</para>
<para><function>sd_event_source_get_time_accuracy()</function> <para><function>sd_event_source_get_time_accuracy()</function>
retrieves the configured accuracy value of an event source retrieves the configured accuracy value of an event source
@ -255,6 +281,13 @@
<listitem><para>The passed event source is not a timer event source.</para></listitem> <listitem><para>The passed event source is not a timer event source.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><constant>-EOVERFLOW</constant></term>
<listitem><para>The passed relative time is outside of the allowed range for time values (i.e. the
specified value added to the current time is outside the 64 bit unsigned integer range).</para></listitem>
</varlistentry>
</variablelist> </variablelist>
</refsect2> </refsect2>
</refsect1> </refsect1>

View File

@ -1799,11 +1799,11 @@ public_programs += executable(
include_directories : includes, include_directories : includes,
link_with : [libshared], link_with : [libshared],
dependencies : [threads, dependencies : [threads,
libqrencode, libdl,
libxz, libxz,
liblz4, liblz4,
libpcre2, libzstd,
libzstd], libdl],
install_rpath : rootlibexecdir, install_rpath : rootlibexecdir,
install : true, install : true,
install_dir : rootbindir) install_dir : rootbindir)

40
src/basic/dlfcn-util.c Normal file
View File

@ -0,0 +1,40 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#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 */
va_start(ap, level);
for (;;) {
void (**fn)(void);
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;
}
*fn = tfn;
}
va_end(ap);
return 0;
}

View File

@ -6,3 +6,5 @@
#include "macro.h" #include "macro.h"
DEFINE_TRIVIAL_CLEANUP_FUNC(void*, dlclose); DEFINE_TRIVIAL_CLEANUP_FUNC(void*, dlclose);
int dlsym_many_and_warn(void *dl, int level, ...);

View File

@ -39,6 +39,7 @@ basic_sources = files('''
device-nodes.h device-nodes.h
dirent-util.c dirent-util.c
dirent-util.h dirent-util.h
dlfcn-util.c
dlfcn-util.h dlfcn-util.h
efivars.c efivars.c
efivars.h efivars.h

View File

@ -709,25 +709,25 @@ static int automount_dispatch_expire(sd_event_source *source, usec_t usec, void
} }
static int automount_start_expire(Automount *a) { static int automount_start_expire(Automount *a) {
int r;
usec_t timeout; usec_t timeout;
int r;
assert(a); assert(a);
if (a->timeout_idle_usec == 0) if (a->timeout_idle_usec == 0)
return 0; return 0;
timeout = now(CLOCK_MONOTONIC) + MAX(a->timeout_idle_usec/3, USEC_PER_SEC); timeout = MAX(a->timeout_idle_usec/3, USEC_PER_SEC);
if (a->expire_event_source) { if (a->expire_event_source) {
r = sd_event_source_set_time(a->expire_event_source, timeout); r = sd_event_source_set_time_relative(a->expire_event_source, timeout);
if (r < 0) if (r < 0)
return r; return r;
return sd_event_source_set_enabled(a->expire_event_source, SD_EVENT_ONESHOT); return sd_event_source_set_enabled(a->expire_event_source, SD_EVENT_ONESHOT);
} }
r = sd_event_add_time( r = sd_event_add_time_relative(
UNIT(a)->manager->event, UNIT(a)->manager->event,
&a->expire_event_source, &a->expire_event_source,
CLOCK_MONOTONIC, timeout, 0, CLOCK_MONOTONIC, timeout, 0,

View File

@ -2902,15 +2902,13 @@ static int manager_dispatch_idle_pipe_fd(sd_event_source *source, int fd, uint32
static int manager_dispatch_jobs_in_progress(sd_event_source *source, usec_t usec, void *userdata) { static int manager_dispatch_jobs_in_progress(sd_event_source *source, usec_t usec, void *userdata) {
Manager *m = userdata; Manager *m = userdata;
int r; int r;
uint64_t next;
assert(m); assert(m);
assert(source); assert(source);
manager_print_jobs_in_progress(m); manager_print_jobs_in_progress(m);
next = now(CLOCK_MONOTONIC) + JOBS_IN_PROGRESS_PERIOD_USEC; r = sd_event_source_set_time_relative(source, JOBS_IN_PROGRESS_PERIOD_USEC);
r = sd_event_source_set_time(source, next);
if (r < 0) if (r < 0)
return r; return r;

View File

@ -1480,9 +1480,9 @@ static int luks_format(
_cleanup_(crypt_freep) struct crypt_device *cd = NULL; _cleanup_(crypt_freep) struct crypt_device *cd = NULL;
_cleanup_(erase_and_freep) void *volume_key = NULL; _cleanup_(erase_and_freep) void *volume_key = NULL;
struct crypt_pbkdf_type good_pbkdf, minimal_pbkdf; struct crypt_pbkdf_type good_pbkdf, minimal_pbkdf;
char suuid[ID128_UUID_STRING_MAX], **pp;
_cleanup_free_ char *text = NULL; _cleanup_free_ char *text = NULL;
size_t volume_key_size; size_t volume_key_size;
char suuid[37], **pp;
int slot = 0, r; int slot = 0, r;
assert(node); assert(node);
@ -1614,7 +1614,7 @@ static int make_partition_table(
_cleanup_free_ char *path = NULL, *disk_uuid_as_string = NULL; _cleanup_free_ char *path = NULL, *disk_uuid_as_string = NULL;
uint64_t offset, size; uint64_t offset, size;
sd_id128_t disk_uuid; sd_id128_t disk_uuid;
char uuids[37]; char uuids[ID128_UUID_STRING_MAX];
int r; int r;
assert(fd >= 0); assert(fd >= 0);

View File

@ -275,7 +275,7 @@ int user_record_add_binding(
gid_t gid) { gid_t gid) {
_cleanup_(json_variant_unrefp) JsonVariant *new_binding_entry = NULL, *binding = NULL; _cleanup_(json_variant_unrefp) JsonVariant *new_binding_entry = NULL, *binding = NULL;
char smid[SD_ID128_STRING_MAX], partition_uuids[37], luks_uuids[37], fs_uuids[37]; char smid[SD_ID128_STRING_MAX], partition_uuids[ID128_UUID_STRING_MAX], luks_uuids[ID128_UUID_STRING_MAX], fs_uuids[ID128_UUID_STRING_MAX];
_cleanup_free_ char *ip = NULL, *hd = NULL, *ip_auto = NULL, *lc = NULL, *lcm = NULL, *fst = NULL; _cleanup_free_ char *ip = NULL, *hd = NULL, *ip_auto = NULL, *lc = NULL, *lcm = NULL, *fst = NULL;
sd_id128_t mid; sd_id128_t mid;
int r; int r;

View File

@ -139,16 +139,16 @@ static int curl_glue_timer_callback(CURLM *curl, long timeout_ms, void *userdata
return 0; return 0;
} }
usec = now(clock_boottime_or_monotonic()) + (usec_t) timeout_ms * USEC_PER_MSEC + USEC_PER_MSEC - 1; usec = (usec_t) timeout_ms * USEC_PER_MSEC + USEC_PER_MSEC - 1;
if (g->timer) { if (g->timer) {
if (sd_event_source_set_time(g->timer, usec) < 0) if (sd_event_source_set_time_relative(g->timer, usec) < 0)
return -1; return -1;
if (sd_event_source_set_enabled(g->timer, SD_EVENT_ONESHOT) < 0) if (sd_event_source_set_enabled(g->timer, SD_EVENT_ONESHOT) < 0)
return -1; return -1;
} else { } else {
if (sd_event_add_time(g->event, &g->timer, clock_boottime_or_monotonic(), usec, 0, curl_glue_on_timer, g) < 0) if (sd_event_add_time_relative(g->event, &g->timer, clock_boottime_or_monotonic(), usec, 0, curl_glue_on_timer, g) < 0)
return -1; return -1;
(void) sd_event_source_set_description(g->timer, "curl-timer"); (void) sd_event_source_set_description(g->timer, "curl-timer");

View File

@ -1978,7 +1978,6 @@ static int post_change_thunk(sd_event_source *timer, uint64_t usec, void *userda
} }
static void schedule_post_change(JournalFile *f) { static void schedule_post_change(JournalFile *f) {
uint64_t now;
int r; int r;
assert(f); assert(f);
@ -1992,13 +1991,7 @@ static void schedule_post_change(JournalFile *f) {
if (r > 0) if (r > 0)
return; return;
r = sd_event_now(sd_event_source_get_event(f->post_change_timer), CLOCK_MONOTONIC, &now); r = sd_event_source_set_time_relative(f->post_change_timer, f->post_change_timer_period);
if (r < 0) {
log_debug_errno(r, "Failed to get clock's now for scheduling ftruncate: %m");
goto fail;
}
r = sd_event_source_set_time(f->post_change_timer, now + f->post_change_timer_period);
if (r < 0) { if (r < 0) {
log_debug_errno(r, "Failed to set time for scheduling ftruncate: %m"); log_debug_errno(r, "Failed to set time for scheduling ftruncate: %m");
goto fail; goto fail;

View File

@ -6,29 +6,34 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "alloc-util.h"
#include "dlfcn-util.h"
#include "fd-util.h"
#include "fileio.h" #include "fileio.h"
#include "journal-qrcode.h" #include "journal-qrcode.h"
#include "locale-util.h"
#include "macro.h" #include "macro.h"
#include "terminal-util.h"
#define WHITE_ON_BLACK "\033[40;37;1m" #define ANSI_WHITE_ON_BLACK "\033[40;37;1m"
#define NORMAL "\033[0m"
static void print_border(FILE *output, unsigned width) { static void print_border(FILE *output, unsigned width) {
unsigned x, y; unsigned x, y;
/* Four rows of border */ /* Four rows of border */
for (y = 0; y < 4; y += 2) { for (y = 0; y < 4; y += 2) {
fputs(WHITE_ON_BLACK, output); fputs(ANSI_WHITE_ON_BLACK, output);
for (x = 0; x < 4 + width + 4; x++) for (x = 0; x < 4 + width + 4; x++)
fputs("\342\226\210", output); fputs("\342\226\210", output);
fputs(NORMAL "\n", output); fputs(ANSI_NORMAL "\n", output);
} }
} }
int print_qr_code( int print_qr_code(
FILE *output, FILE *output,
const char *prefix_text,
const void *seed, const void *seed,
size_t seed_size, size_t seed_size,
uint64_t start, uint64_t start,
@ -36,15 +41,38 @@ int print_qr_code(
const char *hn, const char *hn,
sd_id128_t machine) { sd_id128_t machine) {
FILE *f; QRcode* (*sym_QRcode_encodeString)(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive);
char *url = NULL; void (*sym_QRcode_free)(QRcode *qrcode);
_cleanup_(dlclosep) void *dl = NULL;
_cleanup_free_ char *url = NULL;
_cleanup_fclose_ FILE *f = NULL;
size_t url_size = 0, i; size_t url_size = 0, i;
QRcode* qr;
unsigned x, y; unsigned x, y;
QRcode* qr;
int r;
assert(seed); assert(seed);
assert(seed_size > 0); assert(seed_size > 0);
/* If this is not an UTF-8 system or ANSI colors aren't supported/disabled don't print any QR
* codes */
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,
&sym_QRcode_encodeString, "QRcode_encodeString",
&sym_QRcode_free, "QRcode_free",
NULL);
if (r < 0)
return r;
f = open_memstream_unlocked(&url, &url_size); f = open_memstream_unlocked(&url, &url_size);
if (!f) if (!f)
return -ENOMEM; return -ENOMEM;
@ -65,20 +93,19 @@ int print_qr_code(
if (hn) if (hn)
fprintf(f, ";hostname=%s", hn); fprintf(f, ";hostname=%s", hn);
if (ferror(f)) { r = fflush_and_check(f);
fclose(f); if (r < 0)
free(url); return r;
return -ENOMEM;
}
fclose(f); f = safe_fclose(f);
qr = QRcode_encodeString(url, 0, QR_ECLEVEL_L, QR_MODE_8, 1);
free(url);
qr = sym_QRcode_encodeString(url, 0, QR_ECLEVEL_L, QR_MODE_8, 1);
if (!qr) if (!qr)
return -ENOMEM; return -ENOMEM;
if (prefix_text)
fputs(prefix_text, output);
print_border(output, qr->width); print_border(output, qr->width);
for (y = 0; y < (unsigned) qr->width; y += 2) { for (y = 0; y < (unsigned) qr->width; y += 2) {
@ -87,7 +114,7 @@ int print_qr_code(
row1 = qr->data + qr->width * y; row1 = qr->data + qr->width * y;
row2 = row1 + qr->width; row2 = row1 + qr->width;
fputs(WHITE_ON_BLACK, output); fputs(ANSI_WHITE_ON_BLACK, output);
for (x = 0; x < 4; x++) for (x = 0; x < 4; x++)
fputs("\342\226\210", output); fputs("\342\226\210", output);
@ -109,11 +136,11 @@ int print_qr_code(
for (x = 0; x < 4; x++) for (x = 0; x < 4; x++)
fputs("\342\226\210", output); fputs("\342\226\210", output);
fputs(NORMAL "\n", output); fputs(ANSI_NORMAL "\n", output);
} }
print_border(output, qr->width); print_border(output, qr->width);
QRcode_free(qr); sym_QRcode_free(qr);
return 0; return 0;
} }

View File

@ -6,4 +6,4 @@
#include "sd-id128.h" #include "sd-id128.h"
int print_qr_code(FILE *f, const void *seed, size_t seed_size, uint64_t start, uint64_t interval, const char *hn, sd_id128_t machine); int print_qr_code(FILE *f, const char *prefix_text, const void *seed, size_t seed_size, uint64_t start, uint64_t interval, const char *hn, sd_id128_t machine);

View File

@ -56,13 +56,15 @@
#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 "random-util.h"
#include "rlimit-util.h" #include "rlimit-util.h"
#include "set.h" #include "set.h"
#include "sigbus.h" #include "sigbus.h"
#include "stdio-util.h"
#include "string-table.h" #include "string-table.h"
#include "strv.h" #include "strv.h"
#include "stdio-util.h"
#include "syslog-util.h" #include "syslog-util.h"
#include "terminal-util.h" #include "terminal-util.h"
#include "tmpfile-util.h" #include "tmpfile-util.h"
@ -160,20 +162,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 +185,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 +1088,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 +1107,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;
@ -1774,12 +1779,14 @@ static int add_syslog_identifier(sd_journal *j) {
static int setup_keys(void) { static int setup_keys(void) {
#if HAVE_GCRYPT #if HAVE_GCRYPT
size_t mpk_size, seed_size, state_size, i; size_t mpk_size, seed_size, state_size, i;
_cleanup_(unlink_and_freep) char *k = NULL;
_cleanup_free_ char *p = NULL;
uint8_t *mpk, *seed, *state; uint8_t *mpk, *seed, *state;
int fd = -1, r; _cleanup_close_ int fd = -1;
sd_id128_t machine, boot; sd_id128_t machine, boot;
char *p = NULL, *k = NULL;
uint64_t n;
struct stat st; struct stat st;
uint64_t n;
int r;
r = stat("/var/log/journal", &st); r = stat("/var/log/journal", &st);
if (r < 0 && !IN_SET(errno, ENOENT, ENOTDIR)) if (r < 0 && !IN_SET(errno, ENOENT, ENOTDIR))
@ -1805,21 +1812,15 @@ static int setup_keys(void) {
if (arg_force) { if (arg_force) {
r = unlink(p); r = unlink(p);
if (r < 0 && errno != ENOENT) { if (r < 0 && errno != ENOENT)
r = log_error_errno(errno, "unlink(\"%s\") failed: %m", p); return log_error_errno(errno, "unlink(\"%s\") failed: %m", p);
goto finish; } else if (access(p, F_OK) >= 0)
} return log_error_errno(SYNTHETIC_ERRNO(EEXIST),
} else if (access(p, F_OK) >= 0) { "Sealing key file %s exists already. Use --force to recreate.", p);
log_error("Sealing key file %s exists already. Use --force to recreate.", p);
r = -EEXIST;
goto finish;
}
if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX", if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX",
SD_ID128_FORMAT_VAL(machine)) < 0) { SD_ID128_FORMAT_VAL(machine)) < 0)
r = log_oom(); return log_oom();
goto finish;
}
mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR); mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR);
mpk = alloca(mpk_size); mpk = alloca(mpk_size);
@ -1830,18 +1831,10 @@ static int setup_keys(void) {
state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR); state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
state = alloca(state_size); state = alloca(state_size);
fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY);
if (fd < 0) {
r = log_error_errno(errno, "Failed to open /dev/random: %m");
goto finish;
}
log_info("Generating seed..."); log_info("Generating seed...");
r = loop_read_exact(fd, seed, seed_size, true); r = genuine_random_bytes(seed, seed_size, RANDOM_BLOCK);
if (r < 0) { if (r < 0)
log_error_errno(r, "Failed to read random seed: %m"); return log_error_errno(r, "Failed to acquire random seed: %m");
goto finish;
}
log_info("Generating key pair..."); log_info("Generating key pair...");
FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR); FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR);
@ -1856,18 +1849,25 @@ static int setup_keys(void) {
safe_close(fd); safe_close(fd);
fd = mkostemp_safe(k); fd = mkostemp_safe(k);
if (fd < 0) { if (fd < 0)
r = log_error_errno(fd, "Failed to open %s: %m", k); return log_error_errno(fd, "Failed to open %s: %m", k);
goto finish;
/* Enable secure remove, exclusion from dump, synchronous writing and in-place updating */
static const unsigned chattr_flags[] = {
FS_SECRM_FL,
FS_NODUMP_FL,
FS_SYNC_FL,
FS_NOCOW_FL,
};
for (size_t j = 0; j < ELEMENTSOF(chattr_flags); j++) {
r = chattr_fd(fd, chattr_flags[j], chattr_flags[j], NULL);
if (r < 0)
log_full_errno(ERRNO_IS_NOT_SUPPORTED(r) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to set file attribute 0x%x: %m", chattr_flags[j]);
} }
/* Enable secure remove, exclusion from dump, synchronous
* writing and in-place updating */
r = chattr_fd(fd, FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL, FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL, NULL);
if (r < 0)
log_warning_errno(r, "Failed to set file attributes: %m");
struct FSSHeader h = { struct FSSHeader h = {
.signature = { 'K', 'S', 'H', 'H', 'R', 'H', 'L', 'P' },
.machine_id = machine, .machine_id = machine,
.boot_id = boot, .boot_id = boot,
.header_size = htole64(sizeof(h)), .header_size = htole64(sizeof(h)),
@ -1877,24 +1877,18 @@ static int setup_keys(void) {
.fsprg_state_size = htole64(state_size), .fsprg_state_size = htole64(state_size),
}; };
memcpy(h.signature, "KSHHRHLP", 8);
r = loop_write(fd, &h, sizeof(h), false); r = loop_write(fd, &h, sizeof(h), false);
if (r < 0) { if (r < 0)
log_error_errno(r, "Failed to write header: %m"); return log_error_errno(r, "Failed to write header: %m");
goto finish;
}
r = loop_write(fd, state, state_size, false); r = loop_write(fd, state, state_size, false);
if (r < 0) { if (r < 0)
log_error_errno(r, "Failed to write state: %m"); return log_error_errno(r, "Failed to write state: %m");
goto finish;
}
if (link(k, p) < 0) { if (rename(k, p) < 0)
r = log_error_errno(errno, "Failed to link file: %m"); return log_error_errno(errno, "Failed to link file: %m");
goto finish;
} k = mfree(k);
if (on_tty()) { if (on_tty()) {
fprintf(stderr, fprintf(stderr,
@ -1923,7 +1917,8 @@ static int setup_keys(void) {
printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval); printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval);
if (on_tty()) { if (on_tty()) {
char tsb[FORMAT_TIMESPAN_MAX], *hn; _cleanup_free_ char *hn = NULL;
char tsb[FORMAT_TIMESPAN_MAX];
fprintf(stderr, fprintf(stderr,
"%s\n" "%s\n"
@ -1932,7 +1927,6 @@ static int setup_keys(void) {
format_timespan(tsb, sizeof(tsb), arg_interval, 0)); format_timespan(tsb, sizeof(tsb), arg_interval, 0));
hn = gethostname_malloc(); hn = gethostname_malloc();
if (hn) { if (hn) {
hostname_cleanup(hn); hostname_cleanup(hn);
fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine)); fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine));
@ -1940,28 +1934,15 @@ static int setup_keys(void) {
fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine)); fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine));
#if HAVE_QRENCODE #if HAVE_QRENCODE
/* If this is not an UTF-8 system don't print any QR codes */ (void) print_qr_code(stderr,
if (is_locale_utf8()) { "\nTo transfer the verification key to your phone please scan the QR code below:\n\n",
fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr); seed, seed_size,
print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine); n, arg_interval,
} hn, machine);
#endif #endif
free(hn);
} }
r = 0; return 0;
finish:
safe_close(fd);
if (k) {
(void) unlink(k);
free(k);
}
free(p);
return r;
#else #else
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"Forward-secure sealing not available."); "Forward-secure sealing not available.");
@ -2630,12 +2611,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 +2633,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 +2648,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 +2747,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

View File

@ -1677,27 +1677,20 @@ int server_schedule_sync(Server *s, int priority) {
return 0; return 0;
if (s->sync_interval_usec > 0) { if (s->sync_interval_usec > 0) {
usec_t when;
r = sd_event_now(s->event, CLOCK_MONOTONIC, &when);
if (r < 0)
return r;
when += s->sync_interval_usec;
if (!s->sync_event_source) { if (!s->sync_event_source) {
r = sd_event_add_time( r = sd_event_add_time_relative(
s->event, s->event,
&s->sync_event_source, &s->sync_event_source,
CLOCK_MONOTONIC, CLOCK_MONOTONIC,
when, 0, s->sync_interval_usec, 0,
server_dispatch_sync, s); server_dispatch_sync, s);
if (r < 0) if (r < 0)
return r; return r;
r = sd_event_source_set_priority(s->sync_event_source, SD_EVENT_PRIORITY_IMPORTANT); r = sd_event_source_set_priority(s->sync_event_source, SD_EVENT_PRIORITY_IMPORTANT);
} else { } else {
r = sd_event_source_set_time(s->sync_event_source, when); r = sd_event_source_set_time_relative(s->sync_event_source, s->sync_interval_usec);
if (r < 0) if (r < 0)
return r; return r;
@ -1888,7 +1881,7 @@ static int server_connect_notify(Server *s) {
if (sd_watchdog_enabled(false, &s->watchdog_usec) > 0) { if (sd_watchdog_enabled(false, &s->watchdog_usec) > 0) {
s->send_watchdog = true; s->send_watchdog = true;
r = sd_event_add_time(s->event, &s->watchdog_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + s->watchdog_usec/2, s->watchdog_usec/4, dispatch_watchdog, s); r = sd_event_add_time_relative(s->event, &s->watchdog_event_source, CLOCK_MONOTONIC, s->watchdog_usec/2, s->watchdog_usec/4, dispatch_watchdog, s);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to add watchdog time event: %m"); return log_error_errno(r, "Failed to add watchdog time event: %m");
} }
@ -2116,7 +2109,6 @@ static int server_idle_handler(sd_event_source *source, uint64_t usec, void *use
int server_start_or_stop_idle_timer(Server *s) { int server_start_or_stop_idle_timer(Server *s) {
_cleanup_(sd_event_source_unrefp) sd_event_source *source = NULL; _cleanup_(sd_event_source_unrefp) sd_event_source *source = NULL;
usec_t when;
int r; int r;
assert(s); assert(s);
@ -2129,11 +2121,7 @@ int server_start_or_stop_idle_timer(Server *s) {
if (s->idle_event_source) if (s->idle_event_source)
return 1; return 1;
r = sd_event_now(s->event, CLOCK_MONOTONIC, &when); r = sd_event_add_time_relative(s->event, &source, CLOCK_MONOTONIC, IDLE_TIMEOUT_USEC, 0, server_idle_handler, s);
if (r < 0)
return log_error_errno(r, "Failed to determine current time: %m");
r = sd_event_add_time(s->event, &source, CLOCK_MONOTONIC, usec_add(when, IDLE_TIMEOUT_USEC), 0, server_idle_handler, s);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to allocate idle timer: %m"); return log_error_errno(r, "Failed to allocate idle timer: %m");
@ -2148,7 +2136,6 @@ int server_start_or_stop_idle_timer(Server *s) {
} }
int server_refresh_idle_timer(Server *s) { int server_refresh_idle_timer(Server *s) {
usec_t when;
int r; int r;
assert(s); assert(s);
@ -2156,11 +2143,7 @@ int server_refresh_idle_timer(Server *s) {
if (!s->idle_event_source) if (!s->idle_event_source)
return 0; return 0;
r = sd_event_now(s->event, CLOCK_MONOTONIC, &when); r = sd_event_source_set_time_relative(s->idle_event_source, IDLE_TIMEOUT_USEC);
if (r < 0)
return log_error_errno(r, "Failed to determine current time: %m");
r = sd_event_source_set_time(s->idle_event_source, usec_add(when, IDLE_TIMEOUT_USEC));
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to refresh idle timer: %m"); return log_error_errno(r, "Failed to refresh idle timer: %m");

View File

@ -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',

View 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

View 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);

View File

@ -514,7 +514,6 @@ static int test_addr_acq_recv_discover(size_t size, DHCPMessage *discover) {
} }
static void test_addr_acq(sd_event *e) { static void test_addr_acq(sd_event *e) {
usec_t time_now = now(clock_boottime_or_monotonic());
sd_dhcp_client *client; sd_dhcp_client *client;
int res, r; int res, r;
@ -535,9 +534,10 @@ static void test_addr_acq(sd_event *e) {
callback_recv = test_addr_acq_recv_discover; callback_recv = test_addr_acq_recv_discover;
assert_se(sd_event_add_time(e, &test_hangcheck, assert_se(sd_event_add_time_relative(
e, &test_hangcheck,
clock_boottime_or_monotonic(), clock_boottime_or_monotonic(),
time_now + 2 * USEC_PER_SEC, 0, 2 * USEC_PER_SEC, 0,
test_dhcp_hangcheck, NULL) >= 0); test_dhcp_hangcheck, NULL) >= 0);
res = sd_dhcp_client_start(client); res = sd_dhcp_client_start(client);

View File

@ -942,7 +942,6 @@ int dhcp6_network_bind_udp_socket(int ifindex, struct in6_addr *local_address) {
static int test_client_solicit(sd_event *e) { static int test_client_solicit(sd_event *e) {
sd_dhcp6_client *client; sd_dhcp6_client *client;
usec_t time_now = now(clock_boottime_or_monotonic());
struct in6_addr address = { { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01 } } }; struct in6_addr address = { { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01 } } };
int val; int val;
@ -968,8 +967,8 @@ static int test_client_solicit(sd_event *e) {
assert_se(sd_dhcp6_client_set_callback(client, assert_se(sd_dhcp6_client_set_callback(client,
test_client_information_cb, e) >= 0); test_client_information_cb, e) >= 0);
assert_se(sd_event_add_time(e, &hangcheck, clock_boottime_or_monotonic(), assert_se(sd_event_add_time_relative(e, &hangcheck, clock_boottime_or_monotonic(),
time_now + 2 * USEC_PER_SEC, 0, 2 * USEC_PER_SEC, 0,
test_hangcheck, NULL) >= 0); test_hangcheck, NULL) >= 0);
assert_se(sd_dhcp6_client_set_local_address(client, &address) >= 0); assert_se(sd_dhcp6_client_set_local_address(client, &address) >= 0);

View File

@ -293,7 +293,6 @@ static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdat
static void test_ra(void) { static void test_ra(void) {
sd_event *e; sd_event *e;
sd_radv *ra; sd_radv *ra;
usec_t time_now = now(clock_boottime_or_monotonic());
unsigned i; unsigned i;
printf("* %s\n", __FUNCTION__); printf("* %s\n", __FUNCTION__);
@ -339,8 +338,9 @@ static void test_ra(void) {
assert_se(sd_event_add_io(e, &recv_router_advertisement, test_fd[0], assert_se(sd_event_add_io(e, &recv_router_advertisement, test_fd[0],
EPOLLIN, radv_recv, ra) >= 0); EPOLLIN, radv_recv, ra) >= 0);
assert_se(sd_event_add_time(e, &test_hangcheck, clock_boottime_or_monotonic(), assert_se(sd_event_add_time_relative(
time_now + 2 *USEC_PER_SEC, 0, e, &test_hangcheck, clock_boottime_or_monotonic(),
2 *USEC_PER_SEC, 0,
test_rs_hangcheck, NULL) >= 0); test_rs_hangcheck, NULL) >= 0);
assert_se(sd_radv_start(ra) >= 0); assert_se(sd_radv_start(ra) >= 0);

View File

@ -272,7 +272,6 @@ static void test_callback(sd_ndisc *nd, sd_ndisc_event event, sd_ndisc_router *r
static void test_rs(void) { static void test_rs(void) {
sd_event *e; sd_event *e;
sd_ndisc *nd; sd_ndisc *nd;
usec_t time_now = now(clock_boottime_or_monotonic());
if (verbose) if (verbose)
printf("* %s\n", __FUNCTION__); printf("* %s\n", __FUNCTION__);
@ -290,8 +289,9 @@ static void test_rs(void) {
assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0); assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0);
assert_se(sd_ndisc_set_callback(nd, test_callback, e) >= 0); assert_se(sd_ndisc_set_callback(nd, test_callback, e) >= 0);
assert_se(sd_event_add_time(e, &test_hangcheck, clock_boottime_or_monotonic(), assert_se(sd_event_add_time_relative(
time_now + 30 * USEC_PER_SEC, 0, e, &test_hangcheck, clock_boottime_or_monotonic(),
30 * USEC_PER_SEC, 0,
test_rs_hangcheck, NULL) >= 0); test_rs_hangcheck, NULL) >= 0);
assert_se(sd_ndisc_stop(nd) >= 0); assert_se(sd_ndisc_stop(nd) >= 0);
@ -373,7 +373,6 @@ static int test_timeout_value(uint8_t flags) {
static void test_timeout(void) { static void test_timeout(void) {
sd_event *e; sd_event *e;
sd_ndisc *nd; sd_ndisc *nd;
usec_t time_now = now(clock_boottime_or_monotonic());
if (verbose) if (verbose)
printf("* %s\n", __FUNCTION__); printf("* %s\n", __FUNCTION__);
@ -392,8 +391,9 @@ static void test_timeout(void) {
assert_se(sd_ndisc_set_ifindex(nd, 42) >= 0); assert_se(sd_ndisc_set_ifindex(nd, 42) >= 0);
assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0); assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0);
assert_se(sd_event_add_time(e, &test_hangcheck, clock_boottime_or_monotonic(), assert_se(sd_event_add_time_relative(
time_now + 30 * USEC_PER_SEC, 0, e, &test_hangcheck, clock_boottime_or_monotonic(),
30 * USEC_PER_SEC, 0,
test_rs_hangcheck, NULL) >= 0); test_rs_hangcheck, NULL) >= 0);
assert_se(sd_ndisc_start(nd) >= 0); assert_se(sd_ndisc_start(nd) >= 0);

View File

@ -721,3 +721,9 @@ global:
sd_journal_enumerate_available_data; sd_journal_enumerate_available_data;
sd_journal_enumerate_available_unique; sd_journal_enumerate_available_unique;
} LIBSYSTEMD_245; } LIBSYSTEMD_245;
LIBSYSTEMD_247 {
global:
sd_event_add_time_relative;
sd_event_source_set_time_relative;
} LIBSYSTEMD_246;

View File

@ -1146,6 +1146,31 @@ _public_ int sd_event_add_time(
return 0; return 0;
} }
_public_ int sd_event_add_time_relative(
sd_event *e,
sd_event_source **ret,
clockid_t clock,
uint64_t usec,
uint64_t accuracy,
sd_event_time_handler_t callback,
void *userdata) {
usec_t t;
int r;
/* Same as sd_event_add_time() but operates relative to the event loop's current point in time, and
* checks for overflow. */
r = sd_event_now(e, clock, &t);
if (r < 0)
return r;
if (usec >= USEC_INFINITY - t)
return -EOVERFLOW;
return sd_event_add_time(e, ret, clock, t + usec, accuracy, callback, userdata);
}
static int signal_exit_callback(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { static int signal_exit_callback(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
assert(s); assert(s);
@ -2402,6 +2427,23 @@ _public_ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) {
return 0; return 0;
} }
_public_ int sd_event_source_set_time_relative(sd_event_source *s, uint64_t usec) {
usec_t t;
int r;
assert_return(s, -EINVAL);
assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM);
r = sd_event_now(s->event, event_source_type_to_clock(s->type), &t);
if (r < 0)
return r;
if (usec >= USEC_INFINITY - t)
return -EOVERFLOW;
return sd_event_source_set_time(s, t + usec);
}
_public_ int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *usec) { _public_ int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *usec) {
assert_return(s, -EINVAL); assert_return(s, -EINVAL);
assert_return(usec, -EINVAL); assert_return(usec, -EINVAL);

View File

@ -1720,26 +1720,26 @@ static int delay_shutdown_or_sleep(
const char *unit_name) { const char *unit_name) {
int r; int r;
usec_t timeout_val;
assert(m); assert(m);
assert(w >= 0); assert(w >= 0);
assert(w < _INHIBIT_WHAT_MAX); assert(w < _INHIBIT_WHAT_MAX);
assert(unit_name); assert(unit_name);
timeout_val = now(CLOCK_MONOTONIC) + m->inhibit_delay_max;
if (m->inhibit_timeout_source) { if (m->inhibit_timeout_source) {
r = sd_event_source_set_time(m->inhibit_timeout_source, timeout_val); r = sd_event_source_set_time_relative(m->inhibit_timeout_source, m->inhibit_delay_max);
if (r < 0) if (r < 0)
return log_error_errno(r, "sd_event_source_set_time() failed: %m"); return log_error_errno(r, "sd_event_source_set_time_relative() failed: %m");
r = sd_event_source_set_enabled(m->inhibit_timeout_source, SD_EVENT_ONESHOT); r = sd_event_source_set_enabled(m->inhibit_timeout_source, SD_EVENT_ONESHOT);
if (r < 0) if (r < 0)
return log_error_errno(r, "sd_event_source_set_enabled() failed: %m"); return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
} else { } else {
r = sd_event_add_time(m->event, &m->inhibit_timeout_source, CLOCK_MONOTONIC, r = sd_event_add_time_relative(
timeout_val, 0, manager_inhibit_timeout_handler, m); m->event,
&m->inhibit_timeout_source,
CLOCK_MONOTONIC, m->inhibit_delay_max, 0,
manager_inhibit_timeout_handler, m);
if (r < 0) if (r < 0)
return r; return r;
} }

View File

@ -896,10 +896,11 @@ int session_release(Session *s) {
if (s->timer_event_source) if (s->timer_event_source)
return 0; return 0;
return sd_event_add_time(s->manager->event, return sd_event_add_time_relative(
s->manager->event,
&s->timer_event_source, &s->timer_event_source,
CLOCK_MONOTONIC, CLOCK_MONOTONIC,
usec_add(now(CLOCK_MONOTONIC), RELEASE_USEC), 0, RELEASE_USEC, 0,
release_timeout_callback, s); release_timeout_callback, s);
} }

View File

@ -332,7 +332,7 @@ static int link_send_lldp(Link *link) {
static int on_lldp_timer(sd_event_source *s, usec_t t, void *userdata) { static int on_lldp_timer(sd_event_source *s, usec_t t, void *userdata) {
Link *link = userdata; Link *link = userdata;
usec_t current, delay, next; usec_t delay;
int r; int r;
assert(s); assert(s);
@ -347,12 +347,10 @@ static int on_lldp_timer(sd_event_source *s, usec_t t, void *userdata) {
if (link->lldp_tx_fast > 0) if (link->lldp_tx_fast > 0)
link->lldp_tx_fast--; link->lldp_tx_fast--;
assert_se(sd_event_now(sd_event_source_get_event(s), clock_boottime_or_monotonic(), &current) >= 0);
delay = link->lldp_tx_fast > 0 ? LLDP_FAST_TX_USEC : LLDP_TX_INTERVAL_USEC; delay = link->lldp_tx_fast > 0 ? LLDP_FAST_TX_USEC : LLDP_TX_INTERVAL_USEC;
next = usec_add(usec_add(current, delay), (usec_t) random_u64() % LLDP_JITTER_USEC); delay = usec_add(delay, (usec_t) random_u64() % LLDP_JITTER_USEC);
r = sd_event_source_set_time(s, next); r = sd_event_source_set_time_relative(s, delay);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Failed to restart LLDP timer: %m"); return log_link_error_errno(link, r, "Failed to restart LLDP timer: %m");

View File

@ -687,11 +687,11 @@ int dns_query_go(DnsQuery *q) {
dns_query_reset_answer(q); dns_query_reset_answer(q);
r = sd_event_add_time( r = sd_event_add_time_relative(
q->manager->event, q->manager->event,
&q->timeout_event_source, &q->timeout_event_source,
clock_boottime_or_monotonic(), clock_boottime_or_monotonic(),
now(clock_boottime_or_monotonic()) + SD_RESOLVED_QUERY_TIMEOUT_USEC, SD_RESOLVED_QUERY_TIMEOUT_USEC,
0, on_query_timeout, q); 0, on_query_timeout, q);
if (r < 0) if (r < 0)
goto fail; goto fail;

View File

@ -1059,10 +1059,11 @@ int dns_scope_notify_conflict(DnsScope *scope, DnsResourceRecord *rr) {
random_bytes(&jitter, sizeof(jitter)); random_bytes(&jitter, sizeof(jitter));
jitter %= LLMNR_JITTER_INTERVAL_USEC; jitter %= LLMNR_JITTER_INTERVAL_USEC;
r = sd_event_add_time(scope->manager->event, r = sd_event_add_time_relative(
scope->manager->event,
&scope->conflict_event_source, &scope->conflict_event_source,
clock_boottime_or_monotonic(), clock_boottime_or_monotonic(),
now(clock_boottime_or_monotonic()) + jitter, jitter,
LLMNR_JITTER_INTERVAL_USEC, LLMNR_JITTER_INTERVAL_USEC,
on_conflict_dispatch, scope); on_conflict_dispatch, scope);
if (r < 0) if (r < 0)
@ -1318,18 +1319,13 @@ int dns_scope_announce(DnsScope *scope, bool goodbye) {
/* In section 8.3 of RFC6762: "The Multicast DNS responder MUST send at least two unsolicited /* In section 8.3 of RFC6762: "The Multicast DNS responder MUST send at least two unsolicited
* responses, one second apart." */ * responses, one second apart." */
if (!scope->announced) { if (!scope->announced) {
usec_t ts;
scope->announced = true; scope->announced = true;
assert_se(sd_event_now(scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0); r = sd_event_add_time_relative(
ts += MDNS_ANNOUNCE_DELAY;
r = sd_event_add_time(
scope->manager->event, scope->manager->event,
&scope->announce_event_source, &scope->announce_event_source,
clock_boottime_or_monotonic(), clock_boottime_or_monotonic(),
ts, MDNS_ANNOUNCE_DELAY,
MDNS_JITTER_RANGE_USEC, MDNS_JITTER_RANGE_USEC,
on_announcement_timeout, scope); on_announcement_timeout, scope);
if (r < 0) if (r < 0)

View File

@ -445,7 +445,7 @@ static int on_stream_io(sd_event_source *es, int fd, uint32_t revents, void *use
/* If we did something, let's restart the timeout event source */ /* If we did something, let's restart the timeout event source */
if (progressed && s->timeout_event_source) { if (progressed && s->timeout_event_source) {
r = sd_event_source_set_time(s->timeout_event_source, now(clock_boottime_or_monotonic()) + DNS_STREAM_TIMEOUT_USEC); r = sd_event_source_set_time_relative(s->timeout_event_source, DNS_STREAM_TIMEOUT_USEC);
if (r < 0) if (r < 0)
log_warning_errno(errno, "Couldn't restart TCP connection timeout, ignoring: %m"); log_warning_errno(errno, "Couldn't restart TCP connection timeout, ignoring: %m");
} }
@ -528,11 +528,11 @@ int dns_stream_new(
(void) sd_event_source_set_description(s->io_event_source, "dns-stream-io"); (void) sd_event_source_set_description(s->io_event_source, "dns-stream-io");
r = sd_event_add_time( r = sd_event_add_time_relative(
m->event, m->event,
&s->timeout_event_source, &s->timeout_event_source,
clock_boottime_or_monotonic(), clock_boottime_or_monotonic(),
now(clock_boottime_or_monotonic()) + DNS_STREAM_TIMEOUT_USEC, 0, DNS_STREAM_TIMEOUT_USEC, 0,
on_stream_timeout, s); on_stream_timeout, s);
if (r < 0) if (r < 0)
return r; return r;

View File

@ -182,8 +182,9 @@ int device_wait_for_initialization(sd_device *device, const char *subsystem, use
return log_error_errno(r, "Failed to start device monitor: %m"); return log_error_errno(r, "Failed to start device monitor: %m");
if (timeout != USEC_INFINITY) { if (timeout != USEC_INFINITY) {
r = sd_event_add_time(event, &timeout_source, r = sd_event_add_time_relative(
CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + timeout, 0, event, &timeout_source,
CLOCK_MONOTONIC, timeout, 0,
device_timeout_handler, NULL); device_timeout_handler, NULL);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to add timeout event source: %m"); return log_error_errno(r, "Failed to add timeout event source: %m");

View File

@ -95,16 +95,14 @@ static int idle_time_cb(sd_event_source *s, uint64_t usec, void *userdata) {
} }
static int connection_release(Connection *c) { static int connection_release(Connection *c) {
int r;
Context *context = c->context; Context *context = c->context;
usec_t idle_instant; int r;
connection_free(c); connection_free(c);
if (arg_exit_idle_time < USEC_INFINITY && set_isempty(context->connections)) { if (arg_exit_idle_time < USEC_INFINITY && set_isempty(context->connections)) {
idle_instant = usec_add(now(CLOCK_MONOTONIC), arg_exit_idle_time);
if (context->idle_time) { if (context->idle_time) {
r = sd_event_source_set_time(context->idle_time, idle_instant); r = sd_event_source_set_time_relative(context->idle_time, arg_exit_idle_time);
if (r < 0) if (r < 0)
return log_error_errno(r, "Error while setting idle time: %m"); return log_error_errno(r, "Error while setting idle time: %m");
@ -112,8 +110,9 @@ static int connection_release(Connection *c) {
if (r < 0) if (r < 0)
return log_error_errno(r, "Error while enabling idle time: %m"); return log_error_errno(r, "Error while enabling idle time: %m");
} else { } else {
r = sd_event_add_time(context->event, &context->idle_time, CLOCK_MONOTONIC, r = sd_event_add_time_relative(
idle_instant, 0, idle_time_cb, context); context->event, &context->idle_time, CLOCK_MONOTONIC,
arg_exit_idle_time, 0, idle_time_cb, context);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to create idle timer: %m"); return log_error_errno(r, "Failed to create idle timer: %m");
} }

View File

@ -88,6 +88,7 @@ sd_event* sd_event_unref(sd_event *e);
int sd_event_add_io(sd_event *e, sd_event_source **s, int fd, uint32_t events, sd_event_io_handler_t callback, void *userdata); int sd_event_add_io(sd_event *e, sd_event_source **s, int fd, uint32_t events, sd_event_io_handler_t callback, void *userdata);
int sd_event_add_time(sd_event *e, sd_event_source **s, clockid_t clock, uint64_t usec, uint64_t accuracy, sd_event_time_handler_t callback, void *userdata); int sd_event_add_time(sd_event *e, sd_event_source **s, clockid_t clock, uint64_t usec, uint64_t accuracy, sd_event_time_handler_t callback, void *userdata);
int sd_event_add_time_relative(sd_event *e, sd_event_source **s, clockid_t clock, uint64_t usec, uint64_t accuracy, sd_event_time_handler_t callback, void *userdata);
int sd_event_add_signal(sd_event *e, sd_event_source **s, int sig, sd_event_signal_handler_t callback, void *userdata); int sd_event_add_signal(sd_event *e, sd_event_source **s, int sig, sd_event_signal_handler_t callback, void *userdata);
int sd_event_add_child(sd_event *e, sd_event_source **s, pid_t pid, int options, sd_event_child_handler_t callback, void *userdata); int sd_event_add_child(sd_event *e, sd_event_source **s, pid_t pid, int options, sd_event_child_handler_t callback, void *userdata);
int sd_event_add_child_pidfd(sd_event *e, sd_event_source **s, int pidfd, int options, sd_event_child_handler_t callback, void *userdata); int sd_event_add_child_pidfd(sd_event *e, sd_event_source **s, int pidfd, int options, sd_event_child_handler_t callback, void *userdata);
@ -138,6 +139,7 @@ int sd_event_source_set_io_events(sd_event_source *s, uint32_t events);
int sd_event_source_get_io_revents(sd_event_source *s, uint32_t* revents); int sd_event_source_get_io_revents(sd_event_source *s, uint32_t* revents);
int sd_event_source_get_time(sd_event_source *s, uint64_t *usec); int sd_event_source_get_time(sd_event_source *s, uint64_t *usec);
int sd_event_source_set_time(sd_event_source *s, uint64_t usec); int sd_event_source_set_time(sd_event_source *s, uint64_t usec);
int sd_event_source_set_time_relative(sd_event_source *s, uint64_t usec);
int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *usec); int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *usec);
int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec); int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec);
int sd_event_source_get_time_clock(sd_event_source *s, clockid_t *clock); int sd_event_source_get_time_clock(sd_event_source *s, clockid_t *clock);

View File

@ -180,18 +180,18 @@ static int manager_arm_timer(Manager *m, usec_t next) {
} }
if (m->event_timer) { if (m->event_timer) {
r = sd_event_source_set_time(m->event_timer, now(clock_boottime_or_monotonic()) + next); r = sd_event_source_set_time_relative(m->event_timer, next);
if (r < 0) if (r < 0)
return r; return r;
return sd_event_source_set_enabled(m->event_timer, SD_EVENT_ONESHOT); return sd_event_source_set_enabled(m->event_timer, SD_EVENT_ONESHOT);
} }
return sd_event_add_time( return sd_event_add_time_relative(
m->event, m->event,
&m->event_timer, &m->event_timer,
clock_boottime_or_monotonic(), clock_boottime_or_monotonic(),
now(clock_boottime_or_monotonic()) + next, 0, next, 0,
manager_timer, m); manager_timer, m);
} }
@ -786,7 +786,7 @@ int manager_connect(Manager *m) {
if (!ratelimit_below(&m->ratelimit)) { if (!ratelimit_below(&m->ratelimit)) {
log_debug("Delaying attempts to contact servers."); log_debug("Delaying attempts to contact servers.");
r = sd_event_add_time(m->event, &m->event_retry, clock_boottime_or_monotonic(), now(clock_boottime_or_monotonic()) + RETRY_USEC, 0, manager_retry_connect, m); r = sd_event_add_time_relative(m->event, &m->event_retry, clock_boottime_or_monotonic(), RETRY_USEC, 0, manager_retry_connect, m);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to create retry timer: %m"); return log_error_errno(r, "Failed to create retry timer: %m");
@ -840,7 +840,7 @@ int manager_connect(Manager *m) {
if (restart && !m->exhausted_servers && m->poll_interval_usec) { if (restart && !m->exhausted_servers && m->poll_interval_usec) {
log_debug("Waiting after exhausting servers."); log_debug("Waiting after exhausting servers.");
r = sd_event_add_time(m->event, &m->event_retry, clock_boottime_or_monotonic(), now(clock_boottime_or_monotonic()) + m->poll_interval_usec, 0, manager_retry_connect, m); r = sd_event_add_time_relative(m->event, &m->event_retry, clock_boottime_or_monotonic(), m->poll_interval_usec, 0, manager_retry_connect, m);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to create retry timer: %m"); return log_error_errno(r, "Failed to create retry timer: %m");

View File

@ -392,8 +392,9 @@ int udev_ctrl_wait(struct udev_ctrl *uctrl, usec_t timeout) {
(void) sd_event_source_set_description(source_io, "udev-ctrl-wait-io"); (void) sd_event_source_set_description(source_io, "udev-ctrl-wait-io");
if (timeout != USEC_INFINITY) { if (timeout != USEC_INFINITY) {
r = sd_event_add_time(uctrl->event, &source_timeout, clock_boottime_or_monotonic(), r = sd_event_add_time_relative(
usec_add(now(clock_boottime_or_monotonic()), timeout), uctrl->event, &source_timeout, clock_boottime_or_monotonic(),
timeout,
0, NULL, INT_TO_PTR(-ETIMEDOUT)); 0, NULL, INT_TO_PTR(-ETIMEDOUT));
if (r < 0) if (r < 0)
return r; return r;

View File

@ -251,7 +251,6 @@ static int on_event_timeout_warning(sd_event_source *s, uint64_t usec, void *use
static void worker_attach_event(struct worker *worker, struct event *event) { static void worker_attach_event(struct worker *worker, struct event *event) {
sd_event *e; sd_event *e;
uint64_t usec;
assert(worker); assert(worker);
assert(worker->manager); assert(worker->manager);
@ -266,13 +265,13 @@ static void worker_attach_event(struct worker *worker, struct event *event) {
e = worker->manager->event; e = worker->manager->event;
assert_se(sd_event_now(e, CLOCK_MONOTONIC, &usec) >= 0); (void) sd_event_add_time_relative(e, &event->timeout_warning_event, CLOCK_MONOTONIC,
udev_warn_timeout(arg_event_timeout_usec), USEC_PER_SEC,
on_event_timeout_warning, event);
(void) sd_event_add_time(e, &event->timeout_warning_event, CLOCK_MONOTONIC, (void) sd_event_add_time_relative(e, &event->timeout_event, CLOCK_MONOTONIC,
usec + udev_warn_timeout(arg_event_timeout_usec), USEC_PER_SEC, on_event_timeout_warning, event); arg_event_timeout_usec, USEC_PER_SEC,
on_event_timeout, event);
(void) sd_event_add_time(e, &event->timeout_event, CLOCK_MONOTONIC,
usec + arg_event_timeout_usec, USEC_PER_SEC, on_event_timeout, event);
} }
static void manager_clear_for_worker(Manager *manager) { static void manager_clear_for_worker(Manager *manager) {

View File

@ -22,8 +22,9 @@ preprocess() {
# see meson.build how to extract this. gcc -E was used before to # see meson.build how to extract this. gcc -E was used before to
# get this value from config.h, however the autopkgtest fails with # get this value from config.h, however the autopkgtest fails with
# it # it
SYSTEM_UID_MAX=$(awk 'BEGIN { uid=999 } /^\s*SYS_UID_MAX\s+/ { uid=$2 } END { print uid }' /etc/login.defs) [[ -e /etc/login.defs ]] && login_defs_file="/etc/login.defs" || login_defs_file="/usr/etc/login.defs"
SYSTEM_GID_MAX=$(awk 'BEGIN { gid=999 } /^\s*SYS_GID_MAX\s+/ { gid=$2 } END { print gid }' /etc/login.defs) SYSTEM_UID_MAX=$(awk 'BEGIN { uid=999 } /^\s*SYS_UID_MAX\s+/ { uid=$2 } END { print uid }' $login_defs_file)
SYSTEM_GID_MAX=$(awk 'BEGIN { gid=999 } /^\s*SYS_GID_MAX\s+/ { gid=$2 } END { print gid }' $login_defs_file)
# we can't rely on config.h to get the nologin path, as autopkgtest # we can't rely on config.h to get the nologin path, as autopkgtest
# uses pre-compiled binaries, so extract it from the systemd-sysusers # uses pre-compiled binaries, so extract it from the systemd-sysusers

View File

@ -9,6 +9,16 @@ mkdir -p "$root"
mkdir "$root/bin" mkdir "$root/bin"
cp $(type -P busybox) "$root/bin" cp $(type -P busybox) "$root/bin"
ID_LIKE=$(awk -F= '$1=="ID_LIKE" { print $2 ;}' /etc/os-release)
if [[ "$ID_LIKE" = *"suse"* ]]; then
mkdir -p "$root/lib"
mkdir -p "$root/lib64"
for lib in $(find /lib*/ld*); do
[[ -d $root/$(dirname $lib) ]] || mkdir -p $root/$(dirname $lib)
cp $lib $root/$lib
done
fi
mkdir -p "$root/usr/lib" mkdir -p "$root/usr/lib"
touch "$root/usr/lib/os-release" touch "$root/usr/lib/os-release"

View File

@ -31,13 +31,19 @@ if unshare -U sh -c :; then
is_user_ns_supported=yes is_user_ns_supported=yes
fi fi
SUSE_OPTS=""
ID_LIKE=$(awk -F= '$1=="ID_LIKE" { print $2 ;}' /etc/os-release)
if [[ "$ID_LIKE" = *"suse"* ]]; then
SUSE_OPTS="--bind /lib64 --bind /usr/lib64 "
fi
function check_bind_tmp_path { function check_bind_tmp_path {
# https://github.com/systemd/systemd/issues/4789 # https://github.com/systemd/systemd/issues/4789
local _root="/var/lib/machines/testsuite-13.bind-tmp-path" local _root="/var/lib/machines/testsuite-13.bind-tmp-path"
rm -rf "$_root" rm -rf "$_root"
/usr/lib/systemd/tests/testdata/create-busybox-container "$_root" /usr/lib/systemd/tests/testdata/create-busybox-container "$_root"
>/tmp/bind >/tmp/bind
systemd-nspawn --register=no -D "$_root" --bind=/tmp/bind /bin/sh -c 'test -e /tmp/bind' systemd-nspawn $SUSE_OPTS--register=no -D "$_root" --bind=/tmp/bind /bin/sh -c 'test -e /tmp/bind'
} }
function check_norbind { function check_norbind {
@ -49,15 +55,15 @@ function check_norbind {
mount -t tmpfs tmpfs /tmp/binddir/subdir mount -t tmpfs tmpfs /tmp/binddir/subdir
echo -n "inner" > /tmp/binddir/subdir/file echo -n "inner" > /tmp/binddir/subdir/file
/usr/lib/systemd/tests/testdata/create-busybox-container "$_root" /usr/lib/systemd/tests/testdata/create-busybox-container "$_root"
systemd-nspawn --register=no -D "$_root" --bind=/tmp/binddir:/mnt:norbind /bin/sh -c 'CONTENT=$(cat /mnt/subdir/file); if [[ $CONTENT != "outer" ]]; then echo "*** unexpected content: $CONTENT"; return 1; fi' systemd-nspawn $SUSE_OPTS--register=no -D "$_root" --bind=/tmp/binddir:/mnt:norbind /bin/sh -c 'CONTENT=$(cat /mnt/subdir/file); if [[ $CONTENT != "outer" ]]; then echo "*** unexpected content: $CONTENT"; return 1; fi'
} }
function check_notification_socket { function check_notification_socket {
# https://github.com/systemd/systemd/issues/4944 # https://github.com/systemd/systemd/issues/4944
local _cmd='echo a | $(busybox which nc) -U -u -w 1 /run/systemd/nspawn/notify' local _cmd='echo a | $(busybox which nc) -U -u -w 1 /run/systemd/nspawn/notify'
# /testsuite-13.nc-container is prepared by test.sh # /testsuite-13.nc-container is prepared by test.sh
systemd-nspawn --register=no -D /testsuite-13.nc-container /bin/sh -x -c "$_cmd" systemd-nspawn $SUSE_OPTS--register=no -D /testsuite-13.nc-container /bin/sh -x -c "$_cmd"
systemd-nspawn --register=no -D /testsuite-13.nc-container -U /bin/sh -x -c "$_cmd" systemd-nspawn $SUSE_OPTS--register=no -D /testsuite-13.nc-container -U /bin/sh -x -c "$_cmd"
} }
function check_os_release { function check_os_release {
@ -79,7 +85,7 @@ if echo test >> /run/host/os-release; then exit 1; fi
echo MARKER=1 >> /etc/os-release echo MARKER=1 >> /etc/os-release
fi fi
systemd-nspawn --register=no -D /testsuite-13.nc-container --bind="${_os_release_source}":/tmp/os-release /bin/sh -x -e -c "$_cmd" systemd-nspawn $SUSE_OPTS--register=no -D /testsuite-13.nc-container --bind="${_os_release_source}":/tmp/os-release /bin/sh -x -e -c "$_cmd"
if grep -q MARKER /etc/os-release; then if grep -q MARKER /etc/os-release; then
rm /etc/os-release rm /etc/os-release
@ -100,16 +106,16 @@ function run {
local _root="/var/lib/machines/testsuite-13.unified-$1-cgns-$2-api-vfs-writable-$3" local _root="/var/lib/machines/testsuite-13.unified-$1-cgns-$2-api-vfs-writable-$3"
rm -rf "$_root" rm -rf "$_root"
/usr/lib/systemd/tests/testdata/create-busybox-container "$_root" /usr/lib/systemd/tests/testdata/create-busybox-container "$_root"
SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" -b SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" -b
SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" --private-network -b SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" --private-network -b
if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" -U -b; then if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" -U -b; then
[[ "$is_user_ns_supported" = "yes" && "$3" = "network" ]] && return 1 [[ "$is_user_ns_supported" = "yes" && "$3" = "network" ]] && return 1
else else
[[ "$is_user_ns_supported" = "no" && "$3" = "network" ]] && return 1 [[ "$is_user_ns_supported" = "no" && "$3" = "network" ]] && return 1
fi fi
if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" --private-network -U -b; then if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" --private-network -U -b; then
[[ "$is_user_ns_supported" = "yes" && "$3" = "yes" ]] && return 1 [[ "$is_user_ns_supported" = "yes" && "$3" = "yes" ]] && return 1
else else
[[ "$is_user_ns_supported" = "no" && "$3" = "yes" ]] && return 1 [[ "$is_user_ns_supported" = "no" && "$3" = "yes" ]] && return 1
@ -118,43 +124,43 @@ function run {
local _netns_opt="--network-namespace-path=/proc/self/ns/net" local _netns_opt="--network-namespace-path=/proc/self/ns/net"
# --network-namespace-path and network-related options cannot be used together # --network-namespace-path and network-related options cannot be used together
if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" "$_netns_opt" --network-interface=lo -b; then if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" "$_netns_opt" --network-interface=lo -b; then
return 1 return 1
fi fi
if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" "$_netns_opt" --network-macvlan=lo -b; then if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" "$_netns_opt" --network-macvlan=lo -b; then
return 1 return 1
fi fi
if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" "$_netns_opt" --network-ipvlan=lo -b; then if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" "$_netns_opt" --network-ipvlan=lo -b; then
return 1 return 1
fi fi
if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" "$_netns_opt" --network-veth -b; then if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" "$_netns_opt" --network-veth -b; then
return 1 return 1
fi fi
if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" "$_netns_opt" --network-veth-extra=lo -b; then if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" "$_netns_opt" --network-veth-extra=lo -b; then
return 1 return 1
fi fi
if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" "$_netns_opt" --network-bridge=lo -b; then if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" "$_netns_opt" --network-bridge=lo -b; then
return 1 return 1
fi fi
if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" "$_netns_opt" --network-zone=zone -b; then if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" "$_netns_opt" --network-zone=zone -b; then
return 1 return 1
fi fi
# allow combination of --network-namespace-path and --private-network # allow combination of --network-namespace-path and --private-network
if ! SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" "$_netns_opt" --private-network -b; then if ! SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" "$_netns_opt" --private-network -b; then
return 1 return 1
fi fi
# test --network-namespace-path works with a network namespace created by "ip netns" # test --network-namespace-path works with a network namespace created by "ip netns"
ip netns add nspawn_test ip netns add nspawn_test
_netns_opt="--network-namespace-path=/run/netns/nspawn_test" _netns_opt="--network-namespace-path=/run/netns/nspawn_test"
SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" "$_netns_opt" /bin/ip a | grep -v -E '^1: lo.*UP' SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" "$_netns_opt" /bin/ip a | grep -v -E '^1: lo.*UP'
local r=$? local r=$?
ip netns del nspawn_test ip netns del nspawn_test