From 9a88f822a6e604434abc51b9eee4e6087a6e8483 Mon Sep 17 00:00:00 2001 From: Yu Watanabe 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) {