From e0b8a238df5bded9d41d9adf4371123c1b99c1df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Mon, 15 Oct 2018 12:29:48 +0200 Subject: [PATCH 01/14] shared/install: generate list of files in separate function No functional change. --- src/shared/install.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/shared/install.c b/src/shared/install.c index 8629304cef..5a1fff47c4 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -2820,20 +2820,16 @@ static int split_pattern_into_name_and_instances(const char *pattern, char **out return 0; } -static int read_presets(UnitFileScope scope, const char *root_dir, Presets *presets) { - _cleanup_(presets_freep) Presets ps = {}; - size_t n_allocated = 0; - _cleanup_strv_free_ char **files = NULL; - char **p; +static int presets_find_config(UnitFileScope scope, const char *root_dir, char ***files) { int r; assert(scope >= 0); assert(scope < _UNIT_FILE_SCOPE_MAX); - assert(presets); + assert(files); switch (scope) { case UNIT_FILE_SYSTEM: - r = conf_files_list(&files, ".preset", root_dir, 0, + r = conf_files_list(files, ".preset", root_dir, 0, "/etc/systemd/system-preset", "/run/systemd/system-preset", "/usr/local/lib/systemd/system-preset", @@ -2846,7 +2842,7 @@ static int read_presets(UnitFileScope scope, const char *root_dir, Presets *pres case UNIT_FILE_GLOBAL: case UNIT_FILE_USER: - r = conf_files_list(&files, ".preset", root_dir, 0, + r = conf_files_list(files, ".preset", root_dir, 0, "/etc/systemd/user-preset", "/run/systemd/user-preset", "/usr/local/lib/systemd/user-preset", @@ -2858,6 +2854,21 @@ static int read_presets(UnitFileScope scope, const char *root_dir, Presets *pres assert_not_reached("Invalid unit file scope"); } + return r; +} + +static int read_presets(UnitFileScope scope, const char *root_dir, Presets *presets) { + _cleanup_(presets_freep) Presets ps = {}; + size_t n_allocated = 0; + _cleanup_strv_free_ char **files = NULL; + char **p; + int r; + + assert(scope >= 0); + assert(scope < _UNIT_FILE_SCOPE_MAX); + assert(presets); + + r = presets_find_config(scope, root_dir, &files); if (r < 0) return r; From f7767d76bb8598c31deb1c0122a7b17947b5df4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 2 Jan 2019 13:12:18 +0100 Subject: [PATCH 02/14] Introduce CONF_PATHS_USR_STRV to mirror CONF_PATHS_STRV --- src/basic/def.h | 20 ++++++++++++++------ src/shared/install.c | 23 +++++------------------ 2 files changed, 19 insertions(+), 24 deletions(-) diff --git a/src/basic/def.h b/src/basic/def.h index 5be018d82e..929da726ae 100644 --- a/src/basic/def.h +++ b/src/basic/def.h @@ -66,12 +66,20 @@ "/usr/lib/" n "\0" \ _CONF_PATHS_SPLIT_USR_NULSTR(n) +#define CONF_PATHS_USR(n) \ + "/etc/" n, \ + "/run/" n, \ + "/usr/local/lib/" n, \ + "/usr/lib/" n + +#define CONF_PATHS(n) \ + CONF_PATHS_USR(n) \ + _CONF_PATHS_SPLIT_USR(n) + +#define CONF_PATHS_USR_STRV(n) \ + STRV_MAKE(CONF_PATHS_USR(n)) + #define CONF_PATHS_STRV(n) \ - STRV_MAKE( \ - "/etc/" n, \ - "/run/" n, \ - "/usr/local/lib/" n, \ - "/usr/lib/" n \ - _CONF_PATHS_SPLIT_USR(n)) + STRV_MAKE(CONF_PATHS(n)) #define HIGH_RLIMIT_MEMLOCK (1024ULL*1024ULL*64ULL) diff --git a/src/shared/install.c b/src/shared/install.c index 5a1fff47c4..9e88ac46bd 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -15,6 +15,7 @@ #include "alloc-util.h" #include "conf-files.h" #include "conf-parser.h" +#include "def.h" #include "dirent-util.h" #include "extract-word.h" #include "fd-util.h" @@ -2821,40 +2822,26 @@ static int split_pattern_into_name_and_instances(const char *pattern, char **out } static int presets_find_config(UnitFileScope scope, const char *root_dir, char ***files) { - int r; + const char* const* dirs; assert(scope >= 0); assert(scope < _UNIT_FILE_SCOPE_MAX); - assert(files); switch (scope) { case UNIT_FILE_SYSTEM: - r = conf_files_list(files, ".preset", root_dir, 0, - "/etc/systemd/system-preset", - "/run/systemd/system-preset", - "/usr/local/lib/systemd/system-preset", - "/usr/lib/systemd/system-preset", -#if HAVE_SPLIT_USR - "/lib/systemd/system-preset", -#endif - NULL); + dirs = (const char* const*) CONF_PATHS_STRV("systemd/system-preset"); break; case UNIT_FILE_GLOBAL: case UNIT_FILE_USER: - r = conf_files_list(files, ".preset", root_dir, 0, - "/etc/systemd/user-preset", - "/run/systemd/user-preset", - "/usr/local/lib/systemd/user-preset", - "/usr/lib/systemd/user-preset", - NULL); + dirs = (const char* const*) CONF_PATHS_USR_STRV("systemd/user-preset"); break; default: assert_not_reached("Invalid unit file scope"); } - return r; + return conf_files_list_strv(files, ".preset", root_dir, 0, dirs); } static int read_presets(UnitFileScope scope, const char *root_dir, Presets *presets) { From 514fbdd78b4519f97ee07851b35ebd8c46081a3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 2 Jan 2019 13:28:47 +0100 Subject: [PATCH 03/14] resolved: add missing spdx header --- src/resolve/resolved-dnssd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/resolve/resolved-dnssd.c b/src/resolve/resolved-dnssd.c index b8e6a7abe1..b5346a97b1 100644 --- a/src/resolve/resolved-dnssd.c +++ b/src/resolve/resolved-dnssd.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ #include "conf-files.h" #include "conf-parser.h" From 5ae4336abc14d43c0917e25a362aff6cb76c0141 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 2 Jan 2019 13:53:49 +0100 Subject: [PATCH 04/14] man: document paths under /usr/local in standard-conf.xml standard-conf.xml is currently included by: man/binfmt.d.xml man/environment.d.xml man/modules-load.d.xml man/sysctl.d.xml man/coredump.conf.xml man/journal-remote.conf.xml man/journal-upload.conf.xml man/journald.conf.xml man/logind.conf.xml man/networkd.conf.xml man/resolved.conf.xml man/systemd-sleep.conf.xml man/systemd-system.conf.xml All those programs actually use CONF_PATHS_NULSTR or CONF_PATHS_STRV, so this changes the documentation to match code. --- man/standard-conf.xml | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/man/standard-conf.xml b/man/standard-conf.xml index f5c961a0c2..1db859ac2f 100644 --- a/man/standard-conf.xml +++ b/man/standard-conf.xml @@ -11,18 +11,16 @@ Configuration Directories and Precedence - Configuration files are read from directories in - /etc/, /run/, and - /usr/lib/, in order of precedence. - Each configuration file in these configuration directories shall be named in - the style of filename.conf. - Files in /etc/ override files with the same name in - /run/ and /usr/lib/. Files in - /run/ override files with the same name in - /usr/lib/. + Configuration files are read from directories in /etc/, /run/, + /usr/local/lib/, and /usr/lib/, in order of precedence. Each + configuration file in these configuration directories shall be named in the style of + filename.conf. Files in /etc/ override files + with the same name in /run/, /usr/local/lib/, and + /usr/lib/. Files in /run/ override files with the same name under + /usr/. - Packages should install their configuration files in - /usr/lib/. Files in /etc/ are + Packages should install their configuration files in /usr/lib/ (distribution packages) + or /usr/local/lib/ (local installs). Files in /etc/ are reserved for the local administrator, who may use this logic to override the configuration files installed by vendor packages. All configuration files are sorted by their filename in lexicographic order, regardless of which of @@ -52,7 +50,8 @@ When packages need to customize the configuration, they can install configuration snippets in - /usr/lib/systemd/*.conf.d/. Files in + /usr/lib/systemd/*.conf.d/ or + /usr/local/lib/systemd/*.conf.d/. Files in /etc/ are reserved for the local administrator, who may use this logic to override the configuration files installed by vendor packages. The main From 8561869cdebbcf710edc2f625a3b34a8a7ccc4eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 2 Jan 2019 13:55:47 +0100 Subject: [PATCH 05/14] man: add missing spdx header --- man/systemd.dnssd.xml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/man/systemd.dnssd.xml b/man/systemd.dnssd.xml index dc00591fcd..7538a463f9 100644 --- a/man/systemd.dnssd.xml +++ b/man/systemd.dnssd.xml @@ -1,9 +1,7 @@ - - + From 8864425d6cbca36e14c35fb02cefd9297fdc1bfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 2 Jan 2019 16:42:30 +0100 Subject: [PATCH 06/14] man: fix section numbers --- man/systemd-environment-d-generator.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/man/systemd-environment-d-generator.xml b/man/systemd-environment-d-generator.xml index 44880e76e2..1df1388f4e 100644 --- a/man/systemd-environment-d-generator.xml +++ b/man/systemd-environment-d-generator.xml @@ -37,7 +37,7 @@ systemd-environment-d-generator is a systemd.environment-generator7 that reads environment configuration specified by - environment.d7 + environment.d5 configuration files and passes it to the systemd1 user manager instance. @@ -49,7 +49,7 @@ systemd1, systemctl1, systemd.environment-generator7, - systemd.generator7 + systemd.generator5 From eb5f4dde96aabedd3cb4dc9e830de4c24de11c6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 2 Jan 2019 14:20:00 +0100 Subject: [PATCH 07/14] resolved: use standard paths for .dnssd files /usr/local/lib/systemd/dnssd is now also included in the search path. This path is of limited usefulness, but it makes sense to be consistent. Documentation is updated to match. Outdated advice against drop-ins in /usr is removed. --- man/systemd.dnssd.xml | 33 ++++++++++++++++----------------- src/resolve/resolved-dnssd.c | 15 ++++----------- 2 files changed, 20 insertions(+), 28 deletions(-) diff --git a/man/systemd.dnssd.xml b/man/systemd.dnssd.xml index 7538a463f9..1c05cffba6 100644 --- a/man/systemd.dnssd.xml +++ b/man/systemd.dnssd.xml @@ -34,15 +34,16 @@ The main network service file must have the extension .dnssd; other extensions are ignored. - The .dnssd files are read from the files located in the system - network directory /usr/lib/systemd/dnssd, the volatile runtime network - directory /run/systemd/dnssd and the local administration network - directory /etc/systemd/dnssd. All configuration files are collectively - sorted and processed in lexical order, regardless of the directories in which they live. - However, files with identical filenames replace each other. Files in /etc - have the highest priority, files in /run take precedence over files with - the same name in /usr/lib. This can be used to override a system-supplied - configuration file with a local file if needed. + The .dnssd files are read from the files located in the system network + directories /usr/lib/systemd/dnssd and + /usr/local/lib/systemd/dnssd, the volatile runtime network directory + /run/systemd/dnssd and the local administration network directory + /etc/systemd/dnssd. All configuration files are collectively sorted and processed in + lexical order, regardless of the directories in which they live. However, files with identical filenames + replace each other. Files in /etc have the highest priority, files in + /run take precedence over files with the same name in + /usr/lib. This can be used to override a system-supplied configuration file with a + local file if needed. Along with the network service file foo.dnssd, a "drop-in" directory foo.dnssd.d/ may exist. All files with the suffix @@ -50,14 +51,12 @@ parsed. This is useful to alter or add configuration settings, without having to modify the main configuration file. Each drop-in file must have appropriate section headers. - In addition to /etc/systemd/dnssd, drop-in .d - directories can be placed in /usr/lib/systemd/dnssd or - /run/systemd/dnssd directories. Drop-in files in - /etc take precedence over those in /run which in turn - take precedence over those in /usr/lib. Drop-in files under any of these - directories take precedence over the main network service file wherever located. (Of course, since - /run is temporary and /usr/lib is for vendors, it is - unlikely drop-ins should be used in either of those places.) + In addition to /etc/systemd/dnssd, drop-in .d directories + can be placed in /usr/lib/systemd/dnssd or /run/systemd/dnssd + directories. Drop-in files in /etc take precedence over those in + /run which in turn take precedence over those in /usr/lib or + /usr/local/lib. Drop-in files under any of these directories take precedence over + the main network service file wherever located. diff --git a/src/resolve/resolved-dnssd.c b/src/resolve/resolved-dnssd.c index b5346a97b1..0e6fa1d0c9 100644 --- a/src/resolve/resolved-dnssd.c +++ b/src/resolve/resolved-dnssd.c @@ -2,21 +2,14 @@ #include "conf-files.h" #include "conf-parser.h" +#include "def.h" #include "resolved-dnssd.h" #include "resolved-dns-rr.h" #include "resolved-manager.h" #include "specifier.h" #include "strv.h" -const char* const dnssd_service_dirs[] = { - "/etc/systemd/dnssd", - "/run/systemd/dnssd", - "/usr/lib/systemd/dnssd", -#if HAVE_SPLIT_USR - "/lib/systemd/dnssd", -#endif - NULL -}; +#define DNSSD_SERVICE_DIRS ((const char* const*) CONF_PATHS_STRV("systemd/dnssd")) DnssdTxtData *dnssd_txtdata_free(DnssdTxtData *txt_data) { if (!txt_data) @@ -93,7 +86,7 @@ static int dnssd_service_load(Manager *manager, const char *filename) { dropin_dirname = strjoina(service->name, ".dnssd.d"); - r = config_parse_many(filename, dnssd_service_dirs, dropin_dirname, + r = config_parse_many(filename, DNSSD_SERVICE_DIRS, dropin_dirname, "Service\0", config_item_perf_lookup, resolved_dnssd_gperf_lookup, false, service); @@ -196,7 +189,7 @@ int dnssd_load(Manager *manager) { if (manager->mdns_support != RESOLVE_SUPPORT_YES) return 0; - r = conf_files_list_strv(&files, ".dnssd", NULL, 0, dnssd_service_dirs); + r = conf_files_list_strv(&files, ".dnssd", NULL, 0, DNSSD_SERVICE_DIRS); if (r < 0) return log_error_errno(r, "Failed to enumerate .dnssd files: %m"); From dc0d40785141aeb5a11cfccd03b236703554b42e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 2 Jan 2019 14:30:24 +0100 Subject: [PATCH 08/14] udev,network: use standard paths for .network and .link files This centralizes the configuration to one header file. /usr/local/lib is now included in the search list, and documentation is updated accordingly. --- man/systemd.network.xml | 26 +++++++++++------------ src/libsystemd-network/network-internal.h | 4 ++++ src/network/netdev/netdev.c | 6 +++--- src/network/networkd-manager.c | 14 +++--------- src/network/networkd-manager.h | 2 -- src/network/networkd-network.c | 4 ++-- src/udev/net/link-config.c | 18 +++++----------- 7 files changed, 29 insertions(+), 45 deletions(-) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 1a02672713..fc2ac4b505 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -37,17 +37,17 @@ The main network file must have the extension .network; other extensions are ignored. Networks are applied to links whenever the links appear. - The .network files are read from the files located in the system - network directory /usr/lib/systemd/network, the volatile runtime network - directory /run/systemd/network and the local administration network - directory /etc/systemd/network. All configuration files are collectively - sorted and processed in lexical order, regardless of the directories in which they live. - However, files with identical filenames replace each other. Files in /etc - have the highest priority, files in /run take precedence over files with - the same name in /usr/lib. This can be used to override a system-supplied - configuration file with a local file if needed. As a special case, an empty file (file size 0) - or symlink with the same name pointing to /dev/null disables the - configuration file entirely (it is "masked"). + The .network files are read from the files located in the system network + directories /usr/lib/systemd/network and + /usr/local/lib/systemd/network, the volatile runtime network directory + /run/systemd/network and the local administration network directory + /etc/systemd/network. All configuration files are collectively sorted and processed + in lexical order, regardless of the directories in which they live. However, files with identical + filenames replace each other. Files in /etc have the highest priority, files in + /run take precedence over files with the same name under + /usr. This can be used to override a system-supplied configuration file with a local + file if needed. As a special case, an empty file (file size 0) or symlink with the same name pointing to + /dev/null disables the configuration file entirely (it is "masked"). Along with the network file foo.network, a "drop-in" directory foo.network.d/ may exist. All files with the suffix @@ -60,9 +60,7 @@ /run/systemd/network directories. Drop-in files in /etc take precedence over those in /run which in turn take precedence over those in /usr/lib. Drop-in files under any of these - directories take precedence over the main netdev file wherever located. (Of course, since - /run is temporary and /usr/lib is for vendors, it is - unlikely drop-ins should be used in either of those places.) + directories take precedence over the main netdev file wherever located. Note that an interface without any static IPv6 addresses configured, and neither DHCPv6 nor IPv6LL enabled, shall be considered to have no IPv6 support. IPv6 will be automatically diff --git a/src/libsystemd-network/network-internal.h b/src/libsystemd-network/network-internal.h index 0c8da848c1..96623e6f09 100644 --- a/src/libsystemd-network/network-internal.h +++ b/src/libsystemd-network/network-internal.h @@ -8,7 +8,9 @@ #include "condition.h" #include "conf-parser.h" +#include "def.h" #include "set.h" +#include "strv.h" #define LINK_BRIDGE_PORT_PRIORITY_INVALID 128 #define LINK_BRIDGE_PORT_PRIORITY_MAX 63 @@ -54,3 +56,5 @@ int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t /* It is not necessary to add deserialize_dhcp_option(). Use unhexmem() instead. */ int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size); + +#define NETWORK_DIRS ((const char* const*) CONF_PATHS_STRV("systemd/network")) diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c index 0263917468..1ad13b81a8 100644 --- a/src/network/netdev/netdev.c +++ b/src/network/netdev/netdev.c @@ -661,7 +661,7 @@ int netdev_load_one(Manager *manager, const char *filename) { }; dropin_dirname = strjoina(basename(filename), ".d"); - r = config_parse_many(filename, network_dirs, dropin_dirname, + r = config_parse_many(filename, NETWORK_DIRS, dropin_dirname, "Match\0NetDev\0", config_item_perf_lookup, network_netdev_gperf_lookup, CONFIG_PARSE_WARN|CONFIG_PARSE_RELAXED, netdev_raw); @@ -702,7 +702,7 @@ int netdev_load_one(Manager *manager, const char *filename) { if (NETDEV_VTABLE(netdev)->init) NETDEV_VTABLE(netdev)->init(netdev); - r = config_parse_many(filename, network_dirs, dropin_dirname, + r = config_parse_many(filename, NETWORK_DIRS, dropin_dirname, NETDEV_VTABLE(netdev)->sections, config_item_perf_lookup, network_netdev_gperf_lookup, CONFIG_PARSE_WARN, netdev); @@ -802,7 +802,7 @@ int netdev_load(Manager *manager) { hashmap_clear_with_destructor(manager->netdevs, netdev_unref); - r = conf_files_list_strv(&files, ".netdev", NULL, 0, network_dirs); + r = conf_files_list_strv(&files, ".netdev", NULL, 0, NETWORK_DIRS); if (r < 0) return log_error_errno(r, "Failed to enumerate netdev files: %m"); diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index c8d369e2a0..cf8aca3b29 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -18,6 +18,7 @@ #include "fileio.h" #include "local-addresses.h" #include "netlink-util.h" +#include "network-internal.h" #include "networkd-manager.h" #include "ordered-set.h" #include "path-util.h" @@ -29,15 +30,6 @@ /* use 8 MB for receive socket kernel queue. */ #define RCVBUF_SIZE (8*1024*1024) -const char* const network_dirs[] = { - "/etc/systemd/network", - "/run/systemd/network", - "/usr/lib/systemd/network", -#if HAVE_SPLIT_USR - "/lib/systemd/network", -#endif - NULL}; - static int setup_default_address_pool(Manager *m) { AddressPool *p; int r; @@ -1485,7 +1477,7 @@ int manager_load_config(Manager *m) { int r; /* update timestamp */ - paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, true); + paths_check_timestamp(NETWORK_DIRS, &m->network_dirs_ts_usec, true); r = netdev_load(m); if (r < 0) @@ -1499,7 +1491,7 @@ int manager_load_config(Manager *m) { } bool manager_should_reload(Manager *m) { - return paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, false); + return paths_check_timestamp(NETWORK_DIRS, &m->network_dirs_ts_usec, false); } int manager_rtnl_enumerate_links(Manager *m) { diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h index 289ca96216..33f80bf19f 100644 --- a/src/network/networkd-manager.h +++ b/src/network/networkd-manager.h @@ -18,8 +18,6 @@ #include "networkd-link.h" #include "networkd-network.h" -extern const char* const network_dirs[]; - struct Manager { sd_netlink *rtnl; /* lazy initialized */ diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 2d23322378..04ab529108 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -211,7 +211,7 @@ int network_load_one(Manager *manager, const char *filename) { .ipv6_accept_ra_route_table = RT_TABLE_MAIN, }; - r = config_parse_many(filename, network_dirs, dropin_dirname, + r = config_parse_many(filename, NETWORK_DIRS, dropin_dirname, "Match\0" "Link\0" "Network\0" @@ -291,7 +291,7 @@ int network_load(Manager *manager) { while ((network = manager->networks)) network_free(network); - r = conf_files_list_strv(&files, ".network", NULL, 0, network_dirs); + r = conf_files_list_strv(&files, ".network", NULL, 0, NETWORK_DIRS); if (r < 0) return log_error_errno(r, "Failed to enumerate network files: %m"); diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c index 60da08a86f..52a697e9f2 100644 --- a/src/udev/net/link-config.c +++ b/src/udev/net/link-config.c @@ -8,6 +8,7 @@ #include "alloc-util.h" #include "conf-files.h" #include "conf-parser.h" +#include "def.h" #include "device-util.h" #include "ethtool-util.h" #include "fd-util.h" @@ -36,18 +37,9 @@ struct link_config_ctx { sd_netlink *rtnl; - usec_t link_dirs_ts_usec; + usec_t network_dirs_ts_usec; }; -static const char* const link_dirs[] = { - "/etc/systemd/network", - "/run/systemd/network", - "/usr/lib/systemd/network", -#if HAVE_SPLIT_USR - "/lib/systemd/network", -#endif - NULL}; - static void link_config_free(link_config *link) { if (!link) return; @@ -216,9 +208,9 @@ int link_config_load(link_config_ctx *ctx) { } /* update timestamp */ - paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, true); + paths_check_timestamp(NETWORK_DIRS, &ctx->network_dirs_ts_usec, true); - r = conf_files_list_strv(&files, ".link", NULL, 0, link_dirs); + r = conf_files_list_strv(&files, ".link", NULL, 0, NETWORK_DIRS); if (r < 0) return log_error_errno(r, "failed to enumerate link files: %m"); @@ -232,7 +224,7 @@ int link_config_load(link_config_ctx *ctx) { } bool link_config_should_reload(link_config_ctx *ctx) { - return paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, false); + return paths_check_timestamp(NETWORK_DIRS, &ctx->network_dirs_ts_usec, false); } int link_config_get(link_config_ctx *ctx, sd_device *device, link_config **ret) { From 3dd84d4615a1bce46f5958718a677556c791a45b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 2 Jan 2019 17:34:55 +0100 Subject: [PATCH 09/14] environment-d-generator: do not include /lib/environment.d in the list This makes the code match documentation (opposite compared to previous commits). This is user configuration, hence it should not depend on stuff in /lib/ even when split-usr is used. --- src/environment-d-generator/environment-d-generator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/environment-d-generator/environment-d-generator.c b/src/environment-d-generator/environment-d-generator.c index 9d64d95738..b2558f0c84 100644 --- a/src/environment-d-generator/environment-d-generator.c +++ b/src/environment-d-generator/environment-d-generator.c @@ -14,7 +14,7 @@ static int environment_dirs(char ***ret) { _cleanup_free_ char *c = NULL; int r; - dirs = strv_split_nulstr(CONF_PATHS_NULSTR("environment.d")); + dirs = strv_new(CONF_PATHS_USR("environment.d"), NULL); if (!dirs) return -ENOMEM; From 116b91e8ccfee1d44fc2b140d831d688e3747902 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 3 Jan 2019 12:31:06 +0100 Subject: [PATCH 10/14] udev: use the usual set of load paths for udev rules This adds /usr/local/lib/udev/rules.d to the search path on non-split-usr systems. On split-usr systems, the paths with /usr/-prefixes are added too. In the past, on split-usr systems, it made sense to only load rules from /lib/udev/rules.d, because /usr could be mounted late. But we don't support running without /usr since 80758717a63, so in practice it doesn't matter whether the rules files are in /lib/udev/rules.d or /usr/lib/udev/rules.d. Distributions that maintain the illusion of functional split-usr are welcome to simply not put any files in /usr/lib/udev/rules.d/. In practice this doesn't change much, but it makes udev more consistent with the rest of the systemd suite. --- man/udev.xml | 26 ++++++++++++-------------- src/udev/udev-rules.c | 13 ++++--------- 2 files changed, 16 insertions(+), 23 deletions(-) diff --git a/man/udev.xml b/man/udev.xml index 74aab8e024..c82a3998f4 100644 --- a/man/udev.xml +++ b/man/udev.xml @@ -45,20 +45,18 @@ Rules Files - The udev rules are read from the files located in the - system rules directory /usr/lib/udev/rules.d, - the volatile runtime directory /run/udev/rules.d - and the local administration directory /etc/udev/rules.d. - All rules files are collectively sorted and processed in lexical order, - regardless of the directories in which they live. However, files with - identical filenames replace each other. Files in /etc - have the highest priority, files in /run take precedence - over files with the same name in /usr/lib. This can be - used to override a system-supplied rules file with a local file if needed; - a symlink in /etc with the same name as a rules file in - /usr/lib, pointing to /dev/null, - disables the rules file entirely. Rule files must have the extension - .rules; other extensions are ignored. + The udev rules are read from the files located in the system rules directories + /usr/lib/udev/rules.d and /usr/local/lib/udev/rules.d, the + volatile runtime directory /run/udev/rules.d and the local administration + directory /etc/udev/rules.d. All rules files are collectively sorted and + processed in lexical order, regardless of the directories in which they live. However, files with + identical filenames replace each other. Files in /etc have the highest priority, + files in /run take precedence over files with the same name under + /usr. This can be used to override a system-supplied rules file with a local + file if needed; a symlink in /etc with the same name as a rules file in + /usr/lib, pointing to /dev/null, disables the rules file + entirely. Rule files must have the extension .rules; other extensions are + ignored. Every line in the rules file contains at least one key-value pair. Except for empty lines or lines beginning with #, which are ignored. diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c index 8603c75cb6..a38853df00 100644 --- a/src/udev/udev-rules.c +++ b/src/udev/udev-rules.c @@ -15,6 +15,7 @@ #include "alloc-util.h" #include "conf-files.h" +#include "def.h" #include "device-private.h" #include "device-util.h" #include "dirent-util.h" @@ -41,6 +42,7 @@ #include "util.h" #define PREALLOC_TOKEN 2048 +#define RULES_DIRS (const char* const*) CONF_PATHS_STRV("udev/rules.d") struct uid_gid { unsigned name_off; @@ -50,13 +52,6 @@ struct uid_gid { }; }; -static const char* const rules_dirs[] = { - "/etc/udev/rules.d", - "/run/udev/rules.d", - UDEVLIBEXECDIR "/rules.d", - NULL -}; - struct UdevRules { usec_t dirs_ts_usec; ResolveNameTiming resolve_name_timing; @@ -1609,7 +1604,7 @@ int udev_rules_new(UdevRules **ret_rules, ResolveNameTiming resolve_name_timing) udev_rules_check_timestamp(rules); - r = conf_files_list_strv(&files, ".rules", NULL, 0, rules_dirs); + r = conf_files_list_strv(&files, ".rules", NULL, 0, RULES_DIRS); if (r < 0) return log_error_errno(r, "Failed to enumerate rules files: %m"); @@ -1661,7 +1656,7 @@ bool udev_rules_check_timestamp(UdevRules *rules) { if (!rules) return false; - return paths_check_timestamp(rules_dirs, &rules->dirs_ts_usec, true); + return paths_check_timestamp(RULES_DIRS, &rules->dirs_ts_usec, true); } static bool match_key(UdevRules *rules, struct token *token, const char *val) { From c2953e0808204eaf34fda095dbafa1c1ecc3b419 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 2 Jan 2019 22:53:03 +0100 Subject: [PATCH 11/14] analyze: use SYNTHETIC_ERRNO --- src/analyze/analyze.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c index 3915b66739..06a409ca25 100644 --- a/src/analyze/analyze.c +++ b/src/analyze/analyze.c @@ -270,14 +270,13 @@ static int acquire_boot_times(sd_bus *bus, struct boot_times **bt) { if (r < 0) return log_error_errno(r, "Failed to get timestamp properties: %s", bus_error_message(&error, r)); - if (times.finish_time <= 0) { - log_error("Bootup is not yet finished (org.freedesktop.systemd1.Manager.FinishTimestampMonotonic=%"PRIu64").\n" - "Please try again later.\n" - "Hint: Use 'systemctl%s list-jobs' to see active jobs", - times.finish_time, - arg_scope == UNIT_FILE_SYSTEM ? "" : " --user"); - return -EINPROGRESS; - } + if (times.finish_time <= 0) + return log_error_errno(SYNTHETIC_ERRNO(EINPROGRESS), + "Bootup is not yet finished (org.freedesktop.systemd1.Manager.FinishTimestampMonotonic=%"PRIu64").\n" + "Please try again later.\n" + "Hint: Use 'systemctl%s list-jobs' to see active jobs", + times.finish_time, + arg_scope == UNIT_FILE_SYSTEM ? "" : " --user"); if (arg_scope == UNIT_FILE_SYSTEM && times.security_start_time > 0) { /* security_start_time is set when systemd is not running under container environment. */ @@ -312,7 +311,6 @@ finish: } static void free_host_info(struct host_info *hi) { - if (!hi) return; @@ -385,7 +383,8 @@ static int acquire_time_data(sd_bus *bus, struct unit_times **out) { NULL, t); if (r < 0) - return log_error_errno(r, "Failed to get timestamp properties of unit %s: %s", u.id, bus_error_message(&error, r)); + return log_error_errno(r, "Failed to get timestamp properties of unit %s: %s", + u.id, bus_error_message(&error, r)); subtract_timestamp(&t->activating, boot_times->reverse_offset); subtract_timestamp(&t->activated, boot_times->reverse_offset); @@ -458,7 +457,8 @@ static int acquire_host_info(sd_bus *bus, struct host_info **hi) { NULL, host); if (r < 0) { - log_debug_errno(r, "Failed to get host information from systemd-hostnamed, ignoring: %s", bus_error_message(&error, r)); + log_debug_errno(r, "Failed to get host information from systemd-hostnamed, ignoring: %s", + bus_error_message(&error, r)); sd_bus_error_free(&error); } @@ -472,10 +472,10 @@ manager: NULL, host); if (r < 0) - return log_error_errno(r, "Failed to get host information from systemd: %s", bus_error_message(&error, r)); + return log_error_errno(r, "Failed to get host information from systemd: %s", + bus_error_message(&error, r)); *hi = TAKE_PTR(host); - return 0; } @@ -1328,7 +1328,8 @@ static int dump(int argc, char *argv[], void *userdata) { if (r < 0) { /* fall back to Dump if DumpByFileDescriptor is not supported */ if (!IN_SET(r, -EACCES, -EBADR)) - return log_error_errno(r, "Failed to issue method call DumpByFileDescriptor: %s", bus_error_message(&error, r)); + return log_error_errno(r, "Failed to issue method call DumpByFileDescriptor: %s", + bus_error_message(&error, r)); return dump_fallback(bus); } @@ -1365,8 +1366,7 @@ static int cat_config(int argc, char *argv[], void *userdata) { if (!t) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "Path %s does not start with any known prefix.", - *arg); + "Path %s does not start with any known prefix.", *arg); } else t = *arg; @@ -1628,8 +1628,8 @@ static int dump_syscall_filters(int argc, char *argv[], void *userdata) { /* make sure the error appears below normal output */ fflush(stdout); - log_error("Filter set \"%s\" not found.", *name); - return -ENOENT; + return log_error_errno(SYNTHETIC_ERRNO(ENOENT), + "Filter set \"%s\" not found.", *name); } dump_syscall_filter(set); From f1d9d36ac5958006bbd464944ef490a198d38189 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 3 Jan 2019 11:34:22 +0100 Subject: [PATCH 12/14] analyze: generalize cat-config to apply to tmpfiles, presets, hwdb.d, etc. Fixes #10256. What works: systemd-analyze cat-config systemd/system-preset systemd-analyze cat-config systemd/user-preset systemd-analyze cat-config tmpfiles.d systemd-analyze cat-config sysusers.d systemd-analyze cat-config systemd/sleep.conf systemd-analyze cat-config systemd/user.conf systemd-analyze cat-config systemd/system.conf systemd-analyze cat-config udev/udev.conf (and other .conf files) systemd-analyze cat-config udev/rules.d systemd-analyze cat-config environment.d systemd-analyze cat-config environment Directories may be specified with the trailing dash or not. The caveat is that for user configuration, systemd and other tools also look at ~/.config/. It would be nice to support this, but this patch doesn't. "cat-config --user" is rejected, and we may allow it in the future and then extend the search path with directories under ~/.config. What doesn't work (and probably shouldn't because those files cannot be meaningfully concatenated): systemd-analyze cat-config systemd/system (.service, .slice, .socket, ...) systemd-analyze cat-config systemd/user systemd-analyze cat-config systemd/network (.network, .link, and .dnssd) The hardcoding of information about paths in this manner is a bit ugly, but OTOH, it is not too onerous, and at least we have one place where all the schemes are "documented" through code. It'll make us think twice before adding yet another slightly different scheme. --- src/analyze/analyze.c | 4 +++ src/shared/pretty-print.c | 75 +++++++++++++++++++++++++++++++++------ 2 files changed, 69 insertions(+), 10 deletions(-) diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c index 06a409ca25..6fa6ef93cc 100644 --- a/src/analyze/analyze.c +++ b/src/analyze/analyze.c @@ -2000,6 +2000,10 @@ static int parse_argv(int argc, char *argv[]) { return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Option --global only makes sense with verbs dot, unit-paths, verify."); + if (streq_ptr(argv[optind], "cat-config") && arg_scope == UNIT_FILE_USER) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Option --user is not supported for cat-config right now."); + if (arg_root && !streq_ptr(argv[optind], "cat-config")) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Option --root is only supported for cat-config right now."); diff --git a/src/shared/pretty-print.c b/src/shared/pretty-print.c index de6274a3da..ce71a7ef60 100644 --- a/src/shared/pretty-print.c +++ b/src/shared/pretty-print.c @@ -213,33 +213,88 @@ void print_separator(void) { fputs("\n\n", stdout); } +static int guess_type(const char **name, bool *is_usr, bool *is_collection, const char **extension) { + /* Try to figure out if name is like tmpfiles.d/ or systemd/system-presets/, + * i.e. a collection of directories without a main config file. */ + + _cleanup_free_ char *n = NULL; + bool usr = false, coll = false; + const char *ext = ".conf"; + + if (path_equal(*name, "environment.d")) + /* Special case: we need to include /etc/environment in the search path, even + * though the whole concept is called environment.d. */ + *name = "environment"; + + n = strdup(*name); + if (!n) + return log_oom(); + + delete_trailing_chars(n, "/"); + + if (endswith(n, ".d")) + coll = true; + + if (path_equal(n, "environment")) + usr = true; + + if (path_equal(n, "udev/hwdb.d")) + ext = ".hwdb"; + + if (path_equal(n, "udev/rules.d")) + ext = ".rules"; + + if (PATH_IN_SET(n, "systemd/system-preset", "systemd/user-preset")) { + coll = true; + ext = ".preset"; + } + + if (path_equal(n, "systemd/user-preset")) + usr = true; + + *is_usr = usr; + *is_collection = coll; + *extension = ext; + return 0; +} + int conf_files_cat(const char *root, const char *name) { _cleanup_strv_free_ char **dirs = NULL, **files = NULL; _cleanup_free_ char *path = NULL; - const char *dir; + char **dir; + bool is_usr, is_collection; + const char *extension; char **t; int r; - NULSTR_FOREACH(dir, CONF_PATHS_NULSTR("")) { - assert(endswith(dir, "/")); - r = strv_extendf(&dirs, "%s%s.d", dir, name); + r = guess_type(&name, &is_usr, &is_collection, &extension); + if (r < 0) + return r; + + STRV_FOREACH(dir, is_usr ? CONF_PATHS_USR_STRV("") : CONF_PATHS_STRV("")) { + assert(endswith(*dir, "/")); + r = strv_extendf(&dirs, "%s%s%s", *dir, name, + is_collection ? "" : ".d"); if (r < 0) return log_error_errno(r, "Failed to build directory list: %m"); } - r = conf_files_list_strv(&files, ".conf", root, 0, (const char* const*) dirs); + r = conf_files_list_strv(&files, extension, root, 0, (const char* const*) dirs); if (r < 0) return log_error_errno(r, "Failed to query file list: %m"); - path = path_join(root, "/etc", name); - if (!path) - return log_oom(); + if (!is_collection) { + path = path_join(root, "/etc", name); + if (!path) + return log_oom(); + } if (DEBUG_LOGGING) { log_debug("Looking for configuration in:"); - log_debug(" %s", path); + if (path) + log_debug(" %s", path); STRV_FOREACH(t, dirs) - log_debug(" %s/*.conf", *t); + log_debug(" %s/*%s", *t, extension); } /* show */ From f32c79ca50aac9d4f817b026e8a1c16dc982ffb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 3 Jan 2019 12:18:19 +0100 Subject: [PATCH 13/14] meson: drop unused "udevhomedir" --- meson.build | 1 - 1 file changed, 1 deletion(-) diff --git a/meson.build b/meson.build index 56c98b9c1b..8d341ebee5 100644 --- a/meson.build +++ b/meson.build @@ -135,7 +135,6 @@ systemsleepdir = join_paths(rootlibexecdir, 'system-sleep') systemunitdir = join_paths(rootprefixdir, 'lib/systemd/system') systempresetdir = join_paths(rootprefixdir, 'lib/systemd/system-preset') udevlibexecdir = join_paths(rootprefixdir, 'lib/udev') -udevhomedir = udevlibexecdir udevrulesdir = join_paths(udevlibexecdir, 'rules.d') udevhwdbdir = join_paths(udevlibexecdir, 'hwdb.d') catalogdir = join_paths(prefixdir, 'lib/systemd/catalog') From 796ac4c12c47b05dc9ebff512729bb9802d9a93f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 3 Jan 2019 12:33:42 +0100 Subject: [PATCH 14/14] core: update comment Initially, the check was that /usr is not a separate fs, and was later relaxed to allow /usr to be mounted in the initramfs. Documentation was updated in 9e93f6f09229ffdbc46ab, but this comment wasn't. Let's update it too. --- src/core/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/main.c b/src/core/main.c index 561f956f0a..47a976ad0f 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1382,7 +1382,7 @@ static int bump_rlimit_memlock(struct rlimit *saved_rlimit) { static void test_usr(void) { - /* Check that /usr is not a separate fs */ + /* Check that /usr is either on the same file system as / or mounted already. */ if (dir_is_empty("/usr") <= 0) return;