From: dongshengyuan <545258830@qq.com> Date: Fri, 31 Jul 2026 07:10:51 +0000 (+0800) Subject: udevadm: improve symlink query output X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=574eed3b0d9ca695212dbe7abdf33d8768e6f7d5;p=thirdparty%2Fsystemd.git udevadm: improve symlink query output Implement the TODO item for `udevadm info -q symlink`: keep the default space-separated output pager-free, and make `--value` print one symlink per line with an empty separator line between devices. --- diff --git a/TODO.md b/TODO.md index db817f33c36..1697add812f 100644 --- a/TODO.md +++ b/TODO.md @@ -2804,10 +2804,6 @@ SPDX-License-Identifier: LGPL-2.1-or-later - re-enable ProtectClock= once only cgroupsv2 is supported. See f562abe2963bad241d34e0b308e48cf114672c84. -- **udevadm: to make symlink querying with udevadm nicer:** - - do not enable the pager for queries like 'udevadm info -q symlink -r' - - add mode with newlines instead of spaces (for grep)? - - udevd: extend memory pressure logic: also kill any idle worker processes - unify how blockdev_get_root() and sysupdate find the default root block device diff --git a/man/udevadm.xml b/man/udevadm.xml index e13ff9842be..82f24d715a9 100644 --- a/man/udevadm.xml +++ b/man/udevadm.xml @@ -158,6 +158,9 @@ When showing device properties using the option, print only their values, and skip the property name and =. + When showing device symlinks using the option, + print one path per line instead of separating paths with spaces. An empty line is printed + after each device, including the last one. Cannot be used together with or . diff --git a/src/udev/udevadm-info.c b/src/udev/udevadm-info.c index 9defc516bd7..439cdfd7436 100644 --- a/src/udev/udevadm-info.c +++ b/src/udev/udevadm-info.c @@ -748,9 +748,15 @@ static int query_device(QueryType query, sd_device* device) { FOREACH_DEVICE_DEVLINK(device, devlink) { if (!arg_root) assert_se(devlink = path_startswith(devlink, "/dev/")); - printf("%s%s", prefix, devlink); - prefix = " "; + + if (arg_value) + printf("%s\n", devlink); + else { + printf("%s%s", prefix, devlink); + prefix = " "; + } } + puts(""); return 0; } @@ -1024,8 +1030,7 @@ static int parse_argv(int argc, char *argv[]) { } break; - OPTION_LONG("value", NULL, - "When showing properties, print only their values"): + OPTION_LONG("value", NULL, "Print only values"): arg_value = true; break; @@ -1213,7 +1218,11 @@ int verb_info_main(int argc, char *argv[], uintptr_t _data, void *userdata) { if (arg_action_type == ACTION_DEVICE_ID_FILE) return stat_device(); - pager_open(arg_pager_flags); + PagerFlags pager_flags = arg_pager_flags; + if (arg_action_type == ACTION_QUERY && arg_query == QUERY_SYMLINK && !arg_value) + pager_flags |= PAGER_DISABLE; + + pager_open(pager_flags); if (arg_action_type == ACTION_EXPORT) return export_devices(); diff --git a/test/units/TEST-17-UDEV.symlink-query.sh b/test/units/TEST-17-UDEV.symlink-query.sh new file mode 100755 index 00000000000..f3dc03aac0b --- /dev/null +++ b/test/units/TEST-17-UDEV.symlink-query.sh @@ -0,0 +1,88 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: LGPL-2.1-or-later +set -ex +set -o pipefail + +# shellcheck source=test/units/util.sh +. "$(dirname "$0")"/util.sh + +assert_array_contains() { + local needle="${1:?}" + local item + + shift + for item in "$@"; do + [[ "$item" == "$needle" ]] && return 0 + done + + echo >&2 "FAIL: '$needle' not found" + return 1 +} + +# shellcheck disable=SC2329 +cleanup() { + set +e + + rm -f "$rules" + udevadm control --reload + udevadm trigger --settle --action change /dev/null /dev/full + rm -rf /dev/test-udevadm-symlink-query +} + +rules="/run/udev/rules.d/99-test-17.symlink-query.rules" + +trap cleanup EXIT + +mkdir -p "${rules%/*}" +cat >"$rules" <<'EOF' +SUBSYSTEM=="mem", KERNEL=="null", SYMLINK+="test-udevadm-symlink-query/null-a" +SUBSYSTEM=="mem", KERNEL=="null", SYMLINK+="test-udevadm-symlink-query/null-b" +SUBSYSTEM=="mem", KERNEL=="full", SYMLINK+="test-udevadm-symlink-query/full-a" +SUBSYSTEM=="mem", KERNEL=="full", SYMLINK+="test-udevadm-symlink-query/full-b" +EOF +udevadm control --reload +udevadm trigger --settle --action change /dev/null /dev/full + +read -r -a null_links < <(udevadm info -q symlink /dev/null) +read -r -a full_links < <(udevadm info -q symlink /dev/full) + +assert_array_contains "test-udevadm-symlink-query/null-a" "${null_links[@]}" +assert_array_contains "test-udevadm-symlink-query/null-b" "${null_links[@]}" +assert_array_contains "test-udevadm-symlink-query/full-a" "${full_links[@]}" +assert_array_contains "test-udevadm-symlink-query/full-b" "${full_links[@]}" + +mapfile -t links_by_value < <(udevadm info -q symlink --value /dev/null /dev/full) +value_null_links=() +value_full_links=() +n_separators=0 + +for link in "${links_by_value[@]}"; do + if [[ -z "$link" ]]; then + n_separators=$((n_separators + 1)) + continue + fi + + case "$n_separators" in + 0) + value_null_links+=("$link") + ;; + 1) + value_full_links+=("$link") + ;; + *) + assert_not_reached + esac +done + +assert_eq "$n_separators" 2 +assert_eq "${#value_null_links[@]}" "${#null_links[@]}" +assert_eq "${#value_full_links[@]}" "${#full_links[@]}" + +for link in "${null_links[@]}"; do + assert_array_contains "$link" "${value_null_links[@]}" +done +for link in "${full_links[@]}"; do + assert_array_contains "$link" "${value_full_links[@]}" +done + +exit 0