+ 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);
+
+ 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 == SYSTEMD_USER &&
+ !c->working_directory) {
+
+ r = get_home_dir(&c->working_directory);
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
+}
+
+ExecContext *unit_get_exec_context(Unit *u) {
+ size_t offset;
+ assert(u);
+
+ offset = UNIT_VTABLE(u)->exec_context_offset;
+ if (offset <= 0)
+ return NULL;
+
+ return (ExecContext*) ((uint8_t*) u + offset);
+}
+
+static int drop_in_file(Unit *u, bool runtime, const char *name, char **_p, char **_q) {
+ char *p, *q;
+ int r;
+
+ assert(u);
+ assert(name);
+ assert(_p);
+ assert(_q);
+
+ if (u->manager->running_as == SYSTEMD_USER && runtime)
+ return -ENOTSUP;
+
+ if (!filename_is_safe(name))
+ return -EINVAL;
+
+ if (u->manager->running_as == SYSTEMD_USER) {
+ _cleanup_free_ char *c = NULL;
+
+ r = user_config_home(&c);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -ENOENT;
+
+ p = strjoin(c, "/", u->id, ".d", NULL);
+ } else if (runtime)
+ p = strjoin("/run/systemd/system/", u->id, ".d", NULL);
+ else
+ p = strjoin("/etc/systemd/system/", u->id, ".d", NULL);
+ if (!p)
+ return -ENOMEM;
+
+ q = strjoin(p, "/50-", name, ".conf", NULL);
+ if (!q) {
+ free(p);
+ return -ENOMEM;
+ }
+
+ *_p = p;
+ *_q = q;
+ return 0;
+}
+
+int unit_write_drop_in(Unit *u, bool runtime, const char *name, const char *data) {
+ _cleanup_free_ char *p = NULL, *q = NULL;
+ int r;
+
+ assert(u);
+
+ r = drop_in_file(u, runtime, name, &p, &q);
+ if (r < 0)
+ return r;
+
+ mkdir_p(p, 0755);
+ return write_string_file_atomic_label(q, data);
+}
+
+int unit_remove_drop_in(Unit *u, bool runtime, const char *name) {
+ _cleanup_free_ char *p = NULL, *q = NULL;
+ int r;
+
+ assert(u);
+
+ r = drop_in_file(u, runtime, name, &p, &q);
+ if (unlink(q) < 0)
+ r = -errno;
+ else
+ r = 0;
+
+ rmdir(p);
+ return r;
+}
+
+int unit_kill_context(
+ Unit *u,
+ KillContext *c,
+ bool sigkill,
+ pid_t main_pid,
+ pid_t control_pid,
+ bool main_pid_alien) {
+
+ int sig, wait_for_exit = 0, r;
+
+ assert(u);
+ assert(c);
+
+ if (c->kill_mode == KILL_NONE)
+ return 0;
+
+ sig = sigkill ? SIGKILL : c->kill_signal;
+
+ if (main_pid > 0) {
+ r = kill_and_sigcont(main_pid, sig);
+
+ if (r < 0 && r != -ESRCH) {
+ _cleanup_free_ char *comm = NULL;
+ get_process_comm(main_pid, &comm);
+
+ log_warning_unit(u->id, "Failed to kill main process %li (%s): %s",
+ (long) main_pid, strna(comm), strerror(-r));
+ } else
+ wait_for_exit = !main_pid_alien;
+ }
+
+ if (control_pid > 0) {
+ r = kill_and_sigcont(control_pid, sig);
+
+ if (r < 0 && r != -ESRCH) {
+ _cleanup_free_ char *comm = NULL;
+ get_process_comm(control_pid, &comm);
+
+ log_warning_unit(u->id,
+ "Failed to kill control process %li (%s): %s",
+ (long) control_pid, strna(comm), strerror(-r));
+ } else
+ wait_for_exit = true;
+ }
+
+ if (c->kill_mode == KILL_CONTROL_GROUP) {
+ _cleanup_set_free_ Set *pid_set = NULL;
+
+ pid_set = set_new(trivial_hash_func, trivial_compare_func);
+ if (!pid_set)
+ return -ENOMEM;
+
+ /* Exclude the main/control pids from being killed via the cgroup */
+ if (main_pid > 0) {
+ r = set_put(pid_set, LONG_TO_PTR(main_pid));
+ if (r < 0)
+ return r;
+ }
+
+ if (control_pid > 0) {
+ r = set_put(pid_set, LONG_TO_PTR(control_pid));
+ if (r < 0)
+ return r;
+ }
+
+ r = cgroup_bonding_kill_list(u->cgroup_bondings, sig, true, false, pid_set, NULL);
+ if (r < 0) {
+ if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
+ log_warning_unit(u->id, "Failed to kill control group: %s", strerror(-r));
+ } else if (r > 0)
+ wait_for_exit = true;
+ }
+
+ return wait_for_exit;
+}