summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--catalog/systemd.zh_CN.catalog.in2
-rw-r--r--configure.ac18
-rw-r--r--hwdb/60-sensor.hwdb13
-rw-r--r--hwdb/70-mouse.hwdb4
-rw-r--r--man/systemd-firstboot.xml10
-rw-r--r--po/hr.po2
-rw-r--r--shell-completion/bash/systemctl.in2
-rw-r--r--shell-completion/zsh/_journalctl4
-rw-r--r--src/basic/fs-util.c23
-rw-r--r--src/basic/khash.c2
-rw-r--r--src/basic/proc-cmdline.c2
-rw-r--r--src/basic/virt.c2
-rw-r--r--src/core/dbus-execute.c4
-rw-r--r--src/core/dbus.c4
-rw-r--r--src/core/execute.c6
-rw-r--r--src/core/unit.c24
-rw-r--r--src/coredump/coredump.c6
-rw-r--r--src/hostname/hostnamed.c4
-rw-r--r--src/journal-remote/journal-gatewayd.c3
-rw-r--r--src/libudev/libudev-util.c14
-rw-r--r--src/nspawn/nspawn-stub-pid1.c2
-rw-r--r--src/resolve/resolved-link-bus.c2
-rw-r--r--src/systemctl/systemctl.c21
-rw-r--r--src/test/test-fs-util.c7
-rw-r--r--src/udev/udev-event.c449
-rw-r--r--src/veritysetup/veritysetup-generator.c4
-rwxr-xr-xtest/udev-test.pl80
-rw-r--r--units/initrd-switch-root.service.in1
-rw-r--r--units/systemd-vconsole-setup.service.in1
29 files changed, 427 insertions, 289 deletions
diff --git a/catalog/systemd.zh_CN.catalog.in b/catalog/systemd.zh_CN.catalog.in
index ba7c697c16..13030e14dc 100644
--- a/catalog/systemd.zh_CN.catalog.in
+++ b/catalog/systemd.zh_CN.catalog.in
@@ -137,7 +137,7 @@ Support: %SUPPORT_URL%
-- 6bbd95ee977941e497c48be27c254128
Subject: 系统已进入 @SLEEP@ 睡眠状态
Defined-By: systemd
-Support: http://lists.freedesktop.org/mailman/listinfo/systemd-deve
+Support: %SUPPORT_URL%
系统现已进入 @SLEEP@ 睡眠状态。
diff --git a/configure.ac b/configure.ac
index 48c71ce340..b9143d28ca 100644
--- a/configure.ac
+++ b/configure.ac
@@ -601,6 +601,15 @@ AC_ARG_WITH([nobody-group],
AC_SUBST(NOBODY_GROUP_NAME)
AC_DEFINE_UNQUOTED(NOBODY_GROUP_NAME, ["$NOBODY_GROUP_NAME"], [The name of the nobody group (the one with GID 65534)])
+AC_ARG_WITH([fallback-hostname],
+ AS_HELP_STRING([--with-fallback-hostname=NAME],
+ [specify the hostname used if none configured]),
+ [FALLBACK_HOSTNAME="$withval"],
+ [FALLBACK_HOSTNAME=localhost])
+
+AC_SUBST(FALLBACK_HOSTNAME)
+AC_DEFINE_UNQUOTED(FALLBACK_HOSTNAME, ["$FALLBACK_HOSTNAME"], [The hostname used if none configured])
+
# ------------------------------------------------------------------------------
have_xz=no
AC_ARG_ENABLE(xz, AS_HELP_STRING([--disable-xz], [disable optional XZ support]))
@@ -1715,12 +1724,13 @@ AC_MSG_RESULT([
Wheel group: ${have_wheel_group}
Debug shell: ${SUSHELL} @ ${DEBUGTTY}
TTY GID: ${TTY_GID}
- Maximum System UID: ${SYSTEM_UID_MAX}
- Maximum System GID: ${SYSTEM_GID_MAX}
+ Maximum system UID: ${SYSTEM_UID_MAX}
+ Maximum system GID: ${SYSTEM_GID_MAX}
Certificate root: ${CERTIFICATEROOT}
Support URL: ${SUPPORT_URL}
- Nobody User Name: ${NOBODY_USER_NAME}
- Nobody Group Name: ${NOBODY_GROUP_NAME}
+ nobody user name: ${NOBODY_USER_NAME}
+ nobody group name: ${NOBODY_GROUP_NAME}
+ Fallback hostname: ${FALLBACK_HOSTNAME}
CFLAGS: ${OUR_CFLAGS} ${CFLAGS}
CPPFLAGS: ${OUR_CPPFLAGS} ${CPPFLAGS}
diff --git a/hwdb/60-sensor.hwdb b/hwdb/60-sensor.hwdb
index 3160cf77e8..fcbdcabf30 100644
--- a/hwdb/60-sensor.hwdb
+++ b/hwdb/60-sensor.hwdb
@@ -15,7 +15,7 @@
# /etc/udev/hwdb.d/61-sensor-local.hwdb
# and add your rules there. To load the new rules execute (as root):
# systemd-hwdb update
-# udevadm trigger `dirname $(udevadm info -n "/dev/iio:deviceXXX" -q path)`
+# udevadm trigger -y `dirname $(udevadm info -n "/dev/iio:deviceXXX" -q path)`
# where /dev/iio:deviceXXX is the device in question.
#
# If your changes are generally applicable, preferably send them as a pull
@@ -25,6 +25,9 @@
# include your new rules, a description of the device, and the output of
# udevadm info --export-db
#
+# For hwdb format and systemd behavior:
+# https://www.freedesktop.org/software/systemd/man/hwdb.html
+#
# Allowed properties are:
# ACCEL_MOUNT_MATRIX=<matrix>
#
@@ -34,11 +37,17 @@
# eg. the identity matrix.
#
# [1]: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=dfc57732ad38f93ae6232a3b4e64fd077383a0f1
-
+#
#
# Sort by brand, model
#########################################
+# AsusTek
+#########################################
+sensor:modalias:acpi:SMO8500*:dmi:*svn*ASUSTeK*:*pn*TP500LB*
+ ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 0
+
+#########################################
# Winbook
#########################################
sensor:modalias:acpi:BMA250*:dmi:*svn*WinBook*:*pn*TW100*
diff --git a/hwdb/70-mouse.hwdb b/hwdb/70-mouse.hwdb
index 7b1a85fb03..772534f495 100644
--- a/hwdb/70-mouse.hwdb
+++ b/hwdb/70-mouse.hwdb
@@ -531,6 +531,10 @@ mouse:bluetooth:v056ep0061:name:Laser BTmouse:
mouse:usb:v1532p0042:name:Razer Razer Abyssus:
MOUSE_DPI=3500@1000
+# Razer DeathAdder Black Edition
+mouse:usb:v1532p0029:name:Razer Razer DeathAdder:
+ MOUSE_DPI=3500@1000
+
##########################################
# Roccat
##########################################
diff --git a/man/systemd-firstboot.xml b/man/systemd-firstboot.xml
index 8cdc297a0e..539422ab98 100644
--- a/man/systemd-firstboot.xml
+++ b/man/systemd-firstboot.xml
@@ -63,8 +63,14 @@
<para><command>systemd-firstboot</command> initializes the most
basic system settings interactively on the first boot, or
- optionally non-interactively when a system image is created. The
- following settings may be set up:</para>
+ optionally non-interactively when a system image is created.
+ The service is started if <varname>ConditionFirstBoot=yes</varname>
+ is satisfied. This essentially means that <filename>/etc</filename>
+ is empty, see
+ <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for details.</para>
+
+ <para>The following settings may be set up:</para>
<itemizedlist>
<listitem><para>The system locale, more specifically the two
diff --git a/po/hr.po b/po/hr.po
index a0aff4331f..e98e88aeb7 100644
--- a/po/hr.po
+++ b/po/hr.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: systemd master\n"
"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n"
-"POT-Creation-Date: 2016-27-04 11:57+0100\n"
+"POT-Creation-Date: 2016-04-27 11:57+0100\n"
"PO-Revision-Date: 2016-04-27 12:11+0200\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
diff --git a/shell-completion/bash/systemctl.in b/shell-completion/bash/systemctl.in
index 34589e2888..7765010869 100644
--- a/shell-completion/bash/systemctl.in
+++ b/shell-completion/bash/systemctl.in
@@ -124,7 +124,7 @@ _systemctl () {
local -A OPTS=(
[STANDALONE]='--all -a --reverse --after --before --defaults --force -f --full -l --global
- --help -h --no-ask-password --no-block --no-legend --no-pager --no-reload --no-wall
+ --help -h --no-ask-password --no-block --no-legend --no-pager --no-reload --no-wall --now
--quiet -q --privileged -P --system --user --version --runtime --recursive -r --firmware-setup
--show-types -i --ignore-inhibitors --plain'
[ARG]='--host -H --kill-who --property -p --signal -s --type -t --state --job-mode --root
diff --git a/shell-completion/zsh/_journalctl b/shell-completion/zsh/_journalctl
index ef67fcf2a0..4a78a2e946 100644
--- a/shell-completion/zsh/_journalctl
+++ b/shell-completion/zsh/_journalctl
@@ -107,8 +107,8 @@ _arguments -s \
'--user[Show messages from user services]' \
'(--directory -D -M --machine --root --file)'{-M+,--machine=}'[Operate on local container]:machines:_sd_machines' \
'(--directory -D -M --machine --root --file)'{-D+,--directory=}'[Show journal files from directory]:directories:_directories' \
- '(--directory -D -M --machine --root --file)''--root=[Operate on catalog hierarchy under specified directory]:directories:_directories' \
- '(--directory -D -M --machine --root)--file=[Operate on specified journal files]:file:_files' \
+ '(--directory -D -M --machine --root --file)--root=[Operate on catalog hierarchy under specified directory]:directories:_directories' \
+ '(--directory -D -M --machine --root)*--file=[Operate on specified journal files]:file:_files' \
'--new-id128[Generate a new 128 Bit ID]' \
'--header[Show journal header information]' \
'--disk-usage[Show total disk usage]' \
diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c
index e31fa2711a..8fe19ee4e4 100644
--- a/src/basic/fs-util.c
+++ b/src/basic/fs-util.c
@@ -723,6 +723,8 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
return -errno;
if (S_ISLNK(st.st_mode)) {
+ char *joined;
+
_cleanup_free_ char *destination = NULL;
/* This is a symlink, in this case read the destination. But let's make sure we don't follow
@@ -746,9 +748,6 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
if (fd < 0)
return -errno;
- free_and_replace(buffer, destination);
-
- todo = buffer;
free(done);
/* Note that we do not revalidate the root, we take it as is. */
@@ -760,19 +759,17 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
return -ENOMEM;
}
- } else {
- char *joined;
+ }
- /* A relative destination. If so, this is what we'll prefix what's left to do with what
- * we just read, and start the loop again, but remain in the current directory. */
+ /* Prefix what's left to do with what we just read, and start the loop again,
+ * but remain in the current directory. */
- joined = strjoin("/", destination, todo);
- if (!joined)
- return -ENOMEM;
+ joined = strjoin("/", destination, todo);
+ if (!joined)
+ return -ENOMEM;
- free(buffer);
- todo = buffer = joined;
- }
+ free(buffer);
+ todo = buffer = joined;
continue;
}
diff --git a/src/basic/khash.c b/src/basic/khash.c
index 9a2a3edb75..84648dc1c9 100644
--- a/src/basic/khash.c
+++ b/src/basic/khash.c
@@ -143,7 +143,7 @@ int khash_dup(khash *h, khash **ret) {
copy->fd = -1;
copy->algorithm = strdup(h->algorithm);
- if (!copy)
+ if (!copy->algorithm)
return -ENOMEM;
copy->fd = accept4(h->fd, NULL, 0, SOCK_CLOEXEC);
diff --git a/src/basic/proc-cmdline.c b/src/basic/proc-cmdline.c
index 6ecb6c3f0d..f703e7f145 100644
--- a/src/basic/proc-cmdline.c
+++ b/src/basic/proc-cmdline.c
@@ -148,7 +148,7 @@ int proc_cmdline_get_key(const char *key, unsigned flags, char **value) {
* a) The "value" parameter is used. In this case a parameter beginning with the "key" string followed by "="
* is searched, and the value following this is returned in "value".
*
- * b) as above, but the PROC_CMDLINE_VALUE_OPTIONAL flag is set. In this case if the the key is found as a
+ * b) as above, but the PROC_CMDLINE_VALUE_OPTIONAL flag is set. In this case if the key is found as a
* separate word (i.e. not followed by "=" but instead by whitespace or the end of the command line), then
* this is also accepted, and "value" is returned as NULL.
*
diff --git a/src/basic/virt.c b/src/basic/virt.c
index 33641e6886..03ce71a728 100644
--- a/src/basic/virt.c
+++ b/src/basic/virt.c
@@ -49,7 +49,7 @@ static int detect_vm_cpuid(void) {
{ "KVMKVMKVM", VIRTUALIZATION_KVM },
/* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
{ "VMwareVMware", VIRTUALIZATION_VMWARE },
- /* http://msdn.microsoft.com/en-us/library/ff542428.aspx */
+ /* https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/tlfs */
{ "Microsoft Hv", VIRTUALIZATION_MICROSOFT },
/* https://wiki.freebsd.org/bhyve */
{ "bhyve bhyve ", VIRTUALIZATION_BHYVE },
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
index 9960b7a811..cc10e2d8e7 100644
--- a/src/core/dbus-execute.c
+++ b/src/core/dbus-execute.c
@@ -1382,7 +1382,7 @@ int bus_exec_context_set_transient_property(
_cleanup_free_ char *joined = NULL;
_cleanup_fclose_ FILE *f = NULL;
- _cleanup_free_ char **l = NULL;
+ _cleanup_strv_free_ char **l = NULL;
size_t size = 0;
char **i;
@@ -1698,7 +1698,7 @@ int bus_exec_context_set_transient_property(
if (!path_is_absolute(source))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path %s is not absolute.", source);
if (!path_is_absolute(destination))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path %s is not absolute.", source);
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path %s is not absolute.", destination);
if (!IN_SET(mount_flags, 0, MS_REC))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown mount flags.");
diff --git a/src/core/dbus.c b/src/core/dbus.c
index 1f9bf2085f..a3f701c064 100644
--- a/src/core/dbus.c
+++ b/src/core/dbus.c
@@ -477,7 +477,7 @@ static int bus_kill_context_find(sd_bus *bus, const char *path, const char *inte
}
static int bus_job_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
- _cleanup_free_ char **l = NULL;
+ _cleanup_strv_free_ char **l = NULL;
Manager *m = userdata;
unsigned k = 0;
Iterator i;
@@ -504,7 +504,7 @@ static int bus_job_enumerate(sd_bus *bus, const char *path, void *userdata, char
}
static int bus_unit_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
- _cleanup_free_ char **l = NULL;
+ _cleanup_strv_free_ char **l = NULL;
Manager *m = userdata;
unsigned k = 0;
Iterator i;
diff --git a/src/core/execute.c b/src/core/execute.c
index 06a291fd39..d0faba5a85 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -1896,8 +1896,8 @@ static int compile_read_write_paths(
_cleanup_strv_free_ char **l = NULL;
char **rt;
- /* Compile the list of writable paths. This is the combination of the explicitly configured paths, plus all
- * runtime directories. */
+ /* Compile the list of writable paths. This is the combination of
+ * the explicitly configured paths, plus all runtime directories. */
if (strv_isempty(context->read_write_paths) &&
strv_isempty(context->runtime_directory)) {
@@ -1930,7 +1930,7 @@ static int apply_mount_namespace(Unit *u, const ExecContext *context,
const ExecParameters *params,
ExecRuntime *runtime) {
int r;
- _cleanup_free_ char **rw = NULL;
+ _cleanup_strv_free_ char **rw = NULL;
char *tmp = NULL, *var = NULL;
const char *root_dir = NULL;
NameSpaceInfo ns_info = {
diff --git a/src/core/unit.c b/src/core/unit.c
index 409668f6d2..44f1d5e206 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -1083,6 +1083,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
/* Common implementation for multiple backends */
int unit_load_fragment_and_dropin(Unit *u) {
+ Unit *t;
int r;
assert(u);
@@ -1095,16 +1096,18 @@ int unit_load_fragment_and_dropin(Unit *u) {
if (u->load_state == UNIT_STUB)
return -ENOENT;
- /* Load drop-in directory data */
- r = unit_load_dropin(unit_follow_merge(u));
- if (r < 0)
- return r;
+ /* If the unit is an alias and the final unit has already been
+ * loaded, there's no point in reloading the dropins one more time. */
+ t = unit_follow_merge(u);
+ if (t != u && t->load_state != UNIT_STUB)
+ return 0;
- return 0;
+ return unit_load_dropin(t);
}
/* Common implementation for multiple backends */
int unit_load_fragment_and_dropin_optional(Unit *u) {
+ Unit *t;
int r;
assert(u);
@@ -1120,12 +1123,13 @@ int unit_load_fragment_and_dropin_optional(Unit *u) {
if (u->load_state == UNIT_STUB)
u->load_state = UNIT_LOADED;
- /* Load drop-in directory data */
- r = unit_load_dropin(unit_follow_merge(u));
- if (r < 0)
- return r;
+ /* If the unit is an alias and the final unit has already been
+ * loaded, there's no point in reloading the dropins one more time. */
+ t = unit_follow_merge(u);
+ if (t != u && t->load_state != UNIT_STUB)
+ return 0;
- return 0;
+ return unit_load_dropin(t);
}
int unit_add_default_target_dependency(Unit *u, Unit *target) {
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
index d55d896df4..1f6fb5de1e 100644
--- a/src/coredump/coredump.c
+++ b/src/coredump/coredump.c
@@ -642,7 +642,11 @@ static int get_process_container_parent_cmdline(pid_t pid, char** cmdline) {
if (r < 0)
return r;
- return get_process_cmdline(container_pid, 0, false, cmdline);
+ r = get_process_cmdline(container_pid, 0, false, cmdline);
+ if (r < 0)
+ return r;
+
+ return 1;
}
static int change_uid_gid(const char *context[]) {
diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c
index 74256e4444..4657cf8c77 100644
--- a/src/hostname/hostnamed.c
+++ b/src/hostname/hostnamed.c
@@ -283,7 +283,7 @@ static int context_update_kernel_hostname(Context *c) {
/* ... and the ultimate fallback */
else
- hn = "localhost";
+ hn = FALLBACK_HOSTNAME;
if (sethostname_idempotent(hn) < 0)
return -errno;
@@ -419,7 +419,7 @@ static int method_set_hostname(sd_bus_message *m, void *userdata, sd_bus_error *
name = c->data[PROP_STATIC_HOSTNAME];
if (isempty(name))
- name = "localhost";
+ name = FALLBACK_HOSTNAME;
if (!hostname_is_valid(name, false))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", name);
diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c
index 8ad9738edf..f86b67faa2 100644
--- a/src/journal-remote/journal-gatewayd.c
+++ b/src/journal-remote/journal-gatewayd.c
@@ -912,7 +912,7 @@ static int parse_argv(int argc, char *argv[]) {
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
+ while ((c = getopt_long(argc, argv, "hD:", options, NULL)) >= 0)
switch(c) {
@@ -958,6 +958,7 @@ static int parse_argv(int argc, char *argv[]) {
break;
#else
log_error("Option --trust is not available.");
+ return -EINVAL;
#endif
case 'D':
arg_directory = optarg;
diff --git a/src/libudev/libudev-util.c b/src/libudev/libudev-util.c
index a9819b9db3..1d73d8f090 100644
--- a/src/libudev/libudev-util.c
+++ b/src/libudev/libudev-util.c
@@ -161,6 +161,20 @@ void util_remove_trailing_chars(char *path, char c)
path[--len] = '\0';
}
+/*
+ * Copy from 'str' to 'to', while removing all leading and trailing whitespace,
+ * and replacing each run of consecutive whitespace with a single underscore.
+ * The chars from 'str' are copied up to the \0 at the end of the string, or
+ * at most 'len' chars. This appends \0 to 'to', at the end of the copied
+ * characters.
+ *
+ * If 'len' chars are copied into 'to', the final \0 is placed at len+1
+ * (i.e. 'to[len] = \0'), so the 'to' buffer must have at least len+1
+ * chars available.
+ *
+ * Note this may be called with 'str' == 'to', i.e. to replace whitespace
+ * in-place in a buffer. This function can handle that situation.
+ */
int util_replace_whitespace(const char *str, char *to, size_t len)
{
size_t i, j;
diff --git a/src/nspawn/nspawn-stub-pid1.c b/src/nspawn/nspawn-stub-pid1.c
index 38ab37367e..7f2a53a245 100644
--- a/src/nspawn/nspawn-stub-pid1.c
+++ b/src/nspawn/nspawn-stub-pid1.c
@@ -87,7 +87,7 @@ int stub_pid1(sd_id128_t uuid) {
/* Flush out /proc/self/environ, so that we don't leak the environment from the host into the container. Also,
* set $container= and $container_uuid= so that clients in the container that query it from /proc/1/environ
- * find them set set. */
+ * find them set. */
sd_id128_to_string(uuid, new_environment + sizeof(new_environment) - SD_ID128_STRING_MAX);
reset_environ(new_environment, sizeof(new_environment));
diff --git a/src/resolve/resolved-link-bus.c b/src/resolve/resolved-link-bus.c
index 364812250f..59cd6cf1cb 100644
--- a/src/resolve/resolved-link-bus.c
+++ b/src/resolve/resolved-link-bus.c
@@ -462,7 +462,7 @@ int bus_link_method_set_dnssec(sd_bus_message *message, void *userdata, sd_bus_e
int bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_set_free_free_ Set *ns = NULL;
- _cleanup_free_ char **ntas = NULL;
+ _cleanup_strv_free_ char **ntas = NULL;
Link *l = userdata;
int r;
char **i;
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 41e8d6075a..a20ca1bcb5 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -5655,16 +5655,22 @@ static int switch_root(int argc, char *argv[], void *userdata) {
}
/* Instruct PID1 to exclude us from its killing spree applied during
- * the transition from the initrd to the main system otherwise we would
- * exit with a failure status even though the switch to the new root
- * has succeed. */
- if (in_initrd())
- argv_cmdline[0] = '@';
+ * the transition. Otherwise we would exit with a failure status even
+ * though the switch to the new root has succeed. */
+ argv_cmdline[0] = '@';
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
return r;
+ /* If we are slow to exit after the root switch, the new systemd instance
+ * will send us a signal to terminate. Just ignore it and exit normally.
+ * This way the unit does not end up as failed.
+ */
+ r = ignore_signals(SIGTERM, -1);
+ if (r < 0)
+ log_warning_errno(r, "Failed to change disposition of SIGTERM to ignore: %m");
+
log_debug("Switching root - root: %s; init: %s", root, strna(init));
r = sd_bus_call_method(
@@ -5676,8 +5682,11 @@ static int switch_root(int argc, char *argv[], void *userdata) {
&error,
NULL,
"ss", root, init);
- if (r < 0)
+ if (r < 0) {
+ (void) default_signals(SIGTERM, -1);
+
return log_error_errno(r, "Failed to switch root: %s", bus_error_message(&error, r));
+ }
return 0;
}
diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c
index ae68587be9..4cb465d0d2 100644
--- a/src/test/test-fs-util.c
+++ b/src/test/test-fs-util.c
@@ -186,6 +186,13 @@ static void test_chase_symlinks(void) {
r = chase_symlinks(p, NULL, CHASE_NONEXISTENT, &result);
assert_se(r == -ENOENT);
+ p = strjoina(temp, "/target");
+ q = strjoina(temp, "/top");
+ assert_se(symlink(q, p) >= 0);
+ p = strjoina(temp, "/target/idontexist");
+ r = chase_symlinks(p, NULL, 0, &result);
+ assert_se(r == -ENOENT);
+
assert_se(rm_rf(temp, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
}
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index deffefd60b..3f9c3ed0cf 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -73,29 +73,219 @@ void udev_event_unref(struct udev_event *event) {
free(event);
}
+enum subst_type {
+ SUBST_UNKNOWN,
+ SUBST_DEVNODE,
+ SUBST_ATTR,
+ SUBST_ENV,
+ SUBST_KERNEL,
+ SUBST_KERNEL_NUMBER,
+ SUBST_DRIVER,
+ SUBST_DEVPATH,
+ SUBST_ID,
+ SUBST_MAJOR,
+ SUBST_MINOR,
+ SUBST_RESULT,
+ SUBST_PARENT,
+ SUBST_NAME,
+ SUBST_LINKS,
+ SUBST_ROOT,
+ SUBST_SYS,
+};
+
+static size_t subst_format_var(struct udev_event *event, struct udev_device *dev,
+ enum subst_type type, char *attr,
+ char *dest, size_t l) {
+ char *s = dest;
+
+ switch (type) {
+ case SUBST_DEVPATH:
+ l = strpcpy(&s, l, udev_device_get_devpath(dev));
+ break;
+ case SUBST_KERNEL:
+ l = strpcpy(&s, l, udev_device_get_sysname(dev));
+ break;
+ case SUBST_KERNEL_NUMBER:
+ if (udev_device_get_sysnum(dev) == NULL)
+ break;
+ l = strpcpy(&s, l, udev_device_get_sysnum(dev));
+ break;
+ case SUBST_ID:
+ if (event->dev_parent == NULL)
+ break;
+ l = strpcpy(&s, l, udev_device_get_sysname(event->dev_parent));
+ break;
+ case SUBST_DRIVER: {
+ const char *driver;
+
+ if (event->dev_parent == NULL)
+ break;
+
+ driver = udev_device_get_driver(event->dev_parent);
+ if (driver == NULL)
+ break;
+ l = strpcpy(&s, l, driver);
+ break;
+ }
+ case SUBST_MAJOR: {
+ char num[UTIL_PATH_SIZE];
+
+ sprintf(num, "%u", major(udev_device_get_devnum(dev)));
+ l = strpcpy(&s, l, num);
+ break;
+ }
+ case SUBST_MINOR: {
+ char num[UTIL_PATH_SIZE];
+
+ sprintf(num, "%u", minor(udev_device_get_devnum(dev)));
+ l = strpcpy(&s, l, num);
+ break;
+ }
+ case SUBST_RESULT: {
+ char *rest;
+ int i;
+
+ if (event->program_result == NULL)
+ break;
+ /* get part of the result string */
+ i = 0;
+ if (attr != NULL)
+ i = strtoul(attr, &rest, 10);
+ if (i > 0) {
+ char result[UTIL_PATH_SIZE];
+ char tmp[UTIL_PATH_SIZE];
+ char *cpos;
+
+ strscpy(result, sizeof(result), event->program_result);
+ cpos = result;
+ while (--i) {
+ while (cpos[0] != '\0' && !isspace(cpos[0]))
+ cpos++;
+ while (isspace(cpos[0]))
+ cpos++;
+ if (cpos[0] == '\0')
+ break;
+ }
+ if (i > 0) {
+ log_error("requested part of result string not found");
+ break;
+ }
+ strscpy(tmp, sizeof(tmp), cpos);
+ /* %{2+}c copies the whole string from the second part on */
+ if (rest[0] != '+') {
+ cpos = strchr(tmp, ' ');
+ if (cpos)
+ cpos[0] = '\0';
+ }
+ l = strpcpy(&s, l, tmp);
+ } else {
+ l = strpcpy(&s, l, event->program_result);
+ }
+ break;
+ }
+ case SUBST_ATTR: {
+ const char *value = NULL;
+ char vbuf[UTIL_NAME_SIZE];
+ size_t len;
+ int count;
+
+ if (attr == NULL) {
+ log_error("missing file parameter for attr");
+ break;
+ }
+
+ /* try to read the value specified by "[dmi/id]product_name" */
+ if (util_resolve_subsys_kernel(event->udev, attr, vbuf, sizeof(vbuf), 1) == 0)
+ value = vbuf;
+
+ /* try to read the attribute the device */
+ if (value == NULL)
+ value = udev_device_get_sysattr_value(event->dev, attr);
+
+ /* try to read the attribute of the parent device, other matches have selected */
+ if (value == NULL && event->dev_parent != NULL && event->dev_parent != event->dev)
+ value = udev_device_get_sysattr_value(event->dev_parent, attr);
+
+ if (value == NULL)
+ break;
+
+ /* strip trailing whitespace, and replace unwanted characters */
+ if (value != vbuf)
+ strscpy(vbuf, sizeof(vbuf), value);
+ len = strlen(vbuf);
+ while (len > 0 && isspace(vbuf[--len]))
+ vbuf[len] = '\0';
+ count = util_replace_chars(vbuf, UDEV_ALLOWED_CHARS_INPUT);
+ if (count > 0)
+ log_debug("%i character(s) replaced" , count);
+ l = strpcpy(&s, l, vbuf);
+ break;
+ }
+ case SUBST_PARENT: {
+ struct udev_device *dev_parent;
+ const char *devnode;
+
+ dev_parent = udev_device_get_parent(event->dev);
+ if (dev_parent == NULL)
+ break;
+ devnode = udev_device_get_devnode(dev_parent);
+ if (devnode != NULL)
+ l = strpcpy(&s, l, devnode + strlen("/dev/"));
+ break;
+ }
+ case SUBST_DEVNODE:
+ if (udev_device_get_devnode(dev) != NULL)
+ l = strpcpy(&s, l, udev_device_get_devnode(dev));
+ break;
+ case SUBST_NAME:
+ if (event->name != NULL)
+ l = strpcpy(&s, l, event->name);
+ else if (udev_device_get_devnode(dev) != NULL)
+ l = strpcpy(&s, l, udev_device_get_devnode(dev) + strlen("/dev/"));
+ else
+ l = strpcpy(&s, l, udev_device_get_sysname(dev));
+ break;
+ case SUBST_LINKS: {
+ struct udev_list_entry *list_entry;
+
+ list_entry = udev_device_get_devlinks_list_entry(dev);
+ if (list_entry == NULL)
+ break;
+ l = strpcpy(&s, l, udev_list_entry_get_name(list_entry) + strlen("/dev/"));
+ udev_list_entry_foreach(list_entry, udev_list_entry_get_next(list_entry))
+ l = strpcpyl(&s, l, " ", udev_list_entry_get_name(list_entry) + strlen("/dev/"), NULL);
+ break;
+ }
+ case SUBST_ROOT:
+ l = strpcpy(&s, l, "/dev");
+ break;
+ case SUBST_SYS:
+ l = strpcpy(&s, l, "/sys");
+ break;
+ case SUBST_ENV:
+ if (attr == NULL) {
+ break;
+ } else {
+ const char *value;
+
+ value = udev_device_get_property_value(event->dev, attr);
+ if (value == NULL)
+ break;
+ l = strpcpy(&s, l, value);
+ break;
+ }
+ default:
+ log_error("unknown substitution type=%i", type);
+ break;
+ }
+
+ return s - dest;
+}
+
size_t udev_event_apply_format(struct udev_event *event,
const char *src, char *dest, size_t size,
bool replace_whitespace) {
struct udev_device *dev = event->dev;
- enum subst_type {
- SUBST_UNKNOWN,
- SUBST_DEVNODE,
- SUBST_ATTR,
- SUBST_ENV,
- SUBST_KERNEL,
- SUBST_KERNEL_NUMBER,
- SUBST_DRIVER,
- SUBST_DEVPATH,
- SUBST_ID,
- SUBST_MAJOR,
- SUBST_MINOR,
- SUBST_RESULT,
- SUBST_PARENT,
- SUBST_NAME,
- SUBST_LINKS,
- SUBST_ROOT,
- SUBST_SYS,
- };
static const struct subst_map {
const char *name;
const char fmt;
@@ -132,10 +322,9 @@ size_t udev_event_apply_format(struct udev_event *event,
for (;;) {
enum subst_type type = SUBST_UNKNOWN;
- char attrbuf[UTIL_PATH_SIZE], sbuf[UTIL_PATH_SIZE];
- char *attr = NULL, *_s;
- size_t _l;
- bool replws = replace_whitespace;
+ char attrbuf[UTIL_PATH_SIZE];
+ char *attr = NULL;
+ size_t subst_len;
while (from[0] != '\0') {
if (from[0] == '$') {
@@ -204,213 +393,17 @@ subst:
attr = NULL;
}
- /* result subst handles space as field separator */
- if (type == SUBST_RESULT)
- replws = false;
-
- if (replws) {
- /* store dest string ptr and remaining len */
- _s = s;
- _l = l;
- /* temporarily use sbuf */
- s = sbuf;
- l = UTIL_PATH_SIZE;
- }
-
- switch (type) {
- case SUBST_DEVPATH:
- l = strpcpy(&s, l, udev_device_get_devpath(dev));
- break;
- case SUBST_KERNEL:
- l = strpcpy(&s, l, udev_device_get_sysname(dev));
- break;
- case SUBST_KERNEL_NUMBER:
- if (udev_device_get_sysnum(dev) == NULL)
- break;
- l = strpcpy(&s, l, udev_device_get_sysnum(dev));
- break;
- case SUBST_ID:
- if (event->dev_parent == NULL)
- break;
- l = strpcpy(&s, l, udev_device_get_sysname(event->dev_parent));
- break;
- case SUBST_DRIVER: {
- const char *driver;
-
- if (event->dev_parent == NULL)
- break;
-
- driver = udev_device_get_driver(event->dev_parent);
- if (driver == NULL)
- break;
- l = strpcpy(&s, l, driver);
- break;
- }
- case SUBST_MAJOR: {
- char num[UTIL_PATH_SIZE];
-
- sprintf(num, "%u", major(udev_device_get_devnum(dev)));
- l = strpcpy(&s, l, num);
- break;
- }
- case SUBST_MINOR: {
- char num[UTIL_PATH_SIZE];
-
- sprintf(num, "%u", minor(udev_device_get_devnum(dev)));
- l = strpcpy(&s, l, num);
- break;
- }
- case SUBST_RESULT: {
- char *rest;
- int i;
-
- if (event->program_result == NULL)
- break;
- /* get part of the result string */
- i = 0;
- if (attr != NULL)
- i = strtoul(attr, &rest, 10);
- if (i > 0) {
- char result[UTIL_PATH_SIZE];
- char tmp[UTIL_PATH_SIZE];
- char *cpos;
-
- strscpy(result, sizeof(result), event->program_result);
- cpos = result;
- while (--i) {
- while (cpos[0] != '\0' && !isspace(cpos[0]))
- cpos++;
- while (isspace(cpos[0]))
- cpos++;
- if (cpos[0] == '\0')
- break;
- }
- if (i > 0) {
- log_error("requested part of result string not found");
- break;
- }
- strscpy(tmp, sizeof(tmp), cpos);
- /* %{2+}c copies the whole string from the second part on */
- if (rest[0] != '+') {
- cpos = strchr(tmp, ' ');
- if (cpos)
- cpos[0] = '\0';
- }
- l = strpcpy(&s, l, tmp);
- } else {
- l = strpcpy(&s, l, event->program_result);
- }
- break;
- }
- case SUBST_ATTR: {
- const char *value = NULL;
- char vbuf[UTIL_NAME_SIZE];
- size_t len;
- int count;
-
- if (attr == NULL) {
- log_error("missing file parameter for attr");
- break;
- }
-
- /* try to read the value specified by "[dmi/id]product_name" */
- if (util_resolve_subsys_kernel(event->udev, attr, vbuf, sizeof(vbuf), 1) == 0)
- value = vbuf;
-
- /* try to read the attribute the device */
- if (value == NULL)
- value = udev_device_get_sysattr_value(event->dev, attr);
-
- /* try to read the attribute of the parent device, other matches have selected */
- if (value == NULL && event->dev_parent != NULL && event->dev_parent != event->dev)
- value = udev_device_get_sysattr_value(event->dev_parent, attr);
-
- if (value == NULL)
- break;
+ subst_len = subst_format_var(event, dev, type, attr, s, l);
- /* strip trailing whitespace, and replace unwanted characters */
- if (value != vbuf)
- strscpy(vbuf, sizeof(vbuf), value);
- len = strlen(vbuf);
- while (len > 0 && isspace(vbuf[--len]))
- vbuf[len] = '\0';
- count = util_replace_chars(vbuf, UDEV_ALLOWED_CHARS_INPUT);
- if (count > 0)
- log_debug("%i character(s) replaced" , count);
- l = strpcpy(&s, l, vbuf);
- break;
- }
- case SUBST_PARENT: {
- struct udev_device *dev_parent;
- const char *devnode;
-
- dev_parent = udev_device_get_parent(event->dev);
- if (dev_parent == NULL)
- break;
- devnode = udev_device_get_devnode(dev_parent);
- if (devnode != NULL)
- l = strpcpy(&s, l, devnode + strlen("/dev/"));
- break;
- }
- case SUBST_DEVNODE:
- if (udev_device_get_devnode(dev) != NULL)
- l = strpcpy(&s, l, udev_device_get_devnode(dev));
- break;
- case SUBST_NAME:
- if (event->name != NULL)
- l = strpcpy(&s, l, event->name);
- else if (udev_device_get_devnode(dev) != NULL)
- l = strpcpy(&s, l, udev_device_get_devnode(dev) + strlen("/dev/"));
- else
- l = strpcpy(&s, l, udev_device_get_sysname(dev));
- break;
- case SUBST_LINKS: {
- struct udev_list_entry *list_entry;
+ /* SUBST_RESULT handles spaces itself */
+ if (replace_whitespace && type != SUBST_RESULT)
+ /* util_replace_whitespace can replace in-place,
+ * and does nothing if subst_len == 0
+ */
+ subst_len = util_replace_whitespace(s, s, subst_len);
- list_entry = udev_device_get_devlinks_list_entry(dev);
- if (list_entry == NULL)
- break;
- l = strpcpy(&s, l, udev_list_entry_get_name(list_entry) + strlen("/dev/"));
- udev_list_entry_foreach(list_entry, udev_list_entry_get_next(list_entry))
- l = strpcpyl(&s, l, " ", udev_list_entry_get_name(list_entry) + strlen("/dev/"), NULL);
- break;
- }
- case SUBST_ROOT:
- l = strpcpy(&s, l, "/dev");
- break;
- case SUBST_SYS:
- l = strpcpy(&s, l, "/sys");
- break;
- case SUBST_ENV:
- if (attr == NULL) {
- break;
- } else {
- const char *value;
-
- value = udev_device_get_property_value(event->dev, attr);
- if (value == NULL)
- break;
- l = strpcpy(&s, l, value);
- break;
- }
- default:
- log_error("unknown substitution type=%i", type);
- break;
- }
-
- /* replace whitespace in sbuf and copy to dest */
- if (replws) {
- size_t tmplen = UTIL_PATH_SIZE - l;
-
- /* restore s and l to dest string values */
- s = _s;
- l = _l;
-
- /* copy ws-replaced value to s */
- tmplen = util_replace_whitespace(sbuf, s, MIN(tmplen, l));
- l -= tmplen;
- s += tmplen;
- }
+ s += subst_len;
+ l -= subst_len;
}
out:
diff --git a/src/veritysetup/veritysetup-generator.c b/src/veritysetup/veritysetup-generator.c
index 519ac050f9..0bb0bd6e8f 100644
--- a/src/veritysetup/veritysetup-generator.c
+++ b/src/veritysetup/veritysetup-generator.c
@@ -76,10 +76,10 @@ static int create_device(void) {
r = unit_name_from_path(u, ".device", &d);
if (r < 0)
- return log_error_errno(r, "Failed to to generate unit name: %m");
+ return log_error_errno(r, "Failed to generate unit name: %m");
r = unit_name_from_path(v, ".device", &e);
if (r < 0)
- return log_error_errno(r, "Failed to to generate unit name: %m");
+ return log_error_errno(r, "Failed to generate unit name: %m");
f = fopen(p, "wxe");
if (!f)
diff --git a/test/udev-test.pl b/test/udev-test.pl
index 9723386b23..7e33479004 100755
--- a/test/udev-test.pl
+++ b/test/udev-test.pl
@@ -741,6 +741,86 @@ KERNEL=="ttyACM[0-9]*", SYMLINK=" one two "
EOF
},
{
+ desc => "symlink with spaces in substituted variable",
+ devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
+ exp_name => "name-one_two_three-end",
+ not_exp_name => " ",
+ rules => <<EOF
+ENV{WITH_WS}="one two three"
+SYMLINK="name-\$env{WITH_WS}-end"
+EOF
+ },
+ {
+ desc => "symlink with leading space in substituted variable",
+ devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
+ exp_name => "name-one_two_three-end",
+ not_exp_name => " ",
+ rules => <<EOF
+ENV{WITH_WS}=" one two three"
+SYMLINK="name-\$env{WITH_WS}-end"
+EOF
+ },
+ {
+ desc => "symlink with trailing space in substituted variable",
+ devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
+ exp_name => "name-one_two_three-end",
+ not_exp_name => " ",
+ rules => <<EOF
+ENV{WITH_WS}="one two three "
+SYMLINK="name-\$env{WITH_WS}-end"
+EOF
+ },
+ {
+ desc => "symlink with lots of space in substituted variable",
+ devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
+ exp_name => "name-one_two_three-end",
+ not_exp_name => " ",
+ rules => <<EOF
+ENV{WITH_WS}=" one two three "
+SYMLINK="name-\$env{WITH_WS}-end"
+EOF
+ },
+ {
+ desc => "symlink with multiple spaces in substituted variable",
+ devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
+ exp_name => "name-one_two_three-end",
+ not_exp_name => " ",
+ rules => <<EOF
+ENV{WITH_WS}=" one two three "
+SYMLINK="name-\$env{WITH_WS}-end"
+EOF
+ },
+ {
+ desc => "symlink with space and var with space, part 1",
+ devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
+ exp_name => "first",
+ not_exp_name => " ",
+ rules => <<EOF
+ENV{WITH_WS}=" one two three "
+SYMLINK=" first name-\$env{WITH_WS}-end another_symlink a b c "
+EOF
+ },
+ {
+ desc => "symlink with space and var with space, part 2",
+ devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
+ exp_name => "name-one_two_three-end",
+ not_exp_name => " ",
+ rules => <<EOF
+ENV{WITH_WS}=" one two three "
+SYMLINK=" first name-\$env{WITH_WS}-end another_symlink a b c "
+EOF
+ },
+ {
+ desc => "symlink with space and var with space, part 3",
+ devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
+ exp_name => "another_symlink",
+ not_exp_name => " ",
+ rules => <<EOF
+ENV{WITH_WS}=" one two three "
+SYMLINK=" first name-\$env{WITH_WS}-end another_symlink a b c "
+EOF
+ },
+ {
desc => "symlink creation (same directory)",
devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
exp_name => "modem0",
diff --git a/units/initrd-switch-root.service.in b/units/initrd-switch-root.service.in
index 219748d19b..d31497f5e3 100644
--- a/units/initrd-switch-root.service.in
+++ b/units/initrd-switch-root.service.in
@@ -16,4 +16,3 @@ AllowIsolate=yes
[Service]
Type=oneshot
ExecStart=@rootbindir@/systemctl --no-block switch-root /sysroot
-KillMode=none
diff --git a/units/systemd-vconsole-setup.service.in b/units/systemd-vconsole-setup.service.in
index 2bd1fd1a5d..8bb75c6a4f 100644
--- a/units/systemd-vconsole-setup.service.in
+++ b/units/systemd-vconsole-setup.service.in
@@ -9,6 +9,7 @@
Description=Setup Virtual Console
Documentation=man:systemd-vconsole-setup.service(8) man:vconsole.conf(5)
DefaultDependencies=no
+Before=initrd-switch-root.target shutdown.target
ConditionPathExists=/dev/tty0
[Service]