From 268f5a54630ef997d85f29a3ffc2b951f7a996c7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 28 Apr 2020 20:03:56 +0200 Subject: [PATCH 1/3] tree-wide: support a bunch of additional specifiers --- src/core/unit-printf.c | 16 ++++++++++-- src/resolve/resolved-conf.c | 7 +++++- src/resolve/resolved-dnssd.c | 7 +++++- src/shared/install-printf.c | 7 +++++- src/shared/specifier.c | 48 ++++++++++++++++++++++++++++++++++++ src/shared/specifier.h | 5 ++++ src/sysusers/sysusers.c | 5 ++++ src/test/test-strv.c | 24 ++++++++++++------ src/tmpfiles/tmpfiles.c | 5 ++++ 9 files changed, 112 insertions(+), 12 deletions(-) diff --git a/src/core/unit-printf.c b/src/core/unit-printf.c index 7507479ce2..049a2f5596 100644 --- a/src/core/unit-printf.c +++ b/src/core/unit-printf.c @@ -186,8 +186,14 @@ int unit_name_printf(const Unit *u, const char* format, char **ret) { * %u: the username of the running user * * %m: the machine ID of the running system - * %H: the hostname of the running system * %b: the boot ID of the running system + * %H: the hostname of the running system + * %v: the kernel version + * %a: the native userspace architecture + * %o: the OS ID according to /etc/os-release + * %w: the OS version ID, according to /etc/os-release + * %B: the OS build ID, according to /etc/os-release + * %W: the OS variant ID, according to /etc/os-release */ const Specifier table[] = { @@ -203,8 +209,14 @@ int unit_name_printf(const Unit *u, const char* format, char **ret) { { 'u', specifier_user_name, NULL }, { 'm', specifier_machine_id, NULL }, - { 'H', specifier_host_name, NULL }, { 'b', specifier_boot_id, NULL }, + { 'H', specifier_host_name, NULL }, + { 'v', specifier_kernel_release, NULL }, + { 'a', specifier_architecture, NULL }, + { 'o', specifier_os_id, NULL }, + { 'w', specifier_os_version_id, NULL }, + { 'B', specifier_os_build_id, NULL }, + { 'W', specifier_os_variant_id, NULL }, {} }; diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c index ca5b8e7918..6ad66113e8 100644 --- a/src/resolve/resolved-conf.c +++ b/src/resolve/resolved-conf.c @@ -218,10 +218,15 @@ int config_parse_search_domains( int config_parse_dnssd_service_name(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { static const Specifier specifier_table[] = { + { 'm', specifier_machine_id, NULL }, { 'b', specifier_boot_id, NULL }, { 'H', specifier_host_name, NULL }, - { 'm', specifier_machine_id, NULL }, { 'v', specifier_kernel_release, NULL }, + { 'a', specifier_architecture, NULL }, + { 'o', specifier_os_id, NULL }, + { 'w', specifier_os_version_id, NULL }, + { 'B', specifier_os_build_id, NULL }, + { 'W', specifier_os_variant_id, NULL }, {} }; DnssdService *s = userdata; diff --git a/src/resolve/resolved-dnssd.c b/src/resolve/resolved-dnssd.c index 0e6fa1d0c9..bc886fd0e0 100644 --- a/src/resolve/resolved-dnssd.c +++ b/src/resolve/resolved-dnssd.c @@ -153,10 +153,15 @@ static int specifier_dnssd_host_name(char specifier, const void *data, const voi int dnssd_render_instance_name(DnssdService *s, char **ret_name) { static const Specifier specifier_table[] = { + { 'm', specifier_machine_id, NULL }, { 'b', specifier_boot_id, NULL }, { 'H', specifier_dnssd_host_name, NULL }, - { 'm', specifier_machine_id, NULL }, { 'v', specifier_kernel_release, NULL }, + { 'a', specifier_architecture, NULL }, + { 'o', specifier_os_id, NULL }, + { 'w', specifier_os_version_id, NULL }, + { 'B', specifier_os_build_id, NULL }, + { 'W', specifier_os_variant_id, NULL }, {} }; _cleanup_free_ char *name = NULL; diff --git a/src/shared/install-printf.c b/src/shared/install-printf.c index 03184cf7e2..9267d52b96 100644 --- a/src/shared/install-printf.c +++ b/src/shared/install-printf.c @@ -133,9 +133,14 @@ int install_full_printf(const UnitFileInstallInfo *i, const char *format, char * { 'u', specifier_user_name, NULL }, { 'm', specifier_machine_id, NULL }, - { 'H', specifier_host_name, NULL }, { 'b', specifier_boot_id, NULL }, + { 'H', specifier_host_name, NULL }, { 'v', specifier_kernel_release, NULL }, + { 'a', specifier_architecture, NULL }, + { 'o', specifier_os_id, NULL }, + { 'w', specifier_os_version_id, NULL }, + { 'B', specifier_os_build_id, NULL }, + { 'W', specifier_os_variant_id, NULL }, {} }; diff --git a/src/shared/specifier.c b/src/shared/specifier.c index b036ff67dd..c784222be6 100644 --- a/src/shared/specifier.c +++ b/src/shared/specifier.c @@ -9,10 +9,12 @@ #include "sd-id128.h" #include "alloc-util.h" +#include "architecture.h" #include "format-util.h" #include "fs-util.h" #include "hostname-util.h" #include "macro.h" +#include "os-util.h" #include "specifier.h" #include "string-util.h" #include "strv.h" @@ -175,6 +177,52 @@ int specifier_kernel_release(char specifier, const void *data, const void *userd return 0; } +int specifier_architecture(char specifier, const void *data, const void *userdata, char **ret) { + char *t; + + t = strdup(architecture_to_string(uname_architecture())); + if (!t) + return -ENOMEM; + + *ret = t; + return 0; +} + +static int specifier_os_release_common(const char *field, char **ret) { + char *t = NULL; + int r; + + r = parse_os_release(NULL, field, &t, NULL); + if (r < 0) + return r; + if (!t) { + /* fields in /etc/os-release might quite possibly be missing, even if everything is entirely + * valid otherwise. Let's hence return "" in that case. */ + t = strdup(""); + if (!t) + return -ENOMEM; + } + + *ret = t; + return 0; +} + +int specifier_os_id(char specifier, const void *data, const void *userdata, char **ret) { + return specifier_os_release_common("ID", ret); +} + +int specifier_os_version_id(char specifier, const void *data, const void *userdata, char **ret) { + return specifier_os_release_common("VERSION_ID", ret); +} + +int specifier_os_build_id(char specifier, const void *data, const void *userdata, char **ret) { + return specifier_os_release_common("BUILD_ID", ret); +} + +int specifier_os_variant_id(char specifier, const void *data, const void *userdata, char **ret) { + return specifier_os_release_common("VARIANT_ID", ret); +} + int specifier_group_name(char specifier, const void *data, const void *userdata, char **ret) { char *t; diff --git a/src/shared/specifier.h b/src/shared/specifier.h index d0221ef714..33c17eae67 100644 --- a/src/shared/specifier.h +++ b/src/shared/specifier.h @@ -19,6 +19,11 @@ int specifier_machine_id(char specifier, const void *data, const void *userdata, int specifier_boot_id(char specifier, const void *data, const void *userdata, char **ret); int specifier_host_name(char specifier, const void *data, const void *userdata, char **ret); int specifier_kernel_release(char specifier, const void *data, const void *userdata, char **ret); +int specifier_architecture(char specifier, const void *data, const void *userdata, char **ret); +int specifier_os_id(char specifier, const void *data, const void *userdata, char **ret); +int specifier_os_version_id(char specifier, const void *data, const void *userdata, char **ret); +int specifier_os_build_id(char specifier, const void *data, const void *userdata, char **ret); +int specifier_os_variant_id(char specifier, const void *data, const void *userdata, char **ret); int specifier_group_name(char specifier, const void *data, const void *userdata, char **ret); int specifier_group_id(char specifier, const void *data, const void *userdata, char **ret); diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c index f0359e3019..a36cfb210f 100644 --- a/src/sysusers/sysusers.c +++ b/src/sysusers/sysusers.c @@ -1393,6 +1393,11 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { { 'b', specifier_boot_id, NULL }, { 'H', specifier_host_name, NULL }, { 'v', specifier_kernel_release, NULL }, + { 'a', specifier_architecture, NULL }, + { 'o', specifier_os_id, NULL }, + { 'w', specifier_os_version_id, NULL }, + { 'B', specifier_os_build_id, NULL }, + { 'W', specifier_os_variant_id, NULL }, { 'T', specifier_tmp_dir, NULL }, { 'V', specifier_var_tmp_dir, NULL }, {} diff --git a/src/test/test-strv.c b/src/test/test-strv.c index ae128dd7e5..cba5441d4b 100644 --- a/src/test/test-strv.c +++ b/src/test/test-strv.c @@ -9,12 +9,17 @@ static void test_specifier_printf(void) { static const Specifier table[] = { - { 'a', specifier_string, (char*) "AAAA" }, - { 'b', specifier_string, (char*) "BBBB" }, - { 'm', specifier_machine_id, NULL }, - { 'B', specifier_boot_id, NULL }, - { 'H', specifier_host_name, NULL }, + { 'X', specifier_string, (char*) "AAAA" }, + { 'Y', specifier_string, (char*) "BBBB" }, + { 'm', specifier_machine_id, NULL }, + { 'b', specifier_boot_id, NULL }, + { 'H', specifier_host_name, NULL }, { 'v', specifier_kernel_release, NULL }, + { 'a', specifier_architecture, NULL }, + { 'o', specifier_os_id, NULL }, + { 'w', specifier_os_version_id, NULL }, + { 'B', specifier_os_build_id, NULL }, + { 'W', specifier_os_variant_id, NULL }, {} }; @@ -23,7 +28,7 @@ static void test_specifier_printf(void) { log_info("/* %s */", __func__); - r = specifier_printf("xxx a=%a b=%b yyy", table, NULL, &w); + r = specifier_printf("xxx a=%X b=%Y yyy", table, NULL, &w); assert_se(r >= 0); assert_se(w); @@ -31,10 +36,15 @@ static void test_specifier_printf(void) { assert_se(streq(w, "xxx a=AAAA b=BBBB yyy")); free(w); - r = specifier_printf("machine=%m, boot=%B, host=%H, version=%v", table, NULL, &w); + r = specifier_printf("machine=%m, boot=%b, host=%H, version=%v, arch=%a", table, NULL, &w); assert_se(r >= 0); assert_se(w); puts(w); + + w = mfree(w); + specifier_printf("os=%o, os-version=%w, build=%B, variant=%W", table, NULL, &w); + if (w) + puts(w); } static void test_str_in_set(void) { diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index ff1dff13da..deb3d37b03 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -185,6 +185,11 @@ static const Specifier specifier_table[] = { { 'b', specifier_boot_id, NULL }, { 'H', specifier_host_name, NULL }, { 'v', specifier_kernel_release, NULL }, + { 'a', specifier_architecture, NULL }, + { 'o', specifier_os_id, NULL }, + { 'w', specifier_os_version_id, NULL }, + { 'B', specifier_os_build_id, NULL }, + { 'W', specifier_os_variant_id, NULL }, { 'g', specifier_group_name, NULL }, { 'G', specifier_group_id, NULL }, From 503298b7243b60543ef036037508684c30e48ddb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 28 Apr 2020 22:50:50 +0200 Subject: [PATCH 2/3] man: document new specifiers --- man/standard-specifiers.xml | 32 ++++++++++++++++++++++++++++++++ man/systemd.dnssd.xml | 19 +++++++++++++------ man/systemd.unit.xml | 13 ++++++++++++- man/sysusers.d.xml | 5 +++++ man/tmpfiles.d.xml | 8 +++++++- 5 files changed, 69 insertions(+), 8 deletions(-) create mode 100644 man/standard-specifiers.xml diff --git a/man/standard-specifiers.xml b/man/standard-specifiers.xml new file mode 100644 index 0000000000..c5cd6a8862 --- /dev/null +++ b/man/standard-specifiers.xml @@ -0,0 +1,32 @@ + + + + + + + %a + Architecture + A short string identifying the architecture of the local system. A string such as x86, x86-64 or arm64. See the architectures defined for ConditionArchitecture= in systemd.unit5 for a full list. + + + %B + Operating system build ID + The operating system build identifier of the running system, as read from the BUILD_ID= field of /etc/os-release. If not set, resolves to an empty string. See os-release5 for more information. + + + %o + Operating system ID + The operating system identifier of the running system, as read from the ID= field of /etc/os-release. See os-release5 for more information. + + + %w + Operating system version ID + The operating system version identifier of the running system, as read from the VERSION_ID= field of /etc/os-release. If not set, resolves to an empty string. See os-release5 for more information. + + + %W + Operating system variant ID + The operating system variant identifier of the running system, as read from the VARIANT_ID= field of /etc/os-release. If not set, resolves to an empty string. See os-release5 for more information. + + diff --git a/man/systemd.dnssd.xml b/man/systemd.dnssd.xml index 1ac760eec7..d70cc43944 100644 --- a/man/systemd.dnssd.xml +++ b/man/systemd.dnssd.xml @@ -3,7 +3,9 @@ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> - + systemd.dnssd @@ -87,26 +89,31 @@ - - %m - Machine ID - The machine ID of the running system, formatted as string. See machine-id5 for more information. - + %b Boot ID The boot ID of the running system, formatted as string. See random4 for more information. + %H Host name The hostname of the running system. + + %m + Machine ID + The machine ID of the running system, formatted as string. See machine-id5 for more information. + + %v Kernel release Identical to uname -r output. + + diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml index c26937e752..d570016b2f 100644 --- a/man/systemd.unit.xml +++ b/man/systemd.unit.xml @@ -6,7 +6,8 @@ ]> - + systemd.unit @@ -1708,11 +1709,18 @@ + + + %a + Architecture + A short string identifying the architecture of the local system. A string such as x86, x86-64 or arm64. See the architectures defined for ConditionArchitecture= above for a full list. + %b Boot ID The boot ID of the running system, formatted as string. See random4 for more information. + %C Cache directory root @@ -1770,6 +1778,7 @@ Note that this setting is not influenced by the Us Machine ID The machine ID of the running system, formatted as string. See machine-id5 for more information. + %n Full unit name @@ -1844,6 +1853,8 @@ Note that this setting is not influenced by the Us Directory for larger and persistent temporary files This is either /var/tmp or the path $TMPDIR, $TEMP or $TMP are set to. + + %% Single percent sign diff --git a/man/sysusers.d.xml b/man/sysusers.d.xml index f0e0f2bedc..2be41c1030 100644 --- a/man/sysusers.d.xml +++ b/man/sysusers.d.xml @@ -251,11 +251,13 @@ r - 500-900 + %b Boot ID The boot ID of the running system, formatted as string. See random4 for more information. + %H Host name @@ -266,6 +268,7 @@ r - 500-900 Machine ID The machine ID of the running system, formatted as string. See machine-id5 for more information. + %T Directory for temporary files @@ -281,6 +284,8 @@ r - 500-900 Directory for larger and persistent temporary files This is either /var/tmp or the path $TMPDIR, $TEMP or $TMP are set to. + + %% Escaped % diff --git a/man/tmpfiles.d.xml b/man/tmpfiles.d.xml index a29c913ff0..79fd6a9921 100644 --- a/man/tmpfiles.d.xml +++ b/man/tmpfiles.d.xml @@ -6,7 +6,8 @@ Copyright © 2010 Brandon Philips --> - + tmpfiles.d @@ -631,11 +632,13 @@ w- /proc/sys/vm/swappiness - - - - 10 + %b Boot ID The boot ID of the running system, formatted as string. See random4 for more information. + %C System or user cache directory @@ -661,6 +664,7 @@ w- /proc/sys/vm/swappiness - - - - 10 Machine ID The machine ID of the running system, formatted as string. See machine-id5 for more information. + %S System or user state directory @@ -706,6 +710,8 @@ w- /proc/sys/vm/swappiness - - - - 10 Directory for larger and persistent temporary files This is either /var/tmp or the path $TMPDIR, $TEMP or $TMP are set to. + + %% Escaped % From 33bd857f94d6096f740234bd53306a510cef861e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 28 Apr 2020 23:16:35 +0200 Subject: [PATCH 3/3] update TODO --- TODO | 3 --- 1 file changed, 3 deletions(-) diff --git a/TODO b/TODO index 31724bdb34..9fd1fc7c4d 100644 --- a/TODO +++ b/TODO @@ -57,9 +57,6 @@ Features: * by default, in systemd --user service bump the OOMAdjust to 100, as privs allow so that systemd survives -* honour specifiers in unit files that resolve to some very basic - /etc/os-release data, such as ID, VERSION_ID, BUILD_ID, VARIANT_ID. - * cryptsetup: allow encoding key directly in /etc/crypttab, maybe with a "base64:" prefix. Useful in particular for pkcs11 mode.