udevd: convert to VERB_COMMAND and add --introspect-cli

systemd-udevd is the same binary as udevadm, so the introspection data
describes both commands, from either name. The COMMAND intentionally
owns no verbs — all of udevadm's verbs are defined in udevadm.c right
after its own COMMAND, so that they are attributed to it.

The -V/--version output (GIT_VERSION) is preserved.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2026-08-28 09:59:16 +02:00
parent b1a68327bb
commit 378e6c544b
2 changed files with 33 additions and 23 deletions
+16 -23
View File
@@ -2,14 +2,14 @@
#include <stdlib.h>
#include "sd-json.h"
#include "conf-parser.h"
#include "cpu-set-util.h"
#include "daemon-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "format-table.h"
#include "hashmap.h"
#include "help-util.h"
#include "limits-util.h"
#include "options.h"
#include "parse-util.h"
@@ -25,6 +25,7 @@
#include "udev-rules.h"
#include "udev-util.h"
#include "udev-worker.h"
#include "verbs.h"
#include "version.h"
#define WORKER_NUM_MAX UINT64_C(2048)
@@ -149,26 +150,15 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
return 0;
}
static int help(void) {
_cleanup_(table_unrefp) Table *options = NULL;
int r;
r = option_parser_get_help_table_ns("udevd", &options);
if (r < 0)
return r;
help_cmdline("[OPTIONS...]");
help_abstract("Rule-based manager for device events and files.");
help_section("Options");
r = table_print_or_warn(options);
if (r < 0)
return r;
help_man_page_reference("systemd-udevd.service", "8");
return 0;
}
/* systemd-udevd is the same binary as udevadm. This COMMAND intentionally owns no verbs: all of
* udevadm's verbs are defined in udevadm.c right after its own COMMAND, so that they are attributed
* to it. */
COMMAND(
"systemd-udevd\0",
"Rule-based manager for device events and files.",
.man_pages = "systemd-udevd.service(8)\0",
.option_namespace = "udevd",
);
static int parse_argv(int argc, char *argv[], UdevConfig *config) {
int r;
@@ -185,7 +175,7 @@ static int parse_argv(int argc, char *argv[], UdevConfig *config) {
OPTION_NAMESPACE("udevd"): {}
OPTION_COMMON_HELP:
return help();
return command_print_help_name("systemd-udevd");
OPTION('V', "version", NULL, "Show package version"):
printf("%s\n", GIT_VERSION);
@@ -234,6 +224,9 @@ static int parse_argv(int argc, char *argv[], UdevConfig *config) {
else
config->timeout_signal = r;
break;
OPTION_COMMON_INTROSPECT_CLI:
return introspect_cli(SD_JSON_FORMAT_OFF);
}
return 1;
@@ -136,6 +136,7 @@ INTROSPECTABLE=(
systemd-tpm2-clear
systemd-tpm2-setup
systemd-tty-ask-password-agent
systemd-udevd
systemd-umount
systemd-update-done
systemd-validatefs
@@ -222,6 +223,22 @@ udevadm --introspect-cli | jq -e \
udevadm lock -h | grep -E '^> udevadm .* lock .* COMMAND$'
udevadm lock -h | grep -E '^> udevadm .* lock .* --print$'
# udevadm is also systemd-udevd
udevadm --introspect-cli | jq -e \
'[.commands[].names[0]] | sort == ["systemd-udevd", "udevadm"]'
# The systemd-udevd command must own no verbs: the help-verb check in the loop above relies on
# this to never run 'systemd-udevd help', which would start the daemon.
udevadm --introspect-cli | jq -e \
'.commands[] | select(.names[0] == "systemd-udevd") | (.verbs // []) == []'
# Each subcommand's help and introspection must work
for v in cat control hwdb info lock monitor settle test test-builtin trigger verify wait; do
udevadm "$v" --help >/dev/null
udevadm "$v" --introspect-cli | jq -e \
'.mediaType == "application/vnd.io.systemd.cli-introspection-0"'
done
# systemd is optionally a multicall binary that also provides systemd-executor
if [[ "$(readlink "$(command -v systemd-executor)" 2>/dev/null)" == systemd ]]; then
systemd --introspect-cli | jq -e \