unit.c revision 1b64d026af01277e332d10d9e67e2eed5a4ded28
97a9a944b5887e91042b019776c41d5dd74557aferikabele/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
fd9abdda70912b99b24e3bf1a38f26fde908a74cnd This file is part of systemd.
a945f35eff8b6a88009ce73de6d4c862ce58de3cslive Copyright 2010 Lennart Poettering
a945f35eff8b6a88009ce73de6d4c862ce58de3cslive systemd is free software; you can redistribute it and/or modify it
5a58787efeb02a1c3f06569d019ad81fd2efa06end under the terms of the GNU Lesser General Public License as published by
96ad5d81ee4a2cc66a4ae19893efc8aa6d06fae7jailletc the Free Software Foundation; either version 2.1 of the License, or
5a58787efeb02a1c3f06569d019ad81fd2efa06end (at your option) any later version.
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen systemd is distributed in the hope that it will be useful, but
2e545ce2450a9953665f701bb05350f0d3f26275nd WITHOUT ANY WARRANTY; without even the implied warranty of
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen Lesser General Public License for more details.
5a58787efeb02a1c3f06569d019ad81fd2efa06end You should have received a copy of the GNU Lesser General Public License
5a58787efeb02a1c3f06569d019ad81fd2efa06end along with systemd; If not, see <http://www.gnu.org/licenses/>.
9b6a3a558cc90ffdaa0b50bd02546ffec424ded7sliveconst UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = {
2bc7f1cf720973a67f8ff7a8d523e40569ae5b6cnd u->names = set_new(string_hash_func, string_compare_func);
117c1f888a14e73cdd821dc6c23eb0411144a41cnd if (!u->names) {
06ba4a61654b3763ad65f52283832ebf058fdf1cslive char *s, *i = NULL;
8a6d5edcb07aeccca7afba02a17dd6904d6b206ctrawick if (!unit_name_is_valid(s, false)) {
77c77cf89621f21c8e2bbad63058b5eaa5f88d4ajim if ((r = unit_name_to_instance(s, &i)) < 0)
ced7ef1f8c0df1805da0e87dbc5a1b6282910573nd /* Ensure that this unit is either instanced or not instanced,
8a6d5edcb07aeccca7afba02a17dd6904d6b206ctrawick * but not both. */
8a6d5edcb07aeccca7afba02a17dd6904d6b206ctrawick if (u->type != _UNIT_TYPE_INVALID && !u->instance != !i) {
92510838f2eb125726e15c5eb4f7a23c7a0396e4slive if (hashmap_size(u->manager->units) >= MANAGER_MAX_NAMES) {
4aa603e6448b99f9371397d439795c91a93637eand if (r == -EEXIST)
654d8eb036bedc99e90e11910ee02d3421417697rbowen if ((r = hashmap_put(u->manager->units, s, u)) < 0) {
709e3a21ba73b8433462959cd56c773454b34441trawick LIST_PREPEND(Unit, units_by_type, u->manager->units_by_type[t], u);
0d0ba3a410038e179b695446bb149cce6264e0abnd char *s, *t = NULL, *i;
0d0ba3a410038e179b695446bb149cce6264e0abnd if (!(t = unit_name_replace_instance(name, u->instance)))
7fec19672a491661b2fe4b29f685bc7f4efa64d4nd /* Selects one of the names of this unit as the id */
return -ENOENT;
if ((r = unit_name_to_instance(s, &i)) < 0)
u->id = s;
u->instance = i;
assert(u);
return -ENOMEM;
u->description = s;
assert(u);
if (u->no_gc)
if (u->job)
if (u->nop_job)
assert(u);
u->in_load_queue = true;
assert(u);
if (u->in_cleanup_queue)
u->in_cleanup_queue = true;
assert(u);
if (unit_check_gc(u))
u->in_gc_queue = true;
assert(u);
u->sent_dbus_new_signal = true;
u->in_dbus_queue = true;
Iterator i;
assert(u);
for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++)
set_free(s);
Iterator i;
assert(u);
if (u->job) {
job_uninstall(j);
job_free(j);
if (u->nop_job) {
job_uninstall(j);
job_free(j);
for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++)
if (u->requires_mounts_for) {
if (u->in_load_queue)
if (u->in_dbus_queue)
if (u->in_cleanup_queue)
if (u->in_gc_queue) {
while (u->refs)
free(u);
assert(u);
assert(u);
assert(s);
if (!*other)
*s = *other;
Iterator i;
assert(u);
Iterator i;
assert(u);
for (k = 0; k < _UNIT_DEPENDENCY_MAX; k++)
if (r == -EEXIST)
assert(u);
if (other == u)
return -EINVAL;
return -EINVAL;
return -EEXIST;
return -EEXIST;
return -EEXIST;
return -EEXIST;
for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++)
char *s = NULL;
assert(u);
if (!u->instance)
return -EINVAL;
return -ENOMEM;
name = s;
free(s);
assert(u);
assert(u);
assert(c);
if ((r = unit_add_two_dependencies_by_name(u, UNIT_REQUIRES, UNIT_AFTER, SPECIAL_JOURNALD_SOCKET, NULL, true)) < 0)
assert(u);
if (u->description)
return u->description;
Iterator i;
char *p2;
const char *prefix2;
assert(u);
if (!prefix)
fprintf(f,
prefix, strna(format_timestamp(timestamp1, sizeof(timestamp1), u->inactive_exit_timestamp.realtime)),
prefix, strna(format_timestamp(timestamp2, sizeof(timestamp2), u->active_enter_timestamp.realtime)),
prefix, strna(format_timestamp(timestamp4, sizeof(timestamp4), u->inactive_enter_timestamp.realtime)),
if (u->fragment_path)
if (u->source_path)
if (u->job_timeout > 0)
fprintf(f, "%s\tJob Timeout: %s\n", prefix, format_timespan(timespan, sizeof(timespan), u->job_timeout));
fprintf(f,
for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) {
fprintf(f,
CGroupBonding *b;
CGroupAttribute *a;
fprintf(f,
char *v = NULL;
if (a->map_callback)
free(v);
fprintf(f,
if (u->job)
if (u->nop_job)
assert(u);
if ((r = unit_load_fragment(u)) < 0)
return -ENOENT;
assert(u);
if ((r = unit_load_fragment(u)) < 0)
assert(u);
if (!u->default_dependencies ||
Iterator i;
assert(u);
assert(u);
if (u->in_load_queue) {
u->in_load_queue = false;
return -EINVAL;
goto fail;
r = -ENOENT;
goto fail;
if ((r = unit_add_default_dependencies(u)) < 0)
goto fail;
r = unit_add_mount_links(u);
if (u->on_failure_isolate &&
log_error("More than one OnFailure= dependencies specified for %s but OnFailureIsolate= enabled. Refusing.",
u->id);
r = -EINVAL;
goto fail;
fail:
u->load_error = r;
assert(u);
return u->condition_result;
const char *format;
if (!format_table)
if (!format)
assert(u);
return -EINVAL;
return -EALREADY;
!unit_condition_test(u)) {
return -EALREADY;
unit_status_print_starting_stopping(u, false);
return -EBADR;
assert(u);
assert(u);
return unit_can_start(u) &&
u->allow_isolate;
assert(u);
return -EALREADY;
unit_status_print_starting_stopping(u, true);
return -EBADR;
assert(u);
return -EINVAL;
if (!unit_can_reload(u))
return -EBADR;
return -EALREADY;
return -ENOEXEC;
assert(u);
Iterator i;
assert(u);
if (!u->stop_when_unneeded)
Iterator i;
assert(u);
Iterator i;
assert(u);
Iterator i;
assert(u);
Iterator i;
assert(u);
if ((r = manager_add_job(u->manager, JOB_START, other, u->on_failure_isolate ? JOB_ISOLATE : JOB_REPLACE, true, NULL, NULL)) < 0)
bool unexpected;
assert(u);
if (u->job) {
unexpected = false;
case JOB_START:
case JOB_VERIFY_ACTIVE:
unexpected = true;
case JOB_RELOAD:
case JOB_RELOAD_OR_START:
unexpected = true;
case JOB_STOP:
case JOB_RESTART:
case JOB_TRY_RESTART:
unexpected = true;
unexpected = true;
if (unexpected) {
u->in_audit = true;
if (!u->in_audit) {
u->in_audit = false;
assert(u);
assert(w);
fd,
&ev) < 0)
return -errno;
assert(u);
assert(w);
assert(u);
assert(u);
bool ours;
assert(u);
assert(w);
ours = false;
ours = true;
return -errno;
if (delay <= 0) {
flags = 0;
goto fail;
goto fail;
fail:
if (ours)
return -errno;
assert(u);
assert(w);
assert(u);
case JOB_VERIFY_ACTIVE:
case JOB_START:
case JOB_STOP:
case JOB_NOP:
case JOB_RESTART:
case JOB_TRY_RESTART:
return unit_can_start(u);
case JOB_RELOAD:
return unit_can_reload(u);
case JOB_RELOAD_OR_START:
assert(u);
u = unit_follow_merge(u);
if (u == other)
if ((r = set_ensure_allocated(&other->dependencies[inverse_table[d]], trivial_hash_func, trivial_compare_func)) < 0)
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)
goto fail;
if (add_reference) {
goto fail;
goto fail;
fail:
int unit_add_two_dependencies(Unit *u, UnitDependency d, UnitDependency e, Unit *other, bool add_reference) {
assert(u);
assert(u);
if (!name)
*p = NULL;
return name;
if (u->instance)
return NULL;
free(i);
return NULL;
int unit_add_dependency_by_name(Unit *u, UnitDependency d, const char *name, const char *path, bool add_reference) {
assert(u);
return -ENOMEM;
goto finish;
free(s);
int unit_add_two_dependencies_by_name(Unit *u, UnitDependency d, UnitDependency e, const char *name, const char *path, bool add_reference) {
assert(u);
return -ENOMEM;
goto finish;
free(s);
int unit_add_dependency_by_name_inverse(Unit *u, UnitDependency d, const char *name, const char *path, bool add_reference) {
assert(u);
return -ENOMEM;
goto finish;
free(s);
int unit_add_two_dependencies_by_name_inverse(Unit *u, UnitDependency d, UnitDependency e, const char *name, const char *path, bool add_reference) {
assert(u);
return -ENOMEM;
goto finish;
goto finish;
free(s);
int set_unit_path(const char *p) {
char *cwd, *c;
if (path_is_absolute(p)) {
if (!(c = strdup(p)))
return -ENOMEM;
return -errno;
return -ENOMEM;
r = -errno;
free(c);
assert(u);
if (!u->id)
return NULL;
return NULL;
free(e);
assert(u);
assert(b);
if (!b->controller) {
return -ENOMEM;
b->ours = true;
CGroupBonding *l;
b->unit = u;
assert(u);
if (u->instance) {
return NULL;
free(t);
bool ours = false;
assert(u);
if (!path) {
ours = true;
if (!controller) {
ours = true;
return -ENOMEM;
r = -EEXIST;
goto fail;
r = -ENOMEM;
goto fail;
if ((r = unit_add_cgroup(u, b)) < 0)
goto fail;
fail:
free(b);
int r = -ENOMEM;
assert(u);
if (!controller)
return -ENOMEM;
goto fail;
goto fail;
b->ours = true;
if ((r = unit_add_cgroup(u, b)) < 0)
goto fail;
fail:
free(b);
CGroupAttribute *a;
assert(u);
unit_add_one_default_cgroup(u, *c);
assert(u);
int unit_add_cgroup_attribute(Unit *u, const char *controller, const char *name, const char *value, CGroupAttributeMapCallback map_callback) {
char *c = NULL;
CGroupAttribute *a;
assert(u);
if (!controller) {
const char *dot;
if (!dot)
return -EINVAL;
return -ENOMEM;
controller = c;
r = -EINVAL;
goto finish;
r = -ENOMEM;
goto finish;
a->controller = c;
c = NULL;
free(a);
return -ENOMEM;
free(c);
assert(u);
return -ENOMEM;
free(t);
assert(u);
return -ENOMEM;
free(t);
if (!found)
return -ENOENT;
assert(u);
assert(u);
assert(u);
return NULL;
r = unit_name_unescape(p);
free(p);
assert(u);
if (u->instance)
assert(u);
if (u->instance)
assert(u);
return default_cgroup_path(u);
assert(u);
free(p);
assert(u);
return strdup(e);
assert(u);
* %r root cgroup path of this systemd instance (e.g. "/user/lennart/shared/systemd-4711")
assert(u);
size_t n;
assert(u);
n = strv_length(l);
return NULL;
if (!(*j = unit_full_printf(u, *i)))
goto fail;
*j = NULL;
fail:
free(*j);
free(r);
return NULL;
assert(u);
assert(u);
assert(u);
assert(u);
assert(f);
if (!unit_can_serialize(u))
if (u->job) {
if (u->nop_job) {
assert(u);
assert(f);
assert(u);
assert(f);
assert(u);
assert(f);
if (!unit_can_serialize(u))
size_t k;
if (feof(f))
return -errno;
return -ENOMEM;
job_free(j);
job_free(j);
r = job_install_deserialized(j);
job_free(j);
if (type < 0)
if ((b = parse_boolean(v)) < 0)
u->condition_result = b;
assert(u);
if (!what)
return -ENOMEM;
free(e);
if (wants)
assert(u);
if (u->job) {
} else if (u->deserialized_job >= 0) {
r = manager_add_job(u->manager, u->deserialized_job, u, JOB_IGNORE_REQUIREMENTS, false, NULL, NULL);
assert(u);
assert(u);
if (u->fragment_path) {
if (u->fragment_mtime > 0 &&
if (u->source_path) {
if (u->source_mtime > 0 &&
assert(u);
assert(u);
return NULL;
assert(u);
assert(u);
if (u->job &&
UnitType t;
assert(n);
for (t = 0; t < _UNIT_TYPE_MAX; t++)
return _UNIT_TYPE_INVALID;
UnitType t;
t = unit_name_to_type(n);
if (t < 0 || t >= _UNIT_TYPE_MAX)
assert(u);
if (m == KILL_NONE)
return -ENOTSUP;
assert(u);
assert(s);
*s = NULL;
assert(u);
return u->unit_file_state;
assert(u);
assert(u);
assert(m);
if (UNIT(m) == u)
assert(u);