From 5656cdfeeabc16b5489f5ec7a0a36025a2ec1f23 Mon Sep 17 00:00:00 2001 From: David Tardon Date: Fri, 5 Jan 2024 14:30:37 +0100 Subject: [PATCH 1/7] conf-parser: generalize config_parse_config_file() --- src/shared/conf-parser.c | 10 ++++++---- src/shared/conf-parser.h | 13 ++++++++++++- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c index 1d201528ac..8eea223535 100644 --- a/src/shared/conf-parser.c +++ b/src/shared/conf-parser.c @@ -598,10 +598,11 @@ static int config_parse_many_files( return 0; } -/* Parse one main config file located in /etc/systemd and its drop-ins, which is what all systemd daemons +/* Parse one main config file located in /etc/$pkgdir and its drop-ins, which is what all systemd daemons * do. */ -int config_parse_config_file( +int config_parse_config_file_full( const char *conf_file, + const char *pkgdir, const char *sections, ConfigItemLookup lookup, const void *table, @@ -613,6 +614,7 @@ int config_parse_config_file( int r; assert(conf_file); + assert(pkgdir); /* build the dropin dir list */ dropin_dirs = new0(char*, strv_length(conf_paths) + 1); @@ -626,7 +628,7 @@ int config_parse_config_file( STRV_FOREACH(p, conf_paths) { char *d; - d = strjoin(*p, "systemd/", conf_file, ".d"); + d = strjoin(*p, pkgdir, "/", conf_file, ".d"); if (!d) { if (flags & CONFIG_PARSE_WARN) return log_oom(); @@ -640,7 +642,7 @@ int config_parse_config_file( if (r < 0) return r; - const char *sysconf_file = strjoina(PKGSYSCONFDIR, "/", conf_file); + const char *sysconf_file = strjoina(SYSCONF_DIR, "/", pkgdir, "/", conf_file); return config_parse_many_files(STRV_MAKE_CONST(sysconf_file), dropins, sections, lookup, table, flags, userdata, NULL); diff --git a/src/shared/conf-parser.h b/src/shared/conf-parser.h index a1768cd919..4e0054de5e 100644 --- a/src/shared/conf-parser.h +++ b/src/shared/conf-parser.h @@ -93,14 +93,25 @@ int config_parse( void *userdata, struct stat *ret_stat); /* possibly NULL */ -int config_parse_config_file( +int config_parse_config_file_full( const char *conf_file, + const char *pkgdir, const char *sections, /* nulstr */ ConfigItemLookup lookup, const void *table, ConfigParseFlags flags, void *userdata); +static inline int config_parse_config_file( + const char *conf_file, + const char *sections, /* nulstr */ + ConfigItemLookup lookup, + const void *table, + ConfigParseFlags flags, + void *userdata) { + return config_parse_config_file_full(conf_file, "systemd", sections, lookup, table, flags, userdata); +} + int config_parse_many( const char* const* conf_files, /* possibly empty */ const char* const* conf_file_dirs, From 343c8514c1124f224a3e28a27b961771474d0ebd Mon Sep 17 00:00:00 2001 From: David Tardon Date: Fri, 5 Jan 2024 15:31:24 +0100 Subject: [PATCH 2/7] udevd: use config. parser to parse udev.conf This adds support for the usual config. file hierarchy (including dropins). Fixes #30460. --- src/udev/udevd.c | 79 +++++++++++++++--------------------------------- 1 file changed, 24 insertions(+), 55 deletions(-) diff --git a/src/udev/udevd.c b/src/udev/udevd.c index 6f8546385e..ff43c6a2b5 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -10,6 +10,7 @@ #include "sd-daemon.h" +#include "conf-parser.h" #include "env-file.h" #include "errno-util.h" #include "fd-util.h" @@ -65,70 +66,38 @@ static int listen_fds(int *ret_ctrl, int *ret_netlink) { return 0; } +static DEFINE_CONFIG_PARSE_ENUM(config_parse_resolve_name_timing, resolve_name_timing, ResolveNameTiming, "Failed to parse resolve name timing"); + static int manager_parse_udev_config(Manager *manager) { - _cleanup_free_ char *log_val = NULL, *children_max = NULL, *exec_delay = NULL, - *event_timeout = NULL, *resolve_names = NULL, *timeout_signal = NULL; - int r; + int r, log_val = -1; assert(manager); - r = parse_env_file(NULL, "/etc/udev/udev.conf", - "udev_log", &log_val, - "children_max", &children_max, - "exec_delay", &exec_delay, - "event_timeout", &event_timeout, - "resolve_names", &resolve_names, - "timeout_signal", &timeout_signal); + const ConfigTableItem config_table[] = { + { NULL, "udev_log", config_parse_log_level, 0, &log_val }, + { NULL, "children_max", config_parse_unsigned, 0, &manager->children_max }, + { NULL, "exec_delay", config_parse_sec, 0, &manager->exec_delay_usec }, + { NULL, "event_timeout", config_parse_sec, 0, &manager->timeout_usec }, + { NULL, "resolve_names", config_parse_resolve_name_timing, 0, &manager->resolve_name_timing }, + { NULL, "timeout_signal", config_parse_signal, 0, &manager->timeout_signal }, + {} + }; + + r = config_parse_config_file_full( + "udev.conf", + "udev", + /* sections = */ NULL, + config_item_table_lookup, + config_table, + CONFIG_PARSE_WARN, + /* userdata = */ NULL); if (r == -ENOENT) return 0; if (r < 0) return r; - r = udev_set_max_log_level(log_val); - if (r < 0) - log_syntax(NULL, LOG_WARNING, "/etc/udev/udev.conf", 0, r, - "Failed to set udev log level '%s', ignoring: %m", log_val); - - if (children_max) { - r = safe_atou(children_max, &manager->children_max); - if (r < 0) - log_syntax(NULL, LOG_WARNING, "/etc/udev/udev.conf", 0, r, - "Failed to parse children_max=%s, ignoring: %m", children_max); - } - - if (exec_delay) { - r = parse_sec(exec_delay, &manager->exec_delay_usec); - if (r < 0) - log_syntax(NULL, LOG_WARNING, "/etc/udev/udev.conf", 0, r, - "Failed to parse exec_delay=%s, ignoring: %m", exec_delay); - } - - if (event_timeout) { - r = parse_sec(event_timeout, &manager->timeout_usec); - if (r < 0) - log_syntax(NULL, LOG_WARNING, "/etc/udev/udev.conf", 0, r, - "Failed to parse event_timeout=%s, ignoring: %m", event_timeout); - } - - if (resolve_names) { - ResolveNameTiming t; - - t = resolve_name_timing_from_string(resolve_names); - if (t < 0) - log_syntax(NULL, LOG_WARNING, "/etc/udev/udev.conf", 0, r, - "Failed to parse resolve_names=%s, ignoring.", resolve_names); - else - manager->resolve_name_timing = t; - } - - if (timeout_signal) { - r = signal_from_string(timeout_signal); - if (r < 0) - log_syntax(NULL, LOG_WARNING, "/etc/udev/udev.conf", 0, r, - "Failed to parse timeout_signal=%s, ignoring: %m", timeout_signal); - else - manager->timeout_signal = r; - } + if (log_val >= 0) + log_set_max_level(log_val); return 0; } From 07f5e35fe7967c824a87f18a3a1d3c22e5be70f5 Mon Sep 17 00:00:00 2001 From: David Tardon Date: Fri, 5 Jan 2024 15:45:04 +0100 Subject: [PATCH 3/7] udev-util: use config. parser to parse udev.conf --- src/shared/udev-util.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/shared/udev-util.c b/src/shared/udev-util.c index cf28ba8647..5ea03d6740 100644 --- a/src/shared/udev-util.c +++ b/src/shared/udev-util.c @@ -5,6 +5,7 @@ #include #include "alloc-util.h" +#include "conf-parser.h" #include "device-nodes.h" #include "device-private.h" #include "device-util.h" @@ -45,20 +46,27 @@ int udev_set_max_log_level(char *str) { } int udev_parse_config(void) { - _cleanup_free_ char *log_val = NULL; - int r; + int r, log_val = -1; + const ConfigTableItem config_table[] = { + { NULL, "udev_log", config_parse_log_level, 0, &log_val }, + {} + }; - r = parse_env_file(NULL, "/etc/udev/udev.conf", - "udev_log", &log_val); + r = config_parse_config_file_full( + "udev.conf", + "udev", + /* sections = */ NULL, + config_item_table_lookup, + config_table, + CONFIG_PARSE_WARN, + /* userdata = */ NULL); if (r == -ENOENT) return 0; if (r < 0) return r; - r = udev_set_max_log_level(log_val); - if (r < 0) - log_syntax(NULL, LOG_WARNING, "/etc/udev/udev.conf", 0, r, - "Failed to set udev log level '%s', ignoring: %m", log_val); + if (log_val >= 0) + log_set_max_level(log_val); return 0; } From a1c7dc7d1651e105cb5e70eabc7d84521099c840 Mon Sep 17 00:00:00 2001 From: David Tardon Date: Fri, 5 Jan 2024 15:48:31 +0100 Subject: [PATCH 4/7] udev-util: drop unused function --- src/shared/udev-util.c | 22 ---------------------- src/shared/udev-util.h | 1 - 2 files changed, 23 deletions(-) diff --git a/src/shared/udev-util.c b/src/shared/udev-util.c index 5ea03d6740..68e594e065 100644 --- a/src/shared/udev-util.c +++ b/src/shared/udev-util.c @@ -23,28 +23,6 @@ #include "udev-util.h" #include "utf8.h" -int udev_set_max_log_level(char *str) { - size_t n; - - /* This may modify input string. */ - - if (isempty(str)) - return 0; - - /* unquote */ - n = strlen(str); - if (n >= 2 && - ((str[0] == '"' && str[n - 1] == '"') || - (str[0] == '\'' && str[n - 1] == '\''))) { - str[n - 1] = '\0'; - str++; - } - - /* we set the udev log level here explicitly, this is supposed - * to regulate the code in libudev/ and udev/. */ - return log_set_max_level_from_string(str); -} - int udev_parse_config(void) { int r, log_val = -1; const ConfigTableItem config_table[] = { diff --git a/src/shared/udev-util.h b/src/shared/udev-util.h index 651d335b96..958acc9382 100644 --- a/src/shared/udev-util.h +++ b/src/shared/udev-util.h @@ -6,7 +6,6 @@ #include "hashmap.h" #include "time-util.h" -int udev_set_max_log_level(char *str); int udev_parse_config(void); int device_wait_for_initialization(sd_device *device, const char *subsystem, usec_t timeout_usec, sd_device **ret); From 09dd8e77fc7da645e716f34ba7fa38d4666460f6 Mon Sep 17 00:00:00 2001 From: David Tardon Date: Fri, 5 Jan 2024 16:11:24 +0100 Subject: [PATCH 5/7] udev: factor out config parser call into function ... which is then called from both places. This makes sure that the configuration is parsed by udevd and other tools in exactly the same way. --- src/shared/udev-util.c | 22 +++++++++++++++------- src/shared/udev-util.h | 2 ++ src/udev/udevd.c | 11 +---------- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/shared/udev-util.c b/src/shared/udev-util.c index 68e594e065..7a86289d16 100644 --- a/src/shared/udev-util.c +++ b/src/shared/udev-util.c @@ -5,7 +5,6 @@ #include #include "alloc-util.h" -#include "conf-parser.h" #include "device-nodes.h" #include "device-private.h" #include "device-util.h" @@ -23,12 +22,10 @@ #include "udev-util.h" #include "utf8.h" -int udev_parse_config(void) { - int r, log_val = -1; - const ConfigTableItem config_table[] = { - { NULL, "udev_log", config_parse_log_level, 0, &log_val }, - {} - }; +int udev_parse_config_full(const ConfigTableItem config_table[]) { + int r; + + assert(config_table); r = config_parse_config_file_full( "udev.conf", @@ -40,6 +37,17 @@ int udev_parse_config(void) { /* userdata = */ NULL); if (r == -ENOENT) return 0; + return r; +} + +int udev_parse_config(void) { + int r, log_val = -1; + const ConfigTableItem config_table[] = { + { NULL, "udev_log", config_parse_log_level, 0, &log_val }, + {} + }; + + r = udev_parse_config_full(config_table); if (r < 0) return r; diff --git a/src/shared/udev-util.h b/src/shared/udev-util.h index 958acc9382..5f49e87116 100644 --- a/src/shared/udev-util.h +++ b/src/shared/udev-util.h @@ -3,9 +3,11 @@ #include "sd-device.h" +#include "conf-parser.h" #include "hashmap.h" #include "time-util.h" +int udev_parse_config_full(const ConfigTableItem config_table[]); int udev_parse_config(void); int device_wait_for_initialization(sd_device *device, const char *subsystem, usec_t timeout_usec, sd_device **ret); diff --git a/src/udev/udevd.c b/src/udev/udevd.c index ff43c6a2b5..684ced1315 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -83,16 +83,7 @@ static int manager_parse_udev_config(Manager *manager) { {} }; - r = config_parse_config_file_full( - "udev.conf", - "udev", - /* sections = */ NULL, - config_item_table_lookup, - config_table, - CONFIG_PARSE_WARN, - /* userdata = */ NULL); - if (r == -ENOENT) - return 0; + r = udev_parse_config_full(config_table); if (r < 0) return r; From 810a5895e698f7b0b9f899ae7f049cc1bf61c2c7 Mon Sep 17 00:00:00 2001 From: David Tardon Date: Wed, 10 Jan 2024 15:54:28 +0100 Subject: [PATCH 6/7] man: update udev.conf man page --- man/rules/meson.build | 2 +- man/udev.conf.xml | 32 +++++++++++++++++++++++++------- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/man/rules/meson.build b/man/rules/meson.build index 3592b862f7..50493754db 100644 --- a/man/rules/meson.build +++ b/man/rules/meson.build @@ -1174,7 +1174,7 @@ manpages = [ ['timesyncd.conf', '5', ['timesyncd.conf.d'], 'ENABLE_TIMESYNCD'], ['tmpfiles.d', '5', [], ''], ['udev', '7', [], ''], - ['udev.conf', '5', [], ''], + ['udev.conf', '5', ['udev.conf.d'], ''], ['udev_device_get_syspath', '3', ['udev_device_get_action', diff --git a/man/udev.conf.xml b/man/udev.conf.xml index 4ebde474a3..054ab2d139 100644 --- a/man/udev.conf.xml +++ b/man/udev.conf.xml @@ -18,23 +18,35 @@ udev.conf + udev.conf.d Configuration for device event managing daemon - /etc/udev/udev.conf + + + /etc/udev/udev.conf + /run/udev/udev.conf + /usr/lib/udev/udev.conf + /etc/udev/udev.conf.d/*.conf + /run/udev/udev.conf.d/*.conf + /usr/lib/udev/udev.conf.d/*.conf + + Description + These files contain configuration options for + systemd-udevd8. + The syntax of these files is very simple: a list + of assignments, one per line. + All empty lines or lines beginning with # are + ignored. + - systemd-udevd8 - expects its main configuration file at - /etc/udev/udev.conf. It consists of a set - of variables allowing the user to override default udev - values. All empty lines or lines beginning with '#' are - ignored. The following variables can be set: + The following options can be set: @@ -47,6 +59,12 @@ , and . + + This option is also honored by + udevadm8. + + + From dddf640cabc778a1755b7d3b64e4d54c535e063b Mon Sep 17 00:00:00 2001 From: David Tardon Date: Fri, 5 Jan 2024 16:10:50 +0100 Subject: [PATCH 7/7] test: use dropin dir --- test/units/testsuite-17.03.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/units/testsuite-17.03.sh b/test/units/testsuite-17.03.sh index d19d85074f..d6b3162258 100755 --- a/test/units/testsuite-17.03.sh +++ b/test/units/testsuite-17.03.sh @@ -4,11 +4,12 @@ set -eux TMPDIR= TEST_RULE="/run/udev/rules.d/49-test.rules" +TEST_CONF="/run/udev/udev.conf.d/test-17.conf" KILL_PID= setup() { mkdir -p "${TEST_RULE%/*}" - [[ -e /etc/udev/udev.conf ]] && cp -f /etc/udev/udev.conf /etc/udev/udev.conf.bak + mkdir -p /run/udev/udev.conf.d cat >"${TEST_RULE}" </etc/udev/udev.conf <"$TEST_CONF" <