diff --git a/man/rules/meson.build b/man/rules/meson.build index c43bffde69..1e8747e4ef 100644 --- a/man/rules/meson.build +++ b/man/rules/meson.build @@ -1176,7 +1176,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. + + + diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c index fcc7783d57..e34ebcca6e 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 72020b7d69..3057356479 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, diff --git a/src/shared/udev-util.c b/src/shared/udev-util.c index cf28ba8647..7a86289d16 100644 --- a/src/shared/udev-util.c +++ b/src/shared/udev-util.c @@ -22,43 +22,37 @@ #include "udev-util.h" #include "utf8.h" -int udev_set_max_log_level(char *str) { - size_t n; +int udev_parse_config_full(const ConfigTableItem config_table[]) { + int r; - /* This may modify input string. */ + assert(config_table); - if (isempty(str)) + 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; - - /* 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); + return r; } 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); - if (r == -ENOENT) - return 0; + r = udev_parse_config_full(config_table); 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; } diff --git a/src/shared/udev-util.h b/src/shared/udev-util.h index 651d335b96..5f49e87116 100644 --- a/src/shared/udev-util.h +++ b/src/shared/udev-util.h @@ -3,10 +3,11 @@ #include "sd-device.h" +#include "conf-parser.h" #include "hashmap.h" #include "time-util.h" -int udev_set_max_log_level(char *str); +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 6f8546385e..684ced1315 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,29 @@ 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); - if (r == -ENOENT) - return 0; + 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 = udev_parse_config_full(config_table); 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; } 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" <