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/>.
29 #include "selinux-access.h"
31 #include "clock-util.h"
32 #include "path-util.h"
34 #include "architecture.h"
38 #include "dbus-manager.h"
39 #include "dbus-unit.h"
40 #include "dbus-snapshot.h"
41 #include "dbus-execute.h"
42 #include "bus-common-errors.h"
43 #include "formats-util.h"
45 static int property_get_version(
48 const char *interface
,
50 sd_bus_message
*reply
,
52 sd_bus_error
*error
) {
57 return sd_bus_message_append(reply
, "s", PACKAGE_VERSION
);
60 static int property_get_features(
63 const char *interface
,
65 sd_bus_message
*reply
,
67 sd_bus_error
*error
) {
72 return sd_bus_message_append(reply
, "s", SYSTEMD_FEATURES
);
75 static int property_get_virtualization(
78 const char *interface
,
80 sd_bus_message
*reply
,
82 sd_bus_error
*error
) {
84 const char *id
= NULL
;
89 detect_virtualization(&id
);
91 return sd_bus_message_append(reply
, "s", id
);
94 static int property_get_architecture(
97 const char *interface
,
99 sd_bus_message
*reply
,
101 sd_bus_error
*error
) {
106 return sd_bus_message_append(reply
, "s", architecture_to_string(uname_architecture()));
109 static int property_get_tainted(
112 const char *interface
,
113 const char *property
,
114 sd_bus_message
*reply
,
116 sd_bus_error
*error
) {
118 char buf
[sizeof("split-usr:mtab-not-symlink:cgroups-missing:local-hwclock:")] = "", *e
= buf
;
119 _cleanup_free_
char *p
= NULL
;
120 Manager
*m
= userdata
;
127 e
= stpcpy(e
, "split-usr:");
129 if (readlink_malloc("/etc/mtab", &p
) < 0)
130 e
= stpcpy(e
, "mtab-not-symlink:");
132 if (access("/proc/cgroups", F_OK
) < 0)
133 e
= stpcpy(e
, "cgroups-missing:");
135 if (clock_is_localtime() > 0)
136 e
= stpcpy(e
, "local-hwclock:");
138 /* remove the last ':' */
142 return sd_bus_message_append(reply
, "s", buf
);
145 static int property_get_log_target(
148 const char *interface
,
149 const char *property
,
150 sd_bus_message
*reply
,
152 sd_bus_error
*error
) {
157 return sd_bus_message_append(reply
, "s", log_target_to_string(log_get_target()));
160 static int property_set_log_target(
163 const char *interface
,
164 const char *property
,
165 sd_bus_message
*value
,
167 sd_bus_error
*error
) {
175 r
= sd_bus_message_read(value
, "s", &t
);
179 return log_set_target_from_string(t
);
182 static int property_get_log_level(
185 const char *interface
,
186 const char *property
,
187 sd_bus_message
*reply
,
189 sd_bus_error
*error
) {
191 _cleanup_free_
char *t
= NULL
;
197 r
= log_level_to_string_alloc(log_get_max_level(), &t
);
201 return sd_bus_message_append(reply
, "s", t
);
204 static int property_set_log_level(
207 const char *interface
,
208 const char *property
,
209 sd_bus_message
*value
,
211 sd_bus_error
*error
) {
219 r
= sd_bus_message_read(value
, "s", &t
);
223 return log_set_max_level_from_string(t
);
226 static int property_get_n_names(
229 const char *interface
,
230 const char *property
,
231 sd_bus_message
*reply
,
233 sd_bus_error
*error
) {
235 Manager
*m
= userdata
;
241 return sd_bus_message_append(reply
, "u", (uint32_t) hashmap_size(m
->units
));
244 static int property_get_n_failed_units(
247 const char *interface
,
248 const char *property
,
249 sd_bus_message
*reply
,
251 sd_bus_error
*error
) {
253 Manager
*m
= userdata
;
259 return sd_bus_message_append(reply
, "u", (uint32_t) set_size(m
->failed_units
));
262 static int property_get_n_jobs(
265 const char *interface
,
266 const char *property
,
267 sd_bus_message
*reply
,
269 sd_bus_error
*error
) {
271 Manager
*m
= userdata
;
277 return sd_bus_message_append(reply
, "u", (uint32_t) hashmap_size(m
->jobs
));
280 static int property_get_progress(
283 const char *interface
,
284 const char *property
,
285 sd_bus_message
*reply
,
287 sd_bus_error
*error
) {
289 Manager
*m
= userdata
;
296 if (dual_timestamp_is_set(&m
->finish_timestamp
))
299 d
= 1.0 - ((double) hashmap_size(m
->jobs
) / (double) m
->n_installed_jobs
);
301 return sd_bus_message_append(reply
, "d", d
);
304 static int property_get_system_state(
307 const char *interface
,
308 const char *property
,
309 sd_bus_message
*reply
,
311 sd_bus_error
*error
) {
313 Manager
*m
= userdata
;
319 return sd_bus_message_append(reply
, "s", manager_state_to_string(manager_state(m
)));
322 static int property_set_runtime_watchdog(
325 const char *interface
,
326 const char *property
,
327 sd_bus_message
*value
,
329 sd_bus_error
*error
) {
331 usec_t
*t
= userdata
;
337 assert_cc(sizeof(usec_t
) == sizeof(uint64_t));
339 r
= sd_bus_message_read(value
, "t", t
);
343 return watchdog_set_timeout(t
);
346 static int method_get_unit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
347 _cleanup_free_
char *path
= NULL
;
348 Manager
*m
= userdata
;
356 /* Anyone can call this method */
358 r
= sd_bus_message_read(message
, "s", &name
);
363 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
366 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
370 r
= sd_bus_creds_get_pid(creds
, &pid
);
374 u
= manager_get_unit_by_pid(m
, pid
);
376 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_UNIT
, "Client not member of any unit.");
378 u
= manager_get_unit(m
, name
);
380 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_UNIT
, "Unit %s not loaded.", name
);
383 r
= mac_selinux_unit_access_check(u
, message
, "status", error
);
387 path
= unit_dbus_path(u
);
391 return sd_bus_reply_method_return(message
, "o", path
);
394 static int method_get_unit_by_pid(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
395 _cleanup_free_
char *path
= NULL
;
396 Manager
*m
= userdata
;
404 assert_cc(sizeof(pid_t
) == sizeof(uint32_t));
406 /* Anyone can call this method */
408 r
= sd_bus_message_read(message
, "u", &pid
);
412 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid PID " PID_FMT
, pid
);
415 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
417 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
421 r
= sd_bus_creds_get_pid(creds
, &pid
);
426 u
= manager_get_unit_by_pid(m
, pid
);
428 return sd_bus_error_setf(error
, BUS_ERROR_NO_UNIT_FOR_PID
, "PID "PID_FMT
" does not belong to any loaded unit.", pid
);
430 r
= mac_selinux_unit_access_check(u
, message
, "status", error
);
434 path
= unit_dbus_path(u
);
438 return sd_bus_reply_method_return(message
, "o", path
);
441 static int method_load_unit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
442 _cleanup_free_
char *path
= NULL
;
443 Manager
*m
= userdata
;
451 /* Anyone can call this method */
453 r
= sd_bus_message_read(message
, "s", &name
);
458 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
461 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
465 r
= sd_bus_creds_get_pid(creds
, &pid
);
469 u
= manager_get_unit_by_pid(m
, pid
);
471 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_UNIT
, "Client not member of any unit.");
473 r
= manager_load_unit(m
, name
, NULL
, error
, &u
);
478 r
= mac_selinux_unit_access_check(u
, message
, "status", error
);
482 path
= unit_dbus_path(u
);
486 return sd_bus_reply_method_return(message
, "o", path
);
489 static int method_start_unit_generic(sd_bus_message
*message
, Manager
*m
, JobType job_type
, bool reload_if_possible
, sd_bus_error
*error
) {
497 r
= sd_bus_message_read(message
, "s", &name
);
501 r
= manager_load_unit(m
, name
, NULL
, error
, &u
);
505 return bus_unit_method_start_generic(message
, u
, job_type
, reload_if_possible
, error
);
508 static int method_start_unit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
509 return method_start_unit_generic(message
, userdata
, JOB_START
, false, error
);
512 static int method_stop_unit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
513 return method_start_unit_generic(message
, userdata
, JOB_STOP
, false, error
);
516 static int method_reload_unit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
517 return method_start_unit_generic(message
, userdata
, JOB_RELOAD
, false, error
);
520 static int method_restart_unit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
521 return method_start_unit_generic(message
, userdata
, JOB_RESTART
, false, error
);
524 static int method_try_restart_unit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
525 return method_start_unit_generic(message
, userdata
, JOB_TRY_RESTART
, false, error
);
528 static int method_reload_or_restart_unit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
529 return method_start_unit_generic(message
, userdata
, JOB_RESTART
, true, error
);
532 static int method_reload_or_try_restart_unit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
533 return method_start_unit_generic(message
, userdata
, JOB_TRY_RESTART
, true, error
);
536 static int method_start_unit_replace(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
537 Manager
*m
= userdata
;
538 const char *old_name
;
545 r
= sd_bus_message_read(message
, "s", &old_name
);
549 u
= manager_get_unit(m
, old_name
);
550 if (!u
|| !u
->job
|| u
->job
->type
!= JOB_START
)
551 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_JOB
, "No job queued for unit %s", old_name
);
553 return method_start_unit_generic(message
, m
, JOB_START
, false, error
);
556 static int method_kill_unit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
557 Manager
*m
= userdata
;
565 r
= sd_bus_message_read(message
, "s", &name
);
569 u
= manager_get_unit(m
, name
);
571 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_UNIT
, "Unit %s is not loaded.", name
);
573 return bus_unit_method_kill(message
, u
, error
);
576 static int method_reset_failed_unit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
577 Manager
*m
= userdata
;
585 r
= sd_bus_message_read(message
, "s", &name
);
589 u
= manager_get_unit(m
, name
);
591 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_UNIT
, "Unit %s is not loaded.", name
);
593 return bus_unit_method_reset_failed(message
, u
, error
);
596 static int method_set_unit_properties(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
597 Manager
*m
= userdata
;
605 r
= sd_bus_message_read(message
, "s", &name
);
609 u
= manager_get_unit(m
, name
);
611 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_UNIT
, "Unit %s is not loaded.", name
);
613 return bus_unit_method_set_properties(message
, u
, error
);
616 static int transient_unit_from_message(
618 sd_bus_message
*message
,
621 sd_bus_error
*error
) {
630 r
= manager_load_unit(m
, name
, NULL
, error
, &u
);
634 if (u
->load_state
!= UNIT_NOT_FOUND
||
635 set_size(u
->dependencies
[UNIT_REFERENCED_BY
]) > 0)
636 return sd_bus_error_setf(error
, BUS_ERROR_UNIT_EXISTS
, "Unit %s already exists.", name
);
638 /* OK, the unit failed to load and is unreferenced, now let's
639 * fill in the transient data instead */
640 r
= unit_make_transient(u
);
644 /* Set our properties */
645 r
= bus_unit_set_properties(u
, message
, UNIT_RUNTIME
, false, error
);
654 static int transient_aux_units_from_message(
656 sd_bus_message
*message
,
657 sd_bus_error
*error
) {
666 r
= sd_bus_message_enter_container(message
, 'a', "(sa(sv))");
670 while ((r
= sd_bus_message_enter_container(message
, 'r', "sa(sv)")) > 0) {
671 r
= sd_bus_message_read(message
, "s", &name
);
675 r
= transient_unit_from_message(m
, message
, name
, &u
, error
);
676 if (r
< 0 && r
!= -EEXIST
)
685 r
= sd_bus_message_exit_container(message
);
692 r
= sd_bus_message_exit_container(message
);
699 static int method_start_transient_unit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
700 const char *name
, *smode
;
701 Manager
*m
= userdata
;
710 r
= mac_selinux_access_check(message
, "start", error
);
714 r
= sd_bus_message_read(message
, "ss", &name
, &smode
);
718 t
= unit_name_to_type(name
);
720 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid unit type.");
722 if (!unit_vtable
[t
]->can_transient
)
723 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unit type %s does not support transient units.", unit_type_to_string(t
));
725 mode
= job_mode_from_string(smode
);
727 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Job mode %s is invalid.", smode
);
729 r
= bus_verify_manage_units_async(m
, message
, error
);
733 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
735 r
= transient_unit_from_message(m
, message
, name
, &u
, error
);
739 r
= transient_aux_units_from_message(m
, message
, error
);
743 /* And load this stub fully */
748 manager_dispatch_load_queue(m
);
750 /* Finally, start it */
751 return bus_unit_queue_job(message
, u
, JOB_START
, mode
, false, error
);
754 static int method_get_job(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
755 _cleanup_free_
char *path
= NULL
;
756 Manager
*m
= userdata
;
764 /* Anyone can call this method */
766 r
= sd_bus_message_read(message
, "u", &id
);
770 j
= manager_get_job(m
, id
);
772 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_JOB
, "Job %u does not exist.", (unsigned) id
);
774 r
= mac_selinux_unit_access_check(j
->unit
, message
, "status", error
);
778 path
= job_dbus_path(j
);
782 return sd_bus_reply_method_return(message
, "o", path
);
785 static int method_cancel_job(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
786 Manager
*m
= userdata
;
794 r
= sd_bus_message_read(message
, "u", &id
);
798 j
= manager_get_job(m
, id
);
800 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_JOB
, "Job %u does not exist.", (unsigned) id
);
802 return bus_job_method_cancel(message
, j
, error
);
805 static int method_clear_jobs(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
806 Manager
*m
= userdata
;
812 r
= mac_selinux_access_check(message
, "reload", error
);
816 r
= bus_verify_manage_units_async(m
, message
, error
);
820 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
822 manager_clear_jobs(m
);
824 return sd_bus_reply_method_return(message
, NULL
);
827 static int method_reset_failed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
828 Manager
*m
= userdata
;
834 r
= mac_selinux_access_check(message
, "reload", error
);
838 r
= bus_verify_manage_units_async(m
, message
, error
);
842 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
844 manager_reset_failed(m
);
846 return sd_bus_reply_method_return(message
, NULL
);
849 static int list_units_filtered(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
, char **states
) {
850 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
851 Manager
*m
= userdata
;
860 /* Anyone can call this method */
862 r
= mac_selinux_access_check(message
, "status", error
);
866 r
= sd_bus_message_new_method_return(message
, &reply
);
870 r
= sd_bus_message_open_container(reply
, 'a', "(ssssssouso)");
874 HASHMAP_FOREACH_KEY(u
, k
, m
->units
, i
) {
875 _cleanup_free_
char *unit_path
= NULL
, *job_path
= NULL
;
881 following
= unit_following(u
);
883 if (!strv_isempty(states
) &&
884 !strv_contains(states
, unit_load_state_to_string(u
->load_state
)) &&
885 !strv_contains(states
, unit_active_state_to_string(unit_active_state(u
))) &&
886 !strv_contains(states
, unit_sub_state_to_string(u
)))
889 unit_path
= unit_dbus_path(u
);
894 job_path
= job_dbus_path(u
->job
);
899 r
= sd_bus_message_append(
900 reply
, "(ssssssouso)",
903 unit_load_state_to_string(u
->load_state
),
904 unit_active_state_to_string(unit_active_state(u
)),
905 unit_sub_state_to_string(u
),
906 following
? following
->id
: "",
908 u
->job
? u
->job
->id
: 0,
909 u
->job
? job_type_to_string(u
->job
->type
) : "",
910 job_path
? job_path
: "/");
915 r
= sd_bus_message_close_container(reply
);
919 return sd_bus_send(NULL
, reply
, NULL
);
922 static int method_list_units(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
923 return list_units_filtered(message
, userdata
, error
, NULL
);
926 static int method_list_units_filtered(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
927 _cleanup_strv_free_
char **states
= NULL
;
930 r
= sd_bus_message_read_strv(message
, &states
);
934 return list_units_filtered(message
, userdata
, error
, states
);
937 static int method_list_jobs(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
938 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
939 Manager
*m
= userdata
;
947 /* Anyone can call this method */
949 r
= mac_selinux_access_check(message
, "status", error
);
953 r
= sd_bus_message_new_method_return(message
, &reply
);
957 r
= sd_bus_message_open_container(reply
, 'a', "(usssoo)");
961 HASHMAP_FOREACH(j
, m
->jobs
, i
) {
962 _cleanup_free_
char *unit_path
= NULL
, *job_path
= NULL
;
964 job_path
= job_dbus_path(j
);
968 unit_path
= unit_dbus_path(j
->unit
);
972 r
= sd_bus_message_append(
976 job_type_to_string(j
->type
),
977 job_state_to_string(j
->state
),
984 r
= sd_bus_message_close_container(reply
);
988 return sd_bus_send(NULL
, reply
, NULL
);
991 static int method_subscribe(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
992 Manager
*m
= userdata
;
998 /* Anyone can call this method */
1000 r
= mac_selinux_access_check(message
, "status", error
);
1004 if (sd_bus_message_get_bus(message
) == m
->api_bus
) {
1006 /* Note that direct bus connection subscribe by
1007 * default, we only track peers on the API bus here */
1009 if (!m
->subscribed
) {
1010 r
= sd_bus_track_new(sd_bus_message_get_bus(message
), &m
->subscribed
, NULL
, NULL
);
1015 r
= sd_bus_track_add_sender(m
->subscribed
, message
);
1019 return sd_bus_error_setf(error
, BUS_ERROR_ALREADY_SUBSCRIBED
, "Client is already subscribed.");
1022 return sd_bus_reply_method_return(message
, NULL
);
1025 static int method_unsubscribe(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1026 Manager
*m
= userdata
;
1032 /* Anyone can call this method */
1034 r
= mac_selinux_access_check(message
, "status", error
);
1038 if (sd_bus_message_get_bus(message
) == m
->api_bus
) {
1039 r
= sd_bus_track_remove_sender(m
->subscribed
, message
);
1043 return sd_bus_error_setf(error
, BUS_ERROR_NOT_SUBSCRIBED
, "Client is not subscribed.");
1046 return sd_bus_reply_method_return(message
, NULL
);
1049 static int method_dump(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1050 _cleanup_free_
char *dump
= NULL
;
1051 _cleanup_fclose_
FILE *f
= NULL
;
1052 Manager
*m
= userdata
;
1059 /* Anyone can call this method */
1061 r
= mac_selinux_access_check(message
, "status", error
);
1065 f
= open_memstream(&dump
, &size
);
1069 manager_dump_units(m
, f
, NULL
);
1070 manager_dump_jobs(m
, f
, NULL
);
1072 r
= fflush_and_check(f
);
1076 return sd_bus_reply_method_return(message
, "s", dump
);
1079 static int method_create_snapshot(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1080 _cleanup_free_
char *path
= NULL
;
1081 Manager
*m
= userdata
;
1090 r
= mac_selinux_access_check(message
, "start", error
);
1094 r
= sd_bus_message_read(message
, "sb", &name
, &cleanup
);
1101 r
= bus_verify_manage_units_async(m
, message
, error
);
1105 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1107 r
= snapshot_create(m
, name
, cleanup
, error
, &s
);
1111 path
= unit_dbus_path(UNIT(s
));
1115 return sd_bus_reply_method_return(message
, "o", path
);
1118 static int method_remove_snapshot(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1119 Manager
*m
= userdata
;
1127 r
= sd_bus_message_read(message
, "s", &name
);
1131 u
= manager_get_unit(m
, name
);
1133 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_UNIT
, "Unit %s does not exist.", name
);
1135 if (u
->type
!= UNIT_SNAPSHOT
)
1136 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_UNIT
, "Unit %s is not a snapshot", name
);
1138 return bus_snapshot_method_remove(message
, u
, error
);
1141 static int method_reload(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1142 Manager
*m
= userdata
;
1148 r
= mac_selinux_access_check(message
, "reload", error
);
1152 r
= bus_verify_reload_daemon_async(m
, message
, error
);
1156 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1158 /* Instead of sending the reply back right away, we just
1159 * remember that we need to and then send it after the reload
1160 * is finished. That way the caller knows when the reload
1163 assert(!m
->queued_message
);
1164 r
= sd_bus_message_new_method_return(message
, &m
->queued_message
);
1168 m
->exit_code
= MANAGER_RELOAD
;
1173 static int method_reexecute(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1174 Manager
*m
= userdata
;
1180 r
= mac_selinux_access_check(message
, "reload", error
);
1184 r
= bus_verify_reload_daemon_async(m
, message
, error
);
1188 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1190 /* We don't send a reply back here, the client should
1191 * just wait for us disconnecting. */
1193 m
->exit_code
= MANAGER_REEXECUTE
;
1197 static int method_exit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1198 Manager
*m
= userdata
;
1204 r
= mac_selinux_access_check(message
, "halt", error
);
1208 if (m
->running_as
== MANAGER_SYSTEM
)
1209 return sd_bus_error_setf(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Exit is only supported for user service managers.");
1211 m
->exit_code
= MANAGER_EXIT
;
1213 return sd_bus_reply_method_return(message
, NULL
);
1216 static int method_reboot(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1217 Manager
*m
= userdata
;
1223 r
= mac_selinux_access_check(message
, "reboot", error
);
1227 if (m
->running_as
!= MANAGER_SYSTEM
)
1228 return sd_bus_error_setf(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Reboot is only supported for system managers.");
1230 m
->exit_code
= MANAGER_REBOOT
;
1232 return sd_bus_reply_method_return(message
, NULL
);
1235 static int method_poweroff(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1236 Manager
*m
= userdata
;
1242 r
= mac_selinux_access_check(message
, "halt", error
);
1246 if (m
->running_as
!= MANAGER_SYSTEM
)
1247 return sd_bus_error_setf(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Powering off is only supported for system managers.");
1249 m
->exit_code
= MANAGER_POWEROFF
;
1251 return sd_bus_reply_method_return(message
, NULL
);
1254 static int method_halt(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1255 Manager
*m
= userdata
;
1261 r
= mac_selinux_access_check(message
, "halt", error
);
1265 if (m
->running_as
!= MANAGER_SYSTEM
)
1266 return sd_bus_error_setf(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Halt is only supported for system managers.");
1268 m
->exit_code
= MANAGER_HALT
;
1270 return sd_bus_reply_method_return(message
, NULL
);
1273 static int method_kexec(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1274 Manager
*m
= userdata
;
1280 r
= mac_selinux_access_check(message
, "reboot", error
);
1284 if (m
->running_as
!= MANAGER_SYSTEM
)
1285 return sd_bus_error_setf(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "KExec is only supported for system managers.");
1287 m
->exit_code
= MANAGER_KEXEC
;
1289 return sd_bus_reply_method_return(message
, NULL
);
1292 static int method_switch_root(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1293 char *ri
= NULL
, *rt
= NULL
;
1294 const char *root
, *init
;
1295 Manager
*m
= userdata
;
1301 r
= mac_selinux_access_check(message
, "reboot", error
);
1305 if (m
->running_as
!= MANAGER_SYSTEM
)
1306 return sd_bus_error_setf(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Root switching is only supported by system manager.");
1308 r
= sd_bus_message_read(message
, "ss", &root
, &init
);
1312 if (path_equal(root
, "/") || !path_is_absolute(root
))
1313 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid switch root path %s", root
);
1316 if (isempty(init
)) {
1317 if (!path_is_os_tree(root
))
1318 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Specified switch root path %s does not seem to be an OS tree. os-release file is missing.", root
);
1320 _cleanup_free_
char *p
= NULL
;
1322 if (!path_is_absolute(init
))
1323 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid init path %s", init
);
1325 p
= strappend(root
, init
);
1329 if (access(p
, X_OK
) < 0)
1330 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Specified init binary %s does not exist.", p
);
1337 if (!isempty(init
)) {
1345 free(m
->switch_root
);
1346 m
->switch_root
= rt
;
1348 free(m
->switch_root_init
);
1349 m
->switch_root_init
= ri
;
1351 m
->exit_code
= MANAGER_SWITCH_ROOT
;
1353 return sd_bus_reply_method_return(message
, NULL
);
1356 static int method_set_environment(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1357 _cleanup_strv_free_
char **plus
= NULL
;
1358 Manager
*m
= userdata
;
1364 r
= mac_selinux_access_check(message
, "reload", error
);
1368 r
= sd_bus_message_read_strv(message
, &plus
);
1371 if (!strv_env_is_valid(plus
))
1372 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid environment assignments");
1374 r
= bus_verify_set_environment_async(m
, message
, error
);
1378 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1380 r
= manager_environment_add(m
, NULL
, plus
);
1384 return sd_bus_reply_method_return(message
, NULL
);
1387 static int method_unset_environment(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1388 _cleanup_strv_free_
char **minus
= NULL
;
1389 Manager
*m
= userdata
;
1395 r
= mac_selinux_access_check(message
, "reload", error
);
1399 r
= sd_bus_message_read_strv(message
, &minus
);
1403 if (!strv_env_name_or_assignment_is_valid(minus
))
1404 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid environment variable names or assignments");
1406 r
= bus_verify_set_environment_async(m
, message
, error
);
1410 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1412 r
= manager_environment_add(m
, minus
, NULL
);
1416 return sd_bus_reply_method_return(message
, NULL
);
1419 static int method_unset_and_set_environment(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1420 _cleanup_strv_free_
char **minus
= NULL
, **plus
= NULL
;
1421 Manager
*m
= userdata
;
1427 r
= mac_selinux_access_check(message
, "reload", error
);
1431 r
= sd_bus_message_read_strv(message
, &minus
);
1435 r
= sd_bus_message_read_strv(message
, &plus
);
1439 if (!strv_env_name_or_assignment_is_valid(minus
))
1440 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid environment variable names or assignments");
1441 if (!strv_env_is_valid(plus
))
1442 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid environment assignments");
1444 r
= bus_verify_set_environment_async(m
, message
, error
);
1448 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1450 r
= manager_environment_add(m
, minus
, plus
);
1454 return sd_bus_reply_method_return(message
, NULL
);
1457 static int method_list_unit_files(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1458 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1459 Manager
*m
= userdata
;
1468 /* Anyone can call this method */
1470 r
= mac_selinux_access_check(message
, "status", error
);
1474 r
= sd_bus_message_new_method_return(message
, &reply
);
1478 h
= hashmap_new(&string_hash_ops
);
1482 r
= unit_file_get_list(m
->running_as
== MANAGER_SYSTEM
? UNIT_FILE_SYSTEM
: UNIT_FILE_USER
, NULL
, h
);
1486 r
= sd_bus_message_open_container(reply
, 'a', "(ss)");
1490 HASHMAP_FOREACH(item
, h
, i
) {
1492 r
= sd_bus_message_append(reply
, "(ss)", item
->path
, unit_file_state_to_string(item
->state
));
1497 unit_file_list_free(h
);
1499 r
= sd_bus_message_close_container(reply
);
1503 return sd_bus_send(NULL
, reply
, NULL
);
1506 unit_file_list_free(h
);
1510 static int method_get_unit_file_state(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1511 Manager
*m
= userdata
;
1513 UnitFileState state
;
1514 UnitFileScope scope
;
1520 /* Anyone can call this method */
1522 r
= mac_selinux_access_check(message
, "status", error
);
1526 r
= sd_bus_message_read(message
, "s", &name
);
1530 scope
= m
->running_as
== MANAGER_SYSTEM
? UNIT_FILE_SYSTEM
: UNIT_FILE_USER
;
1532 state
= unit_file_get_state(scope
, NULL
, name
);
1536 return sd_bus_reply_method_return(message
, "s", unit_file_state_to_string(state
));
1539 static int method_get_default_target(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1540 _cleanup_free_
char *default_target
= NULL
;
1541 Manager
*m
= userdata
;
1542 UnitFileScope scope
;
1548 /* Anyone can call this method */
1550 r
= mac_selinux_access_check(message
, "status", error
);
1554 scope
= m
->running_as
== MANAGER_SYSTEM
? UNIT_FILE_SYSTEM
: UNIT_FILE_USER
;
1556 r
= unit_file_get_default(scope
, NULL
, &default_target
);
1560 return sd_bus_reply_method_return(message
, "s", default_target
);
1563 static int send_unit_files_changed(sd_bus
*bus
, void *userdata
) {
1564 _cleanup_bus_message_unref_ sd_bus_message
*message
= NULL
;
1569 r
= sd_bus_message_new_signal(bus
, &message
, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged");
1573 return sd_bus_send(bus
, message
, NULL
);
1576 static int reply_unit_file_changes_and_free(
1578 sd_bus_message
*message
,
1579 int carries_install_info
,
1580 UnitFileChange
*changes
,
1581 unsigned n_changes
) {
1583 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1587 if (n_changes
> 0) {
1588 r
= bus_foreach_bus(m
, NULL
, send_unit_files_changed
, NULL
);
1590 log_debug_errno(r
, "Failed to send UnitFilesChanged signal: %m");
1593 r
= sd_bus_message_new_method_return(message
, &reply
);
1597 if (carries_install_info
>= 0) {
1598 r
= sd_bus_message_append(reply
, "b", carries_install_info
);
1603 r
= sd_bus_message_open_container(reply
, 'a', "(sss)");
1607 for (i
= 0; i
< n_changes
; i
++) {
1608 r
= sd_bus_message_append(
1610 unit_file_change_type_to_string(changes
[i
].type
),
1617 r
= sd_bus_message_close_container(reply
);
1621 return sd_bus_send(NULL
, reply
, NULL
);
1624 unit_file_changes_free(changes
, n_changes
);
1628 static int method_enable_unit_files_generic(
1629 sd_bus_message
*message
,
1632 int (*call
)(UnitFileScope scope
, bool runtime
, const char *root_dir
, char *files
[], bool force
, UnitFileChange
**changes
, unsigned *n_changes
),
1633 bool carries_install_info
,
1634 sd_bus_error
*error
) {
1636 _cleanup_strv_free_
char **l
= NULL
;
1637 UnitFileChange
*changes
= NULL
;
1638 unsigned n_changes
= 0;
1639 UnitFileScope scope
;
1640 int runtime
, force
, r
;
1645 r
= sd_bus_message_read_strv(message
, &l
);
1649 r
= sd_bus_message_read(message
, "bb", &runtime
, &force
);
1653 r
= mac_selinux_unit_access_check_strv(l
, message
, m
, verb
, error
);
1657 r
= bus_verify_manage_unit_files_async(m
, message
, error
);
1661 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1663 scope
= m
->running_as
== MANAGER_SYSTEM
? UNIT_FILE_SYSTEM
: UNIT_FILE_USER
;
1665 r
= call(scope
, runtime
, NULL
, l
, force
, &changes
, &n_changes
);
1669 return reply_unit_file_changes_and_free(m
, message
, carries_install_info
? r
: -1, changes
, n_changes
);
1672 static int method_enable_unit_files(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1673 return method_enable_unit_files_generic(message
, userdata
, "enable", unit_file_enable
, true, error
);
1676 static int method_reenable_unit_files(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1677 return method_enable_unit_files_generic(message
, userdata
, "enable", unit_file_reenable
, true, error
);
1680 static int method_link_unit_files(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1681 return method_enable_unit_files_generic(message
, userdata
, "enable", unit_file_link
, false, error
);
1684 static int unit_file_preset_without_mode(UnitFileScope scope
, bool runtime
, const char *root_dir
, char **files
, bool force
, UnitFileChange
**changes
, unsigned *n_changes
) {
1685 return unit_file_preset(scope
, runtime
, root_dir
, files
, UNIT_FILE_PRESET_FULL
, force
, changes
, n_changes
);
1688 static int method_preset_unit_files(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1689 return method_enable_unit_files_generic(message
, userdata
, "enable", unit_file_preset_without_mode
, true, error
);
1692 static int method_mask_unit_files(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1693 return method_enable_unit_files_generic(message
, userdata
, "disable", unit_file_mask
, false, error
);
1696 static int method_preset_unit_files_with_mode(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1698 _cleanup_strv_free_
char **l
= NULL
;
1699 UnitFileChange
*changes
= NULL
;
1700 unsigned n_changes
= 0;
1701 Manager
*m
= userdata
;
1702 UnitFilePresetMode mm
;
1703 UnitFileScope scope
;
1704 int runtime
, force
, r
;
1710 r
= sd_bus_message_read_strv(message
, &l
);
1714 r
= sd_bus_message_read(message
, "sbb", &mode
, &runtime
, &force
);
1719 mm
= UNIT_FILE_PRESET_FULL
;
1721 mm
= unit_file_preset_mode_from_string(mode
);
1726 r
= mac_selinux_unit_access_check_strv(l
, message
, m
, "enable", error
);
1730 r
= bus_verify_manage_unit_files_async(m
, message
, error
);
1734 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1736 scope
= m
->running_as
== MANAGER_SYSTEM
? UNIT_FILE_SYSTEM
: UNIT_FILE_USER
;
1738 r
= unit_file_preset(scope
, runtime
, NULL
, l
, mm
, force
, &changes
, &n_changes
);
1742 return reply_unit_file_changes_and_free(m
, message
, r
, changes
, n_changes
);
1745 static int method_disable_unit_files_generic(
1746 sd_bus_message
*message
,
1749 int (*call
)(UnitFileScope scope
, bool runtime
, const char *root_dir
, char *files
[], UnitFileChange
**changes
, unsigned *n_changes
),
1750 sd_bus_error
*error
) {
1752 _cleanup_strv_free_
char **l
= NULL
;
1753 UnitFileChange
*changes
= NULL
;
1754 unsigned n_changes
= 0;
1755 UnitFileScope scope
;
1761 r
= sd_bus_message_read_strv(message
, &l
);
1765 r
= sd_bus_message_read(message
, "b", &runtime
);
1769 r
= mac_selinux_unit_access_check_strv(l
, message
, m
, verb
, error
);
1773 scope
= m
->running_as
== MANAGER_SYSTEM
? UNIT_FILE_SYSTEM
: UNIT_FILE_USER
;
1775 r
= bus_verify_manage_unit_files_async(m
, message
, error
);
1779 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1781 r
= call(scope
, runtime
, NULL
, l
, &changes
, &n_changes
);
1785 return reply_unit_file_changes_and_free(m
, message
, -1, changes
, n_changes
);
1788 static int method_disable_unit_files(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1789 return method_disable_unit_files_generic(message
, userdata
, "disable", unit_file_disable
, error
);
1792 static int method_unmask_unit_files(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1793 return method_disable_unit_files_generic(message
, userdata
, "enable", unit_file_unmask
, error
);
1796 static int method_set_default_target(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1797 UnitFileChange
*changes
= NULL
;
1798 unsigned n_changes
= 0;
1799 Manager
*m
= userdata
;
1800 UnitFileScope scope
;
1807 r
= mac_selinux_access_check(message
, "enable", error
);
1811 r
= sd_bus_message_read(message
, "sb", &name
, &force
);
1815 r
= bus_verify_manage_unit_files_async(m
, message
, error
);
1819 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1821 scope
= m
->running_as
== MANAGER_SYSTEM
? UNIT_FILE_SYSTEM
: UNIT_FILE_USER
;
1823 r
= unit_file_set_default(scope
, NULL
, name
, force
, &changes
, &n_changes
);
1827 return reply_unit_file_changes_and_free(m
, message
, -1, changes
, n_changes
);
1830 static int method_preset_all_unit_files(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1831 UnitFileChange
*changes
= NULL
;
1832 unsigned n_changes
= 0;
1833 Manager
*m
= userdata
;
1834 UnitFilePresetMode mm
;
1835 UnitFileScope scope
;
1837 int force
, runtime
, r
;
1842 r
= mac_selinux_access_check(message
, "enable", error
);
1846 r
= sd_bus_message_read(message
, "sbb", &mode
, &runtime
, &force
);
1851 mm
= UNIT_FILE_PRESET_FULL
;
1853 mm
= unit_file_preset_mode_from_string(mode
);
1858 r
= bus_verify_manage_unit_files_async(m
, message
, error
);
1862 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1864 scope
= m
->running_as
== MANAGER_SYSTEM
? UNIT_FILE_SYSTEM
: UNIT_FILE_USER
;
1866 r
= unit_file_preset_all(scope
, runtime
, NULL
, mm
, force
, &changes
, &n_changes
);
1870 return reply_unit_file_changes_and_free(m
, message
, -1, changes
, n_changes
);
1873 static int method_add_dependency_unit_files(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1874 _cleanup_strv_free_
char **l
= NULL
;
1875 Manager
*m
= userdata
;
1876 UnitFileChange
*changes
= NULL
;
1877 unsigned n_changes
= 0;
1878 UnitFileScope scope
;
1879 int runtime
, force
, r
;
1887 r
= bus_verify_manage_unit_files_async(m
, message
, error
);
1891 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1893 r
= sd_bus_message_read_strv(message
, &l
);
1897 r
= sd_bus_message_read(message
, "ssbb", &target
, &type
, &runtime
, &force
);
1901 dep
= unit_dependency_from_string(type
);
1905 r
= mac_selinux_unit_access_check_strv(l
, message
, m
, "enable", error
);
1909 scope
= m
->running_as
== MANAGER_SYSTEM
? UNIT_FILE_SYSTEM
: UNIT_FILE_USER
;
1911 r
= unit_file_add_dependency(scope
, runtime
, NULL
, l
, target
, dep
, force
, &changes
, &n_changes
);
1915 return reply_unit_file_changes_and_free(m
, message
, -1, changes
, n_changes
);
1918 const sd_bus_vtable bus_manager_vtable
[] = {
1919 SD_BUS_VTABLE_START(0),
1921 SD_BUS_PROPERTY("Version", "s", property_get_version
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1922 SD_BUS_PROPERTY("Features", "s", property_get_features
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1923 SD_BUS_PROPERTY("Virtualization", "s", property_get_virtualization
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1924 SD_BUS_PROPERTY("Architecture", "s", property_get_architecture
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1925 SD_BUS_PROPERTY("Tainted", "s", property_get_tainted
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1926 BUS_PROPERTY_DUAL_TIMESTAMP("FirmwareTimestamp", offsetof(Manager
, firmware_timestamp
), SD_BUS_VTABLE_PROPERTY_CONST
),
1927 BUS_PROPERTY_DUAL_TIMESTAMP("LoaderTimestamp", offsetof(Manager
, loader_timestamp
), SD_BUS_VTABLE_PROPERTY_CONST
),
1928 BUS_PROPERTY_DUAL_TIMESTAMP("KernelTimestamp", offsetof(Manager
, kernel_timestamp
), SD_BUS_VTABLE_PROPERTY_CONST
),
1929 BUS_PROPERTY_DUAL_TIMESTAMP("InitRDTimestamp", offsetof(Manager
, initrd_timestamp
), SD_BUS_VTABLE_PROPERTY_CONST
),
1930 BUS_PROPERTY_DUAL_TIMESTAMP("UserspaceTimestamp", offsetof(Manager
, userspace_timestamp
), SD_BUS_VTABLE_PROPERTY_CONST
),
1931 BUS_PROPERTY_DUAL_TIMESTAMP("FinishTimestamp", offsetof(Manager
, finish_timestamp
), SD_BUS_VTABLE_PROPERTY_CONST
),
1932 BUS_PROPERTY_DUAL_TIMESTAMP("SecurityStartTimestamp", offsetof(Manager
, security_start_timestamp
), SD_BUS_VTABLE_PROPERTY_CONST
),
1933 BUS_PROPERTY_DUAL_TIMESTAMP("SecurityFinishTimestamp", offsetof(Manager
, security_finish_timestamp
), SD_BUS_VTABLE_PROPERTY_CONST
),
1934 BUS_PROPERTY_DUAL_TIMESTAMP("GeneratorsStartTimestamp", offsetof(Manager
, generators_start_timestamp
), SD_BUS_VTABLE_PROPERTY_CONST
),
1935 BUS_PROPERTY_DUAL_TIMESTAMP("GeneratorsFinishTimestamp", offsetof(Manager
, generators_finish_timestamp
), SD_BUS_VTABLE_PROPERTY_CONST
),
1936 BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadStartTimestamp", offsetof(Manager
, units_load_start_timestamp
), SD_BUS_VTABLE_PROPERTY_CONST
),
1937 BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadFinishTimestamp", offsetof(Manager
, units_load_finish_timestamp
), SD_BUS_VTABLE_PROPERTY_CONST
),
1938 SD_BUS_WRITABLE_PROPERTY("LogLevel", "s", property_get_log_level
, property_set_log_level
, 0, 0),
1939 SD_BUS_WRITABLE_PROPERTY("LogTarget", "s", property_get_log_target
, property_set_log_target
, 0, 0),
1940 SD_BUS_PROPERTY("NNames", "u", property_get_n_names
, 0, 0),
1941 SD_BUS_PROPERTY("NFailedUnits", "u", property_get_n_failed_units
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
1942 SD_BUS_PROPERTY("NJobs", "u", property_get_n_jobs
, 0, 0),
1943 SD_BUS_PROPERTY("NInstalledJobs", "u", bus_property_get_unsigned
, offsetof(Manager
, n_installed_jobs
), 0),
1944 SD_BUS_PROPERTY("NFailedJobs", "u", bus_property_get_unsigned
, offsetof(Manager
, n_failed_jobs
), 0),
1945 SD_BUS_PROPERTY("Progress", "d", property_get_progress
, 0, 0),
1946 SD_BUS_PROPERTY("Environment", "as", NULL
, offsetof(Manager
, environment
), 0),
1947 SD_BUS_PROPERTY("ConfirmSpawn", "b", bus_property_get_bool
, offsetof(Manager
, confirm_spawn
), SD_BUS_VTABLE_PROPERTY_CONST
),
1948 SD_BUS_PROPERTY("ShowStatus", "b", bus_property_get_bool
, offsetof(Manager
, show_status
), SD_BUS_VTABLE_PROPERTY_CONST
),
1949 SD_BUS_PROPERTY("UnitPath", "as", NULL
, offsetof(Manager
, lookup_paths
.unit_path
), SD_BUS_VTABLE_PROPERTY_CONST
),
1950 SD_BUS_PROPERTY("DefaultStandardOutput", "s", bus_property_get_exec_output
, offsetof(Manager
, default_std_output
), SD_BUS_VTABLE_PROPERTY_CONST
),
1951 SD_BUS_PROPERTY("DefaultStandardError", "s", bus_property_get_exec_output
, offsetof(Manager
, default_std_output
), SD_BUS_VTABLE_PROPERTY_CONST
),
1952 SD_BUS_WRITABLE_PROPERTY("RuntimeWatchdogUSec", "t", bus_property_get_usec
, property_set_runtime_watchdog
, offsetof(Manager
, runtime_watchdog
), 0),
1953 SD_BUS_WRITABLE_PROPERTY("ShutdownWatchdogUSec", "t", bus_property_get_usec
, bus_property_set_usec
, offsetof(Manager
, shutdown_watchdog
), 0),
1954 SD_BUS_PROPERTY("ControlGroup", "s", NULL
, offsetof(Manager
, cgroup_root
), 0),
1955 SD_BUS_PROPERTY("SystemState", "s", property_get_system_state
, 0, 0),
1957 SD_BUS_METHOD("GetUnit", "s", "o", method_get_unit
, SD_BUS_VTABLE_UNPRIVILEGED
),
1958 SD_BUS_METHOD("GetUnitByPID", "u", "o", method_get_unit_by_pid
, SD_BUS_VTABLE_UNPRIVILEGED
),
1959 SD_BUS_METHOD("LoadUnit", "s", "o", method_load_unit
, SD_BUS_VTABLE_UNPRIVILEGED
),
1960 SD_BUS_METHOD("StartUnit", "ss", "o", method_start_unit
, SD_BUS_VTABLE_UNPRIVILEGED
),
1961 SD_BUS_METHOD("StartUnitReplace", "sss", "o", method_start_unit_replace
, SD_BUS_VTABLE_UNPRIVILEGED
),
1962 SD_BUS_METHOD("StopUnit", "ss", "o", method_stop_unit
, SD_BUS_VTABLE_UNPRIVILEGED
),
1963 SD_BUS_METHOD("ReloadUnit", "ss", "o", method_reload_unit
, SD_BUS_VTABLE_UNPRIVILEGED
),
1964 SD_BUS_METHOD("RestartUnit", "ss", "o", method_restart_unit
, SD_BUS_VTABLE_UNPRIVILEGED
),
1965 SD_BUS_METHOD("TryRestartUnit", "ss", "o", method_try_restart_unit
, SD_BUS_VTABLE_UNPRIVILEGED
),
1966 SD_BUS_METHOD("ReloadOrRestartUnit", "ss", "o", method_reload_or_restart_unit
, SD_BUS_VTABLE_UNPRIVILEGED
),
1967 SD_BUS_METHOD("ReloadOrTryRestartUnit", "ss", "o", method_reload_or_try_restart_unit
, SD_BUS_VTABLE_UNPRIVILEGED
),
1968 SD_BUS_METHOD("KillUnit", "ssi", NULL
, method_kill_unit
, SD_BUS_VTABLE_UNPRIVILEGED
),
1969 SD_BUS_METHOD("ResetFailedUnit", "s", NULL
, method_reset_failed_unit
, SD_BUS_VTABLE_UNPRIVILEGED
),
1970 SD_BUS_METHOD("SetUnitProperties", "sba(sv)", NULL
, method_set_unit_properties
, SD_BUS_VTABLE_UNPRIVILEGED
),
1971 SD_BUS_METHOD("StartTransientUnit", "ssa(sv)a(sa(sv))", "o", method_start_transient_unit
, SD_BUS_VTABLE_UNPRIVILEGED
),
1972 SD_BUS_METHOD("GetJob", "u", "o", method_get_job
, SD_BUS_VTABLE_UNPRIVILEGED
),
1973 SD_BUS_METHOD("CancelJob", "u", NULL
, method_cancel_job
, SD_BUS_VTABLE_UNPRIVILEGED
),
1974 SD_BUS_METHOD("ClearJobs", NULL
, NULL
, method_clear_jobs
, SD_BUS_VTABLE_UNPRIVILEGED
),
1975 SD_BUS_METHOD("ResetFailed", NULL
, NULL
, method_reset_failed
, SD_BUS_VTABLE_UNPRIVILEGED
),
1976 SD_BUS_METHOD("ListUnits", NULL
, "a(ssssssouso)", method_list_units
, SD_BUS_VTABLE_UNPRIVILEGED
),
1977 SD_BUS_METHOD("ListUnitsFiltered", "as", "a(ssssssouso)", method_list_units_filtered
, SD_BUS_VTABLE_UNPRIVILEGED
),
1978 SD_BUS_METHOD("ListJobs", NULL
, "a(usssoo)", method_list_jobs
, SD_BUS_VTABLE_UNPRIVILEGED
),
1979 SD_BUS_METHOD("Subscribe", NULL
, NULL
, method_subscribe
, SD_BUS_VTABLE_UNPRIVILEGED
),
1980 SD_BUS_METHOD("Unsubscribe", NULL
, NULL
, method_unsubscribe
, SD_BUS_VTABLE_UNPRIVILEGED
),
1981 SD_BUS_METHOD("Dump", NULL
, "s", method_dump
, SD_BUS_VTABLE_UNPRIVILEGED
),
1982 SD_BUS_METHOD("CreateSnapshot", "sb", "o", method_create_snapshot
, SD_BUS_VTABLE_UNPRIVILEGED
),
1983 SD_BUS_METHOD("RemoveSnapshot", "s", NULL
, method_remove_snapshot
, SD_BUS_VTABLE_UNPRIVILEGED
),
1984 SD_BUS_METHOD("Reload", NULL
, NULL
, method_reload
, SD_BUS_VTABLE_UNPRIVILEGED
),
1985 SD_BUS_METHOD("Reexecute", NULL
, NULL
, method_reexecute
, SD_BUS_VTABLE_UNPRIVILEGED
),
1986 SD_BUS_METHOD("Exit", NULL
, NULL
, method_exit
, 0),
1987 SD_BUS_METHOD("Reboot", NULL
, NULL
, method_reboot
, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT
)),
1988 SD_BUS_METHOD("PowerOff", NULL
, NULL
, method_poweroff
, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT
)),
1989 SD_BUS_METHOD("Halt", NULL
, NULL
, method_halt
, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT
)),
1990 SD_BUS_METHOD("KExec", NULL
, NULL
, method_kexec
, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT
)),
1991 SD_BUS_METHOD("SwitchRoot", "ss", NULL
, method_switch_root
, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT
)),
1992 SD_BUS_METHOD("SetEnvironment", "as", NULL
, method_set_environment
, SD_BUS_VTABLE_UNPRIVILEGED
),
1993 SD_BUS_METHOD("UnsetEnvironment", "as", NULL
, method_unset_environment
, SD_BUS_VTABLE_UNPRIVILEGED
),
1994 SD_BUS_METHOD("UnsetAndSetEnvironment", "asas", NULL
, method_unset_and_set_environment
, SD_BUS_VTABLE_UNPRIVILEGED
),
1995 SD_BUS_METHOD("ListUnitFiles", NULL
, "a(ss)", method_list_unit_files
, SD_BUS_VTABLE_UNPRIVILEGED
),
1996 SD_BUS_METHOD("GetUnitFileState", "s", "s", method_get_unit_file_state
, SD_BUS_VTABLE_UNPRIVILEGED
),
1997 SD_BUS_METHOD("EnableUnitFiles", "asbb", "ba(sss)", method_enable_unit_files
, SD_BUS_VTABLE_UNPRIVILEGED
),
1998 SD_BUS_METHOD("DisableUnitFiles", "asb", "a(sss)", method_disable_unit_files
, SD_BUS_VTABLE_UNPRIVILEGED
),
1999 SD_BUS_METHOD("ReenableUnitFiles", "asbb", "ba(sss)", method_reenable_unit_files
, SD_BUS_VTABLE_UNPRIVILEGED
),
2000 SD_BUS_METHOD("LinkUnitFiles", "asbb", "a(sss)", method_link_unit_files
, SD_BUS_VTABLE_UNPRIVILEGED
),
2001 SD_BUS_METHOD("PresetUnitFiles", "asbb", "ba(sss)", method_preset_unit_files
, SD_BUS_VTABLE_UNPRIVILEGED
),
2002 SD_BUS_METHOD("PresetUnitFilesWithMode", "assbb", "ba(sss)", method_preset_unit_files_with_mode
, SD_BUS_VTABLE_UNPRIVILEGED
),
2003 SD_BUS_METHOD("MaskUnitFiles", "asbb", "a(sss)", method_mask_unit_files
, SD_BUS_VTABLE_UNPRIVILEGED
),
2004 SD_BUS_METHOD("UnmaskUnitFiles", "asb", "a(sss)", method_unmask_unit_files
, SD_BUS_VTABLE_UNPRIVILEGED
),
2005 SD_BUS_METHOD("SetDefaultTarget", "sb", "a(sss)", method_set_default_target
, SD_BUS_VTABLE_UNPRIVILEGED
),
2006 SD_BUS_METHOD("GetDefaultTarget", NULL
, "s", method_get_default_target
, SD_BUS_VTABLE_UNPRIVILEGED
),
2007 SD_BUS_METHOD("PresetAllUnitFiles", "sbb", "a(sss)", method_preset_all_unit_files
, SD_BUS_VTABLE_UNPRIVILEGED
),
2008 SD_BUS_METHOD("AddDependencyUnitFiles", "asssbb", "a(sss)", method_add_dependency_unit_files
, SD_BUS_VTABLE_UNPRIVILEGED
),
2010 SD_BUS_SIGNAL("UnitNew", "so", 0),
2011 SD_BUS_SIGNAL("UnitRemoved", "so", 0),
2012 SD_BUS_SIGNAL("JobNew", "uos", 0),
2013 SD_BUS_SIGNAL("JobRemoved", "uoss", 0),
2014 SD_BUS_SIGNAL("StartupFinished", "tttttt", 0),
2015 SD_BUS_SIGNAL("UnitFilesChanged", NULL
, 0),
2016 SD_BUS_SIGNAL("Reloading", "b", 0),
2021 static int send_finished(sd_bus
*bus
, void *userdata
) {
2022 _cleanup_bus_message_unref_ sd_bus_message
*message
= NULL
;
2023 usec_t
*times
= userdata
;
2029 r
= sd_bus_message_new_signal(bus
, &message
, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished");
2033 r
= sd_bus_message_append(message
, "tttttt", times
[0], times
[1], times
[2], times
[3], times
[4], times
[5]);
2037 return sd_bus_send(bus
, message
, NULL
);
2040 void bus_manager_send_finished(
2042 usec_t firmware_usec
,
2046 usec_t userspace_usec
,
2047 usec_t total_usec
) {
2053 r
= bus_foreach_bus(
2066 log_debug_errno(r
, "Failed to send finished signal: %m");
2069 static int send_reloading(sd_bus
*bus
, void *userdata
) {
2070 _cleanup_bus_message_unref_ sd_bus_message
*message
= NULL
;
2075 r
= sd_bus_message_new_signal(bus
, &message
, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "Reloading");
2079 r
= sd_bus_message_append(message
, "b", PTR_TO_INT(userdata
));
2083 return sd_bus_send(bus
, message
, NULL
);
2086 void bus_manager_send_reloading(Manager
*m
, bool active
) {
2091 r
= bus_foreach_bus(m
, NULL
, send_reloading
, INT_TO_PTR(active
));
2093 log_debug_errno(r
, "Failed to send reloading signal: %m");
2096 static int send_changed_signal(sd_bus
*bus
, void *userdata
) {
2099 return sd_bus_emit_properties_changed_strv(bus
,
2100 "/org/freedesktop/systemd1",
2101 "org.freedesktop.systemd1.Manager",
2105 void bus_manager_send_change_signal(Manager
*m
) {
2110 r
= bus_foreach_bus(m
, NULL
, send_changed_signal
, NULL
);
2112 log_debug_errno(r
, "Failed to send manager change signal: %m");