1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include "selinux-access.h"
25 #include "cgroup-util.h"
27 #include "path-util.h"
29 #include "dbus-unit.h"
30 #include "dbus-manager.h"
31 #include "bus-errors.h"
32 #include "dbus-client-track.h"
34 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_load_state, unit_load_state, UnitLoadState);
36 static int property_get_names(
39 const char *interface,
41 sd_bus_message *reply,
54 r = sd_bus_message_open_container(reply, 'a', "s");
58 SET_FOREACH(t, u->names, i) {
59 r = sd_bus_message_append(reply, "s", t);
64 return sd_bus_message_close_container(reply);
67 static int property_get_following(
70 const char *interface,
72 sd_bus_message *reply,
76 Unit *u = userdata, *f;
82 f = unit_following(u);
83 return sd_bus_message_append(reply, "s", f ? f->id : "");
86 static int property_get_dependencies(
89 const char *interface,
91 sd_bus_message *reply,
95 Set *s = *(Set**) userdata;
103 r = sd_bus_message_open_container(reply, 'a', "s");
107 SET_FOREACH(u, s, j) {
108 r = sd_bus_message_append(reply, "s", u->id);
113 return sd_bus_message_close_container(reply);
116 static int property_get_description(
119 const char *interface,
120 const char *property,
121 sd_bus_message *reply,
131 return sd_bus_message_append(reply, "s", unit_description(u));
134 static int property_get_active_state(
137 const char *interface,
138 const char *property,
139 sd_bus_message *reply,
149 return sd_bus_message_append(reply, "s", unit_active_state_to_string(unit_active_state(u)));
152 static int property_get_sub_state(
155 const char *interface,
156 const char *property,
157 sd_bus_message *reply,
167 return sd_bus_message_append(reply, "s", unit_sub_state_to_string(u));
170 static int property_get_unit_file_state(
173 const char *interface,
174 const char *property,
175 sd_bus_message *reply,
185 return sd_bus_message_append(reply, "s", unit_file_state_to_string(unit_get_unit_file_state(u)));
188 static int property_get_can_start(
191 const char *interface,
192 const char *property,
193 sd_bus_message *reply,
203 return sd_bus_message_append(reply, "b", unit_can_start(u) && !u->refuse_manual_start);
206 static int property_get_can_stop(
209 const char *interface,
210 const char *property,
211 sd_bus_message *reply,
221 /* On the lower levels we assume that every unit we can start
222 * we can also stop */
224 return sd_bus_message_append(reply, "b", unit_can_start(u) && !u->refuse_manual_stop);
227 static int property_get_can_reload(
230 const char *interface,
231 const char *property,
232 sd_bus_message *reply,
242 return sd_bus_message_append(reply, "b", unit_can_reload(u));
245 static int property_get_can_isolate(
248 const char *interface,
249 const char *property,
250 sd_bus_message *reply,
260 return sd_bus_message_append(reply, "b", unit_can_isolate(u) && !u->refuse_manual_start);
263 static int property_get_job(
266 const char *interface,
267 const char *property,
268 sd_bus_message *reply,
272 _cleanup_free_ char *p = NULL;
280 return sd_bus_message_append(reply, "(uo)", 0, "/");
282 p = job_dbus_path(u->job);
286 return sd_bus_message_append(reply, "(uo)", u->job->id, p);
289 static int property_get_need_daemon_reload(
292 const char *interface,
293 const char *property,
294 sd_bus_message *reply,
304 return sd_bus_message_append(reply, "b", unit_need_daemon_reload(u));
307 static int property_get_conditions(
310 const char *interface,
311 const char *property,
312 sd_bus_message *reply,
324 r = sd_bus_message_open_container(reply, 'a', "(sbbsi)");
328 LIST_FOREACH(conditions, c, u->conditions) {
329 r = sd_bus_message_append(reply, "sbbsi", condition_type_to_string(c->type), c->trigger, c->negate, c->parameter, c->state);
335 return sd_bus_message_close_container(reply);
338 static int property_get_load_error(
341 const char *interface,
342 const char *property,
343 sd_bus_message *reply,
347 _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
354 if (u->load_error != 0)
355 sd_bus_error_set_errno(&e, u->load_error);
357 return sd_bus_message_append(reply, "(ss)", e.name, e.message);
360 int bus_unit_method_start_generic(sd_bus *bus, sd_bus_message *message, Unit *u, JobType job_type, bool reload_if_possible) {
368 assert(job_type >= 0 && job_type < _JOB_TYPE_MAX);
370 r = sd_bus_message_read(message, "s", &smode);
372 return sd_bus_reply_method_errno(message, r, NULL);
374 mode = job_mode_from_string(smode);
376 return sd_bus_reply_method_errorf(message, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s invalid", smode);
378 return bus_unit_queue_job(bus, message, u, job_type, mode, reload_if_possible);
381 static int method_start(sd_bus *bus, sd_bus_message *message, void *userdata) {
382 return bus_unit_method_start_generic(bus, message, userdata, JOB_START, false);
385 static int method_stop(sd_bus *bus, sd_bus_message *message, void *userdata) {
386 return bus_unit_method_start_generic(bus, message, userdata, JOB_STOP, false);
389 static int method_reload(sd_bus *bus, sd_bus_message *message, void *userdata) {
390 return bus_unit_method_start_generic(bus, message, userdata, JOB_RELOAD, false);
393 static int method_restart(sd_bus *bus, sd_bus_message *message, void *userdata) {
394 return bus_unit_method_start_generic(bus, message, userdata, JOB_RESTART, false);
397 static int method_try_restart(sd_bus *bus, sd_bus_message *message, void *userdata) {
398 return bus_unit_method_start_generic(bus, message, userdata, JOB_TRY_RESTART, false);
401 static int method_reload_or_restart(sd_bus *bus, sd_bus_message *message, void *userdata) {
402 return bus_unit_method_start_generic(bus, message, userdata, JOB_RESTART, true);
405 static int method_reload_or_try_restart(sd_bus *bus, sd_bus_message *message, void *userdata) {
406 return bus_unit_method_start_generic(bus, message, userdata, JOB_TRY_RESTART, true);
409 int bus_unit_method_kill(sd_bus *bus, sd_bus_message *message, void *userdata) {
410 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
421 r = sd_bus_message_read(message, "si", &swho, &signo);
423 return sd_bus_reply_method_errno(message, r, NULL);
428 who = kill_who_from_string(swho);
430 return sd_bus_reply_method_errorf(message, SD_BUS_ERROR_INVALID_ARGS, "Invalid who argument %s", swho);
433 if (signo <= 0 || signo >= _NSIG)
434 return sd_bus_reply_method_errorf(message, SD_BUS_ERROR_INVALID_ARGS, "Signal number out of range.");
436 SELINUX_UNIT_ACCESS_CHECK(u, bus, message, "stop");
438 r = unit_kill(u, who, signo, &error);
440 return sd_bus_reply_method_errno(message, r, &error);
442 return sd_bus_reply_method_return(message, NULL);
445 int bus_unit_method_reset_failed(sd_bus *bus, sd_bus_message *message, void *userdata) {
452 SELINUX_UNIT_ACCESS_CHECK(u, bus, message, "reload");
454 unit_reset_failed(u);
456 return sd_bus_reply_method_return(message, NULL);
459 int bus_unit_method_set_properties(sd_bus *bus, sd_bus_message *message, void *userdata) {
460 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
468 r = sd_bus_message_read(message, "b", &runtime);
470 return sd_bus_reply_method_errno(message, r, NULL);
472 SELINUX_UNIT_ACCESS_CHECK(u, bus, message, "start");
474 r = sd_bus_message_enter_container(message, 'a', "(sv)");
476 return sd_bus_reply_method_errno(message, r, NULL);
478 r = bus_unit_set_properties(u, message, runtime ? UNIT_RUNTIME : UNIT_PERSISTENT, true, &error);
480 return sd_bus_reply_method_errno(message, r, &error);
482 r = sd_bus_message_exit_container(message);
484 return sd_bus_reply_method_errno(message, r, NULL);
486 return sd_bus_reply_method_return(message, NULL);
489 const sd_bus_vtable bus_unit_vtable[] = {
490 SD_BUS_VTABLE_START(0),
492 SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Unit, id), 0),
493 SD_BUS_PROPERTY("Names", "as", property_get_names, 0, 0),
494 SD_BUS_PROPERTY("Following", "s", property_get_following, 0, 0),
495 SD_BUS_PROPERTY("Requires", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRES]), 0),
496 SD_BUS_PROPERTY("RequiresOverridable", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRES_OVERRIDABLE]), 0),
497 SD_BUS_PROPERTY("Requisite", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE]), 0),
498 SD_BUS_PROPERTY("RequisiteOverridable", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE_OVERRIDABLE]), 0),
499 SD_BUS_PROPERTY("Wants", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_WANTS]), 0),
500 SD_BUS_PROPERTY("BindsTo", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BINDS_TO]), 0),
501 SD_BUS_PROPERTY("PartOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_PART_OF]), 0),
502 SD_BUS_PROPERTY("RequiredBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRED_BY]), 0),
503 SD_BUS_PROPERTY("RequiredByOverridable", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRED_BY_OVERRIDABLE]), 0),
504 SD_BUS_PROPERTY("WantedBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_WANTED_BY]), 0),
505 SD_BUS_PROPERTY("BoundBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BOUND_BY]), 0),
506 SD_BUS_PROPERTY("ConsistsOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONSISTS_OF]), 0),
507 SD_BUS_PROPERTY("Conflicts", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONFLICTS]), 0),
508 SD_BUS_PROPERTY("ConflictedBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONFLICTED_BY]), 0),
509 SD_BUS_PROPERTY("Before", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BEFORE]), 0),
510 SD_BUS_PROPERTY("After", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_AFTER]), 0),
511 SD_BUS_PROPERTY("OnFailure", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_ON_FAILURE]), 0),
512 SD_BUS_PROPERTY("Triggers", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_TRIGGERS]), 0),
513 SD_BUS_PROPERTY("TriggeredBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_TRIGGERED_BY]), 0),
514 SD_BUS_PROPERTY("PropagatesReloadTo", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_PROPAGATES_RELOAD_TO]), 0),
515 SD_BUS_PROPERTY("ReloadPropagatedFrom", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_RELOAD_PROPAGATED_FROM]), 0),
516 SD_BUS_PROPERTY("RequiresMountsFor", "as", NULL, offsetof(Unit, requires_mounts_for), 0),
517 SD_BUS_PROPERTY("Documentation", "as", NULL, offsetof(Unit, documentation), 0),
518 SD_BUS_PROPERTY("Description", "s", property_get_description, 0, 0),
519 SD_BUS_PROPERTY("LoadState", "s", property_get_load_state, offsetof(Unit, load_state), 0),
520 SD_BUS_PROPERTY("ActiveState", "s", property_get_active_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
521 SD_BUS_PROPERTY("SubState", "s", property_get_sub_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
522 SD_BUS_PROPERTY("FragmentPath", "s", NULL, offsetof(Unit, fragment_path), 0),
523 SD_BUS_PROPERTY("SourcePath", "s", NULL, offsetof(Unit, source_path), 0),
524 SD_BUS_PROPERTY("DropInPaths", "as", NULL, offsetof(Unit, dropin_paths), 0),
525 SD_BUS_PROPERTY("UnitFileState", "s", property_get_unit_file_state, 0, 0),
526 BUS_PROPERTY_DUAL_TIMESTAMP("InactiveExitTimestamp", offsetof(Unit, inactive_exit_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
527 BUS_PROPERTY_DUAL_TIMESTAMP("ActiveEnterTimestamp", offsetof(Unit, active_enter_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
528 BUS_PROPERTY_DUAL_TIMESTAMP("ActiveExitTimestamp", offsetof(Unit, active_exit_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
529 BUS_PROPERTY_DUAL_TIMESTAMP("InactiveEnterTimestamp", offsetof(Unit, inactive_enter_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
530 SD_BUS_PROPERTY("CanStart", "b", property_get_can_start, 0, 0),
531 SD_BUS_PROPERTY("CanStop", "b", property_get_can_stop, 0, 0),
532 SD_BUS_PROPERTY("CanReload", "b", property_get_can_reload, 0, 0),
533 SD_BUS_PROPERTY("CanIsolate", "b", property_get_can_isolate, 0, 0),
534 SD_BUS_PROPERTY("Job", "(uo)", property_get_job, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
535 SD_BUS_PROPERTY("StopWhenUnneeded", "b", bus_property_get_bool, offsetof(Unit, stop_when_unneeded), 0),
536 SD_BUS_PROPERTY("RefuseManualStart", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_start), 0),
537 SD_BUS_PROPERTY("RefuseManualStop", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_stop), 0),
538 SD_BUS_PROPERTY("AllowIsolate", "b", bus_property_get_bool, offsetof(Unit, allow_isolate), 0),
539 SD_BUS_PROPERTY("DefaultDependencies", "b", bus_property_get_bool, offsetof(Unit, default_dependencies), 0),
540 SD_BUS_PROPERTY("OnFailureIsolate", "b", bus_property_get_bool, offsetof(Unit, on_failure_isolate), 0),
541 SD_BUS_PROPERTY("IgnoreOnIsolate", "b", bus_property_get_bool, offsetof(Unit, ignore_on_isolate), 0),
542 SD_BUS_PROPERTY("IgnoreOnSnapshot", "b", bus_property_get_bool, offsetof(Unit, ignore_on_snapshot), 0),
543 SD_BUS_PROPERTY("NeedDaemonReload", "b", property_get_need_daemon_reload, 0, 0),
544 SD_BUS_PROPERTY("JobTimeoutUSec", "t", bus_property_get_usec, offsetof(Unit, job_timeout), 0),
545 SD_BUS_PROPERTY("ConditionResult", "b", bus_property_get_bool, offsetof(Unit, condition_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
546 BUS_PROPERTY_DUAL_TIMESTAMP("ConditionTimestamp", offsetof(Unit, condition_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
547 SD_BUS_PROPERTY("Conditions", "a(sbbsi)", property_get_conditions, 0, 0),
548 SD_BUS_PROPERTY("LoadError", "(ss)", property_get_load_error, 0, 0),
549 SD_BUS_PROPERTY("Transient", "b", bus_property_get_bool, offsetof(Unit, transient), 0),
551 SD_BUS_METHOD("Start", "s", "o", method_start, 0),
552 SD_BUS_METHOD("Stop", "s", "o", method_stop, 0),
553 SD_BUS_METHOD("Reload", "s", "o", method_reload, 0),
554 SD_BUS_METHOD("Restart", "s", "o", method_restart, 0),
555 SD_BUS_METHOD("TryRestart", "s", "o", method_try_restart, 0),
556 SD_BUS_METHOD("ReloadOrRestart", "s", "o", method_reload_or_restart, 0),
557 SD_BUS_METHOD("ReloadOrTryRestart", "s", "o", method_reload_or_try_restart, 0),
558 SD_BUS_METHOD("Kill", "si", NULL, bus_unit_method_kill, 0),
559 SD_BUS_METHOD("ResetFailed", NULL, NULL, bus_unit_method_reset_failed, 0),
560 SD_BUS_METHOD("SetProperties", "ba(sv)", NULL, bus_unit_method_set_properties, 0),
565 static int property_get_slice(
568 const char *interface,
569 const char *property,
570 sd_bus_message *reply,
580 return sd_bus_message_append(reply, "s", unit_slice_name(u));
583 const sd_bus_vtable bus_unit_cgroup_vtable[] = {
584 SD_BUS_VTABLE_START(0),
585 SD_BUS_PROPERTY("Slice", "s", property_get_slice, 0, 0),
586 SD_BUS_PROPERTY("ControlGroup", "s", NULL, offsetof(Unit, cgroup_path), 0),
590 static int send_new_signal(sd_bus *bus, const char *destination, void *userdata) {
591 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
592 _cleanup_free_ char *p = NULL;
599 p = unit_dbus_path(u);
603 r = sd_bus_message_new_signal(
605 "/org/freedesktop/systemd1",
606 "org.freedesktop.systemd1.Manager",
612 r = sd_bus_message_append(m, "so", u->id, p);
616 return sd_bus_send_to(bus, m, destination, NULL);
619 static int send_changed_signal(sd_bus *bus, const char *destination, void *userdata) {
620 _cleanup_free_ char *p = NULL;
627 p = unit_dbus_path(u);
631 /* Send a properties changed signal. First for the specific
632 * type, then for the generic unit. The clients may rely on
633 * this order to get atomic behavior if needed. */
635 if (UNIT_VTABLE(u)->bus_changing_properties) {
637 r = sd_bus_emit_properties_changed_strv(
639 UNIT_VTABLE(u)->bus_interface,
640 (char**) UNIT_VTABLE(u)->bus_changing_properties);
645 return sd_bus_emit_properties_changed(
647 "org.freedesktop.systemd1.Unit",
650 "InactiveExitTimestamp",
651 "ActiveEnterTimestamp",
652 "ActiveExitTimestamp",
653 "InactiveEnterTimestamp",
656 "ConditionTimestamp",
660 void bus_unit_send_change_signal(Unit *u) {
665 if (u->in_dbus_queue) {
666 LIST_REMOVE(dbus_queue, u->manager->dbus_unit_queue, u);
667 u->in_dbus_queue = false;
673 r = bus_manager_foreach_client(u->manager, u->sent_dbus_new_signal ? send_changed_signal : send_new_signal, u);
675 log_warning("Failed to send unit change signal for %s: %s", u->id, strerror(-r));
677 u->sent_dbus_new_signal = true;
680 static int send_removed_signal(sd_bus *bus, const char *destination, void *userdata) {
681 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
682 _cleanup_free_ char *p = NULL;
689 p = unit_dbus_path(u);
693 r = sd_bus_message_new_signal(
695 "/org/freedesktop/systemd1",
696 "org.freedesktop.systemd1.Manager",
702 r = sd_bus_message_append(m, "so", u->id, p);
706 return sd_bus_send_to(bus, m, destination, NULL);
709 void bus_unit_send_removed_signal(Unit *u) {
714 if (!u->sent_dbus_new_signal)
715 bus_unit_send_change_signal(u);
720 r = bus_manager_foreach_client(u->manager, send_removed_signal, u);
722 log_warning("Failed to send unit change signal for %s: %s", u->id, strerror(-r));
725 int bus_unit_queue_job(
727 sd_bus_message *message,
731 bool reload_if_possible) {
733 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
734 _cleanup_free_ char *path = NULL;
741 assert(type >= 0 && type < _JOB_TYPE_MAX);
742 assert(mode >= 0 && mode < _JOB_MODE_MAX);
744 if (reload_if_possible && unit_can_reload(u)) {
745 if (type == JOB_RESTART)
746 type = JOB_RELOAD_OR_START;
747 else if (type == JOB_TRY_RESTART)
751 SELINUX_UNIT_ACCESS_CHECK(u, bus, message,
752 (type == JOB_START || type == JOB_RESTART || type == JOB_TRY_RESTART) ? "start" :
753 type == JOB_STOP ? "stop" : "reload");
755 if (type == JOB_STOP &&
756 (u->load_state == UNIT_NOT_FOUND || u->load_state == UNIT_ERROR) &&
757 unit_active_state(u) == UNIT_INACTIVE)
758 return sd_bus_reply_method_errorf(message, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", u->id);
760 if ((type == JOB_START && u->refuse_manual_start) ||
761 (type == JOB_STOP && u->refuse_manual_stop) ||
762 ((type == JOB_RESTART || type == JOB_TRY_RESTART) && (u->refuse_manual_start || u->refuse_manual_stop)))
763 return sd_bus_reply_method_errorf(message, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, unit %s may be requested by dependency only.", u->id);
765 r = manager_add_job(u->manager, type, u, mode, true, &error, &j);
767 return sd_bus_reply_method_errno(message, r, &error);
769 r = bus_client_track(&j->subscribed, bus, sd_bus_message_get_sender(message));
771 return sd_bus_reply_method_errno(message, r, NULL);
773 path = job_dbus_path(j);
775 return sd_bus_reply_method_errno(message, r, NULL);
777 return sd_bus_reply_method_return(message, "o", path);
780 static int bus_unit_set_transient_property(
783 sd_bus_message *message,
784 UnitSetPropertiesMode mode,
785 sd_bus_error *error) {
793 if (streq(name, "Description")) {
796 r = sd_bus_message_read(message, "s", &d);
800 if (mode != UNIT_CHECK) {
801 r = unit_set_description(u, d);
805 unit_write_drop_in_format(u, mode, name, "[Unit]\nDescription=%s\n", d);
810 } else if (streq(name, "Slice") && unit_get_cgroup_context(u)) {
813 r = sd_bus_message_read(message, "s", &s);
817 if (!unit_name_is_valid(s, false) || !endswith(s, ".slice"))
818 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid slice name %s", s);
821 if (mode != UNIT_CHECK) {
822 unit_ref_unset(&u->slice);
823 unit_remove_drop_in(u, mode, name);
828 r = manager_load_unit(u->manager, s, NULL, error, &slice);
832 if (slice->type != UNIT_SLICE)
835 if (mode != UNIT_CHECK) {
836 unit_ref_set(&u->slice, slice);
837 unit_write_drop_in_private_format(u, mode, name, "Slice=%s\n", s);
843 } else if (streq(name, "Requires") ||
844 streq(name, "RequiresOverridable") ||
845 streq(name, "Requisite") ||
846 streq(name, "RequisiteOverridable") ||
847 streq(name, "Wants") ||
848 streq(name, "BindsTo") ||
849 streq(name, "Conflicts") ||
850 streq(name, "Before") ||
851 streq(name, "After") ||
852 streq(name, "OnFailure") ||
853 streq(name, "PropagatesReloadTo") ||
854 streq(name, "ReloadPropagatedFrom") ||
855 streq(name, "PartOf")) {
860 d = unit_dependency_from_string(name);
864 r = sd_bus_message_enter_container(message, 'a', "s");
868 while ((r = sd_bus_message_read(message, "s", &other)) > 0) {
869 if (!unit_name_is_valid(other, false))
870 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit name %s", other);
872 if (mode != UNIT_CHECK) {
873 _cleanup_free_ char *label = NULL;
875 r = unit_add_dependency_by_name(u, d, other, NULL, true);
879 label = strjoin(name, "-", other, NULL);
883 unit_write_drop_in_format(u, mode, label, "[Unit]\n%s=%s\n", name, other);
896 int bus_unit_set_properties(
898 sd_bus_message *message,
899 UnitSetPropertiesMode mode,
901 sd_bus_error *error) {
903 bool for_real = false;
911 mode &= UNIT_RUNTIME;
913 /* We iterate through the array twice. First run we just check
914 * if all passed data is valid, second run actually applies
915 * it. This is to implement transaction-like behaviour without
916 * actually providing full transactions. */
918 r = sd_bus_message_enter_container(message, 'a', "(sv)");
925 r = sd_bus_message_enter_container(message, 'r', "sv");
929 if (for_real || mode == UNIT_CHECK)
932 /* Reached EOF. Let's try again, and this time for realz... */
933 r = sd_bus_message_rewind(message, false);
940 r = sd_bus_message_read(message, "s", &name);
944 if (!UNIT_VTABLE(u)->bus_set_property)
945 return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Objects of this type do not support setting properties.");
947 r = sd_bus_message_enter_container(message, 'v', NULL);
951 r = UNIT_VTABLE(u)->bus_set_property(u, name, message, for_real ? mode : UNIT_CHECK, error);
952 if (r == 0 && u->transient && u->load_state == UNIT_STUB)
953 r = bus_unit_set_transient_property(u, name, message, for_real ? mode : UNIT_CHECK, error);
957 return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Cannot set property %s, or unknown property.", name);
959 r = sd_bus_message_exit_container(message);
963 r = sd_bus_message_exit_container(message);
970 if (commit && n > 0 && UNIT_VTABLE(u)->bus_commit_properties)
971 UNIT_VTABLE(u)->bus_commit_properties(u);