Compare commits

...

12 Commits

Author SHA1 Message Date
Zbigniew Jędrzejewski-Szmek 23b13549fa
Merge pull request #17435 from poettering/event-shuffle-refactor
sd-event: split up sd_event_source_set_enable() function
2020-10-28 18:21:13 +01:00
Zbigniew Jędrzejewski-Szmek a1989bd84b
Merge pull request #17454 from keszybz/journal-dlopen-cleanup
Journal dlopen cleanup and qrcode printing test
2020-10-28 18:20:27 +01:00
Zbigniew Jędrzejewski-Szmek 32c3a623ce
Merge pull request #17467 from keszybz/unconditionally-pull-in-cryptsetup-remote
Unconditionally pull in cryptsetup-remote.target in the initramfs
2020-10-28 18:00:04 +01:00
Zbigniew Jędrzejewski-Szmek 158b28313f test: add a simple test for the qr printing code
Ideally, we'd read back what we wrote, but that would have been
much more complicated. But just writing stuff is useful to test under
valgrind or manually.
2020-10-27 18:33:29 +01:00
Zbigniew Jędrzejewski-Szmek f1b823596f journal,homectl: unify implementations of libqrencode loading and fss key printing
We had two of each: both homectl and journalctl had the whole dlopen()
wrapper, and journalctl had two implementations (slightly different) of the
code to print the fss:// pattern.

print_qrcode() now returns -EOPNOTSUPP when compiled with qrcode support. Both
callers ignore the return value, so this changes nothing.

No functional change.
2020-10-27 18:33:29 +01:00
Lennart Poettering ddfde737b5 sd-event: split out enable and disable codepaths from sd_event_source_set_enabled()
So far half of sd_event_source_set_enabled() was doing enabling, the
other half was doing disabling. Let's split that into two separate
calls.

(This also adds a new shortcut to sd_event_source_set_enabled(): if the
caller toggles between "ON" and "ONESHOT" we'll now shortcut this, since
the event source is already enabled in that case and shall remain
enabled.)

This heavily borrows and is inspired from Michal Sekletár's #17284
refactoring.
2020-10-27 14:01:36 +01:00
Michal Sekletár e1951c16a8 sd-event: split out helper functions for reshuffling prioqs
We typically don't just reshuffle a single prioq at once, but always
two. Let's add two helper functions that do this, and reuse them
everywhere.

(Note that this drops one minor optimization:
sd_event_source_set_time_accuracy() previously only reshuffled the
"latest" prioq, since changing the accuracy has no effect on the
earliest time of an event source, just the latest time an event source
can run. This optimization is removed to simplify things, given that
it's not really worth the effort as prioq_reshuffle() on properly
ordered prioqs has practically zero cost O(1)).

(Slightly generalized, commented and split out of #17284 by Lennart)
2020-10-27 14:01:14 +01:00
Jonathan Lebon e921ebb57e units: unconditionally pull in remote-cryptsetup.target in the initramfs
[zjs: Replaces #17149.

I took half of the patch in
https://github.com/systemd/systemd/pull/17149#issuecomment-698399194,
hence I'm keeping Jonathan's authorship.

The original reasoning for 6c5496c492 was that we
enable remote-cryptsetup.target via presets, and since presets are not used for
the initrd, we need a different target. But since parts of the unit and target
tree are shared between the initramfs and the main system, we can't just create
a separate target for the initramfs. All the targets that depend on this one
would need to be split also. That condition is true for initrd-fs.target, but
not for sysinit.target.

So let's instead just uncoditionally pull in remote-cryptsetup.target in the
initramfs. It should normally be empty, so there should be no impact on boots
that don't have units in the target.

Jonathan's patch used initrd-root-fs.target, this version instead uses
initrd-root-device.target. initrd-root-device.target is ordered before
sysroot.mount, which means that the decrypted devices will be available earlier
too.]
2020-10-27 13:49:01 +01:00
Zbigniew Jędrzejewski-Szmek 6bdcb72086 Revert "units: add initrd-cryptsetup.target"
This reverts commit 6c5496c492.

sysinit.target is shared between the initrd and the host system. Pulling in
initrd-cryptsetup.target into sysinit.target causes the following warning at
boot:
Oct 27 10:42:30 workstation-uefi systemd[1]: initrd-cryptsetup.target: Starting requested but asserts failed.
Oct 27 10:42:30 workstation-uefi systemd[1]: Assertion failed for initrd-cryptsetup.target.
2020-10-27 13:36:22 +01:00
Zbigniew Jędrzejewski-Szmek d5816b6138 meson: simplify with_runlevels ternany op usage 2020-10-27 13:36:22 +01:00
Zbigniew Jędrzejewski-Szmek c9e9a57fce shared/qrcode-util: reduce scope of iterator variables 2020-10-23 20:36:37 +02:00
Zbigniew Jędrzejewski-Szmek 9337945233 meson: sort include dirs
Our headers should have unique names, so the sort order shouldn't matter.
2020-10-23 20:33:28 +02:00
16 changed files with 377 additions and 461 deletions

View File

@ -41,7 +41,6 @@
<filename>hybrid-sleep.target</filename>,
<filename>suspend-then-hibernate.target</filename>,
<filename>initrd.target</filename>,
<filename>initrd-cryptsetup.target</filename>,
<filename>initrd-fs.target</filename>,
<filename>initrd-root-device.target</filename>,
<filename>initrd-root-fs.target</filename>,
@ -183,10 +182,8 @@
<varlistentry>
<term><filename>cryptsetup.target</filename></term>
<listitem>
<para>A target that pulls in setup services for local encrypted block devices.
See <filename>remote-cryptsetup.target</filename> below for the equivalent target for remote
volumes, and <filename>initrd-cryptsetup.target</filename> below for the equivalent target in the
initrd.</para>
<para>A target that pulls in setup services for all
encrypted block devices.</para>
</listitem>
</varlistentry>
<varlistentry>
@ -355,20 +352,12 @@
<varlistentry>
<term><filename>initrd.target</filename></term>
<listitem>
<para>This is the default target in the initrd, similar to <filename>default.target</filename>
<para>This is the default target in the initramfs, similar to <filename>default.target</filename>
in the main system. It is used to mount the real root and transition to it. See
<citerefentry><refentrytitle>bootup</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
more discussion.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><filename>initrd-cryptsetup.target</filename></term>
<listitem>
<para>A target that pulls in setup services for all encrypted block devices. See
<filename>cryptsetup.target</filename> and <filename>remote-cryptsetup.target</filename> for the
equivalent targets in the real root.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><filename>initrd-fs.target</filename></term>
<listitem>
@ -560,9 +549,7 @@
<para>Similar to <filename>cryptsetup.target</filename>, but for encrypted
devices which are accessed over the network. It is used for
<citerefentry><refentrytitle>crypttab</refentrytitle><manvolnum>8</manvolnum></citerefentry>
entries marked with <option>_netdev</option>.
See <filename>cryptsetup.target</filename> for the equivalent target for local volumes, and
<filename>initrd-cryptsetup.target</filename> for the equivalent target in the initrd.</para>
entries marked with <option>_netdev</option>.</para>
</listitem>
</varlistentry>
<varlistentry>

View File

@ -1561,21 +1561,11 @@ meson_apply_m4 = find_program('tools/meson-apply-m4.sh')
includes = include_directories('src/basic',
'src/boot',
'src/core',
'src/home',
'src/shared',
'src/systemd',
'src/journal',
'src/journal-remote',
'src/nspawn',
'src/resolve',
'src/timesync',
'src/time-wait-sync',
'src/login',
'src/udev',
'src/libudev',
'src/core',
'src/shutdown',
'src/xdg-autostart-generator',
'src/libsystemd-network',
'src/libsystemd/sd-bus',
'src/libsystemd/sd-device',
'src/libsystemd/sd-event',
@ -1584,7 +1574,17 @@ includes = include_directories('src/basic',
'src/libsystemd/sd-netlink',
'src/libsystemd/sd-network',
'src/libsystemd/sd-resolve',
'src/libsystemd-network',
'src/libudev',
'src/login',
'src/nspawn',
'src/resolve',
'src/shared',
'src/shutdown',
'src/systemd',
'src/time-wait-sync',
'src/timesync',
'src/udev',
'src/xdg-autostart-generator',
'.')
add_project_arguments('-include', 'config.h', language : 'c')

View File

@ -455,16 +455,10 @@ static int create_disk(
}
}
const char *target;
if (in_initrd())
target = "initrd-cryptsetup.target";
else if (netdev)
target = "remote-cryptsetup.target";
else
target = "cryptsetup.target";
if (!nofail)
fprintf(f, "Before=%s\n", target);
fprintf(f,
"Before=%s\n",
netdev ? "remote-cryptsetup.target" : "cryptsetup.target");
if (password && !keydev) {
r = print_dependencies(f, password);
@ -527,7 +521,8 @@ static int create_disk(
return log_error_errno(r, "Failed to write unit file %s: %m", n);
if (!noauto) {
r = generator_add_symlink(arg_dest, target,
r = generator_add_symlink(arg_dest,
netdev ? "remote-cryptsetup.target" : "cryptsetup.target",
nofail ? "wants" : "requires", n);
if (r < 0)
return r;

View File

@ -1,17 +1,12 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#if HAVE_QRENCODE
#include <qrencode.h>
#include "qrcode-util.h"
#endif
#include "dlfcn-util.h"
#include "errno-util.h"
#include "homectl-recovery-key.h"
#include "libcrypt-util.h"
#include "locale-util.h"
#include "memory-util.h"
#include "modhex.h"
#include "qrcode-util.h"
#include "random-util.h"
#include "strv.h"
#include "terminal-util.h"
@ -140,48 +135,6 @@ static int add_secret(JsonVariant **v, const char *password) {
return 0;
}
static int print_qr_code(const char *secret) {
#if HAVE_QRENCODE
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;
/* 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;
qr = sym_QRcode_encodeString(secret, 0, QR_ECLEVEL_L, QR_MODE_8, 0);
if (!qr)
return -ENOMEM;
fprintf(stderr, "\nYou may optionally scan the recovery key off screen:\n\n");
write_qrcode(stderr, qr);
fputc('\n', stderr);
sym_QRcode_free(qr);
#endif
return 0;
}
int identity_add_recovery_key(JsonVariant **v) {
_cleanup_(erase_and_freep) char *password = NULL, *hashed = NULL;
int r;
@ -240,7 +193,7 @@ int identity_add_recovery_key(JsonVariant **v) {
"whenever authentication is requested.\n", stderr);
fflush(stderr);
print_qr_code(password);
(void) print_qrcode(stderr, "You may optionally scan the recovery key off screen", password);
return 0;
}

View File

@ -1,97 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <qrencode.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include "alloc-util.h"
#include "dlfcn-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "journal-qrcode.h"
#include "locale-util.h"
#include "macro.h"
#include "qrcode-util.h"
#include "terminal-util.h"
int print_qr_code(
FILE *output,
const char *prefix_text,
const void *seed,
size_t seed_size,
uint64_t start,
uint64_t interval,
const char *hn,
sd_id128_t machine) {
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;
_cleanup_free_ char *url = NULL;
_cleanup_fclose_ FILE *f = NULL;
size_t url_size = 0;
QRcode* qr;
int r;
assert(seed);
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);
if (!f)
return -ENOMEM;
fputs("fss://", f);
for (size_t i = 0; i < seed_size; i++) {
if (i > 0 && i % 3 == 0)
fputc('-', f);
fprintf(f, "%02x", ((uint8_t*) seed)[i]);
}
fprintf(f, "/%"PRIx64"-%"PRIx64"?machine=" SD_ID128_FORMAT_STR,
start,
interval,
SD_ID128_FORMAT_VAL(machine));
if (hn)
fprintf(f, ";hostname=%s", hn);
r = fflush_and_check(f);
if (r < 0)
return r;
f = safe_fclose(f);
qr = sym_QRcode_encodeString(url, 0, QR_ECLEVEL_L, QR_MODE_8, 1);
if (!qr)
return -ENOMEM;
if (prefix_text)
fputs(prefix_text, output);
write_qrcode(output, qr);
sym_QRcode_free(qr);
return 0;
}

View File

@ -1,9 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
#include <inttypes.h>
#include <stdio.h>
#include "sd-id128.h"
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

@ -43,7 +43,6 @@
#include "io-util.h"
#include "journal-def.h"
#include "journal-internal.h"
#include "journal-qrcode.h"
#include "journal-util.h"
#include "journal-vacuum.h"
#include "journal-verify.h"
@ -60,6 +59,7 @@
#include "path-util.h"
#include "pcre2-dlopen.h"
#include "pretty-print.h"
#include "qrcode-util.h"
#include "random-util.h"
#include "rlimit-util.h"
#include "set.h"
@ -1779,6 +1779,53 @@ static int add_syslog_identifier(sd_journal *j) {
return 0;
}
static int format_journal_url(
const void *seed,
size_t seed_size,
uint64_t start,
uint64_t interval,
const char *hn,
sd_id128_t machine,
bool full,
char **ret_url) {
_cleanup_free_ char *url = NULL;
_cleanup_fclose_ FILE *f = NULL;
size_t url_size = 0;
int r;
assert(seed);
assert(seed_size > 0);
f = open_memstream_unlocked(&url, &url_size);
if (!f)
return -ENOMEM;
if (full)
fputs("fss://", f);
for (size_t i = 0; i < seed_size; i++) {
if (i > 0 && i % 3 == 0)
fputc('-', f);
fprintf(f, "%02x", ((uint8_t*) seed)[i]);
}
fprintf(f, "/%"PRIx64"-%"PRIx64, start, interval);
if (full) {
fprintf(f, "?machine=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(machine));
if (hn)
fprintf(f, ";hostname=%s", hn);
}
r = fflush_and_check(f);
if (r < 0)
return r;
f = safe_fclose(f);
*ret_url = TAKE_PTR(url);
return 0;
}
static int setup_keys(void) {
#if HAVE_GCRYPT
size_t mpk_size, seed_size, state_size;
@ -1893,7 +1940,11 @@ static int setup_keys(void) {
k = mfree(k);
_cleanup_free_ char *hn = NULL;
_cleanup_free_ char *hn = NULL, *key = NULL;
r = format_journal_url(seed, seed_size, n, arg_interval, hn, machine, false, &key);
if (r < 0)
return r;
if (on_tty()) {
hn = gethostname_malloc();
@ -1925,21 +1976,19 @@ static int setup_keys(void) {
fflush(stderr);
}
for (size_t i = 0; i < seed_size; i++) {
if (i > 0 && i % 3 == 0)
putchar('-');
printf("%02x", ((uint8_t*) seed)[i]);
}
printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval);
puts(key);
if (on_tty()) {
fprintf(stderr, "%s", ansi_normal());
#if HAVE_QRENCODE
(void) print_qr_code(stderr,
"\nTo transfer the verification key to your phone scan the QR code below:\n",
seed, seed_size,
n, arg_interval,
hn, machine);
_cleanup_free_ char *url = NULL;
r = format_journal_url(seed, seed_size, n, arg_interval, hn, machine, true, &url);
if (r < 0)
return r;
(void) print_qrcode(stderr,
"To transfer the verification key to your phone scan the QR code below",
url);
#endif
}

View File

@ -107,11 +107,6 @@ journalctl_sources = files('''
pcre2-dlopen.h
'''.split())
if conf.get('HAVE_QRENCODE') == 1
journalctl_sources += files('journal-qrcode.c',
'journal-qrcode.h')
endif
install_data('journald.conf',
install_dir : pkgsysconfdir)

View File

@ -701,6 +701,33 @@ static void event_gc_signal_data(sd_event *e, const int64_t *priority, int sig)
event_unmask_signal_data(e, d, sig);
}
static void event_source_pp_prioq_reshuffle(sd_event_source *s) {
assert(s);
/* Reshuffles the pending + prepare prioqs. Called whenever the dispatch order changes, i.e. when
* they are enabled/disabled or marked pending and such. */
if (s->pending)
prioq_reshuffle(s->event->pending, s, &s->pending_index);
if (s->prepare)
prioq_reshuffle(s->event->prepare, s, &s->prepare_index);
}
static void event_source_time_prioq_reshuffle(sd_event_source *s) {
struct clock_data *d;
assert(s);
assert(EVENT_SOURCE_IS_TIME(s->type));
/* Called whenever the event source's timer ordering properties changed, i.e. time, accuracy,
* pending, enable state. Makes sure the two prioq's are ordered properly again. */
assert_se(d = event_get_clock_data(s->event, s->type));
prioq_reshuffle(d->earliest, s, &s->time.earliest_index);
prioq_reshuffle(d->latest, s, &s->time.latest_index);
d->needs_rearm = true;
}
static void source_disconnect(sd_event_source *s) {
sd_event *event;
@ -907,16 +934,8 @@ static int source_set_pending(sd_event_source *s, bool b) {
} else
assert_se(prioq_remove(s->event->pending, s, &s->pending_index));
if (EVENT_SOURCE_IS_TIME(s->type)) {
struct clock_data *d;
d = event_get_clock_data(s->event, s->type);
assert(d);
prioq_reshuffle(d->earliest, s, &s->time.earliest_index);
prioq_reshuffle(d->latest, s, &s->time.latest_index);
d->needs_rearm = true;
}
if (EVENT_SOURCE_IS_TIME(s->type))
event_source_time_prioq_reshuffle(s);
if (s->type == SOURCE_SIGNAL && !b) {
struct signal_data *d;
@ -2207,11 +2226,7 @@ _public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority)
} else
s->priority = priority;
if (s->pending)
prioq_reshuffle(s->event->pending, s, &s->pending_index);
if (s->prepare)
prioq_reshuffle(s->event->prepare, s, &s->prepare_index);
event_source_pp_prioq_reshuffle(s);
if (s->type == SOURCE_EXIT)
prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index);
@ -2237,6 +2252,152 @@ _public_ int sd_event_source_get_enabled(sd_event_source *s, int *m) {
return s->enabled != SD_EVENT_OFF;
}
static int event_source_disable(sd_event_source *s) {
int r;
assert(s);
assert(s->enabled != SD_EVENT_OFF);
/* Unset the pending flag when this event source is disabled */
if (!IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) {
r = source_set_pending(s, false);
if (r < 0)
return r;
}
s->enabled = SD_EVENT_OFF;
switch (s->type) {
case SOURCE_IO:
source_io_unregister(s);
break;
case SOURCE_TIME_REALTIME:
case SOURCE_TIME_BOOTTIME:
case SOURCE_TIME_MONOTONIC:
case SOURCE_TIME_REALTIME_ALARM:
case SOURCE_TIME_BOOTTIME_ALARM:
event_source_time_prioq_reshuffle(s);
break;
case SOURCE_SIGNAL:
event_gc_signal_data(s->event, &s->priority, s->signal.sig);
break;
case SOURCE_CHILD:
assert(s->event->n_enabled_child_sources > 0);
s->event->n_enabled_child_sources--;
if (EVENT_SOURCE_WATCH_PIDFD(s))
source_child_pidfd_unregister(s);
else
event_gc_signal_data(s->event, &s->priority, SIGCHLD);
break;
case SOURCE_EXIT:
prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index);
break;
case SOURCE_DEFER:
case SOURCE_POST:
case SOURCE_INOTIFY:
break;
default:
assert_not_reached("Wut? I shouldn't exist.");
}
return 0;
}
static int event_source_enable(sd_event_source *s, int m) {
int r;
assert(s);
assert(IN_SET(m, SD_EVENT_ON, SD_EVENT_ONESHOT));
assert(s->enabled == SD_EVENT_OFF);
/* Unset the pending flag when this event source is enabled */
if (!IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) {
r = source_set_pending(s, false);
if (r < 0)
return r;
}
s->enabled = m;
switch (s->type) {
case SOURCE_IO:
r = source_io_register(s, m, s->io.events);
if (r < 0) {
s->enabled = SD_EVENT_OFF;
return r;
}
break;
case SOURCE_TIME_REALTIME:
case SOURCE_TIME_BOOTTIME:
case SOURCE_TIME_MONOTONIC:
case SOURCE_TIME_REALTIME_ALARM:
case SOURCE_TIME_BOOTTIME_ALARM:
event_source_time_prioq_reshuffle(s);
break;
case SOURCE_SIGNAL:
r = event_make_signal_data(s->event, s->signal.sig, NULL);
if (r < 0) {
s->enabled = SD_EVENT_OFF;
event_gc_signal_data(s->event, &s->priority, s->signal.sig);
return r;
}
break;
case SOURCE_CHILD:
s->event->n_enabled_child_sources++;
if (EVENT_SOURCE_WATCH_PIDFD(s)) {
/* yes, we have pidfd */
r = source_child_pidfd_register(s, s->enabled);
if (r < 0) {
s->enabled = SD_EVENT_OFF;
s->event->n_enabled_child_sources--;
return r;
}
} else {
/* no pidfd, or something other to watch for than WEXITED */
r = event_make_signal_data(s->event, SIGCHLD, NULL);
if (r < 0) {
s->enabled = SD_EVENT_OFF;
s->event->n_enabled_child_sources--;
event_gc_signal_data(s->event, &s->priority, SIGCHLD);
return r;
}
}
break;
case SOURCE_EXIT:
prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index);
break;
case SOURCE_DEFER:
case SOURCE_POST:
case SOURCE_INOTIFY:
break;
default:
assert_not_reached("Wut? I shouldn't exist.");
}
return 0;
}
_public_ int sd_event_source_set_enabled(sd_event_source *s, int m) {
int r;
@ -2244,182 +2405,29 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) {
assert_return(IN_SET(m, SD_EVENT_OFF, SD_EVENT_ON, SD_EVENT_ONESHOT), -EINVAL);
assert_return(!event_pid_changed(s->event), -ECHILD);
/* If we are dead anyway, we are fine with turning off
* sources, but everything else needs to fail. */
/* If we are dead anyway, we are fine with turning off sources, but everything else needs to fail. */
if (s->event->state == SD_EVENT_FINISHED)
return m == SD_EVENT_OFF ? 0 : -ESTALE;
if (s->enabled == m)
if (s->enabled == m) /* No change? */
return 0;
if (m == SD_EVENT_OFF) {
/* Unset the pending flag when this event source is disabled */
if (!IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) {
r = source_set_pending(s, false);
if (r < 0)
return r;
if (m == SD_EVENT_OFF)
r = event_source_disable(s);
else {
if (s->enabled != SD_EVENT_OFF) {
/* Switching from "on" to "oneshot" or back? If that's the case, we can take a shortcut, the
* event source is already enabled after all. */
s->enabled = m;
return 0;
}
switch (s->type) {
case SOURCE_IO:
source_io_unregister(s);
s->enabled = m;
break;
case SOURCE_TIME_REALTIME:
case SOURCE_TIME_BOOTTIME:
case SOURCE_TIME_MONOTONIC:
case SOURCE_TIME_REALTIME_ALARM:
case SOURCE_TIME_BOOTTIME_ALARM: {
struct clock_data *d;
s->enabled = m;
d = event_get_clock_data(s->event, s->type);
assert(d);
prioq_reshuffle(d->earliest, s, &s->time.earliest_index);
prioq_reshuffle(d->latest, s, &s->time.latest_index);
d->needs_rearm = true;
break;
}
case SOURCE_SIGNAL:
s->enabled = m;
event_gc_signal_data(s->event, &s->priority, s->signal.sig);
break;
case SOURCE_CHILD:
s->enabled = m;
assert(s->event->n_enabled_child_sources > 0);
s->event->n_enabled_child_sources--;
if (EVENT_SOURCE_WATCH_PIDFD(s))
source_child_pidfd_unregister(s);
else
event_gc_signal_data(s->event, &s->priority, SIGCHLD);
break;
case SOURCE_EXIT:
s->enabled = m;
prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index);
break;
case SOURCE_DEFER:
case SOURCE_POST:
case SOURCE_INOTIFY:
s->enabled = m;
break;
default:
assert_not_reached("Wut? I shouldn't exist.");
}
} else {
/* Unset the pending flag when this event source is enabled */
if (s->enabled == SD_EVENT_OFF && !IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) {
r = source_set_pending(s, false);
if (r < 0)
return r;
}
switch (s->type) {
case SOURCE_IO:
r = source_io_register(s, m, s->io.events);
if (r < 0)
return r;
s->enabled = m;
break;
case SOURCE_TIME_REALTIME:
case SOURCE_TIME_BOOTTIME:
case SOURCE_TIME_MONOTONIC:
case SOURCE_TIME_REALTIME_ALARM:
case SOURCE_TIME_BOOTTIME_ALARM: {
struct clock_data *d;
s->enabled = m;
d = event_get_clock_data(s->event, s->type);
assert(d);
prioq_reshuffle(d->earliest, s, &s->time.earliest_index);
prioq_reshuffle(d->latest, s, &s->time.latest_index);
d->needs_rearm = true;
break;
}
case SOURCE_SIGNAL:
s->enabled = m;
r = event_make_signal_data(s->event, s->signal.sig, NULL);
if (r < 0) {
s->enabled = SD_EVENT_OFF;
event_gc_signal_data(s->event, &s->priority, s->signal.sig);
return r;
}
break;
case SOURCE_CHILD:
if (s->enabled == SD_EVENT_OFF)
s->event->n_enabled_child_sources++;
s->enabled = m;
if (EVENT_SOURCE_WATCH_PIDFD(s)) {
/* yes, we have pidfd */
r = source_child_pidfd_register(s, s->enabled);
if (r < 0) {
s->enabled = SD_EVENT_OFF;
s->event->n_enabled_child_sources--;
return r;
}
} else {
/* no pidfd, or something other to watch for than WEXITED */
r = event_make_signal_data(s->event, SIGCHLD, NULL);
if (r < 0) {
s->enabled = SD_EVENT_OFF;
s->event->n_enabled_child_sources--;
event_gc_signal_data(s->event, &s->priority, SIGCHLD);
return r;
}
}
break;
case SOURCE_EXIT:
s->enabled = m;
prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index);
break;
case SOURCE_DEFER:
case SOURCE_POST:
case SOURCE_INOTIFY:
s->enabled = m;
break;
default:
assert_not_reached("Wut? I shouldn't exist.");
}
r = event_source_enable(s, m);
}
if (r < 0)
return r;
if (s->pending)
prioq_reshuffle(s->event->pending, s, &s->pending_index);
if (s->prepare)
prioq_reshuffle(s->event->prepare, s, &s->prepare_index);
event_source_pp_prioq_reshuffle(s);
return 0;
}
@ -2434,7 +2442,6 @@ _public_ int sd_event_source_get_time(sd_event_source *s, uint64_t *usec) {
}
_public_ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) {
struct clock_data *d;
int r;
assert_return(s, -EINVAL);
@ -2448,13 +2455,7 @@ _public_ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) {
s->time.next = usec;
d = event_get_clock_data(s->event, s->type);
assert(d);
prioq_reshuffle(d->earliest, s, &s->time.earliest_index);
prioq_reshuffle(d->latest, s, &s->time.latest_index);
d->needs_rearm = true;
event_source_time_prioq_reshuffle(s);
return 0;
}
@ -2486,7 +2487,6 @@ _public_ int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *use
}
_public_ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec) {
struct clock_data *d;
int r;
assert_return(s, -EINVAL);
@ -2504,12 +2504,7 @@ _public_ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec
s->time.accuracy = usec;
d = event_get_clock_data(s->event, s->type);
assert(d);
prioq_reshuffle(d->latest, s, &s->time.latest_index);
d->needs_rearm = true;
event_source_time_prioq_reshuffle(s);
return 0;
}
@ -2888,9 +2883,7 @@ static int process_timer(
if (r < 0)
return r;
prioq_reshuffle(d->earliest, s, &s->time.earliest_index);
prioq_reshuffle(d->latest, s, &s->time.latest_index);
d->needs_rearm = true;
event_source_time_prioq_reshuffle(s);
}
return 0;

View File

@ -195,6 +195,8 @@ shared_sources = files('''
ptyfwd.h
pwquality-util.c
pwquality-util.h
qrcode-util.c
qrcode-util.h
reboot-util.c
reboot-util.h
resize-fs.c
@ -304,13 +306,6 @@ if conf.get('HAVE_PAM') == 1
'''.split())
endif
if conf.get('HAVE_QRENCODE') == 1
shared_sources += files('''
qrcode-util.c
qrcode-util.h
'''.split())
endif
generate_ip_protocol_list = find_program('generate-ip-protocol-list.sh')
ip_protocol_list_txt = custom_target(
'ip-protocol-list.txt',

View File

@ -1,25 +1,27 @@
#include "qrcode-util.h"
#if HAVE_QRENCODE
#include <qrencode.h>
#include "dlfcn-util.h"
#include "locale-util.h"
#include "terminal-util.h"
#define ANSI_WHITE_ON_BLACK "\033[40;37;1m"
static void print_border(FILE *output, unsigned width) {
unsigned x, y;
/* Four rows of border */
for (y = 0; y < 4; y += 2) {
for (unsigned y = 0; y < 4; y += 2) {
fputs(ANSI_WHITE_ON_BLACK, output);
for (x = 0; x < 4 + width + 4; x++)
for (unsigned x = 0; x < 4 + width + 4; x++)
fputs("\342\226\210", output);
fputs(ANSI_NORMAL "\n", output);
}
}
void write_qrcode(FILE *output, QRcode *qr) {
unsigned x, y;
static void write_qrcode(FILE *output, QRcode *qr) {
assert(qr);
if (!output)
@ -27,17 +29,15 @@ void write_qrcode(FILE *output, QRcode *qr) {
print_border(output, qr->width);
for (y = 0; y < (unsigned) qr->width; y += 2) {
const uint8_t *row1, *row2;
row1 = qr->data + qr->width * y;
row2 = row1 + qr->width;
for (unsigned y = 0; y < (unsigned) qr->width; y += 2) {
const uint8_t *row1 = qr->data + qr->width * y;
const uint8_t *row2 = row1 + qr->width;
fputs(ANSI_WHITE_ON_BLACK, output);
for (x = 0; x < 4; x++)
for (unsigned x = 0; x < 4; x++)
fputs("\342\226\210", output);
for (x = 0; x < (unsigned) qr->width; x ++) {
for (unsigned x = 0; x < (unsigned) qr->width; x++) {
bool a, b;
a = row1[x] & 1;
@ -53,7 +53,7 @@ void write_qrcode(FILE *output, QRcode *qr) {
fputs("\342\226\210", output);
}
for (x = 0; x < 4; x++)
for (unsigned x = 0; x < 4; x++)
fputs("\342\226\210", output);
fputs(ANSI_NORMAL "\n", output);
}
@ -61,3 +61,45 @@ void write_qrcode(FILE *output, QRcode *qr) {
print_border(output, qr->width);
fflush(output);
}
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;
/* 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;
qr = sym_QRcode_encodeString(string, 0, QR_ECLEVEL_L, QR_MODE_8, 0);
if (!qr)
return -ENOMEM;
if (header)
fprintf(out, "\n%s:\n\n", header);
write_qrcode(out, qr);
fputc('\n', out);
sym_QRcode_free(qr);
return 0;
}
#endif

View File

@ -1,9 +1,13 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
#include <stdio.h>
#include <errno.h>
#if HAVE_QRENCODE
#include <qrencode.h>
#include <stdio.h>
void write_qrcode(FILE *output, QRcode *qr);
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) {
return -EOPNOTSUPP;
}
#endif

View File

@ -819,6 +819,10 @@ tests += [
[['src/test/test-psi-util.c'],
[],
[]],
[['src/test/test-qrcode-util.c'],
[libshared],
[libdl]],
]
############################################################

View File

@ -0,0 +1,23 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include "locale-util.h"
#include "main-func.h"
#include "qrcode-util.h"
#include "tests.h"
static int run(int argc, char **argv) {
int r;
test_setup_logging(LOG_DEBUG);
assert_se(setenv("SYSTEMD_COLORS", "1", 1) == 0); /* Force the qrcode to be printed */
r = print_qrcode(stdout, "This should say \"TEST\"", "TEST");
if (r == -EOPNOTSUPP)
return log_tests_skipped("not supported");
if (r < 0)
return log_error_errno(r, "Failed to print QR code: %m");
return 0;
}
DEFINE_MAIN_FUNCTION(run);

View File

@ -1,17 +0,0 @@
# SPDX-License-Identifier: LGPL-2.1+
#
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=Initrd Encrypted Volumes
Documentation=man:systemd.special(7)
OnFailure=emergency.target
OnFailureJobMode=replace-irreversibly
AssertPathExists=/etc/initrd-release
DefaultDependencies=no
Conflicts=shutdown.target

View File

@ -22,14 +22,12 @@ units = [
'multi-user.target.wants/'],
['getty-pre.target', ''],
['graphical.target', '',
(with_runlevels ? 'runlevel5.target default.target' : 'default.target')],
'default.target' + (with_runlevels ? ' runlevel5.target' : '')],
['halt.target', ''],
['hibernate.target', 'ENABLE_HIBERNATE'],
['hybrid-sleep.target', 'ENABLE_HIBERNATE'],
['suspend-then-hibernate.target', 'ENABLE_HIBERNATE'],
['initrd-cleanup.service', 'ENABLE_INITRD'],
['initrd-cryptsetup.target', 'HAVE_LIBCRYPTSETUP ENABLE_INITRD',
'sysinit.target.wants/'],
['initrd-fs.target', 'ENABLE_INITRD'],
['initrd-parse-etc.service', 'ENABLE_INITRD'],
['initrd-root-device.target', 'ENABLE_INITRD'],
@ -61,8 +59,9 @@ units = [
'sysinit.target.wants/'],
['proc-sys-fs-binfmt_misc.mount', 'ENABLE_BINFMT'],
['reboot.target', '',
(with_runlevels ? 'runlevel6.target ctrl-alt-del.target' : 'ctrl-alt-del.target')],
['remote-cryptsetup.target', 'HAVE_LIBCRYPTSETUP'],
'ctrl-alt-del.target' + (with_runlevels ? ' runlevel6.target' : '')],
['remote-cryptsetup.target', 'HAVE_LIBCRYPTSETUP',
'initrd-root-device.target.wants/'],
['remote-fs-pre.target', ''],
['remote-fs.target', ''],
['rescue.target', '',