From 4f4afc88ecd8ab9cfe9e1eeea7e3aeb937811937 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 7 Apr 2016 15:43:59 +0200 Subject: core: rework how transient unit files and property drop-ins work With this change the logic for placing transient unit files and drop-ins generated via "systemctl set-property" is reworked. The latter are now placed in the newly introduced "control" unit file directory. The fomer are now placed in the "transient" unit file directory. Note that the properties originally set when a transient unit was created will be written to and stay in the transient unit file directory, while later changes are done via drop-ins. This is preparation for a later "systemctl revert" addition, where existing drop-ins are flushed out, but the original transient definition is restored. --- src/core/unit.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 55 insertions(+), 6 deletions(-) (limited to 'src/core/unit.c') diff --git a/src/core/unit.c b/src/core/unit.c index ac29353299..c028f57f13 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -52,6 +52,7 @@ #include "stdio-util.h" #include "string-util.h" #include "strv.h" +#include "umask-util.h" #include "unit-name.h" #include "unit.h" #include "user-util.h" @@ -492,6 +493,9 @@ void unit_free(Unit *u) { assert(u); + if (u->transient_file) + fclose(u->transient_file); + if (!MANAGER_IS_RELOADING(u->manager)) unit_remove_transient(u); @@ -1231,6 +1235,15 @@ int unit_load(Unit *u) { if (u->load_state != UNIT_STUB) return 0; + if (u->transient_file) { + r = fflush_and_check(u->transient_file); + if (r < 0) + goto fail; + + fclose(u->transient_file); + u->transient_file = NULL; + } + if (UNIT_VTABLE(u)->load) { r = UNIT_VTABLE(u)->load(u); if (r < 0) @@ -3327,14 +3340,17 @@ ExecRuntime *unit_get_exec_runtime(Unit *u) { static const char* unit_drop_in_dir(Unit *u, UnitSetPropertiesMode mode) { assert(u); + if (!IN_SET(mode, UNIT_RUNTIME, UNIT_PERSISTENT)) + return NULL; + if (u->transient) /* Redirect drop-ins for transient units always into the transient directory. */ return u->manager->lookup_paths.transient; if (mode == UNIT_RUNTIME) - return u->manager->lookup_paths.runtime_config; + return u->manager->lookup_paths.runtime_control; if (mode == UNIT_PERSISTENT) - return u->manager->lookup_paths.persistent_config; + return u->manager->lookup_paths.persistent_control; return NULL; } @@ -3346,6 +3362,13 @@ int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, co assert(u); + if (u->transient_file) { + /* When this is a transient unit file in creation, then let's not create a new drop-in but instead + * write to the transient unit file. */ + fputs(data, u->transient_file); + return 0; + } + if (!IN_SET(mode, UNIT_PERSISTENT, UNIT_RUNTIME)) return 0; @@ -3435,24 +3458,50 @@ int unit_write_drop_in_private_format(Unit *u, UnitSetPropertiesMode mode, const } int unit_make_transient(Unit *u) { + FILE *f; + char *path; + assert(u); if (!UNIT_VTABLE(u)->can_transient) return -EOPNOTSUPP; - u->load_state = UNIT_STUB; - u->load_error = 0; - u->transient = true; + path = strjoin(u->manager->lookup_paths.transient, "/", u->id, NULL); + if (!path) + return -ENOMEM; + + /* Let's open the file we'll write the transient settings into. This file is kept open as long as we are + * creating the transient, and is closed in unit_load(), as soon as we start loading the file. */ + + RUN_WITH_UMASK(0022) + f = fopen(path, "we"); + if (!f) { + free(path); + return -errno; + } + + if (u->transient_file) + fclose(u->transient_file); + u->transient_file = f; + + free(u->fragment_path); + u->fragment_path = path; - u->fragment_path = mfree(u->fragment_path); u->source_path = mfree(u->source_path); u->dropin_paths = strv_free(u->dropin_paths); u->fragment_mtime = u->source_mtime = u->dropin_mtime = 0; + u->load_state = UNIT_STUB; + u->load_error = 0; + u->transient = true; + unit_add_to_dbus_queue(u); unit_add_to_gc_queue(u); unit_add_to_load_queue(u); + fputs("# This is a transient unit file, created programmatically via the systemd API. Do not edit.\n", + u->transient_file); + return 0; } -- cgit v1.2.3-54-g00ecf