diff --git a/src/core/manager.c b/src/core/manager.c index 156943b356..5bfb74be9d 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1127,8 +1127,7 @@ Manager* manager_free(Manager *m) { if (unit_vtable[c]->shutdown) unit_vtable[c]->shutdown(m); - /* If we reexecute ourselves, we keep the root cgroup - * around */ + /* If we reexecute ourselves, we keep the root cgroup around */ manager_shutdown_cgroup(m, m->exit_code != MANAGER_REEXECUTE); lookup_paths_flush_generator(&m->lookup_paths); @@ -1311,7 +1310,11 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { assert(m); - r = lookup_paths_init(&m->lookup_paths, m->unit_file_scope, 0, NULL); + /* If we are running in test mode, we still want to run the generators, + * but we should not touch the real generator directories. */ + r = lookup_paths_init(&m->lookup_paths, m->unit_file_scope, + m->test_run ? LOOKUP_PATHS_TEMPORARY_GENERATED : 0, + NULL); if (r < 0) return r; @@ -1319,12 +1322,11 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { if (r < 0) return r; - /* Make sure the transient directory always exists, so that it remains in the search path */ - if (!m->test_run) { - r = mkdir_p_label(m->lookup_paths.transient, 0755); - if (r < 0) - return r; - } + /* Make sure the transient directory always exists, so that it remains + * in the search path */ + r = mkdir_p_label(m->lookup_paths.transient, 0755); + if (r < 0) + return r; dual_timestamp_get(&m->generators_start_timestamp); r = manager_run_generators(m); @@ -3146,9 +3148,6 @@ static int manager_run_environment_generators(Manager *m) { const char **paths; void* args[] = {&tmp, &tmp, &m->environment}; - if (m->test_run) - return 0; - paths = MANAGER_IS_SYSTEM(m) ? system_env_generator_binary_paths : user_env_generator_binary_paths; if (!generator_path_any(paths)) @@ -3164,9 +3163,6 @@ static int manager_run_generators(Manager *m) { assert(m); - if (m->test_run) - return 0; - paths = generator_binary_paths(m->unit_file_scope); if (!paths) return log_oom(); diff --git a/src/shared/path-lookup.c b/src/shared/path-lookup.c index e2b3f8b742..0b067ddf01 100644 --- a/src/shared/path-lookup.c +++ b/src/shared/path-lookup.c @@ -23,6 +23,8 @@ #include #include "alloc-util.h" +#include "fileio.h" +#include "fs-util.h" #include "install.h" #include "log.h" #include "macro.h" @@ -226,50 +228,48 @@ static char** user_dirs( static int acquire_generator_dirs( UnitFileScope scope, + const char *tempdir, char **generator, char **generator_early, char **generator_late) { + _cleanup_(rmdir_and_freep) char *t = NULL; _cleanup_free_ char *x = NULL, *y = NULL, *z = NULL; const char *prefix; assert(generator); assert(generator_early); assert(generator_late); + assert(IN_SET(scope, UNIT_FILE_SYSTEM, UNIT_FILE_USER, UNIT_FILE_GLOBAL)); - switch (scope) { + if (scope == UNIT_FILE_GLOBAL) + return -EOPNOTSUPP; - case UNIT_FILE_SYSTEM: - prefix = "/run/systemd/"; - break; + if (tempdir) + prefix = tempdir; - case UNIT_FILE_USER: { + else if (scope == UNIT_FILE_SYSTEM) + prefix = "/run/systemd"; + + else if (scope == UNIT_FILE_USER) { const char *e; e = getenv("XDG_RUNTIME_DIR"); if (!e) return -ENXIO; - prefix = strjoina(e, "/systemd/"); - break; + prefix = strjoina(e, "/systemd"); } - case UNIT_FILE_GLOBAL: - return -EOPNOTSUPP; - - default: - assert_not_reached("Hmm, unexpected scope value."); - } - - x = strappend(prefix, "generator"); + x = strappend(prefix, "/generator"); if (!x) return -ENOMEM; - y = strappend(prefix, "generator.early"); + y = strappend(prefix, "/generator.early"); if (!y) return -ENOMEM; - z = strappend(prefix, "generator.late"); + z = strappend(prefix, "/generator.late"); if (!z) return -ENOMEM; @@ -281,31 +281,30 @@ static int acquire_generator_dirs( return 0; } -static int acquire_transient_dir(UnitFileScope scope, char **ret) { +static int acquire_transient_dir( + UnitFileScope scope, + const char *tempdir, + char **ret) { + + char *transient; + assert(ret); + assert(IN_SET(scope, UNIT_FILE_SYSTEM, UNIT_FILE_USER, UNIT_FILE_GLOBAL)); - switch (scope) { - - case UNIT_FILE_SYSTEM: { - char *transient; - - transient = strdup("/run/systemd/transient"); - if (!transient) - return -ENOMEM; - - *ret = transient; - return 0; - } - - case UNIT_FILE_USER: - return user_runtime_dir(ret, "/systemd/transient"); - - case UNIT_FILE_GLOBAL: + if (scope == UNIT_FILE_GLOBAL) return -EOPNOTSUPP; - default: - assert_not_reached("Hmm, unexpected scope value."); - } + if (tempdir) + transient = strjoin(tempdir, "/transient"); + else if (scope == UNIT_FILE_SYSTEM) + transient = strdup("/run/systemd/transient"); + else + return user_runtime_dir(ret, "/systemd/transient"); + + if (!transient) + return -ENOMEM; + *ret = transient; + return 0; } static int acquire_config_dirs(UnitFileScope scope, char **persistent, char **runtime) { @@ -457,6 +456,7 @@ int lookup_paths_init( LookupPathsFlags flags, const char *root_dir) { + _cleanup_(rmdir_and_freep) char *tempdir = NULL; _cleanup_free_ char *root = NULL, *persistent_config = NULL, *runtime_config = NULL, @@ -487,6 +487,12 @@ int lookup_paths_init( return -ENOMEM; } + if (flags & LOOKUP_PATHS_TEMPORARY_GENERATED) { + r = mkdtemp_malloc("/tmp/systemd-temporary-XXXXXX", &tempdir); + if (r < 0) + return log_error_errno(r, "Failed to create temporary directory: %m"); + } + /* Note: when XDG_RUNTIME_DIR is not set this will not return -ENXIO, but simply set runtime_config to NULL */ r = acquire_config_dirs(scope, &persistent_config, &runtime_config); if (r < 0) @@ -494,13 +500,14 @@ int lookup_paths_init( if ((flags & LOOKUP_PATHS_EXCLUDE_GENERATED) == 0) { /* Note: if XDG_RUNTIME_DIR is not set, this will fail completely with ENXIO */ - r = acquire_generator_dirs(scope, &generator, &generator_early, &generator_late); + r = acquire_generator_dirs(scope, tempdir, + &generator, &generator_early, &generator_late); if (r < 0 && r != -EOPNOTSUPP && r != -ENXIO) return r; } /* Note: if XDG_RUNTIME_DIR is not set, this will fail completely with ENXIO */ - r = acquire_transient_dir(scope, &transient); + r = acquire_transient_dir(scope, tempdir, &transient); if (r < 0 && r != -EOPNOTSUPP && r != -ENXIO) return r; @@ -669,6 +676,9 @@ int lookup_paths_init( p->root_dir = root; root = NULL; + p->temporary_dir = tempdir; + tempdir = NULL; + return 0; } @@ -811,6 +821,9 @@ void lookup_paths_flush_generator(LookupPaths *p) { (void) rm_rf(p->generator_early, REMOVE_ROOT); if (p->generator_late) (void) rm_rf(p->generator_late, REMOVE_ROOT); + + if (p->temporary_dir) + (void) rm_rf(p->temporary_dir, REMOVE_ROOT); } char **generator_binary_paths(UnitFileScope scope) { diff --git a/src/shared/path-lookup.h b/src/shared/path-lookup.h index f9bb2fe237..45fba64d2a 100644 --- a/src/shared/path-lookup.h +++ b/src/shared/path-lookup.h @@ -28,6 +28,7 @@ typedef struct LookupPaths LookupPaths; typedef enum LookupPathsFlags { LOOKUP_PATHS_EXCLUDE_GENERATED = 1, + LOOKUP_PATHS_TEMPORARY_GENERATED, } LookupPathsFlags; struct LookupPaths { @@ -60,6 +61,9 @@ struct LookupPaths { /* The root directory prepended to all items above, or NULL */ char *root_dir; + + /* A temporary directory when running in test mode, to be nuked */ + char *temporary_dir; }; int lookup_paths_init(LookupPaths *p, UnitFileScope scope, LookupPathsFlags flags, const char *root_dir);