1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2010 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include "alloc-util.h"
24 #include "bpf-firewall.h"
25 #include "bus-common-errors.h"
26 #include "cgroup-util.h"
28 #include "dbus-unit.h"
31 #include "locale-util.h"
33 #include "process-util.h"
34 #include "selinux-access.h"
35 #include "signal-util.h"
37 #include "string-util.h"
39 #include "user-util.h"
41 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_collect_mode
, collect_mode
, CollectMode
);
42 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_load_state
, unit_load_state
, UnitLoadState
);
43 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_job_mode
, job_mode
, JobMode
);
44 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_emergency_action
, emergency_action
, EmergencyAction
);
46 static int property_get_names(
49 const char *interface
,
51 sd_bus_message
*reply
,
53 sd_bus_error
*error
) {
64 r
= sd_bus_message_open_container(reply
, 'a', "s");
68 SET_FOREACH(t
, u
->names
, i
) {
69 r
= sd_bus_message_append(reply
, "s", t
);
74 return sd_bus_message_close_container(reply
);
77 static int property_get_following(
80 const char *interface
,
82 sd_bus_message
*reply
,
84 sd_bus_error
*error
) {
86 Unit
*u
= userdata
, *f
;
92 f
= unit_following(u
);
93 return sd_bus_message_append(reply
, "s", f
? f
->id
: "");
96 static int property_get_dependencies(
99 const char *interface
,
100 const char *property
,
101 sd_bus_message
*reply
,
103 sd_bus_error
*error
) {
105 Hashmap
*h
= *(Hashmap
**) userdata
;
114 r
= sd_bus_message_open_container(reply
, 'a', "s");
118 HASHMAP_FOREACH_KEY(v
, u
, h
, j
) {
119 r
= sd_bus_message_append(reply
, "s", u
->id
);
124 return sd_bus_message_close_container(reply
);
127 static int property_get_obsolete_dependencies(
130 const char *interface
,
131 const char *property
,
132 sd_bus_message
*reply
,
134 sd_bus_error
*error
) {
139 /* For dependency types we don't support anymore always return an empty array */
140 return sd_bus_message_append(reply
, "as", 0);
143 static int property_get_requires_mounts_for(
146 const char *interface
,
147 const char *property
,
148 sd_bus_message
*reply
,
150 sd_bus_error
*error
) {
152 Hashmap
*h
= *(Hashmap
**) userdata
;
161 r
= sd_bus_message_open_container(reply
, 'a', "s");
165 HASHMAP_FOREACH_KEY(v
, p
, h
, j
) {
166 r
= sd_bus_message_append(reply
, "s", p
);
171 return sd_bus_message_close_container(reply
);
174 static int property_get_description(
177 const char *interface
,
178 const char *property
,
179 sd_bus_message
*reply
,
181 sd_bus_error
*error
) {
189 return sd_bus_message_append(reply
, "s", unit_description(u
));
192 static int property_get_active_state(
195 const char *interface
,
196 const char *property
,
197 sd_bus_message
*reply
,
199 sd_bus_error
*error
) {
207 return sd_bus_message_append(reply
, "s", unit_active_state_to_string(unit_active_state(u
)));
210 static int property_get_sub_state(
213 const char *interface
,
214 const char *property
,
215 sd_bus_message
*reply
,
217 sd_bus_error
*error
) {
225 return sd_bus_message_append(reply
, "s", unit_sub_state_to_string(u
));
228 static int property_get_unit_file_preset(
231 const char *interface
,
232 const char *property
,
233 sd_bus_message
*reply
,
235 sd_bus_error
*error
) {
244 r
= unit_get_unit_file_preset(u
);
246 return sd_bus_message_append(reply
, "s",
248 r
> 0 ? "enabled" : "disabled");
251 static int property_get_unit_file_state(
254 const char *interface
,
255 const char *property
,
256 sd_bus_message
*reply
,
258 sd_bus_error
*error
) {
266 return sd_bus_message_append(reply
, "s", unit_file_state_to_string(unit_get_unit_file_state(u
)));
269 static int property_get_can_start(
272 const char *interface
,
273 const char *property
,
274 sd_bus_message
*reply
,
276 sd_bus_error
*error
) {
284 return sd_bus_message_append(reply
, "b", unit_can_start(u
) && !u
->refuse_manual_start
);
287 static int property_get_can_stop(
290 const char *interface
,
291 const char *property
,
292 sd_bus_message
*reply
,
294 sd_bus_error
*error
) {
302 return sd_bus_message_append(reply
, "b", unit_can_stop(u
) && !u
->refuse_manual_stop
);
305 static int property_get_can_reload(
308 const char *interface
,
309 const char *property
,
310 sd_bus_message
*reply
,
312 sd_bus_error
*error
) {
320 return sd_bus_message_append(reply
, "b", unit_can_reload(u
));
323 static int property_get_can_isolate(
326 const char *interface
,
327 const char *property
,
328 sd_bus_message
*reply
,
330 sd_bus_error
*error
) {
338 return sd_bus_message_append(reply
, "b", unit_can_isolate(u
) && !u
->refuse_manual_start
);
341 static int property_get_job(
344 const char *interface
,
345 const char *property
,
346 sd_bus_message
*reply
,
348 sd_bus_error
*error
) {
350 _cleanup_free_
char *p
= NULL
;
358 return sd_bus_message_append(reply
, "(uo)", 0, "/");
360 p
= job_dbus_path(u
->job
);
364 return sd_bus_message_append(reply
, "(uo)", u
->job
->id
, p
);
367 static int property_get_need_daemon_reload(
370 const char *interface
,
371 const char *property
,
372 sd_bus_message
*reply
,
374 sd_bus_error
*error
) {
382 return sd_bus_message_append(reply
, "b", unit_need_daemon_reload(u
));
385 static int property_get_conditions(
388 const char *interface
,
389 const char *property
,
390 sd_bus_message
*reply
,
392 sd_bus_error
*error
) {
394 const char *(*to_string
)(ConditionType type
) = NULL
;
395 Condition
**list
= userdata
, *c
;
402 to_string
= streq(property
, "Asserts") ? assert_type_to_string
: condition_type_to_string
;
404 r
= sd_bus_message_open_container(reply
, 'a', "(sbbsi)");
408 LIST_FOREACH(conditions
, c
, *list
) {
412 c
->result
== CONDITION_UNTESTED
? 0 :
413 c
->result
== CONDITION_SUCCEEDED
? 1 : -1;
415 r
= sd_bus_message_append(reply
, "(sbbsi)",
417 c
->trigger
, c
->negate
,
418 c
->parameter
, tristate
);
424 return sd_bus_message_close_container(reply
);
427 static int property_get_load_error(
430 const char *interface
,
431 const char *property
,
432 sd_bus_message
*reply
,
434 sd_bus_error
*error
) {
436 _cleanup_(sd_bus_error_free
) sd_bus_error e
= SD_BUS_ERROR_NULL
;
443 if (u
->load_error
!= 0)
444 sd_bus_error_set_errno(&e
, u
->load_error
);
446 return sd_bus_message_append(reply
, "(ss)", e
.name
, e
.message
);
449 static int bus_verify_manage_units_async_full(
453 const char *polkit_message
,
455 sd_bus_message
*call
,
456 sd_bus_error
*error
) {
458 const char *details
[9] = {
463 if (polkit_message
) {
464 details
[4] = "polkit.message";
465 details
[5] = polkit_message
;
466 details
[6] = "polkit.gettext_domain";
467 details
[7] = GETTEXT_PACKAGE
;
470 return bus_verify_polkit_async(
473 "org.freedesktop.systemd1.manage-units",
477 &u
->manager
->polkit_registry
,
481 int bus_unit_method_start_generic(
482 sd_bus_message
*message
,
485 bool reload_if_possible
,
486 sd_bus_error
*error
) {
490 _cleanup_free_
char *verb
= NULL
;
491 static const char *const polkit_message_for_job
[_JOB_TYPE_MAX
] = {
492 [JOB_START
] = N_("Authentication is required to start '$(unit)'."),
493 [JOB_STOP
] = N_("Authentication is required to stop '$(unit)'."),
494 [JOB_RELOAD
] = N_("Authentication is required to reload '$(unit)'."),
495 [JOB_RESTART
] = N_("Authentication is required to restart '$(unit)'."),
496 [JOB_TRY_RESTART
] = N_("Authentication is required to restart '$(unit)'."),
502 assert(job_type
>= 0 && job_type
< _JOB_TYPE_MAX
);
504 r
= mac_selinux_unit_access_check(
506 job_type_to_access_method(job_type
),
511 r
= sd_bus_message_read(message
, "s", &smode
);
515 mode
= job_mode_from_string(smode
);
517 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Job mode %s invalid", smode
);
519 if (reload_if_possible
)
520 verb
= strjoin("reload-or-", job_type_to_string(job_type
));
522 verb
= strdup(job_type_to_string(job_type
));
526 r
= bus_verify_manage_units_async_full(
530 job_type
< _JOB_TYPE_MAX
? polkit_message_for_job
[job_type
] : NULL
,
537 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
539 return bus_unit_queue_job(message
, u
, job_type
, mode
, reload_if_possible
, error
);
542 static int method_start(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
543 return bus_unit_method_start_generic(message
, userdata
, JOB_START
, false, error
);
546 static int method_stop(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
547 return bus_unit_method_start_generic(message
, userdata
, JOB_STOP
, false, error
);
550 static int method_reload(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
551 return bus_unit_method_start_generic(message
, userdata
, JOB_RELOAD
, false, error
);
554 static int method_restart(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
555 return bus_unit_method_start_generic(message
, userdata
, JOB_RESTART
, false, error
);
558 static int method_try_restart(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
559 return bus_unit_method_start_generic(message
, userdata
, JOB_TRY_RESTART
, false, error
);
562 static int method_reload_or_restart(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
563 return bus_unit_method_start_generic(message
, userdata
, JOB_RESTART
, true, error
);
566 static int method_reload_or_try_restart(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
567 return bus_unit_method_start_generic(message
, userdata
, JOB_TRY_RESTART
, true, error
);
570 int bus_unit_method_kill(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
580 r
= mac_selinux_unit_access_check(u
, message
, "stop", error
);
584 r
= sd_bus_message_read(message
, "si", &swho
, &signo
);
591 who
= kill_who_from_string(swho
);
593 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid who argument %s", swho
);
596 if (!SIGNAL_VALID(signo
))
597 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Signal number out of range.");
599 r
= bus_verify_manage_units_async_full(
603 N_("Authentication is required to kill '$(unit)'."),
610 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
612 r
= unit_kill(u
, who
, signo
, error
);
616 return sd_bus_reply_method_return(message
, NULL
);
619 int bus_unit_method_reset_failed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
626 r
= mac_selinux_unit_access_check(u
, message
, "reload", error
);
630 r
= bus_verify_manage_units_async_full(
634 N_("Authentication is required to reset the \"failed\" state of '$(unit)'."),
641 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
643 unit_reset_failed(u
);
645 return sd_bus_reply_method_return(message
, NULL
);
648 int bus_unit_method_set_properties(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
655 r
= mac_selinux_unit_access_check(u
, message
, "start", error
);
659 r
= sd_bus_message_read(message
, "b", &runtime
);
663 r
= bus_verify_manage_units_async_full(
667 N_("Authentication is required to set properties on '$(unit)'."),
674 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
676 r
= bus_unit_set_properties(u
, message
, runtime
? UNIT_RUNTIME
: UNIT_PERSISTENT
, true, error
);
680 return sd_bus_reply_method_return(message
, NULL
);
683 int bus_unit_method_ref(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
690 r
= mac_selinux_unit_access_check(u
, message
, "start", error
);
694 r
= bus_verify_manage_units_async_full(
705 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
707 r
= bus_unit_track_add_sender(u
, message
);
711 return sd_bus_reply_method_return(message
, NULL
);
714 int bus_unit_method_unref(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
721 r
= bus_unit_track_remove_sender(u
, message
);
723 return sd_bus_error_setf(error
, BUS_ERROR_NOT_REFERENCED
, "Unit has not been referenced yet.");
727 return sd_bus_reply_method_return(message
, NULL
);
730 const sd_bus_vtable bus_unit_vtable
[] = {
731 SD_BUS_VTABLE_START(0),
733 SD_BUS_PROPERTY("Id", "s", NULL
, offsetof(Unit
, id
), SD_BUS_VTABLE_PROPERTY_CONST
),
734 SD_BUS_PROPERTY("Names", "as", property_get_names
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
735 SD_BUS_PROPERTY("Following", "s", property_get_following
, 0, 0),
736 SD_BUS_PROPERTY("Requires", "as", property_get_dependencies
, offsetof(Unit
, dependencies
[UNIT_REQUIRES
]), SD_BUS_VTABLE_PROPERTY_CONST
),
737 SD_BUS_PROPERTY("Requisite", "as", property_get_dependencies
, offsetof(Unit
, dependencies
[UNIT_REQUISITE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
738 SD_BUS_PROPERTY("Wants", "as", property_get_dependencies
, offsetof(Unit
, dependencies
[UNIT_WANTS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
739 SD_BUS_PROPERTY("BindsTo", "as", property_get_dependencies
, offsetof(Unit
, dependencies
[UNIT_BINDS_TO
]), SD_BUS_VTABLE_PROPERTY_CONST
),
740 SD_BUS_PROPERTY("PartOf", "as", property_get_dependencies
, offsetof(Unit
, dependencies
[UNIT_PART_OF
]), SD_BUS_VTABLE_PROPERTY_CONST
),
741 SD_BUS_PROPERTY("RequiredBy", "as", property_get_dependencies
, offsetof(Unit
, dependencies
[UNIT_REQUIRED_BY
]), SD_BUS_VTABLE_PROPERTY_CONST
),
742 SD_BUS_PROPERTY("RequisiteOf", "as", property_get_dependencies
, offsetof(Unit
, dependencies
[UNIT_REQUISITE_OF
]), SD_BUS_VTABLE_PROPERTY_CONST
),
743 SD_BUS_PROPERTY("WantedBy", "as", property_get_dependencies
, offsetof(Unit
, dependencies
[UNIT_WANTED_BY
]), SD_BUS_VTABLE_PROPERTY_CONST
),
744 SD_BUS_PROPERTY("BoundBy", "as", property_get_dependencies
, offsetof(Unit
, dependencies
[UNIT_BOUND_BY
]), SD_BUS_VTABLE_PROPERTY_CONST
),
745 SD_BUS_PROPERTY("ConsistsOf", "as", property_get_dependencies
, offsetof(Unit
, dependencies
[UNIT_CONSISTS_OF
]), SD_BUS_VTABLE_PROPERTY_CONST
),
746 SD_BUS_PROPERTY("Conflicts", "as", property_get_dependencies
, offsetof(Unit
, dependencies
[UNIT_CONFLICTS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
747 SD_BUS_PROPERTY("ConflictedBy", "as", property_get_dependencies
, offsetof(Unit
, dependencies
[UNIT_CONFLICTED_BY
]), SD_BUS_VTABLE_PROPERTY_CONST
),
748 SD_BUS_PROPERTY("Before", "as", property_get_dependencies
, offsetof(Unit
, dependencies
[UNIT_BEFORE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
749 SD_BUS_PROPERTY("After", "as", property_get_dependencies
, offsetof(Unit
, dependencies
[UNIT_AFTER
]), SD_BUS_VTABLE_PROPERTY_CONST
),
750 SD_BUS_PROPERTY("OnFailure", "as", property_get_dependencies
, offsetof(Unit
, dependencies
[UNIT_ON_FAILURE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
751 SD_BUS_PROPERTY("Triggers", "as", property_get_dependencies
, offsetof(Unit
, dependencies
[UNIT_TRIGGERS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
752 SD_BUS_PROPERTY("TriggeredBy", "as", property_get_dependencies
, offsetof(Unit
, dependencies
[UNIT_TRIGGERED_BY
]), SD_BUS_VTABLE_PROPERTY_CONST
),
753 SD_BUS_PROPERTY("PropagatesReloadTo", "as", property_get_dependencies
, offsetof(Unit
, dependencies
[UNIT_PROPAGATES_RELOAD_TO
]), SD_BUS_VTABLE_PROPERTY_CONST
),
754 SD_BUS_PROPERTY("ReloadPropagatedFrom", "as", property_get_dependencies
, offsetof(Unit
, dependencies
[UNIT_RELOAD_PROPAGATED_FROM
]), SD_BUS_VTABLE_PROPERTY_CONST
),
755 SD_BUS_PROPERTY("JoinsNamespaceOf", "as", property_get_dependencies
, offsetof(Unit
, dependencies
[UNIT_JOINS_NAMESPACE_OF
]), SD_BUS_VTABLE_PROPERTY_CONST
),
756 SD_BUS_PROPERTY("RequiresMountsFor", "as", property_get_requires_mounts_for
, offsetof(Unit
, requires_mounts_for
), SD_BUS_VTABLE_PROPERTY_CONST
),
757 SD_BUS_PROPERTY("Documentation", "as", NULL
, offsetof(Unit
, documentation
), SD_BUS_VTABLE_PROPERTY_CONST
),
758 SD_BUS_PROPERTY("Description", "s", property_get_description
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
759 SD_BUS_PROPERTY("LoadState", "s", property_get_load_state
, offsetof(Unit
, load_state
), SD_BUS_VTABLE_PROPERTY_CONST
),
760 SD_BUS_PROPERTY("ActiveState", "s", property_get_active_state
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
761 SD_BUS_PROPERTY("SubState", "s", property_get_sub_state
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
762 SD_BUS_PROPERTY("FragmentPath", "s", NULL
, offsetof(Unit
, fragment_path
), SD_BUS_VTABLE_PROPERTY_CONST
),
763 SD_BUS_PROPERTY("SourcePath", "s", NULL
, offsetof(Unit
, source_path
), SD_BUS_VTABLE_PROPERTY_CONST
),
764 SD_BUS_PROPERTY("DropInPaths", "as", NULL
, offsetof(Unit
, dropin_paths
), SD_BUS_VTABLE_PROPERTY_CONST
),
765 SD_BUS_PROPERTY("UnitFileState", "s", property_get_unit_file_state
, 0, 0),
766 SD_BUS_PROPERTY("UnitFilePreset", "s", property_get_unit_file_preset
, 0, 0),
767 BUS_PROPERTY_DUAL_TIMESTAMP("StateChangeTimestamp", offsetof(Unit
, state_change_timestamp
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
768 BUS_PROPERTY_DUAL_TIMESTAMP("InactiveExitTimestamp", offsetof(Unit
, inactive_exit_timestamp
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
769 BUS_PROPERTY_DUAL_TIMESTAMP("ActiveEnterTimestamp", offsetof(Unit
, active_enter_timestamp
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
770 BUS_PROPERTY_DUAL_TIMESTAMP("ActiveExitTimestamp", offsetof(Unit
, active_exit_timestamp
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
771 BUS_PROPERTY_DUAL_TIMESTAMP("InactiveEnterTimestamp", offsetof(Unit
, inactive_enter_timestamp
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
772 SD_BUS_PROPERTY("CanStart", "b", property_get_can_start
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
773 SD_BUS_PROPERTY("CanStop", "b", property_get_can_stop
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
774 SD_BUS_PROPERTY("CanReload", "b", property_get_can_reload
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
775 SD_BUS_PROPERTY("CanIsolate", "b", property_get_can_isolate
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
776 SD_BUS_PROPERTY("Job", "(uo)", property_get_job
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
777 SD_BUS_PROPERTY("StopWhenUnneeded", "b", bus_property_get_bool
, offsetof(Unit
, stop_when_unneeded
), SD_BUS_VTABLE_PROPERTY_CONST
),
778 SD_BUS_PROPERTY("RefuseManualStart", "b", bus_property_get_bool
, offsetof(Unit
, refuse_manual_start
), SD_BUS_VTABLE_PROPERTY_CONST
),
779 SD_BUS_PROPERTY("RefuseManualStop", "b", bus_property_get_bool
, offsetof(Unit
, refuse_manual_stop
), SD_BUS_VTABLE_PROPERTY_CONST
),
780 SD_BUS_PROPERTY("AllowIsolate", "b", bus_property_get_bool
, offsetof(Unit
, allow_isolate
), SD_BUS_VTABLE_PROPERTY_CONST
),
781 SD_BUS_PROPERTY("DefaultDependencies", "b", bus_property_get_bool
, offsetof(Unit
, default_dependencies
), SD_BUS_VTABLE_PROPERTY_CONST
),
782 SD_BUS_PROPERTY("OnFailureJobMode", "s", property_get_job_mode
, offsetof(Unit
, on_failure_job_mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
783 SD_BUS_PROPERTY("IgnoreOnIsolate", "b", bus_property_get_bool
, offsetof(Unit
, ignore_on_isolate
), SD_BUS_VTABLE_PROPERTY_CONST
),
784 SD_BUS_PROPERTY("NeedDaemonReload", "b", property_get_need_daemon_reload
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
785 SD_BUS_PROPERTY("JobTimeoutUSec", "t", bus_property_get_usec
, offsetof(Unit
, job_timeout
), SD_BUS_VTABLE_PROPERTY_CONST
),
786 SD_BUS_PROPERTY("JobRunningTimeoutUSec", "t", bus_property_get_usec
, offsetof(Unit
, job_running_timeout
), SD_BUS_VTABLE_PROPERTY_CONST
),
787 SD_BUS_PROPERTY("JobTimeoutAction", "s", property_get_emergency_action
, offsetof(Unit
, job_timeout_action
), SD_BUS_VTABLE_PROPERTY_CONST
),
788 SD_BUS_PROPERTY("JobTimeoutRebootArgument", "s", NULL
, offsetof(Unit
, job_timeout_reboot_arg
), SD_BUS_VTABLE_PROPERTY_CONST
),
789 SD_BUS_PROPERTY("ConditionResult", "b", bus_property_get_bool
, offsetof(Unit
, condition_result
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
790 SD_BUS_PROPERTY("AssertResult", "b", bus_property_get_bool
, offsetof(Unit
, assert_result
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
791 BUS_PROPERTY_DUAL_TIMESTAMP("ConditionTimestamp", offsetof(Unit
, condition_timestamp
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
792 BUS_PROPERTY_DUAL_TIMESTAMP("AssertTimestamp", offsetof(Unit
, assert_timestamp
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
793 SD_BUS_PROPERTY("Conditions", "a(sbbsi)", property_get_conditions
, offsetof(Unit
, conditions
), 0),
794 SD_BUS_PROPERTY("Asserts", "a(sbbsi)", property_get_conditions
, offsetof(Unit
, asserts
), 0),
795 SD_BUS_PROPERTY("LoadError", "(ss)", property_get_load_error
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
796 SD_BUS_PROPERTY("Transient", "b", bus_property_get_bool
, offsetof(Unit
, transient
), SD_BUS_VTABLE_PROPERTY_CONST
),
797 SD_BUS_PROPERTY("Perpetual", "b", bus_property_get_bool
, offsetof(Unit
, perpetual
), SD_BUS_VTABLE_PROPERTY_CONST
),
798 SD_BUS_PROPERTY("StartLimitIntervalSec", "t", bus_property_get_usec
, offsetof(Unit
, start_limit
.interval
), SD_BUS_VTABLE_PROPERTY_CONST
),
799 SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned
, offsetof(Unit
, start_limit
.burst
), SD_BUS_VTABLE_PROPERTY_CONST
),
800 SD_BUS_PROPERTY("StartLimitAction", "s", property_get_emergency_action
, offsetof(Unit
, start_limit_action
), SD_BUS_VTABLE_PROPERTY_CONST
),
801 SD_BUS_PROPERTY("RebootArgument", "s", NULL
, offsetof(Unit
, reboot_arg
), SD_BUS_VTABLE_PROPERTY_CONST
),
802 SD_BUS_PROPERTY("InvocationID", "ay", bus_property_get_id128
, offsetof(Unit
, invocation_id
), 0),
803 SD_BUS_PROPERTY("CollectMode", "s", property_get_collect_mode
, offsetof(Unit
, collect_mode
), 0),
805 SD_BUS_METHOD("Start", "s", "o", method_start
, SD_BUS_VTABLE_UNPRIVILEGED
),
806 SD_BUS_METHOD("Stop", "s", "o", method_stop
, SD_BUS_VTABLE_UNPRIVILEGED
),
807 SD_BUS_METHOD("Reload", "s", "o", method_reload
, SD_BUS_VTABLE_UNPRIVILEGED
),
808 SD_BUS_METHOD("Restart", "s", "o", method_restart
, SD_BUS_VTABLE_UNPRIVILEGED
),
809 SD_BUS_METHOD("TryRestart", "s", "o", method_try_restart
, SD_BUS_VTABLE_UNPRIVILEGED
),
810 SD_BUS_METHOD("ReloadOrRestart", "s", "o", method_reload_or_restart
, SD_BUS_VTABLE_UNPRIVILEGED
),
811 SD_BUS_METHOD("ReloadOrTryRestart", "s", "o", method_reload_or_try_restart
, SD_BUS_VTABLE_UNPRIVILEGED
),
812 SD_BUS_METHOD("Kill", "si", NULL
, bus_unit_method_kill
, SD_BUS_VTABLE_UNPRIVILEGED
),
813 SD_BUS_METHOD("ResetFailed", NULL
, NULL
, bus_unit_method_reset_failed
, SD_BUS_VTABLE_UNPRIVILEGED
),
814 SD_BUS_METHOD("SetProperties", "ba(sv)", NULL
, bus_unit_method_set_properties
, SD_BUS_VTABLE_UNPRIVILEGED
),
815 SD_BUS_METHOD("Ref", NULL
, NULL
, bus_unit_method_ref
, SD_BUS_VTABLE_UNPRIVILEGED
),
816 SD_BUS_METHOD("Unref", NULL
, NULL
, bus_unit_method_unref
, SD_BUS_VTABLE_UNPRIVILEGED
),
818 /* Obsolete properties or obsolete alias names */
819 SD_BUS_PROPERTY("RequiresOverridable", "as", property_get_obsolete_dependencies
, 0, SD_BUS_VTABLE_HIDDEN
),
820 SD_BUS_PROPERTY("RequisiteOverridable", "as", property_get_obsolete_dependencies
, 0, SD_BUS_VTABLE_HIDDEN
),
821 SD_BUS_PROPERTY("RequiredByOverridable", "as", property_get_obsolete_dependencies
, 0, SD_BUS_VTABLE_HIDDEN
),
822 SD_BUS_PROPERTY("RequisiteOfOverridable", "as", property_get_obsolete_dependencies
, 0, SD_BUS_VTABLE_HIDDEN
),
823 SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec
, offsetof(Unit
, start_limit
.interval
), SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
827 static int property_get_slice(
830 const char *interface
,
831 const char *property
,
832 sd_bus_message
*reply
,
834 sd_bus_error
*error
) {
842 return sd_bus_message_append(reply
, "s", unit_slice_name(u
));
845 static int property_get_current_memory(
848 const char *interface
,
849 const char *property
,
850 sd_bus_message
*reply
,
852 sd_bus_error
*error
) {
854 uint64_t sz
= (uint64_t) -1;
862 r
= unit_get_memory_current(u
, &sz
);
863 if (r
< 0 && r
!= -ENODATA
)
864 log_unit_warning_errno(u
, r
, "Failed to get memory.usage_in_bytes attribute: %m");
866 return sd_bus_message_append(reply
, "t", sz
);
869 static int property_get_current_tasks(
872 const char *interface
,
873 const char *property
,
874 sd_bus_message
*reply
,
876 sd_bus_error
*error
) {
878 uint64_t cn
= (uint64_t) -1;
886 r
= unit_get_tasks_current(u
, &cn
);
887 if (r
< 0 && r
!= -ENODATA
)
888 log_unit_warning_errno(u
, r
, "Failed to get pids.current attribute: %m");
890 return sd_bus_message_append(reply
, "t", cn
);
893 static int property_get_cpu_usage(
896 const char *interface
,
897 const char *property
,
898 sd_bus_message
*reply
,
900 sd_bus_error
*error
) {
902 nsec_t ns
= (nsec_t
) -1;
910 r
= unit_get_cpu_usage(u
, &ns
);
911 if (r
< 0 && r
!= -ENODATA
)
912 log_unit_warning_errno(u
, r
, "Failed to get cpuacct.usage attribute: %m");
914 return sd_bus_message_append(reply
, "t", ns
);
917 static int property_get_cgroup(
920 const char *interface
,
921 const char *property
,
922 sd_bus_message
*reply
,
924 sd_bus_error
*error
) {
933 /* Three cases: a) u->cgroup_path is NULL, in which case the
934 * unit has no control group, which we report as the empty
935 * string. b) u->cgroup_path is the empty string, which
936 * indicates the root cgroup, which we report as "/". c) all
937 * other cases we report as-is. */
940 t
= isempty(u
->cgroup_path
) ? "/" : u
->cgroup_path
;
944 return sd_bus_message_append(reply
, "s", t
);
947 static int append_process(sd_bus_message
*reply
, const char *p
, pid_t pid
, Set
*pids
) {
948 _cleanup_free_
char *buf
= NULL
, *cmdline
= NULL
;
954 r
= set_put(pids
, PID_TO_PTR(pid
));
955 if (IN_SET(r
, 0, -EEXIST
))
961 r
= cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER
, pid
, &buf
);
970 (void) get_process_cmdline(pid
, 0, true, &cmdline
);
972 return sd_bus_message_append(reply
,
979 static int append_cgroup(sd_bus_message
*reply
, const char *p
, Set
*pids
) {
980 _cleanup_closedir_
DIR *d
= NULL
;
981 _cleanup_fclose_
FILE *f
= NULL
;
987 r
= cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER
, p
, &f
);
996 r
= cg_read_pid(f
, &pid
);
1002 if (is_kernel_thread(pid
) > 0)
1005 r
= append_process(reply
, p
, pid
, pids
);
1010 r
= cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER
, p
, &d
);
1017 _cleanup_free_
char *g
= NULL
, *j
= NULL
;
1019 r
= cg_read_subgroup(d
, &g
);
1025 j
= strjoin(p
, "/", g
);
1029 r
= append_cgroup(reply
, j
, pids
);
1037 int bus_unit_method_get_processes(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1038 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1039 _cleanup_(set_freep
) Set
*pids
= NULL
;
1046 r
= mac_selinux_unit_access_check(u
, message
, "status", error
);
1050 pids
= set_new(NULL
);
1054 r
= sd_bus_message_new_method_return(message
, &reply
);
1058 r
= sd_bus_message_open_container(reply
, 'a', "(sus)");
1062 if (u
->cgroup_path
) {
1063 r
= append_cgroup(reply
, u
->cgroup_path
, pids
);
1068 /* The main and control pids might live outside of the cgroup, hence fetch them separately */
1069 pid
= unit_main_pid(u
);
1071 r
= append_process(reply
, NULL
, pid
, pids
);
1076 pid
= unit_control_pid(u
);
1078 r
= append_process(reply
, NULL
, pid
, pids
);
1083 r
= sd_bus_message_close_container(reply
);
1087 return sd_bus_send(NULL
, reply
, NULL
);
1090 static int property_get_ip_counter(
1093 const char *interface
,
1094 const char *property
,
1095 sd_bus_message
*reply
,
1097 sd_bus_error
*error
) {
1099 CGroupIPAccountingMetric metric
;
1100 uint64_t value
= (uint64_t) -1;
1108 if (streq(property
, "IPIngressBytes"))
1109 metric
= CGROUP_IP_INGRESS_BYTES
;
1110 else if (streq(property
, "IPIngressPackets"))
1111 metric
= CGROUP_IP_INGRESS_PACKETS
;
1112 else if (streq(property
, "IPEgressBytes"))
1113 metric
= CGROUP_IP_EGRESS_BYTES
;
1115 assert(streq(property
, "IPEgressPackets"));
1116 metric
= CGROUP_IP_EGRESS_PACKETS
;
1119 (void) unit_get_ip_accounting(u
, metric
, &value
);
1120 return sd_bus_message_append(reply
, "t", value
);
1123 const sd_bus_vtable bus_unit_cgroup_vtable
[] = {
1124 SD_BUS_VTABLE_START(0),
1125 SD_BUS_PROPERTY("Slice", "s", property_get_slice
, 0, 0),
1126 SD_BUS_PROPERTY("ControlGroup", "s", property_get_cgroup
, 0, 0),
1127 SD_BUS_PROPERTY("MemoryCurrent", "t", property_get_current_memory
, 0, 0),
1128 SD_BUS_PROPERTY("CPUUsageNSec", "t", property_get_cpu_usage
, 0, 0),
1129 SD_BUS_PROPERTY("TasksCurrent", "t", property_get_current_tasks
, 0, 0),
1130 SD_BUS_PROPERTY("IPIngressBytes", "t", property_get_ip_counter
, 0, 0),
1131 SD_BUS_PROPERTY("IPIngressPackets", "t", property_get_ip_counter
, 0, 0),
1132 SD_BUS_PROPERTY("IPEgressBytes", "t", property_get_ip_counter
, 0, 0),
1133 SD_BUS_PROPERTY("IPEgressPackets", "t", property_get_ip_counter
, 0, 0),
1134 SD_BUS_METHOD("GetProcesses", NULL
, "a(sus)", bus_unit_method_get_processes
, SD_BUS_VTABLE_UNPRIVILEGED
),
1138 static int send_new_signal(sd_bus
*bus
, void *userdata
) {
1139 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
1140 _cleanup_free_
char *p
= NULL
;
1147 p
= unit_dbus_path(u
);
1151 r
= sd_bus_message_new_signal(
1154 "/org/freedesktop/systemd1",
1155 "org.freedesktop.systemd1.Manager",
1160 r
= sd_bus_message_append(m
, "so", u
->id
, p
);
1164 return sd_bus_send(bus
, m
, NULL
);
1167 static int send_changed_signal(sd_bus
*bus
, void *userdata
) {
1168 _cleanup_free_
char *p
= NULL
;
1175 p
= unit_dbus_path(u
);
1179 /* Send a properties changed signal. First for the specific
1180 * type, then for the generic unit. The clients may rely on
1181 * this order to get atomic behavior if needed. */
1183 r
= sd_bus_emit_properties_changed_strv(
1185 unit_dbus_interface_from_type(u
->type
),
1190 return sd_bus_emit_properties_changed_strv(
1192 "org.freedesktop.systemd1.Unit",
1196 void bus_unit_send_change_signal(Unit
*u
) {
1200 if (u
->in_dbus_queue
) {
1201 LIST_REMOVE(dbus_queue
, u
->manager
->dbus_unit_queue
, u
);
1202 u
->in_dbus_queue
= false;
1208 r
= bus_foreach_bus(u
->manager
, u
->bus_track
, u
->sent_dbus_new_signal
? send_changed_signal
: send_new_signal
, u
);
1210 log_unit_debug_errno(u
, r
, "Failed to send unit change signal for %s: %m", u
->id
);
1212 u
->sent_dbus_new_signal
= true;
1215 static int send_removed_signal(sd_bus
*bus
, void *userdata
) {
1216 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
1217 _cleanup_free_
char *p
= NULL
;
1224 p
= unit_dbus_path(u
);
1228 r
= sd_bus_message_new_signal(
1231 "/org/freedesktop/systemd1",
1232 "org.freedesktop.systemd1.Manager",
1237 r
= sd_bus_message_append(m
, "so", u
->id
, p
);
1241 return sd_bus_send(bus
, m
, NULL
);
1244 void bus_unit_send_removed_signal(Unit
*u
) {
1248 if (!u
->sent_dbus_new_signal
|| u
->in_dbus_queue
)
1249 bus_unit_send_change_signal(u
);
1254 r
= bus_foreach_bus(u
->manager
, u
->bus_track
, send_removed_signal
, u
);
1256 log_unit_debug_errno(u
, r
, "Failed to send unit remove signal for %s: %m", u
->id
);
1259 int bus_unit_queue_job(
1260 sd_bus_message
*message
,
1264 bool reload_if_possible
,
1265 sd_bus_error
*error
) {
1267 _cleanup_free_
char *path
= NULL
;
1273 assert(type
>= 0 && type
< _JOB_TYPE_MAX
);
1274 assert(mode
>= 0 && mode
< _JOB_MODE_MAX
);
1276 r
= mac_selinux_unit_access_check(
1278 job_type_to_access_method(type
),
1283 if (reload_if_possible
&& unit_can_reload(u
)) {
1284 if (type
== JOB_RESTART
)
1285 type
= JOB_RELOAD_OR_START
;
1286 else if (type
== JOB_TRY_RESTART
)
1287 type
= JOB_TRY_RELOAD
;
1290 if (type
== JOB_STOP
&&
1291 (IN_SET(u
->load_state
, UNIT_NOT_FOUND
, UNIT_ERROR
)) &&
1292 unit_active_state(u
) == UNIT_INACTIVE
)
1293 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_UNIT
, "Unit %s not loaded.", u
->id
);
1295 if ((type
== JOB_START
&& u
->refuse_manual_start
) ||
1296 (type
== JOB_STOP
&& u
->refuse_manual_stop
) ||
1297 (IN_SET(type
, JOB_RESTART
, JOB_TRY_RESTART
) && (u
->refuse_manual_start
|| u
->refuse_manual_stop
)) ||
1298 (type
== JOB_RELOAD_OR_START
&& job_type_collapse(type
, u
) == JOB_START
&& u
->refuse_manual_start
))
1299 return sd_bus_error_setf(error
, BUS_ERROR_ONLY_BY_DEPENDENCY
, "Operation refused, unit %s may be requested by dependency only (it is configured to refuse manual start/stop).", u
->id
);
1301 r
= manager_add_job(u
->manager
, type
, u
, mode
, error
, &j
);
1305 r
= bus_job_track_sender(j
, message
);
1309 path
= job_dbus_path(j
);
1313 return sd_bus_reply_method_return(message
, "o", path
);
1316 static int bus_unit_set_transient_property(
1319 sd_bus_message
*message
,
1320 UnitSetPropertiesMode mode
,
1321 sd_bus_error
*error
) {
1329 if (streq(name
, "Description")) {
1332 r
= sd_bus_message_read(message
, "s", &d
);
1336 if (mode
!= UNIT_CHECK
) {
1337 r
= unit_set_description(u
, d
);
1341 unit_write_drop_in_format(u
, mode
, name
, "[Unit]\nDescription=%s", d
);
1346 } else if (streq(name
, "DefaultDependencies")) {
1349 r
= sd_bus_message_read(message
, "b", &b
);
1353 if (mode
!= UNIT_CHECK
) {
1354 u
->default_dependencies
= b
;
1355 unit_write_drop_in_format(u
, mode
, name
, "[Unit]\nDefaultDependencies=%s", yes_no(b
));
1360 } else if (streq(name
, "CollectMode")) {
1364 r
= sd_bus_message_read(message
, "s", &s
);
1368 m
= collect_mode_from_string(s
);
1370 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown garbage collection mode: %s", s
);
1372 if (mode
!= UNIT_CHECK
) {
1373 u
->collect_mode
= m
;
1374 unit_write_drop_in_format(u
, mode
, name
, "[Unit]\nCollectMode=%s", collect_mode_to_string(m
));
1379 } else if (streq(name
, "Slice")) {
1383 if (!UNIT_HAS_CGROUP_CONTEXT(u
))
1384 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "The slice property is only available for units with control groups.");
1385 if (u
->type
== UNIT_SLICE
)
1386 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Slice may not be set for slice units.");
1387 if (unit_has_name(u
, SPECIAL_INIT_SCOPE
))
1388 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Cannot set slice for init.scope");
1390 r
= sd_bus_message_read(message
, "s", &s
);
1394 if (!unit_name_is_valid(s
, UNIT_NAME_PLAIN
))
1395 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid unit name '%s'", s
);
1397 /* Note that we do not dispatch the load queue here yet, as we don't want our own transient unit to be
1398 * loaded while we are still setting it up. Or in other words, we use manager_load_unit_prepare()
1399 * instead of manager_load_unit() on purpose, here. */
1400 r
= manager_load_unit_prepare(u
->manager
, s
, NULL
, error
, &slice
);
1404 if (slice
->type
!= UNIT_SLICE
)
1405 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unit name '%s' is not a slice", s
);
1407 if (mode
!= UNIT_CHECK
) {
1408 r
= unit_set_slice(u
, slice
);
1412 unit_write_drop_in_private_format(u
, mode
, name
, "Slice=%s", s
);
1417 } else if (STR_IN_SET(name
,
1418 "Requires", "RequiresOverridable",
1419 "Requisite", "RequisiteOverridable",
1425 "PropagatesReloadTo", "ReloadPropagatedFrom",
1431 if (streq(name
, "RequiresOverridable"))
1432 d
= UNIT_REQUIRES
; /* redirect for obsolete unit dependency type */
1433 else if (streq(name
, "RequisiteOverridable"))
1434 d
= UNIT_REQUISITE
; /* same here */
1436 d
= unit_dependency_from_string(name
);
1438 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid unit dependency: %s", name
);
1441 r
= sd_bus_message_enter_container(message
, 'a', "s");
1445 while ((r
= sd_bus_message_read(message
, "s", &other
)) > 0) {
1446 if (!unit_name_is_valid(other
, UNIT_NAME_PLAIN
|UNIT_NAME_INSTANCE
))
1447 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid unit name %s", other
);
1449 if (mode
!= UNIT_CHECK
) {
1450 _cleanup_free_
char *label
= NULL
;
1452 r
= unit_add_dependency_by_name(u
, d
, other
, NULL
, true, UNIT_DEPENDENCY_FILE
);
1456 label
= strjoin(name
, "-", other
);
1460 unit_write_drop_in_format(u
, mode
, label
, "[Unit]\n%s=%s", name
, other
);
1467 r
= sd_bus_message_exit_container(message
);
1473 } else if (streq(name
, "AddRef")) {
1477 /* Why is this called "AddRef" rather than just "Ref", or "Reference"? There's already a "Ref()" method
1478 * on the Unit interface, and it's probably not a good idea to expose a property and a method on the
1479 * same interface (well, strictly speaking AddRef isn't exposed as full property, we just read it for
1480 * transient units, but still). And "References" and "ReferencedBy" is already used as unit reference
1481 * dependency type, hence let's not confuse things with that.
1483 * Note that we don't acually add the reference to the bus track. We do that only after the setup of
1484 * the transient unit is complete, so that setting this property multiple times in the same transient
1485 * unit creation call doesn't count as individual references. */
1487 r
= sd_bus_message_read(message
, "b", &b
);
1491 if (mode
!= UNIT_CHECK
)
1492 u
->bus_track_add
= b
;
1500 int bus_unit_set_properties(
1502 sd_bus_message
*message
,
1503 UnitSetPropertiesMode mode
,
1505 sd_bus_error
*error
) {
1507 bool for_real
= false;
1514 /* We iterate through the array twice. First run we just check
1515 * if all passed data is valid, second run actually applies
1516 * it. This is to implement transaction-like behaviour without
1517 * actually providing full transactions. */
1519 r
= sd_bus_message_enter_container(message
, 'a', "(sv)");
1526 r
= sd_bus_message_enter_container(message
, 'r', "sv");
1530 if (for_real
|| mode
== UNIT_CHECK
)
1533 /* Reached EOF. Let's try again, and this time for realz... */
1534 r
= sd_bus_message_rewind(message
, false);
1542 r
= sd_bus_message_read(message
, "s", &name
);
1546 if (!UNIT_VTABLE(u
)->bus_set_property
)
1547 return sd_bus_error_setf(error
, SD_BUS_ERROR_PROPERTY_READ_ONLY
, "Objects of this type do not support setting properties.");
1549 r
= sd_bus_message_enter_container(message
, 'v', NULL
);
1553 r
= UNIT_VTABLE(u
)->bus_set_property(u
, name
, message
, for_real
? mode
: UNIT_CHECK
, error
);
1554 if (r
== 0 && u
->transient
&& u
->load_state
== UNIT_STUB
)
1555 r
= bus_unit_set_transient_property(u
, name
, message
, for_real
? mode
: UNIT_CHECK
, error
);
1559 return sd_bus_error_setf(error
, SD_BUS_ERROR_PROPERTY_READ_ONLY
, "Cannot set property %s, or unknown property.", name
);
1561 r
= sd_bus_message_exit_container(message
);
1565 r
= sd_bus_message_exit_container(message
);
1572 r
= sd_bus_message_exit_container(message
);
1576 if (commit
&& n
> 0 && UNIT_VTABLE(u
)->bus_commit_properties
)
1577 UNIT_VTABLE(u
)->bus_commit_properties(u
);
1582 int bus_unit_check_load_state(Unit
*u
, sd_bus_error
*error
) {
1585 if (u
->load_state
== UNIT_LOADED
)
1588 /* Give a better description of the unit error when
1589 * possible. Note that in the case of UNIT_MASKED, load_error
1591 if (u
->load_state
== UNIT_MASKED
)
1592 return sd_bus_error_setf(error
, BUS_ERROR_UNIT_MASKED
, "Unit %s is masked.", u
->id
);
1594 if (u
->load_state
== UNIT_NOT_FOUND
)
1595 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_UNIT
, "Unit %s not found.", u
->id
);
1597 return sd_bus_error_set_errnof(error
, u
->load_error
, "Unit %s is not loaded properly: %m.", u
->id
);
1600 static int bus_unit_track_handler(sd_bus_track
*t
, void *userdata
) {
1606 u
->bus_track
= sd_bus_track_unref(u
->bus_track
); /* make sure we aren't called again */
1608 unit_add_to_gc_queue(u
);
1612 static int bus_unit_allocate_bus_track(Unit
*u
) {
1620 r
= sd_bus_track_new(u
->manager
->api_bus
, &u
->bus_track
, bus_unit_track_handler
, u
);
1624 r
= sd_bus_track_set_recursive(u
->bus_track
, true);
1626 u
->bus_track
= sd_bus_track_unref(u
->bus_track
);
1633 int bus_unit_track_add_name(Unit
*u
, const char *name
) {
1638 r
= bus_unit_allocate_bus_track(u
);
1642 return sd_bus_track_add_name(u
->bus_track
, name
);
1645 int bus_unit_track_add_sender(Unit
*u
, sd_bus_message
*m
) {
1650 r
= bus_unit_allocate_bus_track(u
);
1654 return sd_bus_track_add_sender(u
->bus_track
, m
);
1657 int bus_unit_track_remove_sender(Unit
*u
, sd_bus_message
*m
) {
1660 /* If we haven't allocated the bus track object yet, then there's definitely no reference taken yet, return an
1665 return sd_bus_track_remove_sender(u
->bus_track
, m
);