901 lines
45 KiB
Diff
901 lines
45 KiB
Diff
From 9a88f822a6e604434abc51b9eee4e6087a6e8483 Mon Sep 17 00:00:00 2001
|
|
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
|
Date: Wed, 15 Jan 2025 23:47:05 +0900
|
|
Subject: [PATCH] udev-rules: update log messages
|
|
|
|
This also adds trace logs about token result, and skipping assignment
|
|
caused by final value already assigned.
|
|
|
|
(cherry picked from commit 354d063fbcadb277094e47a79e7cde62ae269199)
|
|
|
|
Resolves: RHEL-75774
|
|
---
|
|
src/udev/udev-rules.c | 433 ++++++++++++++++++++++++------------------
|
|
1 file changed, 248 insertions(+), 185 deletions(-)
|
|
|
|
diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c
|
|
index 9aa98a3b3c..c5fa2c660c 100644
|
|
--- a/src/udev/udev-rules.c
|
|
+++ b/src/udev/udev-rules.c
|
|
@@ -297,6 +297,37 @@ static bool token_is_for_parents(UdevRuleToken *token) {
|
|
#define log_event_trace(event, ...) \
|
|
_log_event_trace(event, UNIQ_T(e, UNIQ), __VA_ARGS__)
|
|
|
|
+#define _log_event_result(event, token, result, result_u) \
|
|
+ ({ \
|
|
+ bool result_u = (result); \
|
|
+ \
|
|
+ log_event_trace(event, token, "%s", \
|
|
+ result_u ? "PASS" : "FAIL"); \
|
|
+ result_u; \
|
|
+ })
|
|
+
|
|
+#define log_event_result(event, token, result) \
|
|
+ _log_event_result(event, token, result, UNIQ_T(r, UNIQ))
|
|
+
|
|
+#define log_event_done(event, token) \
|
|
+ ({ \
|
|
+ log_event_trace(event, token, "DONE"); \
|
|
+ true; \
|
|
+ })
|
|
+
|
|
+#define _log_event_final_set(event, token, token_u) \
|
|
+ ({ \
|
|
+ UdevRuleToken *token_u = ASSERT_PTR(token); \
|
|
+ \
|
|
+ log_event_trace(event, token_u, \
|
|
+ "Already assigned final value, ignoring further %s.", \
|
|
+ token_u->op == OP_REMOVE ? "modification" : "assignment"); \
|
|
+ true; \
|
|
+ })
|
|
+
|
|
+#define log_event_final_set(event, token) \
|
|
+ _log_event_final_set(event, token, UNIQ_T(t, UNIQ))
|
|
+
|
|
#define _log_event_truncated(event, token, token_u, what, format) \
|
|
({ \
|
|
UdevRuleToken *token_u = ASSERT_PTR(token); \
|
|
@@ -358,16 +389,6 @@ static bool token_is_for_parents(UdevRuleToken *token) {
|
|
"Invalid value \"%s\" for %s (char %zu: %s), ignoring.", \
|
|
value, key, offset, hint)
|
|
|
|
-static void log_unknown_owner(sd_device *dev, UdevRuleLine *line, int error, const char *entity, const char *name) {
|
|
- assert(line);
|
|
- ASSERT_NON_ZERO(error);
|
|
-
|
|
- if (IN_SET(abs(error), ENOENT, ESRCH))
|
|
- log_udev_rule_line_full(dev, line, LOG_ERR, error, "Unknown %s '%s', ignoring.", entity, name);
|
|
- else
|
|
- log_udev_rule_line_full(dev, line, LOG_ERR, error, "Failed to resolve %s '%s', ignoring: %m", entity, name);
|
|
-}
|
|
-
|
|
/*** Other functions ***/
|
|
|
|
static UdevRuleToken* udev_rule_token_free(UdevRuleToken *token) {
|
|
@@ -452,7 +473,11 @@ static int rule_resolve_user(UdevRuleLine *rule_line, const char *name, uid_t *r
|
|
|
|
r = get_user_creds(&name, &uid, NULL, NULL, NULL, USER_CREDS_ALLOW_MISSING);
|
|
if (r < 0) {
|
|
- log_unknown_owner(NULL, rule_line, r, "user", name);
|
|
+ if (IN_SET(r, -ENOENT, -ESRCH))
|
|
+ log_line_error_errno(rule_line, r, "Unknown user '%s', ignoring.", name);
|
|
+ else
|
|
+ log_line_error_errno(rule_line, r, "Failed to resolve user '%s', ignoring: %m", name);
|
|
+
|
|
*ret = UID_INVALID;
|
|
return 0;
|
|
}
|
|
@@ -488,7 +513,11 @@ static int rule_resolve_group(UdevRuleLine *rule_line, const char *name, gid_t *
|
|
|
|
r = get_group_creds(&name, &gid, USER_CREDS_ALLOW_MISSING);
|
|
if (r < 0) {
|
|
- log_unknown_owner(NULL, rule_line, r, "group", name);
|
|
+ if (IN_SET(r, -ENOENT, -ESRCH))
|
|
+ log_line_error_errno(rule_line, r, "Unknown group '%s', ignoring.", name);
|
|
+ else
|
|
+ log_line_error_errno(rule_line, r, "Failed to resolve group '%s', ignoring: %m", name);
|
|
+
|
|
*ret = GID_INVALID;
|
|
return 0;
|
|
}
|
|
@@ -2011,30 +2040,6 @@ static int get_property_from_string(char *line, char **ret_key, char **ret_value
|
|
return 1;
|
|
}
|
|
|
|
-static int import_parent_into_properties(sd_device *dev, const char *filter) {
|
|
- sd_device *parent;
|
|
- int r;
|
|
-
|
|
- assert(dev);
|
|
- assert(filter);
|
|
-
|
|
- r = sd_device_get_parent(dev, &parent);
|
|
- if (r == -ENOENT)
|
|
- return 0;
|
|
- if (r < 0)
|
|
- return r;
|
|
-
|
|
- FOREACH_DEVICE_PROPERTY(parent, key, val) {
|
|
- if (fnmatch(filter, key, 0) != 0)
|
|
- continue;
|
|
- r = device_add_property(dev, key, val);
|
|
- if (r < 0)
|
|
- return r;
|
|
- }
|
|
-
|
|
- return 1;
|
|
-}
|
|
-
|
|
static int attr_subst_subdir(char attr[static UDEV_PATH_SIZE]) {
|
|
_cleanup_closedir_ DIR *dir = NULL;
|
|
char buf[UDEV_PATH_SIZE], *p;
|
|
@@ -2172,8 +2177,8 @@ static int udev_rule_apply_token_to_event(
|
|
case TK_M_DEVLINK:
|
|
FOREACH_DEVICE_DEVLINK(dev, val)
|
|
if (token_match_string(event, token, strempty(startswith(val, "/dev/")), /* log_result = */ false) == (token->op == OP_MATCH))
|
|
- return token->op == OP_MATCH;
|
|
- return token->op == OP_NOMATCH;
|
|
+ return log_event_result(event, token, token->op == OP_MATCH);
|
|
+ return log_event_result(event, token, token->op == OP_NOMATCH);
|
|
|
|
case TK_M_NAME:
|
|
return token_match_string(event, token, event->name, /* log_result = */ true);
|
|
@@ -2202,8 +2207,8 @@ static int udev_rule_apply_token_to_event(
|
|
case TK_M_PARENTS_TAG:
|
|
FOREACH_DEVICE_CURRENT_TAG(dev, val)
|
|
if (token_match_string(event, token, val, /* log_result = */ false) == (token->op == OP_MATCH))
|
|
- return token->op == OP_MATCH;
|
|
- return token->op == OP_NOMATCH;
|
|
+ return log_event_result(event, token, token->op == OP_MATCH);
|
|
+ return log_event_result(event, token, token->op == OP_NOMATCH);
|
|
|
|
case TK_M_SUBSYSTEM:
|
|
case TK_M_PARENTS_SUBSYSTEM: {
|
|
@@ -2242,7 +2247,7 @@ static int udev_rule_apply_token_to_event(
|
|
|
|
r = sysctl_read(sysctl_normalize(buf), &value);
|
|
if (r < 0 && r != -ENOENT)
|
|
- return log_event_error_errno(event, token, r, "Failed to read sysctl '%s': %m", buf);
|
|
+ return log_event_error_errno(event, token, r, "Failed to read sysctl \"%s\": %m", buf);
|
|
|
|
return token_match_string(event, token, strstrip(value), /* log_result = */ true);
|
|
}
|
|
@@ -2269,23 +2274,26 @@ static int udev_rule_apply_token_to_event(
|
|
assert(!truncated);
|
|
strscpyl_full(buf, sizeof(buf), &truncated, val, "/", tmp, NULL);
|
|
if (truncated)
|
|
- return false;
|
|
+ return log_event_result(event, token, false);
|
|
}
|
|
|
|
r = attr_subst_subdir(buf);
|
|
if (r == -ENOENT)
|
|
- return token->op == OP_NOMATCH;
|
|
+ return log_event_result(event, token, token->op == OP_NOMATCH);
|
|
if (r < 0)
|
|
- return log_event_error_errno(event, token, r, "Failed to test for the existence of '%s': %m", buf);
|
|
+ return log_event_error_errno(event, token, r, "Failed to test for the existence of \"%s\": %m", buf);
|
|
|
|
- if (stat(buf, &statbuf) < 0)
|
|
- return token->op == OP_NOMATCH;
|
|
+ if (stat(buf, &statbuf) < 0) {
|
|
+ if (errno != ENOENT)
|
|
+ log_event_warning_errno(event, token, errno, "Failed to stat \"%s\", ignoring: %m", buf);
|
|
+ return log_event_result(event, token, token->op == OP_NOMATCH);
|
|
+ }
|
|
|
|
if (mode == MODE_INVALID)
|
|
- return token->op == OP_MATCH;
|
|
+ return log_event_result(event, token, token->op == OP_MATCH);
|
|
|
|
match = (statbuf.st_mode & mode) > 0;
|
|
- return token->op == (match ? OP_MATCH : OP_NOMATCH);
|
|
+ return log_event_result(event, token, token->op == (match ? OP_MATCH : OP_NOMATCH));
|
|
}
|
|
case TK_M_PROGRAM: {
|
|
char buf[UDEV_LINE_SIZE], result[UDEV_LINE_SIZE];
|
|
@@ -2295,7 +2303,7 @@ static int udev_rule_apply_token_to_event(
|
|
if (!apply_format_value(event, token, buf, sizeof(buf), "command"))
|
|
return false;
|
|
|
|
- log_event_debug(event, token, "Running PROGRAM=\"%s\"", buf);
|
|
+ log_event_debug(event, token, "Running command \"%s\"", buf);
|
|
|
|
r = udev_event_spawn(event, /* accept_failure = */ true, buf, result, sizeof(result), NULL);
|
|
if (r != 0) {
|
|
@@ -2303,14 +2311,14 @@ static int udev_rule_apply_token_to_event(
|
|
log_event_warning_errno(event, token, r, "Failed to execute \"%s\": %m", buf);
|
|
else /* returned value is positive when program fails */
|
|
log_event_debug(event, token, "Command \"%s\" returned %d (error)", buf, r);
|
|
- return token->op == OP_NOMATCH;
|
|
+ return log_event_result(event, token, token->op == OP_NOMATCH);
|
|
}
|
|
|
|
delete_trailing_chars(result, "\n");
|
|
udev_replace_chars_and_log(event, token, result, UDEV_ALLOWED_CHARS_INPUT, "command output");
|
|
|
|
event->program_result = strdup(result);
|
|
- return token->op == OP_MATCH;
|
|
+ return log_event_result(event, token, token->op == OP_MATCH);
|
|
}
|
|
case TK_M_IMPORT_FILE: {
|
|
_cleanup_fclose_ FILE *f = NULL;
|
|
@@ -2319,13 +2327,13 @@ static int udev_rule_apply_token_to_event(
|
|
if (!apply_format_value(event, token, buf, sizeof(buf), "file name to be imported"))
|
|
return false;
|
|
|
|
- log_event_debug(event, token, "Importing properties from '%s'", buf);
|
|
+ log_event_debug(event, token, "Importing properties from \"%s\"", buf);
|
|
|
|
f = fopen(buf, "re");
|
|
if (!f) {
|
|
if (errno != ENOENT)
|
|
- return log_event_error_errno(event, token, errno, "Failed to open '%s': %m", buf);
|
|
- return token->op == OP_NOMATCH;
|
|
+ return log_event_error_errno(event, token, errno, "Failed to open \"%s\": %m", buf);
|
|
+ return log_event_result(event, token, token->op == OP_NOMATCH);
|
|
}
|
|
|
|
for (;;) {
|
|
@@ -2334,16 +2342,16 @@ static int udev_rule_apply_token_to_event(
|
|
|
|
r = read_line(f, LONG_LINE_MAX, &line);
|
|
if (r < 0) {
|
|
- log_event_debug_errno(event, token, r, "Failed to read '%s', ignoring: %m", buf);
|
|
- return token->op == OP_NOMATCH;
|
|
+ log_event_debug_errno(event, token, r, "Failed to read \"%s\", ignoring: %m", buf);
|
|
+ return log_event_result(event, token, token->op == OP_NOMATCH);
|
|
}
|
|
if (r == 0)
|
|
- break;
|
|
+ return log_event_result(event, token, token->op == OP_MATCH);
|
|
|
|
r = get_property_from_string(line, &key, &value);
|
|
if (r < 0) {
|
|
log_event_debug_errno(event, token, r,
|
|
- "Failed to parse key and value from '%s', ignoring: %m",
|
|
+ "Failed to parse key and value from \"%s\", ignoring: %m",
|
|
line);
|
|
continue;
|
|
}
|
|
@@ -2355,9 +2363,10 @@ static int udev_rule_apply_token_to_event(
|
|
return log_event_error_errno(event, token, r,
|
|
"Failed to add property %s=%s: %m",
|
|
key, value);
|
|
+ log_event_trace(event, token, "Imported property \"%s=%s\".", key, value);
|
|
}
|
|
|
|
- return token->op == OP_MATCH;
|
|
+ assert_not_reached();
|
|
}
|
|
case TK_M_IMPORT_PROGRAM: {
|
|
_cleanup_strv_free_ char **lines = NULL;
|
|
@@ -2367,15 +2376,15 @@ static int udev_rule_apply_token_to_event(
|
|
if (!apply_format_value(event, token, buf, sizeof(buf), "command"))
|
|
return false;
|
|
|
|
- log_event_debug(event, token, "Importing properties from results of '%s'", buf);
|
|
+ log_event_debug(event, token, "Importing properties from results of \"%s\"", buf);
|
|
|
|
r = udev_event_spawn(event, /* accept_failure = */ true, buf, result, sizeof result, &truncated);
|
|
if (r != 0) {
|
|
if (r < 0)
|
|
- log_event_warning_errno(event, token, r, "Failed to execute '%s', ignoring: %m", buf);
|
|
+ log_event_warning_errno(event, token, r, "Failed to execute \"%s\", ignoring: %m", buf);
|
|
else /* returned value is positive when program fails */
|
|
log_event_debug(event, token, "Command \"%s\" returned %d (error), ignoring", buf, r);
|
|
- return token->op == OP_NOMATCH;
|
|
+ return log_event_result(event, token, token->op == OP_NOMATCH);
|
|
}
|
|
|
|
if (truncated) {
|
|
@@ -2399,7 +2408,7 @@ static int udev_rule_apply_token_to_event(
|
|
if (r < 0) {
|
|
log_event_warning_errno(event, token, r,
|
|
"Failed to extract lines from result of command \"%s\", ignoring: %m", buf);
|
|
- return false;
|
|
+ return log_event_result(event, token, false);
|
|
}
|
|
|
|
STRV_FOREACH(line, lines) {
|
|
@@ -2408,7 +2417,7 @@ static int udev_rule_apply_token_to_event(
|
|
r = get_property_from_string(*line, &key, &value);
|
|
if (r < 0) {
|
|
log_event_debug_errno(event, token, r,
|
|
- "Failed to parse key and value from '%s', ignoring: %m",
|
|
+ "Failed to parse key and value from \"%s\", ignoring: %m",
|
|
*line);
|
|
continue;
|
|
}
|
|
@@ -2420,9 +2429,10 @@ static int udev_rule_apply_token_to_event(
|
|
return log_event_error_errno(event, token, r,
|
|
"Failed to add property %s=%s: %m",
|
|
key, value);
|
|
+ log_event_trace(event, token, "Imported property \"%s=%s\".", key, value);
|
|
}
|
|
|
|
- return token->op == OP_MATCH;
|
|
+ return log_event_result(event, token, token->op == OP_MATCH);
|
|
}
|
|
case TK_M_IMPORT_BUILTIN: {
|
|
UdevBuiltinCommand cmd = PTR_TO_UDEV_BUILTIN_CMD(token->data);
|
|
@@ -2433,10 +2443,10 @@ static int udev_rule_apply_token_to_event(
|
|
if (udev_builtin_run_once(cmd)) {
|
|
/* check if we ran already */
|
|
if (event->builtin_run & mask) {
|
|
- log_event_debug(event, token, "Skipping builtin '%s' in IMPORT key",
|
|
+ log_event_debug(event, token, "Builtin command \"%s\" has already run, skipping.",
|
|
udev_builtin_name(cmd));
|
|
/* return the result from earlier run */
|
|
- return token->op == (event->builtin_ret & mask ? OP_NOMATCH : OP_MATCH);
|
|
+ return log_event_result(event, token, token->op == (event->builtin_ret & mask ? OP_NOMATCH : OP_MATCH));
|
|
}
|
|
/* mark as ran */
|
|
event->builtin_run |= mask;
|
|
@@ -2445,34 +2455,36 @@ static int udev_rule_apply_token_to_event(
|
|
if (!apply_format_value(event, token, buf, sizeof(buf), "builtin command"))
|
|
return false;
|
|
|
|
- log_event_debug(event, token, "Importing properties from results of builtin command '%s'", buf);
|
|
+ log_event_debug(event, token, "Importing properties from results of builtin command \"%s\".", buf);
|
|
|
|
r = udev_builtin_run(event, cmd, buf);
|
|
if (r < 0) {
|
|
/* remember failure */
|
|
- log_event_debug_errno(event, token, r, "Failed to run builtin '%s': %m", buf);
|
|
+ log_event_debug_errno(event, token, r, "Failed to run builtin \"%s\": %m", buf);
|
|
event->builtin_ret |= mask;
|
|
}
|
|
- return token->op == (r >= 0 ? OP_MATCH : OP_NOMATCH);
|
|
+ return log_event_result(event, token, token->op == (r >= 0 ? OP_MATCH : OP_NOMATCH));
|
|
}
|
|
case TK_M_IMPORT_DB: {
|
|
const char *val;
|
|
|
|
if (!event->dev_db_clone)
|
|
- return token->op == OP_NOMATCH;
|
|
+ return log_event_result(event, token, token->op == OP_NOMATCH);
|
|
r = sd_device_get_property_value(event->dev_db_clone, token->value, &val);
|
|
if (r == -ENOENT)
|
|
- return token->op == OP_NOMATCH;
|
|
+ return log_event_result(event, token, token->op == OP_NOMATCH);
|
|
if (r < 0)
|
|
return log_event_error_errno(event, token, r,
|
|
- "Failed to get property '%s' from database: %m",
|
|
+ "Failed to get property \"%s\" from database: %m",
|
|
token->value);
|
|
|
|
r = device_add_property(dev, token->value, val);
|
|
if (r < 0)
|
|
- return log_event_error_errno(event, token, r, "Failed to add property '%s=%s': %m",
|
|
+ return log_event_error_errno(event, token, r, "Failed to add property \"%s=%s\": %m",
|
|
token->value, val);
|
|
- return token->op == OP_MATCH;
|
|
+ log_event_trace(event, token, "Imported property \"%s=%s\".", token->value, val);
|
|
+
|
|
+ return log_event_result(event, token, token->op == OP_MATCH);
|
|
}
|
|
case TK_M_IMPORT_CMDLINE: {
|
|
_cleanup_free_ char *value = NULL;
|
|
@@ -2480,16 +2492,19 @@ static int udev_rule_apply_token_to_event(
|
|
r = proc_cmdline_get_key(token->value, PROC_CMDLINE_VALUE_OPTIONAL|PROC_CMDLINE_IGNORE_EFI_OPTIONS, &value);
|
|
if (r < 0)
|
|
return log_event_error_errno(event, token, r,
|
|
- "Failed to read '%s' option from /proc/cmdline: %m",
|
|
+ "Failed to read \"%s\" option from /proc/cmdline: %m",
|
|
token->value);
|
|
if (r == 0)
|
|
- return token->op == OP_NOMATCH;
|
|
+ return log_event_result(event, token, token->op == OP_NOMATCH);
|
|
|
|
- r = device_add_property(dev, token->value, value ?: "1");
|
|
+ const char *val = value ?: "1";
|
|
+ r = device_add_property(dev, token->value, val);
|
|
if (r < 0)
|
|
- return log_event_error_errno(event, token, r, "Failed to add property '%s=%s': %m",
|
|
- token->value, value ?: "1");
|
|
- return token->op == OP_MATCH;
|
|
+ return log_event_error_errno(event, token, r, "Failed to add property \"%s=%s\": %m",
|
|
+ token->value, val);
|
|
+ log_event_trace(event, token, "Imported property \"%s=%s\".", token->value, val);
|
|
+
|
|
+ return log_event_result(event, token, token->op == OP_MATCH);
|
|
}
|
|
case TK_M_IMPORT_PARENT: {
|
|
char buf[UDEV_PATH_SIZE];
|
|
@@ -2497,35 +2512,56 @@ static int udev_rule_apply_token_to_event(
|
|
if (!apply_format_value(event, token, buf, sizeof(buf), "property name"))
|
|
return false;
|
|
|
|
- r = import_parent_into_properties(dev, buf);
|
|
+ sd_device *parent;
|
|
+ r = sd_device_get_parent(dev, &parent);
|
|
+ if (ERRNO_IS_NEG_DEVICE_ABSENT(r))
|
|
+ return log_event_result(event, token, token->op == OP_NOMATCH);
|
|
if (r < 0)
|
|
- return log_event_error_errno(event, token, r,
|
|
- "Failed to import properties '%s' from parent: %m",
|
|
- buf);
|
|
- return token->op == (r > 0 ? OP_MATCH : OP_NOMATCH);
|
|
+ return log_event_error_errno(event, token, r, "Failed to get parent device: %m");
|
|
+
|
|
+ bool have = false;
|
|
+ FOREACH_DEVICE_PROPERTY(parent, key, val) {
|
|
+ if (fnmatch(buf, key, 0) != 0)
|
|
+ continue;
|
|
+
|
|
+ r = device_add_property(dev, key, val);
|
|
+ if (r < 0)
|
|
+ return log_event_error_errno(event, token, r, "Failed to add property \"%s=%s\": %m", key, val);
|
|
+ log_event_trace(event, token, "Imported property \"%s=%s\".", key, val);
|
|
+ have = true;
|
|
+ }
|
|
+
|
|
+ return log_event_result(event, token, token->op == (have ? OP_MATCH : OP_NOMATCH));
|
|
}
|
|
case TK_M_RESULT:
|
|
return token_match_string(event, token, event->program_result, /* log_result = */ true);
|
|
+
|
|
case TK_A_OPTIONS_STRING_ESCAPE_NONE:
|
|
event->esc = ESCAPE_NONE;
|
|
- break;
|
|
+ return log_event_done(event, token);
|
|
+
|
|
case TK_A_OPTIONS_STRING_ESCAPE_REPLACE:
|
|
event->esc = ESCAPE_REPLACE;
|
|
- break;
|
|
+ return log_event_done(event, token);
|
|
+
|
|
case TK_A_OPTIONS_DB_PERSIST:
|
|
device_set_db_persist(dev);
|
|
- break;
|
|
+ return log_event_done(event, token);
|
|
+
|
|
case TK_A_OPTIONS_INOTIFY_WATCH:
|
|
if (event->inotify_watch_final)
|
|
- break;
|
|
+ return log_event_final_set(event, token);
|
|
+
|
|
if (token->op == OP_ASSIGN_FINAL)
|
|
event->inotify_watch_final = true;
|
|
|
|
event->inotify_watch = token->data;
|
|
- break;
|
|
+ return log_event_done(event, token);
|
|
+
|
|
case TK_A_OPTIONS_DEVLINK_PRIORITY:
|
|
device_set_devlink_priority(dev, PTR_TO_INT(token->data));
|
|
- break;
|
|
+ return log_event_done(event, token);
|
|
+
|
|
case TK_A_OPTIONS_LOG_LEVEL: {
|
|
int level = PTR_TO_INT(token->data);
|
|
|
|
@@ -2547,14 +2583,15 @@ static int udev_rule_apply_token_to_event(
|
|
event->log_level_was_debug = true;
|
|
}
|
|
|
|
- break;
|
|
+ return log_event_done(event, token);
|
|
}
|
|
case TK_A_OWNER: {
|
|
char owner[UDEV_NAME_SIZE];
|
|
const char *ow = owner;
|
|
|
|
if (event->owner_final)
|
|
- break;
|
|
+ return log_event_final_set(event, token);
|
|
+
|
|
if (token->op == OP_ASSIGN_FINAL)
|
|
event->owner_final = true;
|
|
|
|
@@ -2562,18 +2599,21 @@ static int udev_rule_apply_token_to_event(
|
|
return true;
|
|
|
|
r = get_user_creds(&ow, &event->uid, NULL, NULL, NULL, USER_CREDS_ALLOW_MISSING);
|
|
- if (r < 0)
|
|
- log_unknown_owner(dev, token->rule_line, r, "user", owner);
|
|
+ if (IN_SET(r, -ENOENT, -ESRCH))
|
|
+ log_event_error_errno(event, token, r, "Unknown user \"%s\", ignoring.", owner);
|
|
+ else if (r < 0)
|
|
+ log_event_error_errno(event, token, r, "Failed to resolve user \"%s\", ignoring: %m", owner);
|
|
else
|
|
- log_event_debug(event, token, "OWNER %s(%u)", owner, event->uid);
|
|
- break;
|
|
+ log_event_debug(event, token, "Set owner: %s(%u)", owner, event->uid);
|
|
+ return true;
|
|
}
|
|
case TK_A_GROUP: {
|
|
char group[UDEV_NAME_SIZE];
|
|
const char *gr = group;
|
|
|
|
if (event->group_final)
|
|
- break;
|
|
+ return log_event_final_set(event, token);
|
|
+
|
|
if (token->op == OP_ASSIGN_FINAL)
|
|
event->group_final = true;
|
|
|
|
@@ -2581,17 +2621,20 @@ static int udev_rule_apply_token_to_event(
|
|
return true;
|
|
|
|
r = get_group_creds(&gr, &event->gid, USER_CREDS_ALLOW_MISSING);
|
|
- if (r < 0)
|
|
- log_unknown_owner(dev, token->rule_line, r, "group", group);
|
|
+ if (IN_SET(r, -ENOENT, -ESRCH))
|
|
+ log_event_error_errno(event, token, r, "Unknown group \"%s\", ignoring.", group);
|
|
+ else if (r < 0)
|
|
+ log_event_error_errno(event, token, r, "Failed to resolve group \"%s\", ignoring: %m", group);
|
|
else
|
|
- log_event_debug(event, token, "GROUP %s(%u)", group, event->gid);
|
|
- break;
|
|
+ log_event_debug(event, token, "Set group: %s(%u)", group, event->gid);
|
|
+ return true;
|
|
}
|
|
case TK_A_MODE: {
|
|
char mode_str[UDEV_NAME_SIZE];
|
|
|
|
if (event->mode_final)
|
|
- break;
|
|
+ return log_event_final_set(event, token);
|
|
+
|
|
if (token->op == OP_ASSIGN_FINAL)
|
|
event->mode_final = true;
|
|
|
|
@@ -2600,41 +2643,44 @@ static int udev_rule_apply_token_to_event(
|
|
|
|
r = parse_mode(mode_str, &event->mode);
|
|
if (r < 0)
|
|
- log_event_error_errno(event, token, r, "Failed to parse mode '%s', ignoring: %m", mode_str);
|
|
+ log_event_error_errno(event, token, r, "Failed to parse mode \"%s\", ignoring: %m", mode_str);
|
|
else
|
|
- log_event_debug(event, token, "MODE %#o", event->mode);
|
|
- break;
|
|
+ log_event_debug(event, token, "Set mode: %#o", event->mode);
|
|
+ return true;
|
|
}
|
|
case TK_A_OWNER_ID:
|
|
if (event->owner_final)
|
|
- break;
|
|
+ return log_event_final_set(event, token);
|
|
+
|
|
if (token->op == OP_ASSIGN_FINAL)
|
|
event->owner_final = true;
|
|
- if (!token->data)
|
|
- break;
|
|
- event->uid = PTR_TO_UID(token->data);
|
|
- log_event_debug(event, token, "OWNER %u", event->uid);
|
|
- break;
|
|
+
|
|
+ event->uid = PTR_TO_UID(ASSERT_PTR(token->data));
|
|
+ log_event_debug(event, token, "Set owner ID: %u", event->uid);
|
|
+ return true;
|
|
+
|
|
case TK_A_GROUP_ID:
|
|
if (event->group_final)
|
|
- break;
|
|
+ return log_event_final_set(event, token);
|
|
+
|
|
if (token->op == OP_ASSIGN_FINAL)
|
|
event->group_final = true;
|
|
- if (!token->data)
|
|
- break;
|
|
- event->gid = PTR_TO_GID(token->data);
|
|
- log_event_debug(event, token, "GROUP %u", event->gid);
|
|
- break;
|
|
+
|
|
+ event->gid = PTR_TO_GID(ASSERT_PTR(token->data));
|
|
+ log_event_debug(event, token, "Set group ID: %u", event->gid);
|
|
+ return true;
|
|
+
|
|
case TK_A_MODE_ID:
|
|
if (event->mode_final)
|
|
- break;
|
|
+ return log_event_final_set(event, token);
|
|
+
|
|
if (token->op == OP_ASSIGN_FINAL)
|
|
event->mode_final = true;
|
|
- if (!token->data)
|
|
- break;
|
|
- event->mode = PTR_TO_MODE(token->data);
|
|
- log_event_debug(event, token, "MODE %#o", event->mode);
|
|
- break;
|
|
+
|
|
+ event->mode = PTR_TO_MODE(ASSERT_PTR(token->data));
|
|
+ log_event_debug(event, token, "Set mode: %#o", event->mode);
|
|
+ return true;
|
|
+
|
|
case TK_A_SECLABEL: {
|
|
_cleanup_free_ char *name = NULL, *label = NULL;
|
|
char label_str[UDEV_LINE_SIZE] = {};
|
|
@@ -2660,13 +2706,13 @@ static int udev_rule_apply_token_to_event(
|
|
if (r == -ENOMEM)
|
|
return log_oom();
|
|
if (r < 0)
|
|
- return log_event_error_errno(event, token, r, "Failed to store SECLABEL{%s}='%s': %m", name, label);
|
|
+ return log_event_error_errno(event, token, r, "Failed to store security label \"%s=%s\": %m", name, label);
|
|
|
|
- log_event_debug(event, token, "SECLABEL{%s}='%s'", name, label);
|
|
+ log_event_debug(event, token, "Set security label: %s=%s", name, label);
|
|
|
|
TAKE_PTR(name);
|
|
TAKE_PTR(label);
|
|
- break;
|
|
+ return true;
|
|
}
|
|
case TK_A_ENV: {
|
|
const char *val, *name = token->data;
|
|
@@ -2675,11 +2721,13 @@ static int udev_rule_apply_token_to_event(
|
|
|
|
if (isempty(token->value)) {
|
|
if (token->op == OP_ADD)
|
|
- break;
|
|
+ return log_event_done(event, token);
|
|
+
|
|
r = device_add_property(dev, name, NULL);
|
|
if (r < 0)
|
|
- return log_event_error_errno(event, token, r, "Failed to remove property '%s': %m", name);
|
|
- break;
|
|
+ return log_event_error_errno(event, token, r, "Failed to remove property \"%s\": %m", name);
|
|
+ log_event_trace(event, token, "Removed property \"%s\".", name);
|
|
+ return true;
|
|
}
|
|
|
|
if (token->op == OP_ADD &&
|
|
@@ -2688,9 +2736,9 @@ static int udev_rule_apply_token_to_event(
|
|
l = strpcpyl_full(&p, l, &truncated, val, " ", NULL);
|
|
if (truncated) {
|
|
log_event_warning(event, token,
|
|
- "The buffer for the property '%s' is full, "
|
|
- "refusing to append the new value '%s'.", name, token->value);
|
|
- break;
|
|
+ "The buffer for the property is full, refusing to append new property \"%s=%s\".",
|
|
+ name, token->value);
|
|
+ return true;
|
|
}
|
|
}
|
|
|
|
@@ -2702,8 +2750,9 @@ static int udev_rule_apply_token_to_event(
|
|
|
|
r = device_add_property(dev, name, value_new);
|
|
if (r < 0)
|
|
- return log_event_error_errno(event, token, r, "Failed to add property '%s=%s': %m", name, value_new);
|
|
- break;
|
|
+ return log_event_error_errno(event, token, r, "Failed to set property \"%s=%s\": %m", name, value_new);
|
|
+ log_event_trace(event, token, "Set property \"%s=%s\".", name, value_new);
|
|
+ return true;
|
|
}
|
|
case TK_A_TAG: {
|
|
char buf[UDEV_PATH_SIZE];
|
|
@@ -2711,33 +2760,39 @@ static int udev_rule_apply_token_to_event(
|
|
if (!apply_format_value(event, token, buf, sizeof(buf), "tag name"))
|
|
return true;
|
|
|
|
+ if (token->op == OP_REMOVE) {
|
|
+ device_remove_tag(dev, buf);
|
|
+ log_event_trace(event, token, "Removed tag \"%s\".", buf);
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ assert(IN_SET(token->op, OP_ASSIGN, OP_ADD));
|
|
+
|
|
if (token->op == OP_ASSIGN)
|
|
device_cleanup_tags(dev);
|
|
|
|
- if (token->op == OP_REMOVE)
|
|
- device_remove_tag(dev, buf);
|
|
- else {
|
|
- r = device_add_tag(dev, buf, true);
|
|
- if (r == -ENOMEM)
|
|
- return log_oom();
|
|
- if (r < 0)
|
|
- log_event_warning_errno(event, token, r, "Failed to add tag '%s', ignoring: %m", buf);
|
|
- }
|
|
- break;
|
|
+ r = device_add_tag(dev, buf, /* both = */ true);
|
|
+ if (r == -ENOMEM)
|
|
+ return log_oom();
|
|
+ if (r < 0)
|
|
+ log_event_warning_errno(event, token, r, "Failed to %s tag \"%s\", ignoring: %m",
|
|
+ token->op == OP_ASSIGN ? "set" : "add", buf);
|
|
+ else
|
|
+ log_event_trace(event, token, "%s tag \"%s\".", token->op == OP_ASSIGN ? "Set" : "Added", buf);
|
|
+ return true;
|
|
}
|
|
case TK_A_NAME: {
|
|
char buf[UDEV_PATH_SIZE];
|
|
|
|
if (event->name_final)
|
|
- break;
|
|
+ return log_event_final_set(event, token);
|
|
+
|
|
if (token->op == OP_ASSIGN_FINAL)
|
|
event->name_final = true;
|
|
|
|
if (sd_device_get_ifindex(dev, NULL) < 0) {
|
|
- log_event_error(event, token,
|
|
- "Only network interfaces can be renamed, ignoring NAME=\"%s\".",
|
|
- token->value);
|
|
- break;
|
|
+ log_event_warning(event, token, "Only network interfaces can be renamed, ignoring.");
|
|
+ return true;
|
|
}
|
|
|
|
if (!apply_format_value(event, token, buf, sizeof(buf), "network interface name"))
|
|
@@ -2750,18 +2805,23 @@ static int udev_rule_apply_token_to_event(
|
|
if (r < 0)
|
|
return r;
|
|
|
|
- log_event_debug(event, token, "NAME '%s'", event->name);
|
|
- break;
|
|
+ log_event_debug(event, token, "Set network interface name: %s", event->name);
|
|
+ return true;
|
|
}
|
|
case TK_A_DEVLINK: {
|
|
char buf[UDEV_PATH_SIZE];
|
|
|
|
if (event->devlink_final)
|
|
- break;
|
|
- if (sd_device_get_devnum(dev, NULL) < 0)
|
|
- break;
|
|
+ return log_event_final_set(event, token);
|
|
+
|
|
+ if (sd_device_get_devnum(dev, NULL) < 0) {
|
|
+ log_event_debug(event, token, "Device does not have device node, ignoring to manage device node symlink.");
|
|
+ return true;
|
|
+ }
|
|
+
|
|
if (token->op == OP_ASSIGN_FINAL)
|
|
event->devlink_final = true;
|
|
+
|
|
if (IN_SET(token->op, OP_ASSIGN, OP_ASSIGN_FINAL))
|
|
device_cleanup_devlinks(dev);
|
|
|
|
@@ -2783,31 +2843,31 @@ static int udev_rule_apply_token_to_event(
|
|
if (r == -ENOMEM)
|
|
return log_oom();
|
|
if (r < 0) {
|
|
- log_warning_errno(r, "Failed to extract first path in SYMLINK=, ignoring: %m");
|
|
- break;
|
|
+ log_warning_errno(r, "Failed to extract first path in device node symlinks, ignoring: %m");
|
|
+ return true;
|
|
}
|
|
if (r == 0)
|
|
- break;
|
|
+ return true;
|
|
|
|
if (token->op == OP_REMOVE) {
|
|
r = device_remove_devlink(dev, path);
|
|
if (r == -ENOMEM)
|
|
return log_oom();
|
|
if (r < 0)
|
|
- log_event_warning_errno(event, token, r, "Failed to remove devlink '%s', ignoring: %m", path);
|
|
+ log_event_warning_errno(event, token, r, "Failed to remove device node symlink \"%s\", ignoring: %m", path);
|
|
else if (r > 0)
|
|
- log_event_debug(event, token, "Dropped SYMLINK '%s'", path);
|
|
+ log_event_debug(event, token, "Removed device node symlink \"%s\"", path);
|
|
} else {
|
|
r = device_add_devlink(dev, path);
|
|
if (r == -ENOMEM)
|
|
return log_oom();
|
|
if (r < 0)
|
|
- log_event_warning_errno(event, token, r, "Failed to add devlink '%s', ignoring: %m", path);
|
|
+ log_event_warning_errno(event, token, r, "Failed to add device node symlink \"%s\", ignoring: %m", path);
|
|
else if (r > 0)
|
|
- log_event_debug(event, token, "Added SYMLINK '%s'", path);
|
|
+ log_event_debug(event, token, "Added device node symlink \"%s\".", path);
|
|
}
|
|
}
|
|
- break;
|
|
+ assert_not_reached();
|
|
}
|
|
case TK_A_ATTR: {
|
|
char buf[UDEV_PATH_SIZE], value[UDEV_NAME_SIZE];
|
|
@@ -2819,34 +2879,36 @@ static int udev_rule_apply_token_to_event(
|
|
strscpyl_full(buf, sizeof(buf), &truncated, val, "/", key_name, NULL);
|
|
if (truncated) {
|
|
log_event_warning(event, token,
|
|
- "The path to the attribute '%s/%s' is too long, refusing to set the attribute.",
|
|
+ "The path to the attribute \"%s/%s\" is too long, refusing to set the attribute.",
|
|
val, key_name);
|
|
- break;
|
|
+ return true;
|
|
}
|
|
}
|
|
|
|
r = attr_subst_subdir(buf);
|
|
if (r < 0) {
|
|
- log_event_error_errno(event, token, r, "Could not find file matches '%s', ignoring: %m", buf);
|
|
- break;
|
|
+ log_event_error_errno(event, token, r, "Could not find file matches \"%s\", ignoring: %m", buf);
|
|
+ return true;
|
|
}
|
|
|
|
if (!apply_format_value(event, token, value, sizeof(value), "attribute value"))
|
|
return true;
|
|
|
|
if (EVENT_MODE_DESTRUCTIVE(event)) {
|
|
- log_event_debug(event, token, "Writing ATTR{'%s'}=\"%s\".", buf, value);
|
|
+ log_event_debug(event, token, "Writing \"%s\" to sysfs attribute \"%s\".", value, buf);
|
|
r = write_string_file(buf, value,
|
|
WRITE_STRING_FILE_VERIFY_ON_FAILURE |
|
|
WRITE_STRING_FILE_DISABLE_BUFFER |
|
|
WRITE_STRING_FILE_AVOID_NEWLINE |
|
|
WRITE_STRING_FILE_VERIFY_IGNORE_NEWLINE);
|
|
if (r < 0)
|
|
- log_event_error_errno(event, token, r, "Failed to write ATTR{%s}=\"%s\", ignoring: %m", buf, value);
|
|
+ log_event_error_errno(event, token, r, "Failed to write \"%s\" to sysfs attribute \"%s\", ignoring: %m", value, buf);
|
|
+ else
|
|
+ log_event_done(event, token);
|
|
} else
|
|
- log_event_debug(event, token, "Running in test mode, skipping writing ATTR{%s}=\"%s\".", buf, value);
|
|
+ log_event_debug(event, token, "Running in test mode, skipping writing \"%s\" to sysfs attribute \"%s\".", value, buf);
|
|
|
|
- break;
|
|
+ return true;
|
|
}
|
|
case TK_A_SYSCTL: {
|
|
char buf[UDEV_PATH_SIZE], value[UDEV_NAME_SIZE];
|
|
@@ -2860,14 +2922,16 @@ static int udev_rule_apply_token_to_event(
|
|
sysctl_normalize(buf);
|
|
|
|
if (EVENT_MODE_DESTRUCTIVE(event)) {
|
|
- log_event_debug(event, token, "Writing SYSCTL{%s}=\"%s\".", buf, value);
|
|
+ log_event_debug(event, token, "Writing \"%s\" to sysctl entry \"%s\".", value, buf);
|
|
r = sysctl_write(buf, value);
|
|
if (r < 0)
|
|
- log_event_error_errno(event, token, r, "Failed to write SYSCTL{%s}=\"%s\", ignoring: %m", buf, value);
|
|
+ log_event_error_errno(event, token, r, "Failed to write \"%s\" to sysctl entry \"%s\", ignoring: %m", value, buf);
|
|
+ else
|
|
+ log_event_done(event, token);
|
|
} else
|
|
- log_event_debug(event, token, "Running in test mode, skipping writing SYSCTL{%s}=\"%s\".", buf, value);
|
|
+ log_event_debug(event, token, "Running in test mode, skipping writing \"%s\" to sysctl entry \"%s\".", value, buf);
|
|
|
|
- break;
|
|
+ return true;
|
|
}
|
|
case TK_A_RUN_BUILTIN:
|
|
case TK_A_RUN_PROGRAM: {
|
|
@@ -2875,7 +2939,8 @@ static int udev_rule_apply_token_to_event(
|
|
char buf[UDEV_LINE_SIZE];
|
|
|
|
if (event->run_final)
|
|
- break;
|
|
+ return log_event_final_set(event, token);
|
|
+
|
|
if (token->op == OP_ASSIGN_FINAL)
|
|
event->run_final = true;
|
|
|
|
@@ -2890,24 +2955,22 @@ static int udev_rule_apply_token_to_event(
|
|
return log_oom();
|
|
|
|
r = ordered_hashmap_ensure_put(&event->run_list, NULL, cmd, token->data);
|
|
- if (r == -ENOMEM)
|
|
- return log_oom();
|
|
if (r < 0)
|
|
- return log_event_error_errno(event, token, r, "Failed to store command '%s': %m", cmd);
|
|
+ return log_event_error_errno(event, token, r, "Failed to store command \"%s\": %m", cmd);
|
|
|
|
+ log_event_debug(event, token, "Set command: %s", cmd);
|
|
TAKE_PTR(cmd);
|
|
-
|
|
- log_event_debug(event, token, "RUN '%s'", token->value);
|
|
- break;
|
|
+ return true;
|
|
}
|
|
case TK_A_OPTIONS_STATIC_NODE:
|
|
/* do nothing for events. */
|
|
- break;
|
|
+ return true;
|
|
+
|
|
default:
|
|
assert_not_reached();
|
|
}
|
|
|
|
- return true;
|
|
+ assert_not_reached();
|
|
}
|
|
|
|
static int udev_rule_apply_parent_token_to_event(UdevRuleToken *head_token, UdevEvent *event) {
|