diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/dbus-manager.c | 166 | ||||
-rw-r--r-- | src/core/dbus-unit.c | 4 | ||||
-rw-r--r-- | src/core/dbus.c | 8 | ||||
-rw-r--r-- | src/core/execute.c | 39 | ||||
-rw-r--r-- | src/core/hostname-setup.c | 6 | ||||
-rw-r--r-- | src/core/job.c | 16 | ||||
-rw-r--r-- | src/core/killall.c | 3 | ||||
-rw-r--r-- | src/core/manager.c | 19 | ||||
-rw-r--r-- | src/core/socket.c | 4 | ||||
-rw-r--r-- | src/core/unit.c | 48 |
10 files changed, 191 insertions, 122 deletions
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index 0136d38833..f87b52a266 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -848,13 +848,9 @@ static int method_get_unit_processes(sd_bus_message *message, void *userdata, sd if (r < 0) return r; - r = manager_load_unit(m, name, NULL, error, &u); - if (r < 0) - return r; - - r = bus_unit_check_load_state(u, error); - if (r < 0) - return r; + u = manager_get_unit(m, name); + if (!u) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", name); return bus_unit_method_get_processes(message, u, error); } @@ -1342,7 +1338,7 @@ static int verify_run_space(const char *message, sd_bus_error *error) { } int verify_run_space_and_log(const char *message) { - sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; r = verify_run_space(message, &error); @@ -1916,63 +1912,6 @@ static int send_unit_files_changed(sd_bus *bus, void *userdata) { return sd_bus_send(bus, message, NULL); } -static int reply_unit_file_changes_and_free( - Manager *m, - sd_bus_message *message, - int carries_install_info, - UnitFileChange *changes, - unsigned n_changes) { - - _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - unsigned i; - int r; - - if (unit_file_changes_have_modification(changes, n_changes)) { - r = bus_foreach_bus(m, NULL, send_unit_files_changed, NULL); - if (r < 0) - log_debug_errno(r, "Failed to send UnitFilesChanged signal: %m"); - } - - r = sd_bus_message_new_method_return(message, &reply); - if (r < 0) - goto fail; - - if (carries_install_info >= 0) { - r = sd_bus_message_append(reply, "b", carries_install_info); - if (r < 0) - goto fail; - } - - r = sd_bus_message_open_container(reply, 'a', "(sss)"); - if (r < 0) - goto fail; - - for (i = 0; i < n_changes; i++) - if (changes[i].type >= 0) { - const char *change = unit_file_change_type_to_string(changes[i].type); - assert(change != NULL); - - r = sd_bus_message_append( - reply, "(sss)", - change, - changes[i].path, - changes[i].source); - if (r < 0) - goto fail; - } - - r = sd_bus_message_close_container(reply); - if (r < 0) - goto fail; - - unit_file_changes_free(changes, n_changes); - return sd_bus_send(NULL, reply, NULL); - -fail: - unit_file_changes_free(changes, n_changes); - return r; -} - /* Create an error reply, using the error information from changes[] * if possible, and fall back to generating an error from error code c. * The error message only describes the first error. @@ -1986,12 +1925,14 @@ static int install_error( unsigned n_changes) { int r; unsigned i; - assert(c < 0); for (i = 0; i < n_changes; i++) + switch(changes[i].type) { + case 0 ... INT_MAX: continue; + case -EEXIST: if (changes[i].source) r = sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, @@ -2002,29 +1943,106 @@ static int install_error( "File %s already exists.", changes[i].path); goto found; + case -ERFKILL: r = sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit file %s is masked.", changes[i].path); goto found; + case -EADDRNOTAVAIL: r = sd_bus_error_setf(error, BUS_ERROR_UNIT_GENERATED, "Unit %s is transient or generated.", changes[i].path); goto found; + case -ELOOP: r = sd_bus_error_setf(error, BUS_ERROR_UNIT_LINKED, "Refusing to operate on linked unit file %s", changes[i].path); goto found; + + case -ENOENT: + r = sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit file %s does not exist.", changes[i].path); + goto found; + default: r = sd_bus_error_set_errnof(error, changes[i].type, "File %s: %m", changes[i].path); goto found; } - r = c; + r = c < 0 ? c : -EINVAL; + found: unit_file_changes_free(changes, n_changes); return r; } +static int reply_unit_file_changes_and_free( + Manager *m, + sd_bus_message *message, + int carries_install_info, + UnitFileChange *changes, + unsigned n_changes, + sd_bus_error *error) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + bool bad = false, good = false; + unsigned i; + int r; + + if (unit_file_changes_have_modification(changes, n_changes)) { + r = bus_foreach_bus(m, NULL, send_unit_files_changed, NULL); + if (r < 0) + log_debug_errno(r, "Failed to send UnitFilesChanged signal: %m"); + } + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + goto fail; + + if (carries_install_info >= 0) { + r = sd_bus_message_append(reply, "b", carries_install_info); + if (r < 0) + goto fail; + } + + r = sd_bus_message_open_container(reply, 'a', "(sss)"); + if (r < 0) + goto fail; + + for (i = 0; i < n_changes; i++) { + + if (changes[i].type < 0) { + bad = true; + continue; + } + + r = sd_bus_message_append( + reply, "(sss)", + unit_file_change_type_to_string(changes[i].type), + changes[i].path, + changes[i].source); + if (r < 0) + goto fail; + + good = true; + } + + /* If there was a failed change, and no successful change, then return the first failure as proper method call + * error. */ + if (bad && !good) + return install_error(error, 0, changes, n_changes); + + r = sd_bus_message_close_container(reply); + if (r < 0) + goto fail; + + unit_file_changes_free(changes, n_changes); + return sd_bus_send(NULL, reply, NULL); + +fail: + unit_file_changes_free(changes, n_changes); + return r; +} + static int method_enable_unit_files_generic( sd_bus_message *message, Manager *m, @@ -2061,7 +2079,7 @@ static int method_enable_unit_files_generic( if (r < 0) return install_error(error, r, changes, n_changes); - return reply_unit_file_changes_and_free(m, message, carries_install_info ? r : -1, changes, n_changes); + return reply_unit_file_changes_and_free(m, message, carries_install_info ? r : -1, changes, n_changes, error); } static int method_enable_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) { @@ -2130,7 +2148,7 @@ static int method_preset_unit_files_with_mode(sd_bus_message *message, void *use if (r < 0) return install_error(error, r, changes, n_changes); - return reply_unit_file_changes_and_free(m, message, r, changes, n_changes); + return reply_unit_file_changes_and_free(m, message, r, changes, n_changes, error); } static int method_disable_unit_files_generic( @@ -2165,7 +2183,7 @@ static int method_disable_unit_files_generic( if (r < 0) return install_error(error, r, changes, n_changes); - return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes); + return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes, error); } static int method_disable_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) { @@ -2200,7 +2218,7 @@ static int method_revert_unit_files(sd_bus_message *message, void *userdata, sd_ if (r < 0) return install_error(error, r, changes, n_changes); - return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes); + return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes, error); } static int method_set_default_target(sd_bus_message *message, void *userdata, sd_bus_error *error) { @@ -2231,7 +2249,7 @@ static int method_set_default_target(sd_bus_message *message, void *userdata, sd if (r < 0) return install_error(error, r, changes, n_changes); - return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes); + return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes, error); } static int method_preset_all_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) { @@ -2274,7 +2292,7 @@ static int method_preset_all_unit_files(sd_bus_message *message, void *userdata, if (r < 0) return install_error(error, r, changes, n_changes); - return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes); + return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes, error); } static int method_add_dependency_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) { @@ -2314,7 +2332,7 @@ static int method_add_dependency_unit_files(sd_bus_message *message, void *userd if (r < 0) return install_error(error, r, changes, n_changes); - return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes); + return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes, error); } static int method_get_unit_file_links(sd_bus_message *message, void *userdata, sd_bus_error *error) { diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index 60e889e1ef..f1306a023f 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -1006,6 +1006,10 @@ int bus_unit_method_get_processes(sd_bus_message *message, void *userdata, sd_bu assert(message); + r = mac_selinux_unit_access_check(u, message, "status", error); + if (r < 0) + return r; + pids = set_new(NULL); if (!pids) return -ENOMEM; diff --git a/src/core/dbus.c b/src/core/dbus.c index 0493e5786c..065f2d81d6 100644 --- a/src/core/dbus.c +++ b/src/core/dbus.c @@ -298,7 +298,7 @@ static int bus_job_find(sd_bus *bus, const char *path, const char *interface, vo } static int find_unit(Manager *m, sd_bus *bus, const char *path, Unit **unit, sd_bus_error *error) { - Unit *u; + Unit *u = NULL; /* just to appease gcc, initialization is not really necessary */ int r; assert(m); @@ -323,15 +323,15 @@ static int find_unit(Manager *m, sd_bus *bus, const char *path, Unit **unit, sd_ return r; u = manager_get_unit_by_pid(m, pid); + if (!u) + return 0; } else { r = manager_load_unit_from_dbus_path(m, path, error, &u); if (r < 0) return 0; + assert(u); } - if (!u) - return 0; - *unit = u; return 1; } diff --git a/src/core/execute.c b/src/core/execute.c index 6041da46d6..d7798387c5 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1144,11 +1144,13 @@ static int setup_pam( /* Tell the parent that our setup is done. This is especially * important regarding dropping privileges. Otherwise, unit - * setup might race against our setresuid(2) call. */ - barrier_place(&barrier); + * setup might race against our setresuid(2) call. + * + * If the parent aborted, we'll detect this below, hence ignore + * return failure here. */ + (void) barrier_place(&barrier); - /* Check if our parent process might already have - * died? */ + /* Check if our parent process might already have died? */ if (getppid() == parent_pid) { sigset_t ss; @@ -1938,10 +1940,13 @@ static int compile_read_write_paths( return 0; } -static int apply_mount_namespace(Unit *u, const ExecContext *context, - const ExecParameters *params, - ExecRuntime *runtime) { - int r; +static int apply_mount_namespace( + Unit *u, + ExecCommand *command, + const ExecContext *context, + const ExecParameters *params, + ExecRuntime *runtime) { + _cleanup_strv_free_ char **rw = NULL; char *tmp = NULL, *var = NULL; const char *root_dir = NULL, *root_image = NULL; @@ -1953,6 +1958,8 @@ static int apply_mount_namespace(Unit *u, const ExecContext *context, .protect_kernel_modules = context->protect_kernel_modules, .mount_apivfs = context->mount_apivfs, }; + bool apply_restrictions; + int r; assert(context); @@ -1986,16 +1993,18 @@ static int apply_mount_namespace(Unit *u, const ExecContext *context, if (!context->dynamic_user && root_dir) ns_info.ignore_protect_paths = true; + apply_restrictions = (params->flags & EXEC_APPLY_PERMISSIONS) && !command->privileged; + r = setup_namespace(root_dir, root_image, &ns_info, rw, - context->read_only_paths, - context->inaccessible_paths, + apply_restrictions ? context->read_only_paths : NULL, + apply_restrictions ? context->inaccessible_paths : NULL, context->bind_mounts, context->n_bind_mounts, tmp, var, - context->protect_home, - context->protect_system, + apply_restrictions ? context->protect_home : PROTECT_HOME_NO, + apply_restrictions ? context->protect_system : PROTECT_SYSTEM_NO, context->mount_flags, DISSECT_IMAGE_DISCARD_ON_LOOP); @@ -2606,7 +2615,7 @@ static int exec_child( needs_mount_namespace = exec_needs_mount_namespace(context, params, runtime); if (needs_mount_namespace) { - r = apply_mount_namespace(unit, context, params, runtime); + r = apply_mount_namespace(unit, command, context, params, runtime); if (r < 0) { *exit_status = EXIT_NAMESPACE; return r; @@ -2974,7 +2983,7 @@ int exec_spawn(Unit *unit, log_open(); if (error_message) log_struct_errno(LOG_ERR, r, - LOG_MESSAGE_ID(SD_MESSAGE_SPAWN_FAILED), + "MESSAGE_ID=" SD_MESSAGE_SPAWN_FAILED_STR, LOG_UNIT_ID(unit), LOG_UNIT_MESSAGE(unit, "%s: %m", error_message), @@ -2982,7 +2991,7 @@ int exec_spawn(Unit *unit, NULL); else log_struct_errno(LOG_ERR, r, - LOG_MESSAGE_ID(SD_MESSAGE_SPAWN_FAILED), + "MESSAGE_ID=" SD_MESSAGE_SPAWN_FAILED_STR, LOG_UNIT_ID(unit), LOG_UNIT_MESSAGE(unit, "Failed at step %s spawning %s: %m", exit_status_to_string(exit_status, EXIT_STATUS_SYSTEMD), diff --git a/src/core/hostname-setup.c b/src/core/hostname-setup.c index 68be52856b..845e31e1c5 100644 --- a/src/core/hostname-setup.c +++ b/src/core/hostname-setup.c @@ -31,10 +31,10 @@ #include "util.h" int hostname_setup(void) { - int r; _cleanup_free_ char *b = NULL; - const char *hn; bool enoent = false; + const char *hn; + int r; r = read_hostname_config("/etc/hostname", &b); if (r < 0) { @@ -56,7 +56,7 @@ int hostname_setup(void) { if (enoent) log_info("No hostname configured."); - hn = "localhost"; + hn = FALLBACK_HOSTNAME; } r = sethostname_idempotent(hn); diff --git a/src/core/job.c b/src/core/job.c index 00f7d7998f..e2349830a8 100644 --- a/src/core/job.c +++ b/src/core/job.c @@ -627,6 +627,8 @@ int job_run_and_invalidate(Job *j) { r = job_finish_and_invalidate(j, JOB_ASSERT, true, false); else if (r == -EOPNOTSUPP) r = job_finish_and_invalidate(j, JOB_UNSUPPORTED, true, false); + else if (r == -ENOLINK) + r = job_finish_and_invalidate(j, JOB_DEPENDENCY, true, false); else if (r == -EAGAIN) job_set_state(j, JOB_WAITING); else if (r < 0) @@ -744,9 +746,8 @@ static void job_print_status_message(Unit *u, JobType t, JobResult result) { } static void job_log_status_message(Unit *u, JobType t, JobResult result) { - const char *format; + const char *format, *mid; char buf[LINE_MAX]; - sd_id128_t mid; static const int job_result_log_level[_JOB_RESULT_MAX] = { [JOB_DONE] = LOG_INFO, [JOB_CANCELED] = LOG_INFO, @@ -782,16 +783,19 @@ static void job_log_status_message(Unit *u, JobType t, JobResult result) { switch (t) { case JOB_START: - mid = result == JOB_DONE ? SD_MESSAGE_UNIT_STARTED : SD_MESSAGE_UNIT_FAILED; + if (result == JOB_DONE) + mid = "MESSAGE_ID=" SD_MESSAGE_UNIT_STARTED_STR; + else + mid = "MESSAGE_ID=" SD_MESSAGE_UNIT_FAILED_STR; break; case JOB_RELOAD: - mid = SD_MESSAGE_UNIT_RELOADED; + mid = "MESSAGE_ID=" SD_MESSAGE_UNIT_RELOADED_STR; break; case JOB_STOP: case JOB_RESTART: - mid = SD_MESSAGE_UNIT_STOPPED; + mid = "MESSAGE_ID=" SD_MESSAGE_UNIT_STOPPED_STR; break; default: @@ -804,7 +808,7 @@ static void job_log_status_message(Unit *u, JobType t, JobResult result) { } log_struct(job_result_log_level[result], - LOG_MESSAGE_ID(mid), + mid, LOG_UNIT_ID(u), LOG_MESSAGE("%s", buf), "RESULT=%s", job_result_to_string(result), diff --git a/src/core/killall.c b/src/core/killall.c index 7a9df546ee..3fe9fa2ed0 100644 --- a/src/core/killall.c +++ b/src/core/killall.c @@ -213,7 +213,8 @@ static int killall(int sig, Set *pids, bool send_sighup) { if (get_ctty_devnr(pid, NULL) >= 0) - kill(pid, SIGHUP); + /* it's OK if the process is gone, just ignore the result */ + (void) kill(pid, SIGHUP); } } diff --git a/src/core/manager.c b/src/core/manager.c index aefe4ca780..d3f6efc91c 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1403,7 +1403,7 @@ tr_abort: } int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, sd_bus_error *e, Job **ret) { - Unit *unit; + Unit *unit = NULL; /* just to appease gcc, initialization is not really necessary */ int r; assert(m); @@ -1414,6 +1414,7 @@ int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode r = manager_load_unit(m, name, NULL, NULL, &unit); if (r < 0) return r; + assert(unit); return manager_add_job(m, type, unit, mode, e, ret); } @@ -1486,6 +1487,7 @@ int manager_load_unit_prepare( assert(m); assert(name || path); + assert(_ret); /* This will prepare the unit for loading, but not actually * load anything from disk. */ @@ -1533,8 +1535,7 @@ int manager_load_unit_prepare( unit_add_to_dbus_queue(ret); unit_add_to_gc_queue(ret); - if (_ret) - *_ret = ret; + *_ret = ret; return 0; } @@ -1549,6 +1550,7 @@ int manager_load_unit( int r; assert(m); + assert(_ret); /* This will load the service information files, but not actually * start any services or anything. */ @@ -1559,8 +1561,7 @@ int manager_load_unit( manager_dispatch_load_queue(m); - if (_ret) - *_ret = unit_follow_merge(*_ret); + *_ret = unit_follow_merge(*_ret); return 0; } @@ -2175,7 +2176,7 @@ static int manager_dispatch_time_change_fd(sd_event_source *source, int fd, uint assert(m->time_change_fd == fd); log_struct(LOG_DEBUG, - LOG_MESSAGE_ID(SD_MESSAGE_TIME_CHANGE), + "MESSAGE_ID=" SD_MESSAGE_TIME_CHANGE_STR, LOG_MESSAGE("Time has been changed"), NULL); @@ -2907,7 +2908,7 @@ static void manager_notify_finished(Manager *m) { initrd_usec = m->userspace_timestamp.monotonic - m->initrd_timestamp.monotonic; log_struct(LOG_INFO, - LOG_MESSAGE_ID(SD_MESSAGE_STARTUP_FINISHED), + "MESSAGE_ID=" SD_MESSAGE_STARTUP_FINISHED_STR, "KERNEL_USEC="USEC_FMT, kernel_usec, "INITRD_USEC="USEC_FMT, initrd_usec, "USERSPACE_USEC="USEC_FMT, userspace_usec, @@ -2922,7 +2923,7 @@ static void manager_notify_finished(Manager *m) { initrd_usec = 0; log_struct(LOG_INFO, - LOG_MESSAGE_ID(SD_MESSAGE_STARTUP_FINISHED), + "MESSAGE_ID=" SD_MESSAGE_STARTUP_FINISHED_STR, "KERNEL_USEC="USEC_FMT, kernel_usec, "USERSPACE_USEC="USEC_FMT, userspace_usec, LOG_MESSAGE("Startup finished in %s (kernel) + %s (userspace) = %s.", @@ -2936,7 +2937,7 @@ static void manager_notify_finished(Manager *m) { total_usec = userspace_usec = m->finish_timestamp.monotonic - m->userspace_timestamp.monotonic; log_struct(LOG_INFO, - LOG_MESSAGE_ID(SD_MESSAGE_USER_STARTUP_FINISHED), + "MESSAGE_ID=" SD_MESSAGE_USER_STARTUP_FINISHED_STR, "USERSPACE_USEC="USEC_FMT, userspace_usec, LOG_MESSAGE("Startup finished in %s.", format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC)), diff --git a/src/core/socket.c b/src/core/socket.c index a7b9ada65c..84b7a1a82d 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -1340,11 +1340,11 @@ static int usbffs_write_descs(int fd, Service *s) { if (!s->usb_function_descriptors || !s->usb_function_strings) return -EINVAL; - r = copy_file_fd(s->usb_function_descriptors, fd, false); + r = copy_file_fd(s->usb_function_descriptors, fd, 0); if (r < 0) return r; - return copy_file_fd(s->usb_function_strings, fd, false); + return copy_file_fd(s->usb_function_strings, fd, 0); } static int usbffs_select_ep(const struct dirent *d) { diff --git a/src/core/unit.c b/src/core/unit.c index 5e4b1567d8..bb05d2abfb 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -1466,9 +1466,8 @@ static void unit_status_print_starting_stopping(Unit *u, JobType t) { } static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) { - const char *format; + const char *format, *mid; char buf[LINE_MAX]; - sd_id128_t mid; assert(u); @@ -1486,9 +1485,9 @@ static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) { snprintf(buf, sizeof buf, format, unit_description(u)); REENABLE_WARNING; - mid = t == JOB_START ? SD_MESSAGE_UNIT_STARTING : - t == JOB_STOP ? SD_MESSAGE_UNIT_STOPPING : - SD_MESSAGE_UNIT_RELOADING; + mid = t == JOB_START ? "MESSAGE_ID=" SD_MESSAGE_UNIT_STARTING_STR : + t == JOB_STOP ? "MESSAGE_ID=" SD_MESSAGE_UNIT_STOPPING_STR : + "MESSAGE_ID=" SD_MESSAGE_UNIT_RELOADING_STR; /* Note that we deliberately use LOG_MESSAGE() instead of * LOG_UNIT_MESSAGE() here, since this is supposed to mimic @@ -1497,7 +1496,7 @@ static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) { * possible, which means we should avoid the low-level unit * name. */ log_struct(LOG_INFO, - LOG_MESSAGE_ID(mid), + mid, LOG_UNIT_ID(u), LOG_MESSAGE("%s", buf), NULL); @@ -1527,6 +1526,7 @@ int unit_start_limit_test(Unit *u) { } bool unit_shall_confirm_spawn(Unit *u) { + assert(u); if (manager_is_confirm_spawn_disabled(u->manager)) return false; @@ -1537,6 +1537,31 @@ bool unit_shall_confirm_spawn(Unit *u) { return !unit_get_exec_context(u)->same_pgrp; } +static bool unit_verify_deps(Unit *u) { + Unit *other; + Iterator j; + + assert(u); + + /* Checks whether all BindsTo= dependencies of this unit are fulfilled — if they are also combined with + * After=. We do not check Requires= or Requisite= here as they only should have an effect on the job + * processing, but do not have any effect afterwards. We don't check BindsTo= dependencies that are not used in + * conjunction with After= as for them any such check would make things entirely racy. */ + + SET_FOREACH(other, u->dependencies[UNIT_BINDS_TO], j) { + + if (!set_contains(u->dependencies[UNIT_AFTER], other)) + continue; + + if (!UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(other))) { + log_unit_notice(u, "Bound to unit %s, but unit isn't active.", other->id); + return false; + } + } + + return true; +} + /* Errors: * -EBADR: This unit type does not support starting. * -EALREADY: Unit is already started. @@ -1545,6 +1570,7 @@ bool unit_shall_confirm_spawn(Unit *u) { * -EPROTO: Assert failed * -EINVAL: Unit not loaded * -EOPNOTSUPP: Unit type not supported + * -ENOLINK: The necessary dependencies are not fulfilled. */ int unit_start(Unit *u) { UnitActiveState state; @@ -1590,6 +1616,12 @@ int unit_start(Unit *u) { if (!unit_supported(u)) return -EOPNOTSUPP; + /* Let's make sure that the deps really are in order before we start this. Normally the job engine should have + * taken care of this already, but let's check this here again. After all, our dependencies might not be in + * effect anymore, due to a reload or due to a failed condition. */ + if (!unit_verify_deps(u)) + return -ENOLINK; + /* Forward to the main object, if we aren't it. */ following = unit_following(u); if (following) { @@ -4036,7 +4068,7 @@ void unit_warn_if_dir_nonempty(Unit *u, const char* where) { } log_struct(LOG_NOTICE, - LOG_MESSAGE_ID(SD_MESSAGE_OVERMOUNTING), + "MESSAGE_ID=" SD_MESSAGE_OVERMOUNTING_STR, LOG_UNIT_ID(u), LOG_UNIT_MESSAGE(u, "Directory %s to mount over is not empty, mounting anyway.", where), "WHERE=%s", where, @@ -4058,7 +4090,7 @@ int unit_fail_if_symlink(Unit *u, const char* where) { return 0; log_struct(LOG_ERR, - LOG_MESSAGE_ID(SD_MESSAGE_OVERMOUNTING), + "MESSAGE_ID=" SD_MESSAGE_OVERMOUNTING_STR, LOG_UNIT_ID(u), LOG_UNIT_MESSAGE(u, "Mount on symlink %s not allowed.", where), "WHERE=%s", where, |