summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/basic/strv.c36
-rw-r--r--src/basic/strv.h1
-rw-r--r--src/core/scope.c25
-rw-r--r--src/core/slice.c1
-rw-r--r--src/core/unit.c61
-rw-r--r--src/core/unit.h3
6 files changed, 109 insertions, 18 deletions
diff --git a/src/basic/strv.c b/src/basic/strv.c
index 8282298dca..97a96e5762 100644
--- a/src/basic/strv.c
+++ b/src/basic/strv.c
@@ -558,6 +558,42 @@ int strv_extend(char ***l, const char *value) {
return strv_consume(l, v);
}
+int strv_extend_front(char ***l, const char *value) {
+ size_t n, m;
+ char *v, **c;
+
+ assert(l);
+
+ /* Like strv_extend(), but prepends rather than appends the new entry */
+
+ if (!value)
+ return 0;
+
+ n = strv_length(*l);
+
+ /* Increase and overflow check. */
+ m = n + 2;
+ if (m < n)
+ return -ENOMEM;
+
+ v = strdup(value);
+ if (!v)
+ return -ENOMEM;
+
+ c = realloc_multiply(*l, sizeof(char*), m);
+ if (!c) {
+ free(v);
+ return -ENOMEM;
+ }
+
+ memmove(c+1, c, n * sizeof(char*));
+ c[0] = v;
+ c[n+1] = NULL;
+
+ *l = c;
+ return 0;
+}
+
char **strv_uniq(char **l) {
char **i;
diff --git a/src/basic/strv.h b/src/basic/strv.h
index 7bfa54408d..f61bbb5386 100644
--- a/src/basic/strv.h
+++ b/src/basic/strv.h
@@ -50,6 +50,7 @@ int strv_extend_strv(char ***a, char **b, bool filter_duplicates);
int strv_extend_strv_concat(char ***a, char **b, const char *suffix);
int strv_extend(char ***l, const char *value);
int strv_extendf(char ***l, const char *format, ...) _printf_(2,0);
+int strv_extend_front(char ***l, const char *value);
int strv_push(char ***l, char *value);
int strv_push_pair(char ***l, char *a, char *b);
int strv_push_prepend(char ***l, char *value);
diff --git a/src/core/scope.c b/src/core/scope.c
index 92a3aed331..7078d1f7e9 100644
--- a/src/core/scope.c
+++ b/src/core/scope.c
@@ -155,25 +155,26 @@ static int scope_load(Unit *u) {
assert(u->load_state == UNIT_STUB);
if (!u->transient && !MANAGER_IS_RELOADING(u->manager))
+ /* Refuse to load non-transient scope units, but allow them while reloading. */
return -ENOENT;
- u->load_state = UNIT_LOADED;
-
- r = unit_load_dropin(u);
+ r = unit_load_fragment_and_dropin_optional(u);
if (r < 0)
return r;
- r = unit_patch_contexts(u);
- if (r < 0)
- return r;
+ if (u->load_state == UNIT_LOADED) {
+ r = unit_patch_contexts(u);
+ if (r < 0)
+ return r;
- r = unit_set_default_slice(u);
- if (r < 0)
- return r;
+ r = unit_set_default_slice(u);
+ if (r < 0)
+ return r;
- r = scope_add_default_dependencies(s);
- if (r < 0)
- return r;
+ r = scope_add_default_dependencies(s);
+ if (r < 0)
+ return r;
+ }
return scope_verify(s);
}
diff --git a/src/core/slice.c b/src/core/slice.c
index 667f61bde5..63a77c9bca 100644
--- a/src/core/slice.c
+++ b/src/core/slice.c
@@ -135,6 +135,7 @@ static int slice_load(Unit *u) {
int r;
assert(s);
+ assert(u->load_state == UNIT_STUB);
r = unit_load_fragment_and_dropin_optional(u);
if (r < 0)
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;
}
diff --git a/src/core/unit.h b/src/core/unit.h
index 601e763ce2..cfdac852a5 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -95,6 +95,9 @@ struct Unit {
usec_t source_mtime;
usec_t dropin_mtime;
+ /* If this is a transient unit we are currently writing, this is where we are writing it to */
+ FILE *transient_file;
+
/* If there is something to do with this unit, then this is the installed job for it */
Job *job;