diff options
-rw-r--r-- | configure.ac | 18 | ||||
-rw-r--r-- | hwdb/60-sensor.hwdb | 13 | ||||
-rw-r--r-- | man/systemd-firstboot.xml | 10 | ||||
-rw-r--r-- | shell-completion/zsh/_journalctl | 4 | ||||
-rw-r--r-- | src/basic/fs-util.c | 23 | ||||
-rw-r--r-- | src/basic/khash.c | 2 | ||||
-rw-r--r-- | src/basic/socket-util.c | 2 | ||||
-rw-r--r-- | src/core/dbus-execute.c | 2 | ||||
-rw-r--r-- | src/coredump/coredump.c | 6 | ||||
-rw-r--r-- | src/hostname/hostnamed.c | 4 | ||||
-rw-r--r-- | src/journal-remote/journal-gatewayd.c | 3 | ||||
-rw-r--r-- | src/libudev/libudev-util.c | 14 | ||||
-rw-r--r-- | src/network/networkd-address.c | 4 | ||||
-rw-r--r-- | src/systemctl/systemctl.c | 21 | ||||
-rw-r--r-- | src/test/test-fs-util.c | 7 | ||||
-rw-r--r-- | src/test/test-socket-util.c | 3 | ||||
-rw-r--r-- | src/udev/udev-event.c | 449 | ||||
-rw-r--r-- | units/initrd-switch-root.service.in | 1 | ||||
-rw-r--r-- | units/systemd-vconsole-setup.service.in | 1 |
19 files changed, 318 insertions, 269 deletions
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/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/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/socket-util.c b/src/basic/socket-util.c index c882b8a12a..77f81a60ba 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -887,7 +887,7 @@ bool ifname_valid(const char *p) { if ((unsigned char) *p <= 32U) return false; - if (*p == '/') + if (*p == ':' || *p == '/') return false; numeric = numeric && (*p >= '0' && *p <= '9'); diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c index 3ae894d59c..cc10e2d8e7 100644 --- a/src/core/dbus-execute.c +++ b/src/core/dbus-execute.c @@ -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/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 b7c4257f49..9a1c5b76ca 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/network/networkd-address.c b/src/network/networkd-address.c index 2b698d9531..ffd2e18a45 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -809,8 +809,8 @@ int config_parse_label( if (r < 0) return r; - if (!ifname_valid(rvalue)) { - log_syntax(unit, LOG_ERR, filename, line, 0, "Interface label is not valid or too long, ignoring assignment: %s", rvalue); + if (strlen(rvalue) >= IFNAMSIZ) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Interface label is too long, ignoring assignment: %s", rvalue); return 0; } 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/test/test-socket-util.c b/src/test/test-socket-util.c index e1f5fd5084..d80613dc84 100644 --- a/src/test/test-socket-util.c +++ b/src/test/test-socket-util.c @@ -30,7 +30,6 @@ static void test_ifname_valid(void) { assert(ifname_valid("foo")); assert(ifname_valid("eth0")); - assert(ifname_valid("eth0:0")); assert(!ifname_valid("0")); assert(!ifname_valid("99")); @@ -45,7 +44,7 @@ static void test_ifname_valid(void) { assert(!ifname_valid(".")); assert(!ifname_valid("..")); assert(ifname_valid("foo.bar")); - assert(ifname_valid("x:y")); + assert(!ifname_valid("x:y")); assert(ifname_valid("xxxxxxxxxxxxxxx")); assert(!ifname_valid("xxxxxxxxxxxxxxxx")); 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/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] |