X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fcore%2Funit.c;h=4eea5b57ae49107dcba461397460e38582d96677;hp=c5fde63afb7727a9e776252553373a8f92b89a8a;hb=41f9172f427bdbb8221c64029f78364b8dd4e527;hpb=5273510e9f228a300ec6207d4502f1c6253aed5e diff --git a/src/core/unit.c b/src/core/unit.c index c5fde63af..4eea5b57a 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -29,15 +29,17 @@ #include #include +#include "systemd/sd-id128.h" +#include "systemd/sd-messages.h" #include "set.h" #include "unit.h" #include "macro.h" #include "strv.h" +#include "path-util.h" #include "load-fragment.h" #include "load-dropin.h" #include "log.h" #include "unit-name.h" -#include "specifier.h" #include "dbus-unit.h" #include "special.h" #include "cgroup-util.h" @@ -249,9 +251,15 @@ bool unit_check_gc(Unit *u) { if (u->job) return true; + if (u->nop_job) + return true; + if (unit_active_state(u) != UNIT_INACTIVE) return true; + if (u->refs) + return true; + if (UNIT_VTABLE(u)->check_gc) if (UNIT_VTABLE(u)->check_gc(u)) return true; @@ -358,9 +366,20 @@ void unit_free(Unit *u) { job_free(j); } + if (u->nop_job) { + Job *j = u->nop_job; + job_uninstall(j); + job_free(j); + } + for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) bidi_set_free(u, u->dependencies[d]); + if (u->requires_mounts_for) { + LIST_REMOVE(Unit, has_requires_mounts_for, u->manager->has_requires_mounts_for, u); + strv_free(u->requires_mounts_for); + } + if (u->type != _UNIT_TYPE_INVALID) LIST_REMOVE(Unit, units_by_type, u->manager->units_by_type[u->type], u); @@ -382,7 +401,9 @@ void unit_free(Unit *u) { cgroup_attribute_free_list(u->cgroup_attributes); free(u->description); + strv_free(u->documentation); free(u->fragment_path); + free(u->source_path); free(u->instance); set_free_free(u->names); @@ -501,6 +522,9 @@ int unit_merge(Unit *u, Unit *other) { if (other->job) return -EEXIST; + if (other->nop_job) + return -EEXIST; + if (!UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) return -EEXIST; @@ -606,7 +630,7 @@ const char *unit_description(Unit *u) { } void unit_dump(Unit *u, FILE *f, const char *prefix) { - char *t; + char *t, **j; UnitDependency d; Iterator i; char *p2; @@ -654,12 +678,18 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { SET_FOREACH(t, u->names, i) fprintf(f, "%s\tName: %s\n", prefix, t); + STRV_FOREACH(j, u->documentation) + fprintf(f, "%s\tDocumentation: %s\n", prefix, *j); + if ((following = unit_following(u))) fprintf(f, "%s\tFollowing: %s\n", prefix, following->id); if (u->fragment_path) fprintf(f, "%s\tFragment Path: %s\n", prefix, u->fragment_path); + if (u->source_path) + fprintf(f, "%s\tSource Path: %s\n", prefix, u->source_path); + if (u->job_timeout > 0) fprintf(f, "%s\tJob Timeout: %s\n", prefix, format_timespan(timespan, sizeof(timespan), u->job_timeout)); @@ -679,6 +709,16 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { fprintf(f, "%s\t%s: %s\n", prefix, unit_dependency_to_string(d), other->id); } + if (!strv_isempty(u->requires_mounts_for)) { + fprintf(f, + "%s\tRequiresMountsFor:", prefix); + + STRV_FOREACH(j, u->requires_mounts_for) + fprintf(f, " %s", *j); + + fputs("\n", f); + } + if (u->load_state == UNIT_LOADED) { CGroupBonding *b; CGroupAttribute *a; @@ -729,6 +769,9 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { if (u->job) job_dump(u->job, f, prefix2); + if (u->nop_job) + job_dump(u->nop_job, f, prefix2); + free(p2); } @@ -854,6 +897,12 @@ int unit_load(Unit *u) { if ((r = unit_add_default_dependencies(u)) < 0) goto fail; + if (u->load_state == UNIT_LOADED) { + r = unit_add_mount_links(u); + if (r < 0) + return r; + } + if (u->on_failure_isolate && set_size(u->dependencies[UNIT_ON_FAILURE]) > 1) { @@ -891,6 +940,96 @@ bool unit_condition_test(Unit *u) { return u->condition_result; } +static const char* unit_get_status_message_format(Unit *u, JobType t) { + const UnitStatusMessageFormats *format_table; + + assert(u); + assert(t >= 0); + assert(t < _JOB_TYPE_MAX); + + if (t != JOB_START && t != JOB_STOP) + return NULL; + + format_table = &UNIT_VTABLE(u)->status_message_formats; + if (!format_table) + return NULL; + + return format_table->starting_stopping[t == JOB_STOP]; +} + +static const char *unit_get_status_message_format_try_harder(Unit *u, JobType t) { + const char *format; + + assert(u); + assert(t >= 0); + assert(t < _JOB_TYPE_MAX); + + format = unit_get_status_message_format(u, t); + if (format) + return format; + + /* Return generic strings */ + if (t == JOB_START) + return "Starting %s."; + else if (t == JOB_STOP) + return "Stopping %s."; + else if (t == JOB_RELOAD) + return "Reloading %s."; + + return NULL; +} + +static void unit_status_print_starting_stopping(Unit *u, JobType t) { + const char *format; + + assert(u); + + /* We only print status messages for selected units on + * selected operations. */ + + format = unit_get_status_message_format(u, t); + if (!format) + return; + + unit_status_printf(u, "", format, unit_description(u)); +} + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-nonliteral" +static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) { + const char *format; + char buf[LINE_MAX]; + sd_id128_t mid; + + assert(u); + + if (t != JOB_START && t != JOB_STOP && t != JOB_RELOAD) + return; + + if (log_on_console()) + return; + + /* We log status messages for all units and all operations. */ + + format = unit_get_status_message_format_try_harder(u, t); + if (!format) + return; + + snprintf(buf, sizeof(buf), format, unit_description(u)); + char_array_0(buf); + + mid = t == JOB_START ? SD_MESSAGE_UNIT_STARTING : + t == JOB_STOP ? SD_MESSAGE_UNIT_STOPPING : + SD_MESSAGE_UNIT_RELOADING; + + log_struct(LOG_INFO, + "MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(mid), + "UNIT=%s", u->id, + "MESSAGE=%s", buf, + NULL); +} +#pragma GCC diagnostic pop + /* Errors: * -EBADR: This unit type does not support starting. * -EALREADY: Unit is already started. @@ -930,6 +1069,9 @@ int unit_start(Unit *u) { return unit_start(following); } + unit_status_log_starting_stopping_reloading(u, JOB_START); + unit_status_print_starting_stopping(u, JOB_START); + /* If it is stopped, but we cannot start it, then fail */ if (!UNIT_VTABLE(u)->start) return -EBADR; @@ -942,7 +1084,6 @@ int unit_start(Unit *u) { unit_add_to_dbus_queue(u); - unit_status_printf(u, NULL, "Starting %s...", unit_description(u)); return UNIT_VTABLE(u)->start(u); } @@ -979,12 +1120,14 @@ int unit_stop(Unit *u) { return unit_stop(following); } + unit_status_log_starting_stopping_reloading(u, JOB_STOP); + unit_status_print_starting_stopping(u, JOB_STOP); + if (!UNIT_VTABLE(u)->stop) return -EBADR; unit_add_to_dbus_queue(u); - unit_status_printf(u, NULL, "Stopping %s...", unit_description(u)); return UNIT_VTABLE(u)->stop(u); } @@ -1017,6 +1160,8 @@ int unit_reload(Unit *u) { return unit_reload(following); } + unit_status_log_starting_stopping_reloading(u, JOB_RELOAD); + unit_add_to_dbus_queue(u); return UNIT_VTABLE(u)->reload(u); } @@ -1082,7 +1227,7 @@ static void retroactively_start_dependencies(Unit *u) { !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other))) manager_add_job(u->manager, JOB_START, other, JOB_REPLACE, true, NULL, NULL); - SET_FOREACH(other, u->dependencies[UNIT_BIND_TO], i) + SET_FOREACH(other, u->dependencies[UNIT_BINDS_TO], i) if (!set_get(u->dependencies[UNIT_AFTER], other) && !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other))) manager_add_job(u->manager, JOB_START, other, JOB_REPLACE, true, NULL, NULL); @@ -1147,7 +1292,7 @@ static void check_unneeded_dependencies(Unit *u) { SET_FOREACH(other, u->dependencies[UNIT_REQUISITE_OVERRIDABLE], i) if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other))) unit_check_unneeded(other); - SET_FOREACH(other, u->dependencies[UNIT_BIND_TO], i) + SET_FOREACH(other, u->dependencies[UNIT_BINDS_TO], i) if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other))) unit_check_unneeded(other); } @@ -1181,7 +1326,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su /* Note that this is called for all low-level state changes, * even if they might map to the same high-level * UnitActiveState! That means that ns == os is OK an expected - * behaviour here. For example: if a mount point is remounted + * behavior here. For example: if a mount point is remounted * this function will be called too! */ if (u->manager->n_reloading <= 0) { @@ -1507,6 +1652,7 @@ bool unit_job_is_applicable(Unit *u, JobType j) { case JOB_VERIFY_ACTIVE: case JOB_START: case JOB_STOP: + case JOB_NOP: return true; case JOB_RESTART: @@ -1532,11 +1678,13 @@ int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_referen [UNIT_WANTS] = UNIT_WANTED_BY, [UNIT_REQUISITE] = UNIT_REQUIRED_BY, [UNIT_REQUISITE_OVERRIDABLE] = UNIT_REQUIRED_BY_OVERRIDABLE, - [UNIT_BIND_TO] = UNIT_BOUND_BY, + [UNIT_BINDS_TO] = UNIT_BOUND_BY, + [UNIT_PART_OF] = UNIT_CONSISTS_OF, [UNIT_REQUIRED_BY] = _UNIT_DEPENDENCY_INVALID, [UNIT_REQUIRED_BY_OVERRIDABLE] = _UNIT_DEPENDENCY_INVALID, [UNIT_WANTED_BY] = _UNIT_DEPENDENCY_INVALID, - [UNIT_BOUND_BY] = UNIT_BIND_TO, + [UNIT_BOUND_BY] = UNIT_BINDS_TO, + [UNIT_CONSISTS_OF] = UNIT_PART_OF, [UNIT_CONFLICTS] = UNIT_CONFLICTED_BY, [UNIT_CONFLICTED_BY] = UNIT_CONFLICTS, [UNIT_BEFORE] = UNIT_AFTER, @@ -1546,8 +1694,8 @@ int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_referen [UNIT_REFERENCED_BY] = UNIT_REFERENCES, [UNIT_TRIGGERS] = UNIT_TRIGGERED_BY, [UNIT_TRIGGERED_BY] = UNIT_TRIGGERS, - [UNIT_PROPAGATE_RELOAD_TO] = UNIT_PROPAGATE_RELOAD_FROM, - [UNIT_PROPAGATE_RELOAD_FROM] = UNIT_PROPAGATE_RELOAD_TO + [UNIT_PROPAGATES_RELOAD_TO] = UNIT_RELOAD_PROPAGATED_FROM, + [UNIT_RELOAD_PROPAGATED_FROM] = UNIT_PROPAGATES_RELOAD_TO, }; int r, q = 0, v = 0, w = 0; @@ -1631,7 +1779,7 @@ static const char *resolve_template(Unit *u, const char *name, const char*path, assert(name || path); if (!name) - name = file_name_from_path(path); + name = path_get_file_name(path); if (!unit_name_is_template(name)) { *p = NULL; @@ -1772,20 +1920,12 @@ int set_unit_path(const char *p) { } char *unit_dbus_path(Unit *u) { - char *p, *e; - assert(u); if (!u->id) return NULL; - if (!(e = bus_path_escape(u->id))) - return NULL; - - p = strappend("/org/freedesktop/systemd1/unit/", e); - free(e); - - return p; + return unit_dbus_path_from_name(u->id); } int unit_add_cgroup(Unit *u, CGroupBonding *b) { @@ -1824,7 +1964,7 @@ int unit_add_cgroup(Unit *u, CGroupBonding *b) { return 0; } -static char *default_cgroup_path(Unit *u) { +char *unit_default_cgroup_path(Unit *u) { char *p; assert(u); @@ -1836,10 +1976,10 @@ static char *default_cgroup_path(Unit *u) { if (!t) return NULL; - p = join(u->manager->cgroup_hierarchy, "/", t, "/", u->instance, NULL); + p = strjoin(u->manager->cgroup_hierarchy, "/", t, "/", u->instance, NULL); free(t); } else - p = join(u->manager->cgroup_hierarchy, "/", u->id, NULL); + p = strjoin(u->manager->cgroup_hierarchy, "/", u->id, NULL); return p; } @@ -1857,7 +1997,7 @@ int unit_add_cgroup_from_text(Unit *u, const char *name) { return r; if (!path) { - path = default_cgroup_path(u); + path = unit_default_cgroup_path(u); ours = true; } @@ -1919,7 +2059,8 @@ static int unit_add_one_default_cgroup(Unit *u, const char *controller) { if (!(b->controller = strdup(controller))) goto fail; - if (!(b->path = default_cgroup_path(u))) + b->path = unit_default_cgroup_path(u); + if (!b->path) goto fail; b->ours = true; @@ -2076,182 +2217,6 @@ int unit_get_related_unit(Unit *u, const char *type, Unit **_found) { return 0; } -static char *specifier_prefix_and_instance(char specifier, void *data, void *userdata) { - Unit *u = userdata; - assert(u); - - return unit_name_to_prefix_and_instance(u->id); -} - -static char *specifier_prefix(char specifier, void *data, void *userdata) { - Unit *u = userdata; - assert(u); - - return unit_name_to_prefix(u->id); -} - -static char *specifier_prefix_unescaped(char specifier, void *data, void *userdata) { - Unit *u = userdata; - char *p, *r; - - assert(u); - - if (!(p = unit_name_to_prefix(u->id))) - return NULL; - - r = unit_name_unescape(p); - free(p); - - return r; -} - -static char *specifier_instance_unescaped(char specifier, void *data, void *userdata) { - Unit *u = userdata; - assert(u); - - if (u->instance) - return unit_name_unescape(u->instance); - - return strdup(""); -} - -static char *specifier_filename(char specifier, void *data, void *userdata) { - Unit *u = userdata; - assert(u); - - if (u->instance) - return unit_name_path_unescape(u->instance); - - return unit_name_to_path(u->instance); -} - -static char *specifier_cgroup(char specifier, void *data, void *userdata) { - Unit *u = userdata; - assert(u); - - return default_cgroup_path(u); -} - -static char *specifier_cgroup_root(char specifier, void *data, void *userdata) { - Unit *u = userdata; - char *p; - assert(u); - - if (specifier == 'r') - return strdup(u->manager->cgroup_hierarchy); - - if (parent_of_path(u->manager->cgroup_hierarchy, &p) < 0) - return strdup(""); - - if (streq(p, "/")) { - free(p); - return strdup(""); - } - - return p; -} - -static char *specifier_runtime(char specifier, void *data, void *userdata) { - Unit *u = userdata; - assert(u); - - if (u->manager->running_as == MANAGER_USER) { - const char *e; - - e = getenv("XDG_RUNTIME_DIR"); - if (e) - return strdup(e); - } - - return strdup("/run"); -} - -char *unit_name_printf(Unit *u, const char* format) { - - /* - * This will use the passed string as format string and - * replace the following specifiers: - * - * %n: the full id of the unit (foo@bar.waldo) - * %N: the id of the unit without the suffix (foo@bar) - * %p: the prefix (foo) - * %i: the instance (bar) - */ - - const Specifier table[] = { - { 'n', specifier_string, u->id }, - { 'N', specifier_prefix_and_instance, NULL }, - { 'p', specifier_prefix, NULL }, - { 'i', specifier_string, u->instance }, - { 0, NULL, NULL } - }; - - assert(u); - assert(format); - - return specifier_printf(format, table, u); -} - -char *unit_full_printf(Unit *u, const char *format) { - - /* This is similar to unit_name_printf() but also supports - * unescaping. Also, adds a couple of additional codes: - * - * %c cgroup path of unit - * %r root cgroup path of this systemd instance (e.g. "/user/lennart/shared/systemd-4711") - * %R parent of root cgroup path (e.g. "/usr/lennart/shared") - * %t the runtime directory to place sockets in (e.g. "/run" or $XDG_RUNTIME_DIR) - */ - - const Specifier table[] = { - { 'n', specifier_string, u->id }, - { 'N', specifier_prefix_and_instance, NULL }, - { 'p', specifier_prefix, NULL }, - { 'P', specifier_prefix_unescaped, NULL }, - { 'i', specifier_string, u->instance }, - { 'I', specifier_instance_unescaped, NULL }, - { 'f', specifier_filename, NULL }, - { 'c', specifier_cgroup, NULL }, - { 'r', specifier_cgroup_root, NULL }, - { 'R', specifier_cgroup_root, NULL }, - { 't', specifier_runtime, NULL }, - { 0, NULL, NULL } - }; - - assert(u); - assert(format); - - return specifier_printf(format, table, u); -} - -char **unit_full_printf_strv(Unit *u, char **l) { - size_t n; - char **r, **i, **j; - - /* Applies unit_full_printf to every entry in l */ - - assert(u); - - n = strv_length(l); - if (!(r = new(char*, n+1))) - return NULL; - - for (i = l, j = r; *i; i++, j++) - if (!(*j = unit_full_printf(u, *i))) - goto fail; - - *j = NULL; - return r; - -fail: - for (j--; j >= r; j--) - free(*j); - - free(r); - - return NULL; -} - int unit_watch_bus_name(Unit *u, const char *name) { assert(u); assert(name); @@ -2275,7 +2240,7 @@ bool unit_can_serialize(Unit *u) { return UNIT_VTABLE(u)->serialize && UNIT_VTABLE(u)->deserialize_item; } -int unit_serialize(Unit *u, FILE *f, FDSet *fds) { +int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) { int r; assert(u); @@ -2288,9 +2253,17 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds) { if ((r = UNIT_VTABLE(u)->serialize(u, f, fds)) < 0) return r; - if (u->job) { - fprintf(f, "job\n"); - job_serialize(u->job, f, fds); + + 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); + } } dual_timestamp_serialize(f, "inactive-exit-timestamp", &u->inactive_exit_timestamp); @@ -2382,12 +2355,18 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { return r; } - job_install_deserialized(j); r = hashmap_put(u->manager->jobs, UINT32_TO_PTR(j->id), j); if (r < 0) { job_free(j); return r; } + + r = job_install_deserialized(j); + if (r < 0) { + hashmap_remove(u->manager->jobs, UINT32_TO_PTR(j->id)); + job_free(j); + return r; + } } else { /* legacy */ JobType type = job_type_from_string(v); @@ -2443,21 +2422,24 @@ int unit_add_node_link(Unit *u, const char *what, bool wants) { if (!is_device_path(what)) return 0; - if (!(e = unit_name_build_escape(what+1, NULL, ".device"))) + e = unit_name_from_path(what, ".device"); + if (!e) return -ENOMEM; r = manager_load_unit(u->manager, e, NULL, NULL, &device); free(e); - if (r < 0) return r; - if ((r = unit_add_two_dependencies(u, UNIT_AFTER, UNIT_BIND_TO, device, true)) < 0) + r = unit_add_two_dependencies(u, UNIT_AFTER, UNIT_BINDS_TO, device, true); + if (r < 0) return r; - if (wants) - if ((r = unit_add_dependency(device, UNIT_WANTS, u, false)) < 0) + if (wants) { + r = unit_add_dependency(device, UNIT_WANTS, u, false); + if (r < 0) return r; + } return 0; } @@ -2493,9 +2475,6 @@ void unit_status_printf(Unit *u, const char *status, const char *format, ...) { assert(u); assert(format); - if (!UNIT_VTABLE(u)->show_status) - return; - if (!manager_get_show_status(u->manager)) return; @@ -2508,11 +2487,11 @@ void unit_status_printf(Unit *u, const char *status, const char *format, ...) { } bool unit_need_daemon_reload(Unit *u) { + struct stat st; + assert(u); if (u->fragment_path) { - struct stat st; - zero(st); if (stat(u->fragment_path, &st) < 0) /* What, cannot access this anymore? */ @@ -2523,8 +2502,15 @@ bool unit_need_daemon_reload(Unit *u) { return true; } - if (UNIT_VTABLE(u)->need_daemon_reload) - return UNIT_VTABLE(u)->need_daemon_reload(u); + if (u->source_path) { + zero(st); + if (stat(u->source_path, &st) < 0) + return true; + + if (u->source_mtime > 0 && + timespec_load(&st.st_mtim) != u->source_mtime) + return true; + } return false; } @@ -2576,42 +2562,16 @@ bool unit_pending_active(Unit *u) { return false; } -UnitType unit_name_to_type(const char *n) { - UnitType t; - - assert(n); - - for (t = 0; t < _UNIT_TYPE_MAX; t++) - if (endswith(n, unit_vtable[t]->suffix)) - return t; - - return _UNIT_TYPE_INVALID; -} - -bool unit_name_is_valid(const char *n, bool template_ok) { - UnitType t; - - t = unit_name_to_type(n); - if (t < 0 || t >= _UNIT_TYPE_MAX) - return false; - - return unit_name_is_valid_no_type(n, template_ok); -} - -int unit_kill(Unit *u, KillWho w, KillMode m, int signo, DBusError *error) { +int unit_kill(Unit *u, KillWho w, int signo, DBusError *error) { assert(u); assert(w >= 0 && w < _KILL_WHO_MAX); - assert(m >= 0 && m < _KILL_MODE_MAX); assert(signo > 0); assert(signo < _NSIG); - if (m == KILL_NONE) - return 0; - if (!UNIT_VTABLE(u)->kill) return -ENOTSUP; - return UNIT_VTABLE(u)->kill(u, w, m, signo, error); + return UNIT_VTABLE(u)->kill(u, w, signo, error); } int unit_following_set(Unit *u, Set **s) { @@ -2631,7 +2591,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 == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, - NULL, file_name_from_path(u->fragment_path)); + NULL, path_get_file_name(u->fragment_path)); return u->unit_file_state; } @@ -2658,15 +2618,71 @@ void unit_ref_unset(UnitRef *ref) { ref->unit = NULL; } -static const char* const unit_load_state_table[_UNIT_LOAD_STATE_MAX] = { - [UNIT_STUB] = "stub", - [UNIT_LOADED] = "loaded", - [UNIT_ERROR] = "error", - [UNIT_MERGED] = "merged", - [UNIT_MASKED] = "masked" -}; +int unit_add_one_mount_link(Unit *u, Mount *m) { + char **i; + + assert(u); + assert(m); + + if (u->load_state != UNIT_LOADED || + UNIT(m)->load_state != UNIT_LOADED) + return 0; + + STRV_FOREACH(i, u->requires_mounts_for) { + + if (UNIT(m) == u) + continue; + + if (!path_startswith(*i, m->where)) + continue; + + return unit_add_two_dependencies(u, UNIT_AFTER, UNIT_REQUIRES, UNIT(m), true); + } + + return 0; +} + +int unit_add_mount_links(Unit *u) { + Unit *other; + int r; + + assert(u); -DEFINE_STRING_TABLE_LOOKUP(unit_load_state, UnitLoadState); + LIST_FOREACH(units_by_type, other, u->manager->units_by_type[UNIT_MOUNT]) { + r = unit_add_one_mount_link(u, MOUNT(other)); + if (r < 0) + return r; + } + + return 0; +} + +int unit_exec_context_defaults(Unit *u, ExecContext *c) { + unsigned i; + int r; + + assert(u); + assert(c); + + /* This only copies in the ones that need memory */ + + for (i = 0; i < RLIMIT_NLIMITS; i++) + if (u->manager->rlimit[i] && !c->rlimit[i]) { + c->rlimit[i] = newdup(struct rlimit, u->manager->rlimit[i], 1); + if (!c->rlimit[i]) + return -ENOMEM; + } + + if (u->manager->running_as == MANAGER_USER && + !c->working_directory) { + + r = get_home_dir(&c->working_directory); + if (r < 0) + return r; + } + + return 0; +} static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = { [UNIT_ACTIVE] = "active", @@ -2682,25 +2698,27 @@ DEFINE_STRING_TABLE_LOOKUP(unit_active_state, UnitActiveState); static const char* const unit_dependency_table[_UNIT_DEPENDENCY_MAX] = { [UNIT_REQUIRES] = "Requires", [UNIT_REQUIRES_OVERRIDABLE] = "RequiresOverridable", - [UNIT_WANTS] = "Wants", [UNIT_REQUISITE] = "Requisite", [UNIT_REQUISITE_OVERRIDABLE] = "RequisiteOverridable", + [UNIT_WANTS] = "Wants", + [UNIT_BINDS_TO] = "BindsTo", + [UNIT_PART_OF] = "PartOf", [UNIT_REQUIRED_BY] = "RequiredBy", [UNIT_REQUIRED_BY_OVERRIDABLE] = "RequiredByOverridable", - [UNIT_BIND_TO] = "BindTo", [UNIT_WANTED_BY] = "WantedBy", + [UNIT_BOUND_BY] = "BoundBy", + [UNIT_CONSISTS_OF] = "ConsistsOf", [UNIT_CONFLICTS] = "Conflicts", [UNIT_CONFLICTED_BY] = "ConflictedBy", - [UNIT_BOUND_BY] = "BoundBy", [UNIT_BEFORE] = "Before", [UNIT_AFTER] = "After", - [UNIT_REFERENCES] = "References", - [UNIT_REFERENCED_BY] = "ReferencedBy", [UNIT_ON_FAILURE] = "OnFailure", [UNIT_TRIGGERS] = "Triggers", [UNIT_TRIGGERED_BY] = "TriggeredBy", - [UNIT_PROPAGATE_RELOAD_TO] = "PropagateReloadTo", - [UNIT_PROPAGATE_RELOAD_FROM] = "PropagateReloadFrom" + [UNIT_PROPAGATES_RELOAD_TO] = "PropagatesReloadTo", + [UNIT_RELOAD_PROPAGATED_FROM] = "ReloadPropagatedFrom", + [UNIT_REFERENCES] = "References", + [UNIT_REFERENCED_BY] = "ReferencedBy", }; DEFINE_STRING_TABLE_LOOKUP(unit_dependency, UnitDependency);