Compare commits

..

No commits in common. "23b13549fa28d7b6b8584a349bd91568de6703d7" and "48625dc437589d328de09887d1ebc360233f5acf" have entirely different histories.

16 changed files with 462 additions and 378 deletions

View File

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

View File

@ -1561,11 +1561,21 @@ meson_apply_m4 = find_program('tools/meson-apply-m4.sh')
includes = include_directories('src/basic', includes = include_directories('src/basic',
'src/boot', 'src/boot',
'src/core',
'src/home', 'src/home',
'src/shared',
'src/systemd',
'src/journal', 'src/journal',
'src/journal-remote', 'src/journal-remote',
'src/libsystemd-network', '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/sd-bus', 'src/libsystemd/sd-bus',
'src/libsystemd/sd-device', 'src/libsystemd/sd-device',
'src/libsystemd/sd-event', 'src/libsystemd/sd-event',
@ -1574,17 +1584,7 @@ includes = include_directories('src/basic',
'src/libsystemd/sd-netlink', 'src/libsystemd/sd-netlink',
'src/libsystemd/sd-network', 'src/libsystemd/sd-network',
'src/libsystemd/sd-resolve', 'src/libsystemd/sd-resolve',
'src/libudev', 'src/libsystemd-network',
'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') add_project_arguments('-include', 'config.h', language : 'c')

View File

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

View File

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

View File

@ -0,0 +1,97 @@
/* 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

@ -0,0 +1,9 @@
/* 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,6 +43,7 @@
#include "io-util.h" #include "io-util.h"
#include "journal-def.h" #include "journal-def.h"
#include "journal-internal.h" #include "journal-internal.h"
#include "journal-qrcode.h"
#include "journal-util.h" #include "journal-util.h"
#include "journal-vacuum.h" #include "journal-vacuum.h"
#include "journal-verify.h" #include "journal-verify.h"
@ -59,7 +60,6 @@
#include "path-util.h" #include "path-util.h"
#include "pcre2-dlopen.h" #include "pcre2-dlopen.h"
#include "pretty-print.h" #include "pretty-print.h"
#include "qrcode-util.h"
#include "random-util.h" #include "random-util.h"
#include "rlimit-util.h" #include "rlimit-util.h"
#include "set.h" #include "set.h"
@ -1779,53 +1779,6 @@ static int add_syslog_identifier(sd_journal *j) {
return 0; 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) { static int setup_keys(void) {
#if HAVE_GCRYPT #if HAVE_GCRYPT
size_t mpk_size, seed_size, state_size; size_t mpk_size, seed_size, state_size;
@ -1940,11 +1893,7 @@ static int setup_keys(void) {
k = mfree(k); k = mfree(k);
_cleanup_free_ char *hn = NULL, *key = NULL; _cleanup_free_ char *hn = NULL;
r = format_journal_url(seed, seed_size, n, arg_interval, hn, machine, false, &key);
if (r < 0)
return r;
if (on_tty()) { if (on_tty()) {
hn = gethostname_malloc(); hn = gethostname_malloc();
@ -1976,19 +1925,21 @@ static int setup_keys(void) {
fflush(stderr); fflush(stderr);
} }
puts(key); 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);
if (on_tty()) { if (on_tty()) {
fprintf(stderr, "%s", ansi_normal()); fprintf(stderr, "%s", ansi_normal());
#if HAVE_QRENCODE #if HAVE_QRENCODE
_cleanup_free_ char *url = NULL; (void) print_qr_code(stderr,
r = format_journal_url(seed, seed_size, n, arg_interval, hn, machine, true, &url); "\nTo transfer the verification key to your phone scan the QR code below:\n",
if (r < 0) seed, seed_size,
return r; n, arg_interval,
hn, machine);
(void) print_qrcode(stderr,
"To transfer the verification key to your phone scan the QR code below",
url);
#endif #endif
} }

View File

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

View File

@ -701,33 +701,6 @@ static void event_gc_signal_data(sd_event *e, const int64_t *priority, int sig)
event_unmask_signal_data(e, d, 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) { static void source_disconnect(sd_event_source *s) {
sd_event *event; sd_event *event;
@ -934,8 +907,16 @@ static int source_set_pending(sd_event_source *s, bool b) {
} else } else
assert_se(prioq_remove(s->event->pending, s, &s->pending_index)); assert_se(prioq_remove(s->event->pending, s, &s->pending_index));
if (EVENT_SOURCE_IS_TIME(s->type)) if (EVENT_SOURCE_IS_TIME(s->type)) {
event_source_time_prioq_reshuffle(s); 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 (s->type == SOURCE_SIGNAL && !b) { if (s->type == SOURCE_SIGNAL && !b) {
struct signal_data *d; struct signal_data *d;
@ -2226,7 +2207,11 @@ _public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority)
} else } else
s->priority = priority; s->priority = priority;
event_source_pp_prioq_reshuffle(s); if (s->pending)
prioq_reshuffle(s->event->pending, s, &s->pending_index);
if (s->prepare)
prioq_reshuffle(s->event->prepare, s, &s->prepare_index);
if (s->type == SOURCE_EXIT) if (s->type == SOURCE_EXIT)
prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index); prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index);
@ -2252,152 +2237,6 @@ _public_ int sd_event_source_get_enabled(sd_event_source *s, int *m) {
return s->enabled != SD_EVENT_OFF; 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) { _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) {
int r; int r;
@ -2405,29 +2244,182 @@ _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(IN_SET(m, SD_EVENT_OFF, SD_EVENT_ON, SD_EVENT_ONESHOT), -EINVAL);
assert_return(!event_pid_changed(s->event), -ECHILD); 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) if (s->event->state == SD_EVENT_FINISHED)
return m == SD_EVENT_OFF ? 0 : -ESTALE; return m == SD_EVENT_OFF ? 0 : -ESTALE;
if (s->enabled == m) /* No change? */ if (s->enabled == m)
return 0; return 0;
if (m == SD_EVENT_OFF) if (m == SD_EVENT_OFF) {
r = event_source_disable(s);
else { /* Unset the pending flag when this event source is disabled */
if (s->enabled != SD_EVENT_OFF) { if (!IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) {
/* Switching from "on" to "oneshot" or back? If that's the case, we can take a shortcut, the r = source_set_pending(s, false);
* event source is already enabled after all. */ if (r < 0)
s->enabled = m; return r;
return 0;
} }
r = event_source_enable(s, m); switch (s->type) {
}
if (r < 0) case SOURCE_IO:
return r; 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.");
}
}
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; return 0;
} }
@ -2442,6 +2434,7 @@ _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) { _public_ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) {
struct clock_data *d;
int r; int r;
assert_return(s, -EINVAL); assert_return(s, -EINVAL);
@ -2455,7 +2448,13 @@ _public_ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) {
s->time.next = usec; s->time.next = usec;
event_source_time_prioq_reshuffle(s); 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;
return 0; return 0;
} }
@ -2487,6 +2486,7 @@ _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) { _public_ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec) {
struct clock_data *d;
int r; int r;
assert_return(s, -EINVAL); assert_return(s, -EINVAL);
@ -2504,7 +2504,12 @@ _public_ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec
s->time.accuracy = usec; s->time.accuracy = usec;
event_source_time_prioq_reshuffle(s); d = event_get_clock_data(s->event, s->type);
assert(d);
prioq_reshuffle(d->latest, s, &s->time.latest_index);
d->needs_rearm = true;
return 0; return 0;
} }
@ -2883,7 +2888,9 @@ static int process_timer(
if (r < 0) if (r < 0)
return r; return r;
event_source_time_prioq_reshuffle(s); prioq_reshuffle(d->earliest, s, &s->time.earliest_index);
prioq_reshuffle(d->latest, s, &s->time.latest_index);
d->needs_rearm = true;
} }
return 0; return 0;

View File

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

View File

@ -1,27 +1,25 @@
#include "qrcode-util.h" #include "qrcode-util.h"
#if HAVE_QRENCODE
#include <qrencode.h>
#include "dlfcn-util.h"
#include "locale-util.h"
#include "terminal-util.h" #include "terminal-util.h"
#define ANSI_WHITE_ON_BLACK "\033[40;37;1m" #define ANSI_WHITE_ON_BLACK "\033[40;37;1m"
static void print_border(FILE *output, unsigned width) { static void print_border(FILE *output, unsigned width) {
unsigned x, y;
/* Four rows of border */ /* Four rows of border */
for (unsigned y = 0; y < 4; y += 2) { for (y = 0; y < 4; y += 2) {
fputs(ANSI_WHITE_ON_BLACK, output); fputs(ANSI_WHITE_ON_BLACK, output);
for (unsigned 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(ANSI_NORMAL "\n", output); fputs(ANSI_NORMAL "\n", output);
} }
} }
static void write_qrcode(FILE *output, QRcode *qr) { void write_qrcode(FILE *output, QRcode *qr) {
unsigned x, y;
assert(qr); assert(qr);
if (!output) if (!output)
@ -29,15 +27,17 @@ static void write_qrcode(FILE *output, QRcode *qr) {
print_border(output, qr->width); print_border(output, qr->width);
for (unsigned y = 0; y < (unsigned) qr->width; y += 2) { for (y = 0; y < (unsigned) qr->width; y += 2) {
const uint8_t *row1 = qr->data + qr->width * y; const uint8_t *row1, *row2;
const uint8_t *row2 = row1 + qr->width;
row1 = qr->data + qr->width * y;
row2 = row1 + qr->width;
fputs(ANSI_WHITE_ON_BLACK, output); fputs(ANSI_WHITE_ON_BLACK, output);
for (unsigned x = 0; x < 4; x++) for (x = 0; x < 4; x++)
fputs("\342\226\210", output); fputs("\342\226\210", output);
for (unsigned x = 0; x < (unsigned) qr->width; x++) { for (x = 0; x < (unsigned) qr->width; x ++) {
bool a, b; bool a, b;
a = row1[x] & 1; a = row1[x] & 1;
@ -53,7 +53,7 @@ static void write_qrcode(FILE *output, QRcode *qr) {
fputs("\342\226\210", output); fputs("\342\226\210", output);
} }
for (unsigned x = 0; x < 4; x++) for (x = 0; x < 4; x++)
fputs("\342\226\210", output); fputs("\342\226\210", output);
fputs(ANSI_NORMAL "\n", output); fputs(ANSI_NORMAL "\n", output);
} }
@ -61,45 +61,3 @@ static void write_qrcode(FILE *output, QRcode *qr) {
print_border(output, qr->width); print_border(output, qr->width);
fflush(output); 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,13 +1,9 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once #pragma once
#include <stdio.h>
#include <errno.h>
#if HAVE_QRENCODE #if HAVE_QRENCODE
int print_qrcode(FILE *out, const char *header, const char *string); #include <qrencode.h>
#else #include <stdio.h>
static inline int print_qrcode(FILE *out, const char *header, const char *string) {
return -EOPNOTSUPP; void write_qrcode(FILE *output, QRcode *qr);
}
#endif #endif

View File

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

View File

@ -1,23 +0,0 @@
/* 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

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