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("StartLimitIntervalUSec", "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("FailureAction", "s", property_get_emergency_action
, offsetof(Unit
, failure_action
), SD_BUS_VTABLE_PROPERTY_CONST
),
802 SD_BUS_PROPERTY("SuccessAction", "s", property_get_emergency_action
, offsetof(Unit
, success_action
), SD_BUS_VTABLE_PROPERTY_CONST
),
803 SD_BUS_PROPERTY("RebootArgument", "s", NULL
, offsetof(Unit
, reboot_arg
), SD_BUS_VTABLE_PROPERTY_CONST
),
804 SD_BUS_PROPERTY("InvocationID", "ay", bus_property_get_id128
, offsetof(Unit
, invocation_id
), 0),
805 SD_BUS_PROPERTY("CollectMode", "s", property_get_collect_mode
, offsetof(Unit
, collect_mode
), 0),
807 SD_BUS_METHOD("Start", "s", "o", method_start
, SD_BUS_VTABLE_UNPRIVILEGED
),
808 SD_BUS_METHOD("Stop", "s", "o", method_stop
, SD_BUS_VTABLE_UNPRIVILEGED
),
809 SD_BUS_METHOD("Reload", "s", "o", method_reload
, SD_BUS_VTABLE_UNPRIVILEGED
),
810 SD_BUS_METHOD("Restart", "s", "o", method_restart
, SD_BUS_VTABLE_UNPRIVILEGED
),
811 SD_BUS_METHOD("TryRestart", "s", "o", method_try_restart
, SD_BUS_VTABLE_UNPRIVILEGED
),
812 SD_BUS_METHOD("ReloadOrRestart", "s", "o", method_reload_or_restart
, SD_BUS_VTABLE_UNPRIVILEGED
),
813 SD_BUS_METHOD("ReloadOrTryRestart", "s", "o", method_reload_or_try_restart
, SD_BUS_VTABLE_UNPRIVILEGED
),
814 SD_BUS_METHOD("Kill", "si", NULL
, bus_unit_method_kill
, SD_BUS_VTABLE_UNPRIVILEGED
),
815 SD_BUS_METHOD("ResetFailed", NULL
, NULL
, bus_unit_method_reset_failed
, SD_BUS_VTABLE_UNPRIVILEGED
),
816 SD_BUS_METHOD("SetProperties", "ba(sv)", NULL
, bus_unit_method_set_properties
, SD_BUS_VTABLE_UNPRIVILEGED
),
817 SD_BUS_METHOD("Ref", NULL
, NULL
, bus_unit_method_ref
, SD_BUS_VTABLE_UNPRIVILEGED
),
818 SD_BUS_METHOD("Unref", NULL
, NULL
, bus_unit_method_unref
, SD_BUS_VTABLE_UNPRIVILEGED
),
820 /* Obsolete properties or obsolete alias names */
821 SD_BUS_PROPERTY("RequiresOverridable", "as", property_get_obsolete_dependencies
, 0, SD_BUS_VTABLE_HIDDEN
),
822 SD_BUS_PROPERTY("RequisiteOverridable", "as", property_get_obsolete_dependencies
, 0, SD_BUS_VTABLE_HIDDEN
),
823 SD_BUS_PROPERTY("RequiredByOverridable", "as", property_get_obsolete_dependencies
, 0, SD_BUS_VTABLE_HIDDEN
),
824 SD_BUS_PROPERTY("RequisiteOfOverridable", "as", property_get_obsolete_dependencies
, 0, SD_BUS_VTABLE_HIDDEN
),
825 SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec
, offsetof(Unit
, start_limit
.interval
), SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
826 SD_BUS_PROPERTY("StartLimitIntervalSec", "t", bus_property_get_usec
, offsetof(Unit
, start_limit
.interval
), SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
830 static int property_get_slice(
833 const char *interface
,
834 const char *property
,
835 sd_bus_message
*reply
,
837 sd_bus_error
*error
) {
845 return sd_bus_message_append(reply
, "s", unit_slice_name(u
));
848 static int property_get_current_memory(
851 const char *interface
,
852 const char *property
,
853 sd_bus_message
*reply
,
855 sd_bus_error
*error
) {
857 uint64_t sz
= (uint64_t) -1;
865 r
= unit_get_memory_current(u
, &sz
);
866 if (r
< 0 && r
!= -ENODATA
)
867 log_unit_warning_errno(u
, r
, "Failed to get memory.usage_in_bytes attribute: %m");
869 return sd_bus_message_append(reply
, "t", sz
);
872 static int property_get_current_tasks(
875 const char *interface
,
876 const char *property
,
877 sd_bus_message
*reply
,
879 sd_bus_error
*error
) {
881 uint64_t cn
= (uint64_t) -1;
889 r
= unit_get_tasks_current(u
, &cn
);
890 if (r
< 0 && r
!= -ENODATA
)
891 log_unit_warning_errno(u
, r
, "Failed to get pids.current attribute: %m");
893 return sd_bus_message_append(reply
, "t", cn
);
896 static int property_get_cpu_usage(
899 const char *interface
,
900 const char *property
,
901 sd_bus_message
*reply
,
903 sd_bus_error
*error
) {
905 nsec_t ns
= (nsec_t
) -1;
913 r
= unit_get_cpu_usage(u
, &ns
);
914 if (r
< 0 && r
!= -ENODATA
)
915 log_unit_warning_errno(u
, r
, "Failed to get cpuacct.usage attribute: %m");
917 return sd_bus_message_append(reply
, "t", ns
);
920 static int property_get_cgroup(
923 const char *interface
,
924 const char *property
,
925 sd_bus_message
*reply
,
927 sd_bus_error
*error
) {
936 /* Three cases: a) u->cgroup_path is NULL, in which case the
937 * unit has no control group, which we report as the empty
938 * string. b) u->cgroup_path is the empty string, which
939 * indicates the root cgroup, which we report as "/". c) all
940 * other cases we report as-is. */
943 t
= isempty(u
->cgroup_path
) ? "/" : u
->cgroup_path
;
947 return sd_bus_message_append(reply
, "s", t
);
950 static int append_process(sd_bus_message
*reply
, const char *p
, pid_t pid
, Set
*pids
) {
951 _cleanup_free_
char *buf
= NULL
, *cmdline
= NULL
;
957 r
= set_put(pids
, PID_TO_PTR(pid
));
958 if (IN_SET(r
, 0, -EEXIST
))
964 r
= cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER
, pid
, &buf
);
973 (void) get_process_cmdline(pid
, 0, true, &cmdline
);
975 return sd_bus_message_append(reply
,
982 static int append_cgroup(sd_bus_message
*reply
, const char *p
, Set
*pids
) {
983 _cleanup_closedir_
DIR *d
= NULL
;
984 _cleanup_fclose_
FILE *f
= NULL
;
990 r
= cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER
, p
, &f
);
999 r
= cg_read_pid(f
, &pid
);
1005 if (is_kernel_thread(pid
) > 0)
1008 r
= append_process(reply
, p
, pid
, pids
);
1013 r
= cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER
, p
, &d
);
1020 _cleanup_free_
char *g
= NULL
, *j
= NULL
;
1022 r
= cg_read_subgroup(d
, &g
);
1028 j
= strjoin(p
, "/", g
);
1032 r
= append_cgroup(reply
, j
, pids
);
1040 int bus_unit_method_get_processes(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1041 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1042 _cleanup_(set_freep
) Set
*pids
= NULL
;
1049 r
= mac_selinux_unit_access_check(u
, message
, "status", error
);
1053 pids
= set_new(NULL
);
1057 r
= sd_bus_message_new_method_return(message
, &reply
);
1061 r
= sd_bus_message_open_container(reply
, 'a', "(sus)");
1065 if (u
->cgroup_path
) {
1066 r
= append_cgroup(reply
, u
->cgroup_path
, pids
);
1071 /* The main and control pids might live outside of the cgroup, hence fetch them separately */
1072 pid
= unit_main_pid(u
);
1074 r
= append_process(reply
, NULL
, pid
, pids
);
1079 pid
= unit_control_pid(u
);
1081 r
= append_process(reply
, NULL
, pid
, pids
);
1086 r
= sd_bus_message_close_container(reply
);
1090 return sd_bus_send(NULL
, reply
, NULL
);
1093 static int property_get_ip_counter(
1096 const char *interface
,
1097 const char *property
,
1098 sd_bus_message
*reply
,
1100 sd_bus_error
*error
) {
1102 CGroupIPAccountingMetric metric
;
1103 uint64_t value
= (uint64_t) -1;
1111 if (streq(property
, "IPIngressBytes"))
1112 metric
= CGROUP_IP_INGRESS_BYTES
;
1113 else if (streq(property
, "IPIngressPackets"))
1114 metric
= CGROUP_IP_INGRESS_PACKETS
;
1115 else if (streq(property
, "IPEgressBytes"))
1116 metric
= CGROUP_IP_EGRESS_BYTES
;
1118 assert(streq(property
, "IPEgressPackets"));
1119 metric
= CGROUP_IP_EGRESS_PACKETS
;
1122 (void) unit_get_ip_accounting(u
, metric
, &value
);
1123 return sd_bus_message_append(reply
, "t", value
);
1126 const sd_bus_vtable bus_unit_cgroup_vtable
[] = {
1127 SD_BUS_VTABLE_START(0),
1128 SD_BUS_PROPERTY("Slice", "s", property_get_slice
, 0, 0),
1129 SD_BUS_PROPERTY("ControlGroup", "s", property_get_cgroup
, 0, 0),
1130 SD_BUS_PROPERTY("MemoryCurrent", "t", property_get_current_memory
, 0, 0),
1131 SD_BUS_PROPERTY("CPUUsageNSec", "t", property_get_cpu_usage
, 0, 0),
1132 SD_BUS_PROPERTY("TasksCurrent", "t", property_get_current_tasks
, 0, 0),
1133 SD_BUS_PROPERTY("IPIngressBytes", "t", property_get_ip_counter
, 0, 0),
1134 SD_BUS_PROPERTY("IPIngressPackets", "t", property_get_ip_counter
, 0, 0),
1135 SD_BUS_PROPERTY("IPEgressBytes", "t", property_get_ip_counter
, 0, 0),
1136 SD_BUS_PROPERTY("IPEgressPackets", "t", property_get_ip_counter
, 0, 0),
1137 SD_BUS_METHOD("GetProcesses", NULL
, "a(sus)", bus_unit_method_get_processes
, SD_BUS_VTABLE_UNPRIVILEGED
),
1141 static int send_new_signal(sd_bus
*bus
, void *userdata
) {
1142 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
1143 _cleanup_free_
char *p
= NULL
;
1150 p
= unit_dbus_path(u
);
1154 r
= sd_bus_message_new_signal(
1157 "/org/freedesktop/systemd1",
1158 "org.freedesktop.systemd1.Manager",
1163 r
= sd_bus_message_append(m
, "so", u
->id
, p
);
1167 return sd_bus_send(bus
, m
, NULL
);
1170 static int send_changed_signal(sd_bus
*bus
, void *userdata
) {
1171 _cleanup_free_
char *p
= NULL
;
1178 p
= unit_dbus_path(u
);
1182 /* Send a properties changed signal. First for the specific
1183 * type, then for the generic unit. The clients may rely on
1184 * this order to get atomic behavior if needed. */
1186 r
= sd_bus_emit_properties_changed_strv(
1188 unit_dbus_interface_from_type(u
->type
),
1193 return sd_bus_emit_properties_changed_strv(
1195 "org.freedesktop.systemd1.Unit",
1199 void bus_unit_send_change_signal(Unit
*u
) {
1203 if (u
->in_dbus_queue
) {
1204 LIST_REMOVE(dbus_queue
, u
->manager
->dbus_unit_queue
, u
);
1205 u
->in_dbus_queue
= false;
1211 r
= bus_foreach_bus(u
->manager
, u
->bus_track
, u
->sent_dbus_new_signal
? send_changed_signal
: send_new_signal
, u
);
1213 log_unit_debug_errno(u
, r
, "Failed to send unit change signal for %s: %m", u
->id
);
1215 u
->sent_dbus_new_signal
= true;
1218 static int send_removed_signal(sd_bus
*bus
, void *userdata
) {
1219 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
1220 _cleanup_free_
char *p
= NULL
;
1227 p
= unit_dbus_path(u
);
1231 r
= sd_bus_message_new_signal(
1234 "/org/freedesktop/systemd1",
1235 "org.freedesktop.systemd1.Manager",
1240 r
= sd_bus_message_append(m
, "so", u
->id
, p
);
1244 return sd_bus_send(bus
, m
, NULL
);
1247 void bus_unit_send_removed_signal(Unit
*u
) {
1251 if (!u
->sent_dbus_new_signal
|| u
->in_dbus_queue
)
1252 bus_unit_send_change_signal(u
);
1257 r
= bus_foreach_bus(u
->manager
, u
->bus_track
, send_removed_signal
, u
);
1259 log_unit_debug_errno(u
, r
, "Failed to send unit remove signal for %s: %m", u
->id
);
1262 int bus_unit_queue_job(
1263 sd_bus_message
*message
,
1267 bool reload_if_possible
,
1268 sd_bus_error
*error
) {
1270 _cleanup_free_
char *path
= NULL
;
1276 assert(type
>= 0 && type
< _JOB_TYPE_MAX
);
1277 assert(mode
>= 0 && mode
< _JOB_MODE_MAX
);
1279 r
= mac_selinux_unit_access_check(
1281 job_type_to_access_method(type
),
1286 if (reload_if_possible
&& unit_can_reload(u
)) {
1287 if (type
== JOB_RESTART
)
1288 type
= JOB_RELOAD_OR_START
;
1289 else if (type
== JOB_TRY_RESTART
)
1290 type
= JOB_TRY_RELOAD
;
1293 if (type
== JOB_STOP
&&
1294 (IN_SET(u
->load_state
, UNIT_NOT_FOUND
, UNIT_ERROR
)) &&
1295 unit_active_state(u
) == UNIT_INACTIVE
)
1296 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_UNIT
, "Unit %s not loaded.", u
->id
);
1298 if ((type
== JOB_START
&& u
->refuse_manual_start
) ||
1299 (type
== JOB_STOP
&& u
->refuse_manual_stop
) ||
1300 (IN_SET(type
, JOB_RESTART
, JOB_TRY_RESTART
) && (u
->refuse_manual_start
|| u
->refuse_manual_stop
)) ||
1301 (type
== JOB_RELOAD_OR_START
&& job_type_collapse(type
, u
) == JOB_START
&& u
->refuse_manual_start
))
1302 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
);
1304 r
= manager_add_job(u
->manager
, type
, u
, mode
, error
, &j
);
1308 r
= bus_job_track_sender(j
, message
);
1312 path
= job_dbus_path(j
);
1316 return sd_bus_reply_method_return(message
, "o", path
);
1319 static int bus_unit_set_live_property(
1322 sd_bus_message
*message
,
1323 UnitWriteFlags flags
,
1324 sd_bus_error
*error
) {
1332 /* Handles setting properties both "live" (i.e. at any time during runtime), and during creation (for transient
1333 * units that are being created). */
1335 if (streq(name
, "Description")) {
1338 r
= sd_bus_message_read(message
, "s", &d
);
1342 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1343 r
= unit_set_description(u
, d
);
1347 unit_write_settingf(u
, flags
|UNIT_ESCAPE_SPECIFIERS
, name
, "Description=%s", d
);
1356 static int bus_unit_set_transient_property(
1359 sd_bus_message
*message
,
1360 UnitWriteFlags flags
,
1361 sd_bus_error
*error
) {
1369 /* Handles settings when transient units are created. This settings cannot be altered anymore after the unit
1370 * has been created. */
1372 if (streq(name
, "DefaultDependencies")) {
1375 r
= sd_bus_message_read(message
, "b", &b
);
1379 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1380 u
->default_dependencies
= b
;
1381 unit_write_settingf(u
, flags
, name
, "DefaultDependencies=%s", yes_no(b
));
1386 } else if (streq(name
, "CollectMode")) {
1390 r
= sd_bus_message_read(message
, "s", &s
);
1394 m
= collect_mode_from_string(s
);
1396 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown garbage collection mode: %s", s
);
1398 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1399 u
->collect_mode
= m
;
1400 unit_write_settingf(u
, flags
, name
, "CollectMode=%s", collect_mode_to_string(m
));
1405 } else if (streq(name
, "Slice")) {
1409 if (!UNIT_HAS_CGROUP_CONTEXT(u
))
1410 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "The slice property is only available for units with control groups.");
1411 if (u
->type
== UNIT_SLICE
)
1412 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Slice may not be set for slice units.");
1413 if (unit_has_name(u
, SPECIAL_INIT_SCOPE
))
1414 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Cannot set slice for init.scope");
1416 r
= sd_bus_message_read(message
, "s", &s
);
1420 if (!unit_name_is_valid(s
, UNIT_NAME_PLAIN
))
1421 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid unit name '%s'", s
);
1423 /* Note that we do not dispatch the load queue here yet, as we don't want our own transient unit to be
1424 * loaded while we are still setting it up. Or in other words, we use manager_load_unit_prepare()
1425 * instead of manager_load_unit() on purpose, here. */
1426 r
= manager_load_unit_prepare(u
->manager
, s
, NULL
, error
, &slice
);
1430 if (slice
->type
!= UNIT_SLICE
)
1431 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unit name '%s' is not a slice", s
);
1433 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1434 r
= unit_set_slice(u
, slice
);
1438 unit_write_settingf(u
, flags
|UNIT_PRIVATE
, name
, "Slice=%s", s
);
1443 } else if (STR_IN_SET(name
,
1444 "Requires", "RequiresOverridable",
1445 "Requisite", "RequisiteOverridable",
1451 "PropagatesReloadTo", "ReloadPropagatedFrom",
1457 if (streq(name
, "RequiresOverridable"))
1458 d
= UNIT_REQUIRES
; /* redirect for obsolete unit dependency type */
1459 else if (streq(name
, "RequisiteOverridable"))
1460 d
= UNIT_REQUISITE
; /* same here */
1462 d
= unit_dependency_from_string(name
);
1464 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid unit dependency: %s", name
);
1467 r
= sd_bus_message_enter_container(message
, 'a', "s");
1471 while ((r
= sd_bus_message_read(message
, "s", &other
)) > 0) {
1472 if (!unit_name_is_valid(other
, UNIT_NAME_PLAIN
|UNIT_NAME_INSTANCE
))
1473 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid unit name %s", other
);
1475 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1476 _cleanup_free_
char *label
= NULL
;
1478 r
= unit_add_dependency_by_name(u
, d
, other
, NULL
, true, UNIT_DEPENDENCY_FILE
);
1482 label
= strjoin(name
, "-", other
);
1486 unit_write_settingf(u
, flags
, label
, "%s=%s", name
, other
);
1493 r
= sd_bus_message_exit_container(message
);
1499 } else if (STR_IN_SET(name
, "FailureAction", "SuccessAction")) {
1500 EmergencyAction action
;
1503 r
= sd_bus_message_read(message
, "s", &s
);
1507 action
= emergency_action_from_string(s
);
1509 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid emergency action: %s", s
);
1511 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1513 if (streq(name
, "FailureAction"))
1514 u
->failure_action
= action
;
1516 u
->success_action
= action
;
1518 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, emergency_action_to_string(action
));
1523 } else if (streq(name
, "AddRef")) {
1527 /* Why is this called "AddRef" rather than just "Ref", or "Reference"? There's already a "Ref()" method
1528 * on the Unit interface, and it's probably not a good idea to expose a property and a method on the
1529 * same interface (well, strictly speaking AddRef isn't exposed as full property, we just read it for
1530 * transient units, but still). And "References" and "ReferencedBy" is already used as unit reference
1531 * dependency type, hence let's not confuse things with that.
1533 * Note that we don't acually add the reference to the bus track. We do that only after the setup of
1534 * the transient unit is complete, so that setting this property multiple times in the same transient
1535 * unit creation call doesn't count as individual references. */
1537 r
= sd_bus_message_read(message
, "b", &b
);
1541 if (!UNIT_WRITE_FLAGS_NOOP(flags
))
1542 u
->bus_track_add
= b
;
1550 int bus_unit_set_properties(
1552 sd_bus_message
*message
,
1553 UnitWriteFlags flags
,
1555 sd_bus_error
*error
) {
1557 bool for_real
= false;
1564 /* We iterate through the array twice. First run we just check
1565 * if all passed data is valid, second run actually applies
1566 * it. This is to implement transaction-like behaviour without
1567 * actually providing full transactions. */
1569 r
= sd_bus_message_enter_container(message
, 'a', "(sv)");
1577 r
= sd_bus_message_enter_container(message
, 'r', "sv");
1581 if (for_real
|| UNIT_WRITE_FLAGS_NOOP(flags
))
1584 /* Reached EOF. Let's try again, and this time for realz... */
1585 r
= sd_bus_message_rewind(message
, false);
1593 r
= sd_bus_message_read(message
, "s", &name
);
1597 if (!UNIT_VTABLE(u
)->bus_set_property
)
1598 return sd_bus_error_setf(error
, SD_BUS_ERROR_PROPERTY_READ_ONLY
, "Objects of this type do not support setting properties.");
1600 r
= sd_bus_message_enter_container(message
, 'v', NULL
);
1604 /* If not for real, then mask out the two target flags */
1605 f
= for_real
? flags
: (flags
& ~(UNIT_RUNTIME
|UNIT_PERSISTENT
));
1607 r
= UNIT_VTABLE(u
)->bus_set_property(u
, name
, message
, f
, error
);
1608 if (r
== 0 && u
->transient
&& u
->load_state
== UNIT_STUB
)
1609 r
= bus_unit_set_transient_property(u
, name
, message
, f
, error
);
1611 r
= bus_unit_set_live_property(u
, name
, message
, f
, error
);
1616 return sd_bus_error_setf(error
, SD_BUS_ERROR_PROPERTY_READ_ONLY
, "Cannot set property %s, or unknown property.", name
);
1618 r
= sd_bus_message_exit_container(message
);
1622 r
= sd_bus_message_exit_container(message
);
1629 r
= sd_bus_message_exit_container(message
);
1633 if (commit
&& n
> 0 && UNIT_VTABLE(u
)->bus_commit_properties
)
1634 UNIT_VTABLE(u
)->bus_commit_properties(u
);
1639 int bus_unit_check_load_state(Unit
*u
, sd_bus_error
*error
) {
1642 if (u
->load_state
== UNIT_LOADED
)
1645 /* Give a better description of the unit error when
1646 * possible. Note that in the case of UNIT_MASKED, load_error
1648 if (u
->load_state
== UNIT_MASKED
)
1649 return sd_bus_error_setf(error
, BUS_ERROR_UNIT_MASKED
, "Unit %s is masked.", u
->id
);
1651 if (u
->load_state
== UNIT_NOT_FOUND
)
1652 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_UNIT
, "Unit %s not found.", u
->id
);
1654 return sd_bus_error_set_errnof(error
, u
->load_error
, "Unit %s is not loaded properly: %m.", u
->id
);
1657 static int bus_unit_track_handler(sd_bus_track
*t
, void *userdata
) {
1663 u
->bus_track
= sd_bus_track_unref(u
->bus_track
); /* make sure we aren't called again */
1665 unit_add_to_gc_queue(u
);
1669 static int bus_unit_allocate_bus_track(Unit
*u
) {
1677 r
= sd_bus_track_new(u
->manager
->api_bus
, &u
->bus_track
, bus_unit_track_handler
, u
);
1681 r
= sd_bus_track_set_recursive(u
->bus_track
, true);
1683 u
->bus_track
= sd_bus_track_unref(u
->bus_track
);
1690 int bus_unit_track_add_name(Unit
*u
, const char *name
) {
1695 r
= bus_unit_allocate_bus_track(u
);
1699 return sd_bus_track_add_name(u
->bus_track
, name
);
1702 int bus_unit_track_add_sender(Unit
*u
, sd_bus_message
*m
) {
1707 r
= bus_unit_allocate_bus_track(u
);
1711 return sd_bus_track_add_sender(u
->bus_track
, m
);
1714 int bus_unit_track_remove_sender(Unit
*u
, sd_bus_message
*m
) {
1717 /* If we haven't allocated the bus track object yet, then there's definitely no reference taken yet, return an
1722 return sd_bus_track_remove_sender(u
->bus_track
, m
);