chiark / gitweb /
core: refuse doing %h, %s, %U specifier resolving in PID 1
[elogind.git] / src / core / unit.c
index 57f0a86c01ad4d23af512066bf262cd1dbbdab87..160a346d8652a5639d3d3c7dfe6f80c33ba4fc7a 100644 (file)
 #include "fileio-label.h"
 #include "bus-errors.h"
 #include "dbus.h"
+#include "execute.h"
 
 const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = {
         [UNIT_SERVICE] = &service_vtable,
-        [UNIT_TIMER] = &timer_vtable,
         [UNIT_SOCKET] = &socket_vtable,
+        [UNIT_BUSNAME] = &busname_vtable,
         [UNIT_TARGET] = &target_vtable,
+        [UNIT_SNAPSHOT] = &snapshot_vtable,
         [UNIT_DEVICE] = &device_vtable,
         [UNIT_MOUNT] = &mount_vtable,
         [UNIT_AUTOMOUNT] = &automount_vtable,
-        [UNIT_SNAPSHOT] = &snapshot_vtable,
         [UNIT_SWAP] = &swap_vtable,
+        [UNIT_TIMER] = &timer_vtable,
         [UNIT_PATH] = &path_vtable,
         [UNIT_SLICE] = &slice_vtable,
         [UNIT_SCOPE] = &scope_vtable
@@ -86,6 +88,7 @@ Unit *unit_new(Manager *m, size_t size) {
         u->deserialized_job = _JOB_TYPE_INVALID;
         u->default_dependencies = true;
         u->unit_file_state = _UNIT_FILE_STATE_INVALID;
+        u->on_failure_job_mode = JOB_REPLACE;
 
         return u;
 }
@@ -826,14 +829,14 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
                         "%s\tRefuseManualStart: %s\n"
                         "%s\tRefuseManualStop: %s\n"
                         "%s\tDefaultDependencies: %s\n"
-                        "%s\tOnFailureIsolate: %s\n"
+                        "%s\tOnFailureJobMode: %s\n"
                         "%s\tIgnoreOnIsolate: %s\n"
                         "%s\tIgnoreOnSnapshot: %s\n",
                         prefix, yes_no(u->stop_when_unneeded),
                         prefix, yes_no(u->refuse_manual_start),
                         prefix, yes_no(u->refuse_manual_stop),
                         prefix, yes_no(u->default_dependencies),
-                        prefix, yes_no(u->on_failure_isolate),
+                        prefix, job_mode_to_string(u->on_failure_job_mode),
                         prefix, yes_no(u->ignore_on_isolate),
                         prefix, yes_no(u->ignore_on_snapshot));
 
@@ -1044,11 +1047,11 @@ int unit_load(Unit *u) {
                 if (r < 0)
                         goto fail;
 
-                if (u->on_failure_isolate &&
+                if (u->on_failure_job_mode == JOB_ISOLATE &&
                     set_size(u->dependencies[UNIT_ON_FAILURE]) > 1) {
 
                         log_error_unit(u->id,
-                                       "More than one OnFailure= dependencies specified for %s but OnFailureIsolate= enabled. Refusing.", u->id);
+                                       "More than one OnFailure= dependencies specified for %s but OnFailureJobMode=isolate set. Refusing.", u->id);
 
                         r = -EINVAL;
                         goto fail;
@@ -1122,6 +1125,8 @@ _pure_ static const char *unit_get_status_message_format_try_harder(Unit *u, Job
         return NULL;
 }
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
 static void unit_status_print_starting_stopping(Unit *u, JobType t) {
         const char *format;
 
@@ -1136,6 +1141,7 @@ static void unit_status_print_starting_stopping(Unit *u, JobType t) {
 
         unit_status_printf(u, "", format);
 }
+#pragma GCC diagnostic pop
 
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
@@ -1298,8 +1304,11 @@ int unit_reload(Unit *u) {
         if (state == UNIT_RELOADING)
                 return -EALREADY;
 
-        if (state != UNIT_ACTIVE)
+        if (state != UNIT_ACTIVE) {
+                log_warning_unit(u->id, "Unit %s cannot be reloaded because it is inactive.",
+                                 u->id);
                 return -ENOEXEC;
+        }
 
         following = unit_following(u);
         if (following) {
@@ -1454,7 +1463,7 @@ void unit_start_on_failure(Unit *u) {
         SET_FOREACH(other, u->dependencies[UNIT_ON_FAILURE], i) {
                 int r;
 
-                r = manager_add_job(u->manager, JOB_START, other, u->on_failure_isolate ? JOB_ISOLATE : JOB_REPLACE, true, NULL, NULL);
+                r = manager_add_job(u->manager, JOB_START, other, u->on_failure_job_mode, true, NULL, NULL);
                 if (r < 0)
                         log_error_unit(u->id, "Failed to enqueue OnFailure= job: %s", strerror(-r));
         }
@@ -1744,6 +1753,7 @@ int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_referen
                 [UNIT_TRIGGERED_BY] = UNIT_TRIGGERS,
                 [UNIT_PROPAGATES_RELOAD_TO] = UNIT_RELOAD_PROPAGATED_FROM,
                 [UNIT_RELOAD_PROPAGATED_FROM] = UNIT_PROPAGATES_RELOAD_TO,
+                [UNIT_JOINS_NAMESPACE_OF] = UNIT_JOINS_NAMESPACE_OF,
         };
         int r, q = 0, v = 0, w = 0;
 
@@ -1759,34 +1769,47 @@ int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_referen
         if (u == other)
                 return 0;
 
-        if ((r = set_ensure_allocated(&u->dependencies[d], trivial_hash_func, trivial_compare_func)) < 0)
+        r = set_ensure_allocated(&u->dependencies[d], trivial_hash_func, trivial_compare_func);
+        if (r < 0)
                 return r;
 
-        if (inverse_table[d] != _UNIT_DEPENDENCY_INVALID)
-                if ((r = set_ensure_allocated(&other->dependencies[inverse_table[d]], trivial_hash_func, trivial_compare_func)) < 0)
+        if (inverse_table[d] != _UNIT_DEPENDENCY_INVALID) {
+                r = set_ensure_allocated(&other->dependencies[inverse_table[d]], trivial_hash_func, trivial_compare_func);
+                if (r < 0)
                         return r;
+        }
 
-        if (add_reference)
-                if ((r = set_ensure_allocated(&u->dependencies[UNIT_REFERENCES], trivial_hash_func, trivial_compare_func)) < 0 ||
-                    (r = set_ensure_allocated(&other->dependencies[UNIT_REFERENCED_BY], trivial_hash_func, trivial_compare_func)) < 0)
+        if (add_reference) {
+                r = set_ensure_allocated(&u->dependencies[UNIT_REFERENCES], trivial_hash_func, trivial_compare_func);
+                if (r < 0)
                         return r;
 
-        if ((q = set_put(u->dependencies[d], other)) < 0)
+                r = set_ensure_allocated(&other->dependencies[UNIT_REFERENCED_BY], trivial_hash_func, trivial_compare_func);
+                if (r < 0)
+                        return r;
+        }
+
+        q = set_put(u->dependencies[d], other);
+        if (q < 0)
                 return q;
 
-        if (inverse_table[d] != _UNIT_DEPENDENCY_INVALID)
-                if ((v = set_put(other->dependencies[inverse_table[d]], u)) < 0) {
+        if (inverse_table[d] != _UNIT_DEPENDENCY_INVALID && inverse_table[d] != d) {
+                v = set_put(other->dependencies[inverse_table[d]], u);
+                if (v < 0) {
                         r = v;
                         goto fail;
                 }
+        }
 
         if (add_reference) {
-                if ((w = set_put(u->dependencies[UNIT_REFERENCES], other)) < 0) {
+                w = set_put(u->dependencies[UNIT_REFERENCES], other);
+                if (w < 0) {
                         r = w;
                         goto fail;
                 }
 
-                if ((r = set_put(other->dependencies[UNIT_REFERENCED_BY], u)) < 0)
+                r = set_put(other->dependencies[UNIT_REFERENCED_BY], u);
+                if (r < 0)
                         goto fail;
         }
 
@@ -1828,7 +1851,7 @@ static const char *resolve_template(Unit *u, const char *name, const char*path,
         assert(p);
 
         if (!name)
-                name = path_get_file_name(path);
+                name = basename(path);
 
         if (!unit_name_is_template(name)) {
                 *p = NULL;
@@ -2081,6 +2104,7 @@ bool unit_can_serialize(Unit *u) {
 }
 
 int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) {
+        ExecRuntime *rt;
         int r;
 
         assert(u);
@@ -2094,17 +2118,11 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) {
         if (r < 0)
                 return r;
 
-
-        if (serialize_jobs) {
-                if (u->job) {
-                        fprintf(f, "job\n");
-                        job_serialize(u->job, f, fds);
-                }
-
-                if (u->nop_job) {
-                        fprintf(f, "job\n");
-                        job_serialize(u->nop_job, f, fds);
-                }
+        rt = unit_get_exec_runtime(u);
+        if (rt) {
+                r = exec_runtime_serialize(rt, u, f, fds);
+                if (r < 0)
+                        return r;
         }
 
         dual_timestamp_serialize(f, "inactive-exit-timestamp", &u->inactive_exit_timestamp);
@@ -2121,6 +2139,18 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) {
         if (u->cgroup_path)
                 unit_serialize_item(u, f, "cgroup", u->cgroup_path);
 
+        if (serialize_jobs) {
+                if (u->job) {
+                        fprintf(f, "job\n");
+                        job_serialize(u->job, f, fds);
+                }
+
+                if (u->nop_job) {
+                        fprintf(f, "job\n");
+                        job_serialize(u->nop_job, f, fds);
+                }
+        }
+
         /* End marker */
         fputc('\n', f);
         return 0;
@@ -2154,6 +2184,8 @@ void unit_serialize_item(Unit *u, FILE *f, const char *key, const char *value) {
 }
 
 int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
+        size_t offset;
+        ExecRuntime **rt = NULL;
         int r;
 
         assert(u);
@@ -2163,6 +2195,10 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
         if (!unit_can_serialize(u))
                 return 0;
 
+        offset = UNIT_VTABLE(u)->exec_runtime_offset;
+        if (offset > 0)
+                rt = (ExecRuntime**) ((uint8_t*) u + offset);
+
         for (;;) {
                 char line[LINE_MAX], *l, *v;
                 size_t k;
@@ -2275,6 +2311,14 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
                         continue;
                 }
 
+                if (rt) {
+                        r = exec_runtime_deserialize_item(rt, u, l, v, fds);
+                        if (r < 0)
+                                return r;
+                        if (r > 0)
+                                continue;
+                }
+
                 r = UNIT_VTABLE(u)->deserialize_item(u, l, v, fds);
                 if (r < 0)
                         return r;
@@ -2574,7 +2618,7 @@ UnitFileState unit_get_unit_file_state(Unit *u) {
         if (u->unit_file_state < 0 && u->fragment_path)
                 u->unit_file_state = unit_file_get_state(
                                 u->manager->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER,
-                                NULL, path_get_file_name(u->fragment_path));
+                                NULL, basename(u->fragment_path));
 
         return u->unit_file_state;
 }
@@ -2659,6 +2703,16 @@ CGroupContext *unit_get_cgroup_context(Unit *u) {
         return (CGroupContext*) ((uint8_t*) u + offset);
 }
 
+ExecRuntime *unit_get_exec_runtime(Unit *u) {
+        size_t offset;
+
+        offset = UNIT_VTABLE(u)->exec_runtime_offset;
+        if (offset <= 0)
+                return NULL;
+
+        return *(ExecRuntime**) ((uint8_t*) u + offset);
+}
+
 static int drop_in_file(Unit *u, UnitSetPropertiesMode mode, const char *name, char **_p, char **_q) {
         _cleanup_free_ char *b = NULL;
         char *p, *q;
@@ -3009,6 +3063,33 @@ int unit_require_mounts_for(Unit *u, const char *path) {
         return 0;
 }
 
+int unit_setup_exec_runtime(Unit *u) {
+        ExecRuntime **rt;
+        size_t offset;
+        Iterator i;
+        Unit *other;
+
+        offset = UNIT_VTABLE(u)->exec_runtime_offset;
+        assert(offset > 0);
+
+        /* Check if ther already is an ExecRuntime for this unit? */
+        rt = (ExecRuntime**) ((uint8_t*) u + offset);
+        if (*rt)
+                return 0;
+
+        /* Try to get it from somebody else */
+        SET_FOREACH(other, u->dependencies[UNIT_JOINS_NAMESPACE_OF], i) {
+
+                *rt = unit_get_exec_runtime(other);
+                if (*rt) {
+                        exec_runtime_ref(*rt);
+                        return 0;
+                }
+        }
+
+        return exec_runtime_make(rt, unit_get_exec_context(u), u->id);
+}
+
 static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = {
         [UNIT_ACTIVE] = "active",
         [UNIT_RELOADING] = "reloading",
@@ -3044,6 +3125,7 @@ static const char* const unit_dependency_table[_UNIT_DEPENDENCY_MAX] = {
         [UNIT_RELOAD_PROPAGATED_FROM] = "ReloadPropagatedFrom",
         [UNIT_REFERENCES] = "References",
         [UNIT_REFERENCED_BY] = "ReferencedBy",
+        [UNIT_JOINS_NAMESPACE_OF] = "JoinsNamespaceOf",
 };
 
 DEFINE_STRING_TABLE_LOOKUP(unit_dependency, UnitDependency);