assert(u);
- if (!(s = strdup(description)))
- return -ENOMEM;
+ if (isempty(description))
+ s = NULL;
+ else {
+ s = strdup(description);
+ if (!s)
+ return -ENOMEM;
+ }
free(u->description);
u->description = s;
u->in_gc_queue = true;
u->manager->n_in_gc_queue ++;
-
- if (u->manager->gc_queue_timestamp <= 0)
- u->manager->gc_queue_timestamp = now(CLOCK_MONOTONIC);
}
void unit_add_to_dbus_queue(Unit *u) {
if (u->in_cgroup_queue)
LIST_REMOVE(Unit, cgroup_queue, u->manager->cgroup_queue, u);
- free(u->cgroup_path);
+ if (u->cgroup_path) {
+ hashmap_remove(u->manager->cgroup_unit, u->cgroup_path);
+ free(u->cgroup_path);
+ }
+
free(u->description);
strv_free(u->documentation);
free(u->fragment_path);
if (UNIT_IS_INACTIVE_OR_FAILED(os) != UNIT_IS_INACTIVE_OR_FAILED(ns)) {
ExecContext *ec = unit_get_exec_context(u);
if (ec && exec_context_may_touch_console(ec)) {
- if (UNIT_IS_INACTIVE_OR_FAILED(ns))
- m->n_on_console--;
- else
- m->n_on_console++;
+ if (UNIT_IS_INACTIVE_OR_FAILED(ns)) {
+ m->n_on_console --;
+
+ if (m->n_on_console == 0)
+ /* unset no_console_output flag, since the console is free */
+ m->no_console_output = 0;
+ } else
+ m->n_on_console ++;
}
}
}
char *unit_default_cgroup_path(Unit *u) {
- _cleanup_free_ char *escaped_instance = NULL, *slice = NULL;
+ _cleanup_free_ char *escaped = NULL, *slice = NULL;
int r;
assert(u);
return NULL;
}
- escaped_instance = cg_escape(u->id);
- if (!escaped_instance)
+ escaped = cg_escape(u->id);
+ if (!escaped)
return NULL;
- if (u->instance) {
- _cleanup_free_ char *t = NULL, *escaped_template = NULL;
-
- t = unit_name_template(u->id);
- if (!t)
- return NULL;
-
- escaped_template = cg_escape(t);
- if (!escaped_template)
- return NULL;
-
- return strjoin(u->manager->cgroup_root, "/",
- slice ? slice : "", slice ? "/" : "",
- escaped_template, "/", escaped_instance, NULL);
- } else
- return strjoin(u->manager->cgroup_root, "/",
- slice ? slice : "", slice ? "/" : "",
- escaped_instance, NULL);
+ if (slice)
+ return strjoin(u->manager->cgroup_root, "/", slice, "/", escaped, NULL);
+ else
+ return strjoin(u->manager->cgroup_root, "/", escaped, NULL);
}
int unit_add_default_slice(Unit *u) {
+ _cleanup_free_ char *b = NULL;
+ const char *slice_name;
Unit *slice;
int r;
if (!unit_get_cgroup_context(u))
return 0;
- r = manager_load_unit(u->manager, u->manager->running_as == SYSTEMD_SYSTEM ? SPECIAL_SYSTEM_SLICE : SPECIAL_ROOT_SLICE, NULL, NULL, &slice);
+ if (u->instance) {
+ _cleanup_free_ char *prefix = NULL, *escaped = NULL;
+ ;
+ /* Implicitly place all instantiated units in their
+ * own per-template slice */
+
+ prefix = unit_name_to_prefix(u->id);
+ if (!prefix)
+ return -ENOMEM;
+
+ /* The prefix is already escaped, but it might include
+ * "-" which has a special meaning for slice units,
+ * hence escape it here extra. */
+ escaped = strreplace(prefix, "-", "\\x2d");
+ if (!escaped)
+ return -ENOMEM;
+
+ if (u->manager->running_as == SYSTEMD_SYSTEM)
+ b = strjoin("system-", escaped, ".slice", NULL);
+ else
+ b = strappend(escaped, ".slice");
+ if (!b)
+ return -ENOMEM;
+
+ slice_name = b;
+ } else
+ slice_name =
+ u->manager->running_as == SYSTEMD_SYSTEM
+ ? SPECIAL_SYSTEM_SLICE
+ : SPECIAL_ROOT_SLICE;
+
+ r = manager_load_unit(u->manager, slice_name, NULL, NULL, &slice);
if (r < 0)
return r;
if (!unit_can_serialize(u))
return 0;
- if ((r = UNIT_VTABLE(u)->serialize(u, f, fds)) < 0)
+ r = UNIT_VTABLE(u)->serialize(u, f, fds);
+ if (r < 0)
return r;
char *s;
s = strdup(v);
- if (!v)
+ if (!s)
return -ENOMEM;
free(u->cgroup_path);
u->cgroup_path = s;
+
+ hashmap_put(u->manager->cgroup_unit, s, u);
continue;
}
}
static int drop_in_file(Unit *u, UnitSetPropertiesMode mode, const char *name, char **_p, char **_q) {
+ _cleanup_free_ char *b = NULL;
char *p, *q;
int r;
assert(_q);
assert(mode & (UNIT_PERSISTENT|UNIT_RUNTIME));
- if (!filename_is_safe(name))
+ b = xescape(name, "/.");
+ if (!b)
+ return -ENOMEM;
+
+ if (!filename_is_safe(b))
return -EINVAL;
if (u->manager->running_as == SYSTEMD_USER) {
if (!p)
return -ENOMEM;
- q = strjoin(p, "/90-", name, ".conf", NULL);
+ q = strjoin(p, "/90-", b, ".conf", NULL);
if (!q) {
free(p);
return -ENOMEM;
return write_string_file_atomic_label(q, data);
}
-int unit_write_drop_in_private_section(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data) {
+int unit_write_drop_in_format(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *format, ...) {
+ _cleanup_free_ char *p = NULL;
+ va_list ap;
+ int r;
+
+ assert(u);
+ assert(name);
+ assert(format);
+
+ if (!(mode & (UNIT_PERSISTENT|UNIT_RUNTIME)))
+ return 0;
+
+ va_start(ap, format);
+ r = vasprintf(&p, format, ap);
+ va_end(ap);
+
+ if (r < 0)
+ return -ENOMEM;
+
+ return unit_write_drop_in(u, mode, name, p);
+}
+
+int unit_write_drop_in_private(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data) {
_cleanup_free_ char *ndata = NULL;
assert(u);
if (!UNIT_VTABLE(u)->private_section)
return -EINVAL;
+ if (!(mode & (UNIT_PERSISTENT|UNIT_RUNTIME)))
+ return 0;
+
ndata = strjoin("[", UNIT_VTABLE(u)->private_section, "]\n", data, NULL);
if (!ndata)
return -ENOMEM;
return unit_write_drop_in(u, mode, name, ndata);
}
+int unit_write_drop_in_private_format(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *format, ...) {
+ _cleanup_free_ char *p = NULL;
+ va_list ap;
+ int r;
+
+ assert(u);
+ assert(name);
+ assert(format);
+
+ if (!(mode & (UNIT_PERSISTENT|UNIT_RUNTIME)))
+ return 0;
+
+ va_start(ap, format);
+ r = vasprintf(&p, format, ap);
+ va_end(ap);
+
+ if (r < 0)
+ return -ENOMEM;
+
+ return unit_write_drop_in_private(u, mode, name, p);
+}
+
int unit_remove_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name) {
_cleanup_free_ char *p = NULL, *q = NULL;
int r;