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,
43 sd_bus_error *error) {
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,
74 sd_bus_error *error) {
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,
93 sd_bus_error *error) {
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,
123 sd_bus_error *error) {
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,
141 sd_bus_error *error) {
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,
159 sd_bus_error *error) {
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,
177 sd_bus_error *error) {
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,
195 sd_bus_error *error) {
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,
213 sd_bus_error *error) {
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,
234 sd_bus_error *error) {
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,
252 sd_bus_error *error) {
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,
270 sd_bus_error *error) {
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,
296 sd_bus_error *error) {
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,
314 sd_bus_error *error) {
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)",
330 condition_type_to_string(c->type),
331 c->trigger, c->negate,
332 c->parameter, c->state);
338 return sd_bus_message_close_container(reply);
341 static int property_get_load_error(
344 const char *interface,
345 const char *property,
346 sd_bus_message *reply,
348 sd_bus_error *error) {
350 _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
357 if (u->load_error != 0)
358 sd_bus_error_set_errno(&e, u->load_error);
360 return sd_bus_message_append(reply, "(ss)", e.name, e.message);
363 int bus_unit_method_start_generic(sd_bus *bus, sd_bus_message *message, Unit *u, JobType job_type, bool reload_if_possible, sd_bus_error *error) {
371 assert(job_type >= 0 && job_type < _JOB_TYPE_MAX);
373 r = sd_bus_message_read(message, "s", &smode);
377 mode = job_mode_from_string(smode);
379 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s invalid", smode);
381 return bus_unit_queue_job(bus, message, u, job_type, mode, reload_if_possible, error);
384 static int method_start(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
385 return bus_unit_method_start_generic(bus, message, userdata, JOB_START, false, error);
388 static int method_stop(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
389 return bus_unit_method_start_generic(bus, message, userdata, JOB_STOP, false, error);
392 static int method_reload(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
393 return bus_unit_method_start_generic(bus, message, userdata, JOB_RELOAD, false, error);
396 static int method_restart(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
397 return bus_unit_method_start_generic(bus, message, userdata, JOB_RESTART, false, error);
400 static int method_try_restart(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
401 return bus_unit_method_start_generic(bus, message, userdata, JOB_TRY_RESTART, false, error);
404 static int method_reload_or_restart(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
405 return bus_unit_method_start_generic(bus, message, userdata, JOB_RESTART, true, error);
408 static int method_reload_or_try_restart(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
409 return bus_unit_method_start_generic(bus, message, userdata, JOB_TRY_RESTART, true, error);
412 int bus_unit_method_kill(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
423 r = sd_bus_message_read(message, "si", &swho, &signo);
430 who = kill_who_from_string(swho);
432 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid who argument %s", swho);
435 if (signo <= 0 || signo >= _NSIG)
436 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Signal number out of range.");
438 r = selinux_unit_access_check(u, bus, message, "stop", error);
442 r = unit_kill(u, who, signo, error);
446 return sd_bus_reply_method_return(message, NULL);
449 int bus_unit_method_reset_failed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
457 r = selinux_unit_access_check(u, bus, message, "reload", error);
461 unit_reset_failed(u);
463 return sd_bus_reply_method_return(message, NULL);
466 int bus_unit_method_set_properties(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
474 r = sd_bus_message_read(message, "b", &runtime);
478 r = selinux_unit_access_check(u, bus, message, "start", error);
482 r = sd_bus_message_enter_container(message, 'a', "(sv)");
486 r = bus_unit_set_properties(u, message, runtime ? UNIT_RUNTIME : UNIT_PERSISTENT, true, error);
490 r = sd_bus_message_exit_container(message);
494 return sd_bus_reply_method_return(message, NULL);
497 const sd_bus_vtable bus_unit_vtable[] = {
498 SD_BUS_VTABLE_START(0),
500 SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Unit, id), 0),
501 SD_BUS_PROPERTY("Names", "as", property_get_names, 0, 0),
502 SD_BUS_PROPERTY("Following", "s", property_get_following, 0, 0),
503 SD_BUS_PROPERTY("Requires", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRES]), 0),
504 SD_BUS_PROPERTY("RequiresOverridable", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRES_OVERRIDABLE]), 0),
505 SD_BUS_PROPERTY("Requisite", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE]), 0),
506 SD_BUS_PROPERTY("RequisiteOverridable", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE_OVERRIDABLE]), 0),
507 SD_BUS_PROPERTY("Wants", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_WANTS]), 0),
508 SD_BUS_PROPERTY("BindsTo", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BINDS_TO]), 0),
509 SD_BUS_PROPERTY("PartOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_PART_OF]), 0),
510 SD_BUS_PROPERTY("RequiredBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRED_BY]), 0),
511 SD_BUS_PROPERTY("RequiredByOverridable", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRED_BY_OVERRIDABLE]), 0),
512 SD_BUS_PROPERTY("WantedBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_WANTED_BY]), 0),
513 SD_BUS_PROPERTY("BoundBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BOUND_BY]), 0),
514 SD_BUS_PROPERTY("ConsistsOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONSISTS_OF]), 0),
515 SD_BUS_PROPERTY("Conflicts", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONFLICTS]), 0),
516 SD_BUS_PROPERTY("ConflictedBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONFLICTED_BY]), 0),
517 SD_BUS_PROPERTY("Before", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BEFORE]), 0),
518 SD_BUS_PROPERTY("After", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_AFTER]), 0),
519 SD_BUS_PROPERTY("OnFailure", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_ON_FAILURE]), 0),
520 SD_BUS_PROPERTY("Triggers", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_TRIGGERS]), 0),
521 SD_BUS_PROPERTY("TriggeredBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_TRIGGERED_BY]), 0),
522 SD_BUS_PROPERTY("PropagatesReloadTo", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_PROPAGATES_RELOAD_TO]), 0),
523 SD_BUS_PROPERTY("ReloadPropagatedFrom", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_RELOAD_PROPAGATED_FROM]), 0),
524 SD_BUS_PROPERTY("RequiresMountsFor", "as", NULL, offsetof(Unit, requires_mounts_for), 0),
525 SD_BUS_PROPERTY("Documentation", "as", NULL, offsetof(Unit, documentation), 0),
526 SD_BUS_PROPERTY("Description", "s", property_get_description, 0, 0),
527 SD_BUS_PROPERTY("LoadState", "s", property_get_load_state, offsetof(Unit, load_state), 0),
528 SD_BUS_PROPERTY("ActiveState", "s", property_get_active_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
529 SD_BUS_PROPERTY("SubState", "s", property_get_sub_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
530 SD_BUS_PROPERTY("FragmentPath", "s", NULL, offsetof(Unit, fragment_path), 0),
531 SD_BUS_PROPERTY("SourcePath", "s", NULL, offsetof(Unit, source_path), 0),
532 SD_BUS_PROPERTY("DropInPaths", "as", NULL, offsetof(Unit, dropin_paths), 0),
533 SD_BUS_PROPERTY("UnitFileState", "s", property_get_unit_file_state, 0, 0),
534 BUS_PROPERTY_DUAL_TIMESTAMP("InactiveExitTimestamp", offsetof(Unit, inactive_exit_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
535 BUS_PROPERTY_DUAL_TIMESTAMP("ActiveEnterTimestamp", offsetof(Unit, active_enter_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
536 BUS_PROPERTY_DUAL_TIMESTAMP("ActiveExitTimestamp", offsetof(Unit, active_exit_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
537 BUS_PROPERTY_DUAL_TIMESTAMP("InactiveEnterTimestamp", offsetof(Unit, inactive_enter_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
538 SD_BUS_PROPERTY("CanStart", "b", property_get_can_start, 0, 0),
539 SD_BUS_PROPERTY("CanStop", "b", property_get_can_stop, 0, 0),
540 SD_BUS_PROPERTY("CanReload", "b", property_get_can_reload, 0, 0),
541 SD_BUS_PROPERTY("CanIsolate", "b", property_get_can_isolate, 0, 0),
542 SD_BUS_PROPERTY("Job", "(uo)", property_get_job, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
543 SD_BUS_PROPERTY("StopWhenUnneeded", "b", bus_property_get_bool, offsetof(Unit, stop_when_unneeded), 0),
544 SD_BUS_PROPERTY("RefuseManualStart", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_start), 0),
545 SD_BUS_PROPERTY("RefuseManualStop", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_stop), 0),
546 SD_BUS_PROPERTY("AllowIsolate", "b", bus_property_get_bool, offsetof(Unit, allow_isolate), 0),
547 SD_BUS_PROPERTY("DefaultDependencies", "b", bus_property_get_bool, offsetof(Unit, default_dependencies), 0),
548 SD_BUS_PROPERTY("OnFailureIsolate", "b", bus_property_get_bool, offsetof(Unit, on_failure_isolate), 0),
549 SD_BUS_PROPERTY("IgnoreOnIsolate", "b", bus_property_get_bool, offsetof(Unit, ignore_on_isolate), 0),
550 SD_BUS_PROPERTY("IgnoreOnSnapshot", "b", bus_property_get_bool, offsetof(Unit, ignore_on_snapshot), 0),
551 SD_BUS_PROPERTY("NeedDaemonReload", "b", property_get_need_daemon_reload, 0, 0),
552 SD_BUS_PROPERTY("JobTimeoutUSec", "t", bus_property_get_usec, offsetof(Unit, job_timeout), 0),
553 SD_BUS_PROPERTY("ConditionResult", "b", bus_property_get_bool, offsetof(Unit, condition_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
554 BUS_PROPERTY_DUAL_TIMESTAMP("ConditionTimestamp", offsetof(Unit, condition_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
555 SD_BUS_PROPERTY("Conditions", "a(sbbsi)", property_get_conditions, 0, 0),
556 SD_BUS_PROPERTY("LoadError", "(ss)", property_get_load_error, 0, 0),
557 SD_BUS_PROPERTY("Transient", "b", bus_property_get_bool, offsetof(Unit, transient), 0),
559 SD_BUS_METHOD("Start", "s", "o", method_start, 0),
560 SD_BUS_METHOD("Stop", "s", "o", method_stop, 0),
561 SD_BUS_METHOD("Reload", "s", "o", method_reload, 0),
562 SD_BUS_METHOD("Restart", "s", "o", method_restart, 0),
563 SD_BUS_METHOD("TryRestart", "s", "o", method_try_restart, 0),
564 SD_BUS_METHOD("ReloadOrRestart", "s", "o", method_reload_or_restart, 0),
565 SD_BUS_METHOD("ReloadOrTryRestart", "s", "o", method_reload_or_try_restart, 0),
566 SD_BUS_METHOD("Kill", "si", NULL, bus_unit_method_kill, 0),
567 SD_BUS_METHOD("ResetFailed", NULL, NULL, bus_unit_method_reset_failed, 0),
568 SD_BUS_METHOD("SetProperties", "ba(sv)", NULL, bus_unit_method_set_properties, 0),
573 static int property_get_slice(
576 const char *interface,
577 const char *property,
578 sd_bus_message *reply,
580 sd_bus_error *error) {
588 return sd_bus_message_append(reply, "s", unit_slice_name(u));
591 const sd_bus_vtable bus_unit_cgroup_vtable[] = {
592 SD_BUS_VTABLE_START(0),
593 SD_BUS_PROPERTY("Slice", "s", property_get_slice, 0, 0),
594 SD_BUS_PROPERTY("ControlGroup", "s", NULL, offsetof(Unit, cgroup_path), 0),
598 static int send_new_signal(sd_bus *bus, const char *destination, void *userdata) {
599 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
600 _cleanup_free_ char *p = NULL;
607 p = unit_dbus_path(u);
611 r = sd_bus_message_new_signal(
613 "/org/freedesktop/systemd1",
614 "org.freedesktop.systemd1.Manager",
620 r = sd_bus_message_append(m, "so", u->id, p);
624 return sd_bus_send_to(bus, m, destination, NULL);
627 static int send_changed_signal(sd_bus *bus, const char *destination, void *userdata) {
628 _cleanup_free_ char *p = NULL;
635 p = unit_dbus_path(u);
639 /* Send a properties changed signal. First for the specific
640 * type, then for the generic unit. The clients may rely on
641 * this order to get atomic behavior if needed. */
643 if (UNIT_VTABLE(u)->bus_changing_properties) {
645 r = sd_bus_emit_properties_changed_strv(
647 UNIT_VTABLE(u)->bus_interface,
648 (char**) UNIT_VTABLE(u)->bus_changing_properties);
653 return sd_bus_emit_properties_changed(
655 "org.freedesktop.systemd1.Unit",
658 "InactiveExitTimestamp",
659 "ActiveEnterTimestamp",
660 "ActiveExitTimestamp",
661 "InactiveEnterTimestamp",
664 "ConditionTimestamp",
668 void bus_unit_send_change_signal(Unit *u) {
672 if (u->in_dbus_queue) {
673 LIST_REMOVE(dbus_queue, u->manager->dbus_unit_queue, u);
674 u->in_dbus_queue = false;
680 r = bus_manager_foreach_client(u->manager, u->sent_dbus_new_signal ? send_changed_signal : send_new_signal, u);
682 log_debug("Failed to send unit change signal for %s: %s", u->id, strerror(-r));
684 u->sent_dbus_new_signal = true;
687 static int send_removed_signal(sd_bus *bus, const char *destination, void *userdata) {
688 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
689 _cleanup_free_ char *p = NULL;
696 p = unit_dbus_path(u);
700 r = sd_bus_message_new_signal(
702 "/org/freedesktop/systemd1",
703 "org.freedesktop.systemd1.Manager",
709 r = sd_bus_message_append(m, "so", u->id, p);
713 return sd_bus_send_to(bus, m, destination, NULL);
716 void bus_unit_send_removed_signal(Unit *u) {
720 if (!u->sent_dbus_new_signal)
721 bus_unit_send_change_signal(u);
726 r = bus_manager_foreach_client(u->manager, send_removed_signal, u);
728 log_debug("Failed to send unit remove signal for %s: %s", u->id, strerror(-r));
731 int bus_unit_queue_job(
733 sd_bus_message *message,
737 bool reload_if_possible,
738 sd_bus_error *error) {
740 _cleanup_free_ char *path = NULL;
747 assert(type >= 0 && type < _JOB_TYPE_MAX);
748 assert(mode >= 0 && mode < _JOB_MODE_MAX);
750 if (reload_if_possible && unit_can_reload(u)) {
751 if (type == JOB_RESTART)
752 type = JOB_RELOAD_OR_START;
753 else if (type == JOB_TRY_RESTART)
757 r = selinux_unit_access_check(
759 (type == JOB_START || type == JOB_RESTART || type == JOB_TRY_RESTART) ? "start" :
760 type == JOB_STOP ? "stop" : "reload", error);
764 if (type == JOB_STOP &&
765 (u->load_state == UNIT_NOT_FOUND || u->load_state == UNIT_ERROR) &&
766 unit_active_state(u) == UNIT_INACTIVE)
767 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", u->id);
769 if ((type == JOB_START && u->refuse_manual_start) ||
770 (type == JOB_STOP && u->refuse_manual_stop) ||
771 ((type == JOB_RESTART || type == JOB_TRY_RESTART) && (u->refuse_manual_start || u->refuse_manual_stop)))
772 return sd_bus_error_setf(error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, unit %s may be requested by dependency only.", u->id);
774 r = manager_add_job(u->manager, type, u, mode, true, error, &j);
778 r = bus_client_track(&j->subscribed, bus, sd_bus_message_get_sender(message));
782 path = job_dbus_path(j);
786 return sd_bus_reply_method_return(message, "o", path);
789 static int bus_unit_set_transient_property(
792 sd_bus_message *message,
793 UnitSetPropertiesMode mode,
794 sd_bus_error *error) {
802 if (streq(name, "Description")) {
805 r = sd_bus_message_read(message, "s", &d);
809 if (mode != UNIT_CHECK) {
810 r = unit_set_description(u, d);
814 unit_write_drop_in_format(u, mode, name, "[Unit]\nDescription=%s\n", d);
819 } else if (streq(name, "Slice") && unit_get_cgroup_context(u)) {
822 r = sd_bus_message_read(message, "s", &s);
826 if (!unit_name_is_valid(s, false) || !endswith(s, ".slice"))
827 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid slice name %s", s);
830 if (mode != UNIT_CHECK) {
831 unit_ref_unset(&u->slice);
832 unit_remove_drop_in(u, mode, name);
837 r = manager_load_unit(u->manager, s, NULL, error, &slice);
841 if (slice->type != UNIT_SLICE)
844 if (mode != UNIT_CHECK) {
845 unit_ref_set(&u->slice, slice);
846 unit_write_drop_in_private_format(u, mode, name, "Slice=%s\n", s);
852 } else if (streq(name, "Requires") ||
853 streq(name, "RequiresOverridable") ||
854 streq(name, "Requisite") ||
855 streq(name, "RequisiteOverridable") ||
856 streq(name, "Wants") ||
857 streq(name, "BindsTo") ||
858 streq(name, "Conflicts") ||
859 streq(name, "Before") ||
860 streq(name, "After") ||
861 streq(name, "OnFailure") ||
862 streq(name, "PropagatesReloadTo") ||
863 streq(name, "ReloadPropagatedFrom") ||
864 streq(name, "PartOf")) {
869 d = unit_dependency_from_string(name);
873 r = sd_bus_message_enter_container(message, 'a', "s");
877 while ((r = sd_bus_message_read(message, "s", &other)) > 0) {
878 if (!unit_name_is_valid(other, false))
879 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit name %s", other);
881 if (mode != UNIT_CHECK) {
882 _cleanup_free_ char *label = NULL;
884 r = unit_add_dependency_by_name(u, d, other, NULL, true);
888 label = strjoin(name, "-", other, NULL);
892 unit_write_drop_in_format(u, mode, label, "[Unit]\n%s=%s\n", name, other);
899 r = sd_bus_message_exit_container(message);
909 int bus_unit_set_properties(
911 sd_bus_message *message,
912 UnitSetPropertiesMode mode,
914 sd_bus_error *error) {
916 bool for_real = false;
924 mode &= UNIT_RUNTIME;
926 /* We iterate through the array twice. First run we just check
927 * if all passed data is valid, second run actually applies
928 * it. This is to implement transaction-like behaviour without
929 * actually providing full transactions. */
931 r = sd_bus_message_enter_container(message, 'a', "(sv)");
938 r = sd_bus_message_enter_container(message, 'r', "sv");
942 if (for_real || mode == UNIT_CHECK)
945 /* Reached EOF. Let's try again, and this time for realz... */
946 r = sd_bus_message_rewind(message, false);
954 r = sd_bus_message_read(message, "s", &name);
958 if (!UNIT_VTABLE(u)->bus_set_property)
959 return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Objects of this type do not support setting properties.");
961 r = sd_bus_message_enter_container(message, 'v', NULL);
965 r = UNIT_VTABLE(u)->bus_set_property(u, name, message, for_real ? mode : UNIT_CHECK, error);
966 if (r == 0 && u->transient && u->load_state == UNIT_STUB)
967 r = bus_unit_set_transient_property(u, name, message, for_real ? mode : UNIT_CHECK, error);
971 return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Cannot set property %s, or unknown property.", name);
973 r = sd_bus_message_exit_container(message);
977 r = sd_bus_message_exit_container(message);
984 r = sd_bus_message_exit_container(message);
988 if (commit && n > 0 && UNIT_VTABLE(u)->bus_commit_properties)
989 UNIT_VTABLE(u)->bus_commit_properties(u);