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.
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 %
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 00e6eb96e9..7137e9fbd7 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 },