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.
This commit is contained in:
dongshengyuan
2026-08-02 19:16:19 +09:00
committed by Yu Watanabe
parent 56d2162bff
commit 574eed3b0d
4 changed files with 105 additions and 9 deletions
-4
View File
@@ -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
+3
View File
@@ -158,6 +158,9 @@
<listitem>
<para>When showing device properties using the <option>--query=property</option>
option, print only their values, and skip the property name and <literal>=</literal>.</para>
<para>When showing device symlinks using the <option>--query=symlink</option> option,
print one path per line instead of separating paths with spaces. An empty line is printed
after each device, including the last one.</para>
<para>Cannot be used together with <option>-x/--export</option> or
<option>-P/--export-prefix</option>.</para>
+14 -5
View File
@@ -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();
+88
View File
@@ -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