diff --git a/man/udevadm.xml b/man/udevadm.xml
index c9a30901ed..2a9963cd14 100644
--- a/man/udevadm.xml
+++ b/man/udevadm.xml
@@ -240,7 +240,7 @@
Print major/minor numbers of the underlying device, where the file lives on.
- If this is specified, all positional arguments are ignored.
+ If this is specified, no positional arguments are accepted.
diff --git a/src/udev/test-udev-manager.c b/src/udev/test-udev-manager.c
index 7de5a37289..c2e70d3c8d 100644
--- a/src/udev/test-udev-manager.c
+++ b/src/udev/test-udev-manager.c
@@ -2,6 +2,7 @@
#include "alloc-util.h"
#include "tests.h"
+#include "udev-config.h"
#include "udev-manager.h"
TEST(devpath_conflict) {
@@ -35,4 +36,16 @@ TEST(worker_free_detaches_event) {
ASSERT_NULL(event->worker);
}
+TEST(manager_load_merges_children_max) {
+ _cleanup_(manager_freep) Manager *manager = ASSERT_PTR(manager_new());
+ char *argv[] = {
+ (char*) "systemd-udevd",
+ (char*) "--children-max=1",
+ NULL,
+ };
+
+ ASSERT_OK_POSITIVE(manager_load(manager, ELEMENTSOF(argv) - 1, argv));
+ ASSERT_EQ(manager->config.children_max, 1U);
+}
+
DEFINE_TEST_MAIN(LOG_DEBUG);
diff --git a/src/udev/udev-builtin-input_id.c b/src/udev/udev-builtin-input_id.c
index ec232f3e93..532e3ed60b 100644
--- a/src/udev/udev-builtin-input_id.c
+++ b/src/udev/udev-builtin-input_id.c
@@ -118,7 +118,7 @@ static void get_cap_mask(
val = bitmask_size / sizeof (unsigned long);
/* skip trailing zeros */
- while (bitmask[val-1] == 0 && val > 0)
+ while (val > 0 && bitmask[val-1] == 0)
--val;
/* IN_SET() cannot be used in assert_cc(). */
diff --git a/src/udev/udev-config.c b/src/udev/udev-config.c
index 27a72f2ac8..c108985c4d 100644
--- a/src/udev/udev-config.c
+++ b/src/udev/udev-config.c
@@ -281,6 +281,7 @@ static void manager_merge_config(Manager *manager) {
manager_merge_config_log_level(manager);
MERGE_NON_NEGATIVE(resolve_name_timing, RESOLVE_NAME_EARLY);
+ MERGE_NON_ZERO(children_max, 0);
MERGE_NON_ZERO(exec_delay_usec, 0);
MERGE_NON_ZERO(timeout_usec, DEFAULT_WORKER_TIMEOUT_USEC);
MERGE_NON_ZERO(timeout_signal, SIGKILL);
diff --git a/src/udev/udevadm-info.c b/src/udev/udevadm-info.c
index 78c9520017..9defc516bd 100644
--- a/src/udev/udevadm-info.c
+++ b/src/udev/udevadm-info.c
@@ -530,7 +530,7 @@ static int setup_matches(sd_device_enumerator *e) {
STRV_FOREACH(a, arg_attr_match) {
_cleanup_free_ char *k = NULL, *v = NULL;
- r = parse_key_value_argument(*a, /* require_value= */ true, &k, &v);
+ r = parse_key_value_argument(*a, /* require_value= */ false, &k, &v);
if (r < 0)
return r;
@@ -542,7 +542,7 @@ static int setup_matches(sd_device_enumerator *e) {
STRV_FOREACH(a, arg_attr_nomatch) {
_cleanup_free_ char *k = NULL, *v = NULL;
- r = parse_key_value_argument(*a, /* require_value= */ true, &k, &v);
+ r = parse_key_value_argument(*a, /* require_value= */ false, &k, &v);
if (r < 0)
return r;
@@ -1118,10 +1118,6 @@ static int parse_argv(int argc, char *argv[]) {
OPTION_LONG("attr-match", "FILE[=VALUE]",
"Query devices that match an attribute"):
- if (!strchr(opts.arg, '='))
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Expected = instead of '%s'", opts.arg);
-
r = strv_extend(&arg_attr_match, opts.arg);
if (r < 0)
return log_oom();
@@ -1129,10 +1125,6 @@ static int parse_argv(int argc, char *argv[]) {
OPTION_LONG("attr-nomatch", "FILE[=VALUE]",
"Query devices that do not match an attribute"):
- if (!strchr(opts.arg, '='))
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Expected = instead of '%s'", opts.arg);
-
r = strv_extend(&arg_attr_nomatch, opts.arg);
if (r < 0)
return log_oom();
diff --git a/src/udev/udevadm-settle.c b/src/udev/udevadm-settle.c
index 77882cc074..c23e87c9d6 100644
--- a/src/udev/udevadm-settle.c
+++ b/src/udev/udevadm-settle.c
@@ -88,6 +88,10 @@ static int parse_argv(int argc, char *argv[]) {
opts.opt->short_code);
}
+ if (option_parser_get_n_args(&opts) > 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "This subprogram takes no positional arguments.");
+
return 1;
}
diff --git a/src/udev/udevadm-trigger.c b/src/udev/udevadm-trigger.c
index e1fdf323cb..f1cdbfe105 100644
--- a/src/udev/udevadm-trigger.c
+++ b/src/udev/udevadm-trigger.c
@@ -469,7 +469,7 @@ static int parse_argv(int argc, char *argv[]) {
if (opts.arg) {
r = parse_sec(opts.arg, &arg_ping_timeout_usec);
if (r < 0)
- log_error_errno(r, "Failed to parse timeout value '%s', ignoring: %m", opts.arg);
+ return log_error_errno(r, "Failed to parse timeout value '%s': %m", opts.arg);
}
break;
diff --git a/src/udev/udevadm-wait.c b/src/udev/udevadm-wait.c
index fa12e6c98c..08c142d5eb 100644
--- a/src/udev/udevadm-wait.c
+++ b/src/udev/udevadm-wait.c
@@ -32,6 +32,7 @@ typedef enum WaitUntil {
static WaitUntil arg_wait_until = WAIT_UNTIL_INITIALIZED;
static usec_t arg_timeout_usec = USEC_INFINITY;
+static bool arg_removed = false;
static bool arg_settle = false;
static char **arg_devices = NULL;
@@ -350,7 +351,7 @@ static int parse_argv(int argc, char *argv[]) {
break;
OPTION_LONG("removed", NULL, "Wait for devices being removed"):
- arg_wait_until = WAIT_UNTIL_REMOVED;
+ arg_removed = true;
break;
OPTION_LONG("settle", NULL, "Also wait for all queued events being processed"):
@@ -358,6 +359,9 @@ static int parse_argv(int argc, char *argv[]) {
break;
}
+ if (arg_removed)
+ arg_wait_until = WAIT_UNTIL_REMOVED;
+
char **args = option_parser_get_args(&opts);
if (strv_isempty(args))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
diff --git a/test/units/TEST-17-UDEV.sanity-check.sh b/test/units/TEST-17-UDEV.sanity-check.sh
index c0bd2b1565..d283aae318 100755
--- a/test/units/TEST-17-UDEV.sanity-check.sh
+++ b/test/units/TEST-17-UDEV.sanity-check.sh
@@ -120,7 +120,9 @@ udevadm info -e --json=short | jq . >/dev/null
udevadm info -e --subsystem-match acpi >/dev/null
udevadm info -e --subsystem-nomatch acpi >/dev/null
udevadm info -e --attr-match ifindex=2 >/dev/null
+udevadm info -e --attr-match ifindex >/dev/null
udevadm info -e --attr-nomatch ifindex=2 >/dev/null
+udevadm info -e --attr-nomatch ifindex >/dev/null
udevadm info -e --property-match SUBSYSTEM=acpi >/dev/null
udevadm info -e --tag-match systemd >/dev/null
udevadm info -e --sysname-match lo >/dev/null
@@ -150,6 +152,7 @@ udevadm monitor -h
udevadm settle
udevadm settle -t 5
udevadm settle -E /sys/class/net/$netdev
+(! udevadm settle /no/such/argument)
udevadm settle -h
udevadm test /dev/null
@@ -279,6 +282,7 @@ udevadm trigger --parent-match /sys/class/net/$netdev --name-match /dev/null
udevadm trigger --initialized-match
udevadm trigger --initialized-nomatch
udevadm trigger -w
+(! udevadm trigger --dry-run --wait-daemon=bad)
udevadm trigger --uuid /sys/class/net/$netdev
udevadm settle -t 300
udevadm trigger --wait-daemon
@@ -301,6 +305,9 @@ udevadm wait -t 5 /sys/class/net/$netdev
udevadm wait --initialized true /sys/class/net/$netdev
udevadm wait --initialized false /sys/class/net/$netdev
(! udevadm wait --initialized hello /sys/class/net/$netdev)
+udevadm wait --timeout=0 --removed /dev/no-such-test-device
+udevadm wait --timeout=0 --removed --initialized=no /dev/no-such-test-device
+udevadm wait --timeout=0 --initialized=no --removed /dev/no-such-test-device
assert_rc 124 timeout 5 udevadm wait --removed /sys/class/net/$netdev
udevadm wait --settle /sys/class/net/$netdev
udevadm wait -h