diff --git a/src/shared/install.c b/src/shared/install.c index 3522af67ec..8195436564 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -3283,7 +3283,7 @@ static int split_pattern_into_name_and_instances(const char *pattern, char **out return 0; } -static int presets_find_config(RuntimeScope scope, const char *root_dir, char ***files) { +static int presets_find_config(RuntimeScope scope, const char *root_dir, char ***ret) { static const char* const initrd_dirs[] = { CONF_PATHS("systemd/initrd-preset"), NULL }; static const char* const system_dirs[] = { CONF_PATHS("systemd/system-preset"), NULL }; static const char* const user_dirs[] = { CONF_PATHS("systemd/user-preset"), NULL }; @@ -3298,13 +3298,26 @@ static int presets_find_config(RuntimeScope scope, const char *root_dir, char ** if (r < 0 && r != -ENOENT) return r; - dirs = r >= 0 ? initrd_dirs : system_dirs; + /* Make sure that we fall back to the system preset directories if we're operating on a root + * directory without initrd preset directories. This makes sure that we don't regress when + * using a newer systemctl to operate on a root directory with an older version of systemd + * installed that doesn't yet known about initrd preset directories. */ + if (r >= 0) + STRV_FOREACH(d, initrd_dirs) { + r = chase_and_access(*d, root_dir, CHASE_PREFIX_ROOT, F_OK, /* ret_path= */ NULL); + if (r >= 0) + return conf_files_list_strv(ret, ".preset", root_dir, 0, initrd_dirs); + if (r != -ENOENT) + return r; + } + + dirs = system_dirs; } else if (IN_SET(scope, RUNTIME_SCOPE_GLOBAL, RUNTIME_SCOPE_USER)) dirs = user_dirs; else assert_not_reached(); - return conf_files_list_strv(files, ".preset", root_dir, 0, dirs); + return conf_files_list_strv(ret, ".preset", root_dir, 0, dirs); } static int read_presets(RuntimeScope scope, const char *root_dir, UnitFilePresets *presets) {