Merge pull request #30016 from dtardon/udevadm-control-p-test

Add test for udevadm control -p
This commit is contained in:
Luca Boccassi
2023-11-13 19:29:53 +00:00
committed by GitHub
7 changed files with 152 additions and 27 deletions
+27
View File
@@ -410,3 +410,30 @@ int device_get_model_string(sd_device *device, const char **ret) {
return -ENOENT;
}
int device_get_property_value_with_fallback(
sd_device *device,
const char *prop,
Hashmap *extra_props,
const char **ret) {
const char *value;
int r;
assert(device);
assert(prop);
assert(ret);
r = sd_device_get_property_value(device, prop, &value);
if (r < 0) {
if (r != -ENOENT)
return r;
value = hashmap_get(extra_props, prop);
if (!value)
return -ENOENT;
}
*ret = value;
return 1;
}
+7
View File
@@ -3,6 +3,7 @@
#include "sd-device.h"
#include "hashmap.h"
#include "time-util.h"
int udev_set_max_log_level(char *str);
@@ -25,3 +26,9 @@ bool udev_available(void);
int device_get_vendor_string(sd_device *device, const char **ret);
int device_get_model_string(sd_device *device, const char **ret);
int device_get_property_value_with_fallback(
sd_device *device,
const char *prop,
Hashmap *extra_props,
const char **ret);
+4 -2
View File
@@ -156,6 +156,7 @@ static ssize_t udev_event_subst_format(
const char *attr,
char *dest,
size_t l,
Hashmap *global_props,
bool *ret_truncated) {
sd_device *parent, *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
@@ -348,7 +349,7 @@ static ssize_t udev_event_subst_format(
case FORMAT_SUBST_ENV:
if (isempty(attr))
return -EINVAL;
r = sd_device_get_property_value(dev, attr, &val);
r = device_get_property_value_with_fallback(dev, attr, global_props, &val);
if (r == -ENOENT)
goto null_terminate;
if (r < 0)
@@ -378,6 +379,7 @@ size_t udev_event_apply_format(
char *dest,
size_t size,
bool replace_whitespace,
Hashmap *global_props,
bool *ret_truncated) {
bool truncated = false;
@@ -410,7 +412,7 @@ size_t udev_event_apply_format(
continue;
}
subst_len = udev_event_subst_format(event, type, attr, dest, size, &t);
subst_len = udev_event_subst_format(event, type, attr, dest, size, global_props, &t);
if (subst_len < 0) {
log_device_warning_errno(event->dev, subst_len,
"Failed to substitute variable '$%s' or apply format '%%%c', ignoring: %m",
+1
View File
@@ -14,6 +14,7 @@ size_t udev_event_apply_format(
char *dest,
size_t size,
bool replace_whitespace,
Hashmap *global_props,
bool *ret_truncated);
int udev_check_format(const char *value, size_t *offset, const char **hint);
+23 -24
View File
@@ -1761,7 +1761,7 @@ static bool token_match_attr(UdevRuleToken *token, sd_device *dev, UdevEvent *ev
switch (token->attr_subst_type) {
case SUBST_TYPE_FORMAT:
(void) udev_event_apply_format(event, name, nbuf, sizeof(nbuf), false, &truncated);
(void) udev_event_apply_format(event, name, nbuf, sizeof(nbuf), false, NULL, &truncated);
if (truncated) {
log_event_truncated(dev, token, "sysfs attribute name", name,
token->type == TK_M_ATTR ? "ATTR" : "ATTRS", /* is_match = */ true);
@@ -1981,10 +1981,9 @@ static int udev_rule_apply_token_to_event(
case TK_M_NAME:
return token_match_string(token, event->name);
case TK_M_ENV: {
const char *val;
const char *val = NULL;
if (sd_device_get_property_value(dev, token->data, &val) < 0)
val = hashmap_get(properties_list, token->data);
(void) device_get_property_value_with_fallback(dev, token->data, properties_list, &val);
return token_match_string(token, val);
}
@@ -2039,7 +2038,7 @@ static int udev_rule_apply_token_to_event(
char buf[UDEV_PATH_SIZE];
bool truncated;
(void) udev_event_apply_format(event, token->data, buf, sizeof(buf), false, &truncated);
(void) udev_event_apply_format(event, token->data, buf, sizeof(buf), false, properties_list, &truncated);
if (truncated) {
log_event_truncated(dev, token, "sysctl entry name", token->data, "SYSCTL", /* is_match = */ true);
return false;
@@ -2057,7 +2056,7 @@ static int udev_rule_apply_token_to_event(
struct stat statbuf;
bool match, truncated;
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated);
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, properties_list, &truncated);
if (truncated) {
log_event_truncated(dev, token, "file name", token->value, "TEST", /* is_match = */ true);
return false;
@@ -2100,7 +2099,7 @@ static int udev_rule_apply_token_to_event(
size_t count;
event->program_result = mfree(event->program_result);
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated);
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, properties_list, &truncated);
if (truncated) {
log_event_truncated(dev, token, "command", token->value, "PROGRAM", /* is_match = */ true);
return false;
@@ -2132,7 +2131,7 @@ static int udev_rule_apply_token_to_event(
char buf[UDEV_PATH_SIZE];
bool truncated;
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated);
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, properties_list, &truncated);
if (truncated) {
log_event_truncated(dev, token, "file name to be imported", token->value, "IMPORT", /* is_match = */ true);
return false;
@@ -2183,7 +2182,7 @@ static int udev_rule_apply_token_to_event(
char buf[UDEV_LINE_SIZE], result[UDEV_LINE_SIZE];
bool truncated;
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated);
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, properties_list, &truncated);
if (truncated) {
log_event_truncated(dev, token, "command", token->value, "IMPORT", /* is_match = */ true);
return false;
@@ -2262,7 +2261,7 @@ static int udev_rule_apply_token_to_event(
event->builtin_run |= mask;
}
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated);
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, properties_list, &truncated);
if (truncated) {
log_event_truncated(dev, token, "builtin command", token->value, "IMPORT", /* is_match = */ true);
return false;
@@ -2318,7 +2317,7 @@ static int udev_rule_apply_token_to_event(
char buf[UDEV_PATH_SIZE];
bool truncated;
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated);
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, properties_list, &truncated);
if (truncated) {
log_event_truncated(dev, token, "property name", token->value, "IMPORT", /* is_match = */ true);
return false;
@@ -2379,7 +2378,7 @@ static int udev_rule_apply_token_to_event(
if (token->op == OP_ASSIGN_FINAL)
event->owner_final = true;
(void) udev_event_apply_format(event, token->value, owner, sizeof(owner), false, &truncated);
(void) udev_event_apply_format(event, token->value, owner, sizeof(owner), false, properties_list, &truncated);
if (truncated) {
log_event_truncated(dev, token, "user name", token->value, "OWNER", /* is_match = */ false);
break;
@@ -2402,7 +2401,7 @@ static int udev_rule_apply_token_to_event(
if (token->op == OP_ASSIGN_FINAL)
event->group_final = true;
(void) udev_event_apply_format(event, token->value, group, sizeof(group), false, &truncated);
(void) udev_event_apply_format(event, token->value, group, sizeof(group), false, properties_list, &truncated);
if (truncated) {
log_event_truncated(dev, token, "group name", token->value, "GROUP", /* is_match = */ false);
break;
@@ -2424,7 +2423,7 @@ static int udev_rule_apply_token_to_event(
if (token->op == OP_ASSIGN_FINAL)
event->mode_final = true;
(void) udev_event_apply_format(event, token->value, mode_str, sizeof(mode_str), false, &truncated);
(void) udev_event_apply_format(event, token->value, mode_str, sizeof(mode_str), false, properties_list, &truncated);
if (truncated) {
log_event_truncated(dev, token, "mode", token->value, "MODE", /* is_match = */ false);
break;
@@ -2476,7 +2475,7 @@ static int udev_rule_apply_token_to_event(
if (!name)
return log_oom();
(void) udev_event_apply_format(event, token->value, label_str, sizeof(label_str), false, &truncated);
(void) udev_event_apply_format(event, token->value, label_str, sizeof(label_str), false, properties_list, &truncated);
if (truncated) {
log_event_truncated(dev, token, "security label", token->value, "SECLABEL", /* is_match = */ false);
break;
@@ -2520,7 +2519,7 @@ static int udev_rule_apply_token_to_event(
}
if (token->op == OP_ADD &&
sd_device_get_property_value(dev, name, &val) >= 0) {
device_get_property_value_with_fallback(dev, name, properties_list, &val) >= 0) {
l = strpcpyl_full(&p, l, &truncated, val, " ", NULL);
if (truncated) {
log_event_warning(dev, token,
@@ -2530,7 +2529,7 @@ static int udev_rule_apply_token_to_event(
}
}
(void) udev_event_apply_format(event, token->value, p, l, false, &truncated);
(void) udev_event_apply_format(event, token->value, p, l, false, properties_list, &truncated);
if (truncated) {
_cleanup_free_ char *key_with_name = strjoin("ENV{", name, "}");
log_event_truncated(dev, token, "property value", token->value,
@@ -2555,7 +2554,7 @@ static int udev_rule_apply_token_to_event(
char buf[UDEV_PATH_SIZE];
bool truncated;
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated);
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, properties_list, &truncated);
if (truncated) {
log_event_truncated(dev, token, "tag name", token->value, "TAG", /* is_match = */ false);
break;
@@ -2592,7 +2591,7 @@ static int udev_rule_apply_token_to_event(
break;
}
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated);
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, properties_list, &truncated);
if (truncated) {
log_event_truncated(dev, token, "network interface name", token->value, "NAME", /* is_match = */ false);
break;
@@ -2630,7 +2629,7 @@ static int udev_rule_apply_token_to_event(
device_cleanup_devlinks(dev);
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf),
/* replace_whitespace = */ event->esc != ESCAPE_NONE, &truncated);
/* replace_whitespace = */ event->esc != ESCAPE_NONE, properties_list, &truncated);
if (truncated) {
log_event_truncated(dev, token, "symbolic link path", token->value, "SYMLINK", /* is_match = */ false);
break;
@@ -2702,7 +2701,7 @@ static int udev_rule_apply_token_to_event(
log_event_error_errno(dev, token, r, "Could not find file matches '%s', ignoring: %m", buf);
break;
}
(void) udev_event_apply_format(event, token->value, value, sizeof(value), false, &truncated);
(void) udev_event_apply_format(event, token->value, value, sizeof(value), false, properties_list, &truncated);
if (truncated) {
log_event_truncated(dev, token, "attribute value", token->value, "ATTR", /* is_match = */ false);
break;
@@ -2722,13 +2721,13 @@ static int udev_rule_apply_token_to_event(
char buf[UDEV_PATH_SIZE], value[UDEV_NAME_SIZE];
bool truncated;
(void) udev_event_apply_format(event, token->data, buf, sizeof(buf), false, &truncated);
(void) udev_event_apply_format(event, token->data, buf, sizeof(buf), false, properties_list, &truncated);
if (truncated) {
log_event_truncated(dev, token, "sysctl entry name", token->data, "SYSCTL", /* is_match = */ false);
break;
}
(void) udev_event_apply_format(event, token->value, value, sizeof(value), false, &truncated);
(void) udev_event_apply_format(event, token->value, value, sizeof(value), false, properties_list, &truncated);
if (truncated) {
_cleanup_free_ char *key_with_name = strjoin("SYSCTL{", buf, "}");
log_event_truncated(dev, token, "sysctl value", token->value,
@@ -2757,7 +2756,7 @@ static int udev_rule_apply_token_to_event(
if (IN_SET(token->op, OP_ASSIGN, OP_ASSIGN_FINAL))
ordered_hashmap_clear_free_key(event->run_list);
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, &truncated);
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false, properties_list, &truncated);
if (truncated) {
log_event_truncated(dev, token, "command", token->value,
token->type == TK_A_RUN_BUILTIN ? "RUN{builtin}" : "RUN{program}",
+1 -1
View File
@@ -138,7 +138,7 @@ int test_main(int argc, char *argv[], void *userdata) {
char program[UDEV_PATH_SIZE];
bool truncated;
(void) udev_event_apply_format(event, cmd, program, sizeof(program), false, &truncated);
(void) udev_event_apply_format(event, cmd, program, sizeof(program), false, NULL, &truncated);
if (truncated)
log_warning("The command '%s' is truncated while substituting into '%s'.", program, cmd);
printf("run: '%s'\n", program);
+89
View File
@@ -0,0 +1,89 @@
#!/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
# Test for `udevadm control -p`
test_not_property() {
assert_eq "$(udevadm info --query property --property "$2" --value "$1")" ""
}
test_property() {
assert_eq "$(udevadm info --query property --property "$2" --value "$1")" "$3"
}
# shellcheck disable=SC2317
cleanup() {
set +e
udevadm control -p FOO= -p BAR=
rm -f "$rules"
}
# Set up a test device
trap cleanup EXIT
rules="/run/udev/rules.d/99-test-17.13.rules"
mkdir -p "${rules%/*}"
cat > "$rules" <<'EOF'
ENV{FOO}=="?*", ENV{PROP_FOO}="$env{FOO}"
ENV{BAR}=="?*", ENV{PROP_BAR}="$env{BAR}"
EOF
udevadm control --reload
test_not_property /dev/null PROP_FOO
test_not_property /dev/null PROP_BAR
: Setting of a property works
udevadm control --property FOO=foo
udevadm trigger --action change --settle /dev/null
test_property /dev/null PROP_FOO foo
test_not_property /dev/null PROP_BAR
: Change of a property works
udevadm control --property FOO=goo
udevadm trigger --action change --settle /dev/null
test_property /dev/null PROP_FOO goo
: Removal of a property works
udevadm control --property FOO=
udevadm trigger --action change --settle /dev/null
test_not_property /dev/null PROP_FOO
: Repeated removal of a property does nothing
udevadm control --property FOO=
udevadm trigger --action change --settle /dev/null
test_not_property /dev/null PROP_FOO
: Multiple properties can be set at once
udevadm control --property FOO=foo --property BAR=bar
udevadm trigger --action change --settle /dev/null
test_property /dev/null PROP_FOO foo
test_property /dev/null PROP_BAR bar
: Multiple setting of the same property is handled correctly
udevadm control --property FOO=foo --property FOO=42
udevadm trigger --action change --settle /dev/null
test_property /dev/null PROP_FOO 42
: Mix of settings and removals of the same property is handled correctly
udevadm control -p FOO= -p FOO=foo -p BAR=car -p BAR=
udevadm trigger --action change --settle /dev/null
test_property /dev/null PROP_FOO foo
test_not_property /dev/null PROP_BAR
exit 0