]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/core/unit.c
tree-wide: use mdash instead of a two minuses
[thirdparty/systemd.git] / src / core / unit.c
index f6c9891aad6b3ee2e8c028ab9521685d83a734fe..1f57293a0b0f8d4c0d3874a4bb3b14aaa08a5daa 100644 (file)
 #include "path-util.h"
 #include "process-util.h"
 #include "set.h"
+#include "signal-util.h"
 #include "special.h"
 #include "stat-util.h"
 #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 +494,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 +1236,17 @@ 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;
+
+                u->dropin_mtime = now(CLOCK_REALTIME);
+        }
+
         if (UNIT_VTABLE(u)->load) {
                 r = UNIT_VTABLE(u)->load(u);
                 if (r < 0)
@@ -2502,12 +2518,11 @@ int unit_install_bus_match(Unit *u, sd_bus *bus, const char *name) {
                 return -EBUSY;
 
         match = strjoina("type='signal',"
-                        "sender='org.freedesktop.DBus',"
-                        "path='/org/freedesktop/DBus',"
-                        "interface='org.freedesktop.DBus',"
-                        "member='NameOwnerChanged',"
-                        "arg0='", name, "'",
-                        NULL);
+                         "sender='org.freedesktop.DBus',"
+                         "path='/org/freedesktop/DBus',"
+                         "interface='org.freedesktop.DBus',"
+                         "member='NameOwnerChanged',"
+                         "arg0='", name, "'");
 
         return sd_bus_add_match(bus, &u->match_bus_slot, match, signal_name_owner_changed, u);
 }
@@ -3049,8 +3064,7 @@ bool unit_active_or_pending(Unit *u) {
 int unit_kill(Unit *u, KillWho w, int signo, sd_bus_error *error) {
         assert(u);
         assert(w >= 0 && w < _KILL_WHO_MAX);
-        assert(signo > 0);
-        assert(signo < _NSIG);
+        assert(SIGNAL_VALID(signo));
 
         if (!UNIT_VTABLE(u)->kill)
                 return -EOPNOTSUPP;
@@ -3327,25 +3341,35 @@ 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;
 }
 
 int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data) {
         _cleanup_free_ char *p = NULL, *q = NULL;
-        const char *dir;
+        const char *dir, *prefixed;
         int r;
 
         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;
 
@@ -3353,19 +3377,23 @@ int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, co
         if (!dir)
                 return -EINVAL;
 
-        r = write_drop_in(dir, u->id, 50, name, data);
+        prefixed = strjoina("# This is a drop-in unit file extension, created via \"systemctl set-property\" or an equivalent operation. Do not edit.\n",
+                            data);
+
+        r = drop_in_file(dir, u->id, 50, name, &p, &q);
         if (r < 0)
                 return r;
 
-        r = drop_in_file(dir, u->id, 50, name, &p, &q);
+        (void) mkdir_p(p, 0755);
+        r = write_string_file_atomic_label(q, prefixed);
         if (r < 0)
                 return r;
 
-        r = strv_extend(&u->dropin_paths, q);
+        r = strv_push(&u->dropin_paths, q);
         if (r < 0)
                 return r;
+        q = NULL;
 
-        strv_sort(u->dropin_paths);
         strv_uniq(u->dropin_paths);
 
         u->dropin_mtime = now(CLOCK_REALTIME);
@@ -3408,7 +3436,7 @@ int unit_write_drop_in_private(Unit *u, UnitSetPropertiesMode mode, const char *
         if (!IN_SET(mode, UNIT_PERSISTENT, UNIT_RUNTIME))
                 return 0;
 
-        ndata = strjoina("[", UNIT_VTABLE(u)->private_section, "]\n", data, NULL);
+        ndata = strjoina("[", UNIT_VTABLE(u)->private_section, "]\n", data);
 
         return unit_write_drop_in(u, mode, name, ndata);
 }
@@ -3436,24 +3464,51 @@ 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;
 }
 
@@ -3545,7 +3600,7 @@ int unit_kill_context(
                          * cases. It doesn't work at all in
                          * containers, and outside of containers it
                          * can be confused easily by left-over
-                         * directories in the cgroup -- which however
+                         * directories in the cgroup  which however
                          * should not exist in non-delegated units. On
                          * the unified hierarchy that's different,
                          * there we get proper events. Hence rely on