From a4f7c9589e0500bf64e5b65c73e1db47d1f54225 Mon Sep 17 00:00:00 2001 From: Skye Soss Date: Sun, 31 May 2026 12:24:33 -0500 Subject: [PATCH] tmpfiles: add %D specifier resolution systemd-tmpfiles now resolves the %D specifier to /usr/share (for the system manager) or $XDG_DATA_HOME (for the user manager). Closes: https://github.com/systemd/systemd/issues/42010 Signed-off-by: Skye Soss --- man/standard-specifiers.xml | 5 +++++ man/systemd.unit.xml | 6 +----- man/tmpfiles.d.xml | 1 + src/tmpfiles/tmpfiles.c | 4 ++++ test/test-systemd-tmpfiles.py | 7 +++++++ 5 files changed, 18 insertions(+), 5 deletions(-) diff --git a/man/standard-specifiers.xml b/man/standard-specifiers.xml index 3a2c0b0266a..f4150531f2d 100644 --- a/man/standard-specifiers.xml +++ b/man/standard-specifiers.xml @@ -27,6 +27,11 @@ 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. + + %D + Shared data directory + This is either /usr/share/ (for the system manager) or the path $XDG_DATA_HOME resolves to (for user managers). + %H Host name diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml index 5d2f32dfcef..d032d91f3a0 100644 --- a/man/systemd.unit.xml +++ b/man/systemd.unit.xml @@ -2452,11 +2452,7 @@ Credentials directory This is the value of the $CREDENTIALS_DIRECTORY environment variable if available. See section "Credentials" in systemd.exec5 for more information. - - %D - Shared data directory - This is either /usr/share/ (for the system manager) or the path $XDG_DATA_HOME resolves to (for user managers). - + %E Configuration directory root diff --git a/man/tmpfiles.d.xml b/man/tmpfiles.d.xml index e5f694611a6..00c6ecb3995 100644 --- a/man/tmpfiles.d.xml +++ b/man/tmpfiles.d.xml @@ -778,6 +778,7 @@ d /tmp/foo/bar - - - bmA:1h - System or user cache directory In mode, this is the same as $XDG_CACHE_HOME, and /var/cache otherwise. + %g User group diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 2c7ac181095..82d68254578 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -205,6 +205,7 @@ typedef enum DirectoryType { DIRECTORY_STATE, DIRECTORY_CACHE, DIRECTORY_LOGS, + DIRECTORY_SHARED, _DIRECTORY_TYPE_MAX, } DirectoryType; @@ -293,6 +294,7 @@ static int specifier_directory( [DIRECTORY_STATE] = { SD_PATH_SYSTEM_STATE_PRIVATE }, [DIRECTORY_CACHE] = { SD_PATH_SYSTEM_STATE_CACHE }, [DIRECTORY_LOGS] = { SD_PATH_SYSTEM_STATE_LOGS }, + [DIRECTORY_SHARED] = { SD_PATH_SYSTEM_SHARED }, }; static const struct table_entry paths_user[] = { @@ -300,6 +302,7 @@ static int specifier_directory( [DIRECTORY_STATE] = { SD_PATH_USER_STATE_PRIVATE }, [DIRECTORY_CACHE] = { SD_PATH_USER_STATE_CACHE }, [DIRECTORY_LOGS] = { SD_PATH_USER_STATE_PRIVATE, "log" }, + [DIRECTORY_SHARED] = { SD_PATH_USER_SHARED }, }; const struct table_entry *paths; @@ -3907,6 +3910,7 @@ static int parse_line( { 'h', specifier_user_home, NULL }, { 'C', specifier_directory, UINT_TO_PTR(DIRECTORY_CACHE) }, + { 'D', specifier_directory, UINT_TO_PTR(DIRECTORY_SHARED) }, { 'L', specifier_directory, UINT_TO_PTR(DIRECTORY_LOGS) }, { 'S', specifier_directory, UINT_TO_PTR(DIRECTORY_STATE) }, { 't', specifier_directory, UINT_TO_PTR(DIRECTORY_RUNTIME) }, diff --git a/test/test-systemd-tmpfiles.py b/test/test-systemd-tmpfiles.py index 03022a9d5de..10e6f69b56a 100755 --- a/test/test-systemd-tmpfiles.py +++ b/test/test-systemd-tmpfiles.py @@ -160,6 +160,13 @@ def test_valid_specifiers(*, user): xdg_cache_home if user else '/var/cache', user=user) # fmt: skip + xdg_data_home = os.getenv('XDG_DATA_HOME') + if xdg_data_home is None and user: + xdg_data_home = os.path.join(home, '.local/share') + test_content('f {} - - - - %D', + xdg_data_home if user else '/usr/share', + user=user) # fmt: skip + test_content('f {} - - - - %L', os.path.join(xdg_state_home, 'log') if user else '/var/log', user=user) # fmt: skip -- 2.47.3