diff --git a/TODO b/TODO
index d6d9901e64..96d28f8bf0 100644
--- a/TODO
+++ b/TODO
@@ -24,6 +24,9 @@ Janitorial Clean-ups:
Features:
+* document specifiers systemd-sysusers understands in its man page (the way
+ it's already documented in tmpfiles.d(5)' man page)
+
* add O_TMPFILE support to copy_file_atomic()
* nspawn: greater control over selinux label?
diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
index 73a0462a2b..b6f4728b00 100644
--- a/man/systemd.unit.xml
+++ b/man/systemd.unit.xml
@@ -1537,24 +1537,29 @@
- %n
- Full unit name
-
+ %b
+ Boot ID
+ The boot ID of the running system, formatted as string. See random4 for more information.
- %N
- Full unit name
- Same as %n, but with the type suffix removed.
+ %C
+ Cache directory root
+ This is either /var/cache (for the system manager) or the path $XDG_CACHE_HOME resolves to (for user managers).
- %p
- Prefix name
- For instantiated units, this refers to the string before the first @ character of the unit name. For non-instantiated units, same as %N.
+ %f
+ Unescaped filename
+ This is either the unescaped instance name (if applicable) with / prepended (if applicable), or the unescaped prefix name prepended with /. This implements unescaping according to the rules for escaping absolute file system paths discussed above.
- %P
- Unescaped prefix name
- Same as %p, but with escaping undone.
+ %h
+ User home directory
+ This is the home directory of the user running the service manager instance. In case of the system manager this resolves to /root.
+
+
+ %H
+ Host name
+ The hostname of the running system at the point in time the unit configuration is loaded.%i
@@ -1577,14 +1582,39 @@
Same as %j, but with escaping undone.
- %f
- Unescaped filename
- This is either the unescaped instance name (if applicable) with / prepended (if applicable), or the unescaped prefix name prepended with /. This implements unescaping according to the rules for escaping absolute file system paths discussed above.
+ %L
+ Log directory root
+ This is either /var/log (for the system manager) or the path $XDG_CONFIG_HOME resolves to with /log appended (for user managers).
- %t
- Runtime directory root
- This is either /run (for the system manager) or the path $XDG_RUNTIME_DIR resolves to (for user managers).
+ %m
+ Machine ID
+ The machine ID of the running system, formatted as string. See machine-id5 for more information.
+
+
+ %n
+ Full unit name
+
+
+
+ %N
+ Full unit name
+ Same as %n, but with the type suffix removed.
+
+
+ %p
+ Prefix name
+ For instantiated units, this refers to the string before the first @ character of the unit name. For non-instantiated units, same as %N.
+
+
+ %P
+ Unescaped prefix name
+ Same as %p, but with escaping undone.
+
+
+ %s
+ User shell
+ This is the shell of the user running the service manager instance. In case of the system manager this resolves to /bin/sh.%S
@@ -1592,14 +1622,14 @@
This is either /var/lib (for the system manager) or the path $XDG_CONFIG_HOME resolves to (for user managers).
- %C
- Cache directory root
- This is either /var/cache (for the system manager) or the path $XDG_CACHE_HOME resolves to (for user managers).
+ %t
+ Runtime directory root
+ This is either /run (for the system manager) or the path $XDG_RUNTIME_DIR resolves to (for user managers).
- %L
- Log directory root
- This is either /var/log (for the system manager) or the path $XDG_CONFIG_HOME resolves to with /log appended (for user managers).
+ %T
+ Directory for temporary files
+ This is either /tmp or the path $TMPDIR, $TEMP or $TMP are set to.%u
@@ -1611,36 +1641,16 @@
User UIDThis is the numeric UID of the user running the service manager instance. In case of the system manager this resolves to 0.
-
- %h
- User home directory
- This is the home directory of the user running the service manager instance. In case of the system manager this resolves to /root.
-
-
- %s
- User shell
- This is the shell of the user running the service manager instance. In case of the system manager this resolves to /bin/sh.
-
-
- %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 at the point in time the unit configuration is loaded.
- %vKernel releaseIdentical to uname -r output
+
+ %V
+ 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/tmpfiles.d.xml b/man/tmpfiles.d.xml
index ed119ad86a..809f992994 100644
--- a/man/tmpfiles.d.xml
+++ b/man/tmpfiles.d.xml
@@ -611,61 +611,71 @@ r! /tmp/.X[0-9]*-lock
-
- %m
- Machine ID
- The machine ID of the running system, formatted as string. See machine-id5 for more information.
- %bBoot IDThe boot ID of the running system, formatted as string. See random4 for more information.
-
- %H
- Host name
- The hostname of the running system.
-
-
- %v
- Kernel release
- Identical to uname -r output.
-
-
- %U
- User UID
- This is the numeric UID of the user running the service manager instance. In case of the system manager this resolves to 0.
-
-
- %u
- User name
- This is the name of the user running the service manager instance. In case of the system manager this resolves to root.
-
-
- %h
- User home directory
- This is the home directory of the user running the service manager instance. In case of the system manager this resolves to /root.
-
-
- %t
- System or user runtime directory
- In --user mode, this is the same $XDG_RUNTIME_DIR, and /run otherwise.
-
-
- %S
- System or user state directory
- In mode, this is the same as $XDG_CONFIG_HOME, and /var/lib otherwise.
- %CSystem or user cache directoryIn mode, this is the same as $XDG_CACHE_HOME, and /var/cache otherwise.
+
+ %h
+ User home directory
+ This is the home directory of the user running the command. In case of the system instance this resolves to /root.
+
+
+ %H
+ Host name
+ The hostname of the running system.
+ %LSystem or user log directoryIn mode, this is the same as $XDG_CONFIG_HOME with /log appended, and /var/log otherwise.
+
+ %m
+ Machine ID
+ The machine ID of the running system, formatted as string. See machine-id5 for more information.
+
+
+ %S
+ System or user state directory
+ In mode, this is the same as $XDG_CONFIG_HOME, and /var/lib otherwise.
+
+
+ %t
+ System or user runtime directory
+ In --user mode, this is the same $XDG_RUNTIME_DIR, and /run otherwise.
+
+
+ %T
+ Directory for temporary files
+ This is either /tmp or the path $TMPDIR, $TEMP or $TMP are set to.
+
+
+ %u
+ User name
+ This is the name of the user running the command. In case of the system instance this resolves to root.
+
+
+ %U
+ User UID
+ This is the numeric UID of the user running the command. In case of the system instance this resolves to 0.
+
+
+ %v
+ Kernel release
+ Identical to uname -r output.
+
+
+ %V
+ 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 d2948ab6aa..20891200ba 100644
--- a/src/core/unit-printf.c
+++ b/src/core/unit-printf.c
@@ -232,6 +232,8 @@ int unit_full_printf(Unit *u, const char *format, char **ret) {
* %S: the state directory root (e.g. /var/lib or $XDG_CONFIG_HOME)
* %C: the cache directory root (e.g. /var/cache or $XDG_CACHE_HOME)
* %L: the log directory root (e.g. /var/log or $XDG_CONFIG_HOME/log)
+ * %T: the temporary directory (e.g. /tmp, or $TMPDIR, $TEMP, $TMP)
+ * %V: the temporary directory for large, persistent stuff (e.g. /var/tmp, or $TMPDIR, $TEMP, $TMP)
*
* %h: the homedir of the running user
* %s: the shell of the running user
@@ -257,10 +259,13 @@ int unit_full_printf(Unit *u, const char *format, char **ret) {
{ 'c', specifier_cgroup, NULL },
{ 'r', specifier_cgroup_slice, NULL },
{ 'R', specifier_cgroup_root, NULL },
+
{ 't', specifier_special_directory, UINT_TO_PTR(EXEC_DIRECTORY_RUNTIME) },
{ 'S', specifier_special_directory, UINT_TO_PTR(EXEC_DIRECTORY_STATE) },
{ 'C', specifier_special_directory, UINT_TO_PTR(EXEC_DIRECTORY_CACHE) },
{ 'L', specifier_special_directory, UINT_TO_PTR(EXEC_DIRECTORY_LOGS) },
+ { 'T', specifier_tmp_dir, NULL },
+ { 'V', specifier_var_tmp_dir, NULL },
{ 'U', specifier_user_id, NULL },
{ 'u', specifier_user_name, NULL },
diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c
index 8803326c29..e9fd148469 100644
--- a/src/resolve/resolved-conf.c
+++ b/src/resolve/resolved-conf.c
@@ -222,8 +222,8 @@ 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[] = {
{ 'b', specifier_boot_id, NULL },
- { 'H', specifier_host_name, NULL },
- { 'm', specifier_machine_id, NULL },
+ { 'H', specifier_host_name, NULL },
+ { 'm', specifier_machine_id, NULL },
{ 'v', specifier_kernel_release, NULL },
{}
};
diff --git a/src/resolve/resolved-dnssd.c b/src/resolve/resolved-dnssd.c
index 02e012f4ec..08b23072d6 100644
--- a/src/resolve/resolved-dnssd.c
+++ b/src/resolve/resolved-dnssd.c
@@ -166,7 +166,7 @@ int dnssd_render_instance_name(DnssdService *s, char **ret_name) {
static const Specifier specifier_table[] = {
{ 'b', specifier_boot_id, NULL },
{ 'H', specifier_dnssd_host_name, NULL },
- { 'm', specifier_machine_id, NULL },
+ { 'm', specifier_machine_id, NULL },
{ 'v', specifier_kernel_release, NULL },
{}
};
diff --git a/src/shared/specifier.c b/src/shared/specifier.c
index 27782b8d5b..c4b2bdc12d 100644
--- a/src/shared/specifier.c
+++ b/src/shared/specifier.c
@@ -15,6 +15,7 @@
#include "sd-id128.h"
#include "alloc-util.h"
+#include "fs-util.h"
#include "hostname-util.h"
#include "macro.h"
#include "specifier.h"
@@ -222,6 +223,40 @@ int specifier_user_shell(char specifier, void *data, void *userdata, char **ret)
return get_shell(ret);
}
+int specifier_tmp_dir(char specifier, void *data, void *userdata, char **ret) {
+ const char *p;
+ char *copy;
+ int r;
+
+ r = tmp_dir(&p);
+ if (r < 0)
+ return r;
+
+ copy = strdup(p);
+ if (!copy)
+ return -ENOMEM;
+
+ *ret = copy;
+ return 0;
+}
+
+int specifier_var_tmp_dir(char specifier, void *data, void *userdata, char **ret) {
+ const char *p;
+ char *copy;
+ int r;
+
+ r = var_tmp_dir(&p);
+ if (r < 0)
+ return r;
+
+ copy = strdup(p);
+ if (!copy)
+ return -ENOMEM;
+
+ *ret = copy;
+ return 0;
+}
+
int specifier_escape_strv(char **l, char ***ret) {
char **z, **p, **q;
diff --git a/src/shared/specifier.h b/src/shared/specifier.h
index b998c2a759..33c0e2727e 100644
--- a/src/shared/specifier.h
+++ b/src/shared/specifier.h
@@ -31,6 +31,9 @@ int specifier_user_id(char specifier, void *data, void *userdata, char **ret);
int specifier_user_home(char specifier, void *data, void *userdata, char **ret);
int specifier_user_shell(char specifier, void *data, void *userdata, char **ret);
+int specifier_tmp_dir(char specifier, void *data, void *userdata, char **ret);
+int specifier_var_tmp_dir(char specifier, void *data, void *userdata, char **ret);
+
static inline char* specifier_escape(const char *string) {
return strreplace(string, "%", "%%");
}
diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c
index af041d2f74..b521200346 100644
--- a/src/sysusers/sysusers.c
+++ b/src/sysusers/sysusers.c
@@ -1359,10 +1359,12 @@ static bool item_equal(Item *a, Item *b) {
static int parse_line(const char *fname, unsigned line, const char *buffer) {
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 },
+ { 'b', specifier_boot_id, NULL },
+ { 'H', specifier_host_name, NULL },
{ 'v', specifier_kernel_release, NULL },
+ { 'T', specifier_tmp_dir, NULL },
+ { 'V', specifier_var_tmp_dir, NULL },
{}
};
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index 9a9cfdd8a2..049e24b8bd 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -179,10 +179,13 @@ static const Specifier specifier_table[] = {
{ 'U', specifier_user_id, NULL },
{ 'u', specifier_user_name, NULL },
{ 'h', specifier_user_home, NULL },
+
{ 't', specifier_directory, UINT_TO_PTR(DIRECTORY_RUNTIME) },
{ 'S', specifier_directory, UINT_TO_PTR(DIRECTORY_STATE) },
{ 'C', specifier_directory, UINT_TO_PTR(DIRECTORY_CACHE) },
{ 'L', specifier_directory, UINT_TO_PTR(DIRECTORY_LOGS) },
+ { 'T', specifier_tmp_dir, NULL },
+ { 'V', specifier_var_tmp_dir, NULL },
{}
};
diff --git a/test/test-execute/exec-specifier.service b/test/test-execute/exec-specifier.service
index 926d45182b..e46373ddfe 100644
--- a/test/test-execute/exec-specifier.service
+++ b/test/test-execute/exec-specifier.service
@@ -16,6 +16,8 @@ ExecStart=test %t = /run
ExecStart=test %S = /var/lib
ExecStart=test %C = /var/cache
ExecStart=test %L = /var/log
+ExecStart=test %T = /tmp
+ExecStart=test %V = /var/tmp
ExecStart=sh -c 'test %u = $$(id -un 0)'
ExecStart=test %U = 0
ExecStart=sh -c 'test %h = $$(getent passwd 0 | cut -d: -f 6)'