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" <