]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dbus-manager.c
core: rename SystemdRunningAs to ManagerRunningAs
[thirdparty/systemd.git] / src / core / dbus-manager.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
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.
12
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.
17
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/>.
20 ***/
21
22 #include <errno.h>
23 #include <unistd.h>
24
25 #include "log.h"
26 #include "strv.h"
27 #include "build.h"
28 #include "install.h"
29 #include "selinux-access.h"
30 #include "watchdog.h"
31 #include "clock-util.h"
32 #include "path-util.h"
33 #include "virt.h"
34 #include "architecture.h"
35 #include "env-util.h"
36 #include "dbus.h"
37 #include "dbus-job.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"
44
45 static int property_get_version(
46 sd_bus *bus,
47 const char *path,
48 const char *interface,
49 const char *property,
50 sd_bus_message *reply,
51 void *userdata,
52 sd_bus_error *error) {
53
54 assert(bus);
55 assert(reply);
56
57 return sd_bus_message_append(reply, "s", PACKAGE_VERSION);
58 }
59
60 static int property_get_features(
61 sd_bus *bus,
62 const char *path,
63 const char *interface,
64 const char *property,
65 sd_bus_message *reply,
66 void *userdata,
67 sd_bus_error *error) {
68
69 assert(bus);
70 assert(reply);
71
72 return sd_bus_message_append(reply, "s", SYSTEMD_FEATURES);
73 }
74
75 static int property_get_virtualization(
76 sd_bus *bus,
77 const char *path,
78 const char *interface,
79 const char *property,
80 sd_bus_message *reply,
81 void *userdata,
82 sd_bus_error *error) {
83
84 const char *id = NULL;
85
86 assert(bus);
87 assert(reply);
88
89 detect_virtualization(&id);
90
91 return sd_bus_message_append(reply, "s", id);
92 }
93
94 static int property_get_architecture(
95 sd_bus *bus,
96 const char *path,
97 const char *interface,
98 const char *property,
99 sd_bus_message *reply,
100 void *userdata,
101 sd_bus_error *error) {
102
103 assert(bus);
104 assert(reply);
105
106 return sd_bus_message_append(reply, "s", architecture_to_string(uname_architecture()));
107 }
108
109 static int property_get_tainted(
110 sd_bus *bus,
111 const char *path,
112 const char *interface,
113 const char *property,
114 sd_bus_message *reply,
115 void *userdata,
116 sd_bus_error *error) {
117
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;
121
122 assert(bus);
123 assert(reply);
124 assert(m);
125
126 if (m->taint_usr)
127 e = stpcpy(e, "split-usr:");
128
129 if (readlink_malloc("/etc/mtab", &p) < 0)
130 e = stpcpy(e, "mtab-not-symlink:");
131
132 if (access("/proc/cgroups", F_OK) < 0)
133 e = stpcpy(e, "cgroups-missing:");
134
135 if (clock_is_localtime() > 0)
136 e = stpcpy(e, "local-hwclock:");
137
138 /* remove the last ':' */
139 if (e != buf)
140 e[-1] = 0;
141
142 return sd_bus_message_append(reply, "s", buf);
143 }
144
145 static int property_get_log_target(
146 sd_bus *bus,
147 const char *path,
148 const char *interface,
149 const char *property,
150 sd_bus_message *reply,
151 void *userdata,
152 sd_bus_error *error) {
153
154 assert(bus);
155 assert(reply);
156
157 return sd_bus_message_append(reply, "s", log_target_to_string(log_get_target()));
158 }
159
160 static int property_set_log_target(
161 sd_bus *bus,
162 const char *path,
163 const char *interface,
164 const char *property,
165 sd_bus_message *value,
166 void *userdata,
167 sd_bus_error *error) {
168
169 const char *t;
170 int r;
171
172 assert(bus);
173 assert(value);
174
175 r = sd_bus_message_read(value, "s", &t);
176 if (r < 0)
177 return r;
178
179 return log_set_target_from_string(t);
180 }
181
182 static int property_get_log_level(
183 sd_bus *bus,
184 const char *path,
185 const char *interface,
186 const char *property,
187 sd_bus_message *reply,
188 void *userdata,
189 sd_bus_error *error) {
190
191 _cleanup_free_ char *t = NULL;
192 int r;
193
194 assert(bus);
195 assert(reply);
196
197 r = log_level_to_string_alloc(log_get_max_level(), &t);
198 if (r < 0)
199 return r;
200
201 return sd_bus_message_append(reply, "s", t);
202 }
203
204 static int property_set_log_level(
205 sd_bus *bus,
206 const char *path,
207 const char *interface,
208 const char *property,
209 sd_bus_message *value,
210 void *userdata,
211 sd_bus_error *error) {
212
213 const char *t;
214 int r;
215
216 assert(bus);
217 assert(value);
218
219 r = sd_bus_message_read(value, "s", &t);
220 if (r < 0)
221 return r;
222
223 return log_set_max_level_from_string(t);
224 }
225
226 static int property_get_n_names(
227 sd_bus *bus,
228 const char *path,
229 const char *interface,
230 const char *property,
231 sd_bus_message *reply,
232 void *userdata,
233 sd_bus_error *error) {
234
235 Manager *m = userdata;
236
237 assert(bus);
238 assert(reply);
239 assert(m);
240
241 return sd_bus_message_append(reply, "u", (uint32_t) hashmap_size(m->units));
242 }
243
244 static int property_get_n_failed_units(
245 sd_bus *bus,
246 const char *path,
247 const char *interface,
248 const char *property,
249 sd_bus_message *reply,
250 void *userdata,
251 sd_bus_error *error) {
252
253 Manager *m = userdata;
254
255 assert(bus);
256 assert(reply);
257 assert(m);
258
259 return sd_bus_message_append(reply, "u", (uint32_t) set_size(m->failed_units));
260 }
261
262 static int property_get_n_jobs(
263 sd_bus *bus,
264 const char *path,
265 const char *interface,
266 const char *property,
267 sd_bus_message *reply,
268 void *userdata,
269 sd_bus_error *error) {
270
271 Manager *m = userdata;
272
273 assert(bus);
274 assert(reply);
275 assert(m);
276
277 return sd_bus_message_append(reply, "u", (uint32_t) hashmap_size(m->jobs));
278 }
279
280 static int property_get_progress(
281 sd_bus *bus,
282 const char *path,
283 const char *interface,
284 const char *property,
285 sd_bus_message *reply,
286 void *userdata,
287 sd_bus_error *error) {
288
289 Manager *m = userdata;
290 double d;
291
292 assert(bus);
293 assert(reply);
294 assert(m);
295
296 if (dual_timestamp_is_set(&m->finish_timestamp))
297 d = 1.0;
298 else
299 d = 1.0 - ((double) hashmap_size(m->jobs) / (double) m->n_installed_jobs);
300
301 return sd_bus_message_append(reply, "d", d);
302 }
303
304 static int property_get_system_state(
305 sd_bus *bus,
306 const char *path,
307 const char *interface,
308 const char *property,
309 sd_bus_message *reply,
310 void *userdata,
311 sd_bus_error *error) {
312
313 Manager *m = userdata;
314
315 assert(bus);
316 assert(reply);
317 assert(m);
318
319 return sd_bus_message_append(reply, "s", manager_state_to_string(manager_state(m)));
320 }
321
322 static int property_set_runtime_watchdog(
323 sd_bus *bus,
324 const char *path,
325 const char *interface,
326 const char *property,
327 sd_bus_message *value,
328 void *userdata,
329 sd_bus_error *error) {
330
331 usec_t *t = userdata;
332 int r;
333
334 assert(bus);
335 assert(value);
336
337 assert_cc(sizeof(usec_t) == sizeof(uint64_t));
338
339 r = sd_bus_message_read(value, "t", t);
340 if (r < 0)
341 return r;
342
343 return watchdog_set_timeout(t);
344 }
345
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;
349 const char *name;
350 Unit *u;
351 int r;
352
353 assert(message);
354 assert(m);
355
356 /* Anyone can call this method */
357
358 r = sd_bus_message_read(message, "s", &name);
359 if (r < 0)
360 return r;
361
362 if (isempty(name)) {
363 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
364 pid_t pid;
365
366 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
367 if (r < 0)
368 return r;
369
370 r = sd_bus_creds_get_pid(creds, &pid);
371 if (r < 0)
372 return r;
373
374 u = manager_get_unit_by_pid(m, pid);
375 if (!u)
376 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Client not member of any unit.");
377 } else {
378 u = manager_get_unit(m, name);
379 if (!u)
380 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", name);
381 }
382
383 r = mac_selinux_unit_access_check(u, message, "status", error);
384 if (r < 0)
385 return r;
386
387 path = unit_dbus_path(u);
388 if (!path)
389 return -ENOMEM;
390
391 return sd_bus_reply_method_return(message, "o", path);
392 }
393
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;
397 pid_t pid;
398 Unit *u;
399 int r;
400
401 assert(message);
402 assert(m);
403
404 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
405
406 /* Anyone can call this method */
407
408 r = sd_bus_message_read(message, "u", &pid);
409 if (r < 0)
410 return r;
411 if (pid < 0)
412 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid PID " PID_FMT, pid);
413
414 if (pid == 0) {
415 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
416
417 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
418 if (r < 0)
419 return r;
420
421 r = sd_bus_creds_get_pid(creds, &pid);
422 if (r < 0)
423 return r;
424 }
425
426 u = manager_get_unit_by_pid(m, pid);
427 if (!u)
428 return sd_bus_error_setf(error, BUS_ERROR_NO_UNIT_FOR_PID, "PID "PID_FMT" does not belong to any loaded unit.", pid);
429
430 r = mac_selinux_unit_access_check(u, message, "status", error);
431 if (r < 0)
432 return r;
433
434 path = unit_dbus_path(u);
435 if (!path)
436 return -ENOMEM;
437
438 return sd_bus_reply_method_return(message, "o", path);
439 }
440
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;
444 const char *name;
445 Unit *u;
446 int r;
447
448 assert(message);
449 assert(m);
450
451 /* Anyone can call this method */
452
453 r = sd_bus_message_read(message, "s", &name);
454 if (r < 0)
455 return r;
456
457 if (isempty(name)) {
458 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
459 pid_t pid;
460
461 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
462 if (r < 0)
463 return r;
464
465 r = sd_bus_creds_get_pid(creds, &pid);
466 if (r < 0)
467 return r;
468
469 u = manager_get_unit_by_pid(m, pid);
470 if (!u)
471 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Client not member of any unit.");
472 } else {
473 r = manager_load_unit(m, name, NULL, error, &u);
474 if (r < 0)
475 return r;
476 }
477
478 r = mac_selinux_unit_access_check(u, message, "status", error);
479 if (r < 0)
480 return r;
481
482 path = unit_dbus_path(u);
483 if (!path)
484 return -ENOMEM;
485
486 return sd_bus_reply_method_return(message, "o", path);
487 }
488
489 static int method_start_unit_generic(sd_bus_message *message, Manager *m, JobType job_type, bool reload_if_possible, sd_bus_error *error) {
490 const char *name;
491 Unit *u;
492 int r;
493
494 assert(message);
495 assert(m);
496
497 r = sd_bus_message_read(message, "s", &name);
498 if (r < 0)
499 return r;
500
501 r = manager_load_unit(m, name, NULL, error, &u);
502 if (r < 0)
503 return r;
504
505 return bus_unit_method_start_generic(message, u, job_type, reload_if_possible, error);
506 }
507
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);
510 }
511
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);
514 }
515
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);
518 }
519
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);
522 }
523
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);
526 }
527
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);
530 }
531
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);
534 }
535
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;
539 Unit *u;
540 int r;
541
542 assert(message);
543 assert(m);
544
545 r = sd_bus_message_read(message, "s", &old_name);
546 if (r < 0)
547 return r;
548
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);
552
553 return method_start_unit_generic(message, m, JOB_START, false, error);
554 }
555
556 static int method_kill_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
557 Manager *m = userdata;
558 const char *name;
559 Unit *u;
560 int r;
561
562 assert(message);
563 assert(m);
564
565 r = sd_bus_message_read(message, "s", &name);
566 if (r < 0)
567 return r;
568
569 u = manager_get_unit(m, name);
570 if (!u)
571 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
572
573 return bus_unit_method_kill(message, u, error);
574 }
575
576 static int method_reset_failed_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
577 Manager *m = userdata;
578 const char *name;
579 Unit *u;
580 int r;
581
582 assert(message);
583 assert(m);
584
585 r = sd_bus_message_read(message, "s", &name);
586 if (r < 0)
587 return r;
588
589 u = manager_get_unit(m, name);
590 if (!u)
591 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
592
593 return bus_unit_method_reset_failed(message, u, error);
594 }
595
596 static int method_set_unit_properties(sd_bus_message *message, void *userdata, sd_bus_error *error) {
597 Manager *m = userdata;
598 const char *name;
599 Unit *u;
600 int r;
601
602 assert(message);
603 assert(m);
604
605 r = sd_bus_message_read(message, "s", &name);
606 if (r < 0)
607 return r;
608
609 u = manager_get_unit(m, name);
610 if (!u)
611 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
612
613 return bus_unit_method_set_properties(message, u, error);
614 }
615
616 static int transient_unit_from_message(
617 Manager *m,
618 sd_bus_message *message,
619 const char *name,
620 Unit **unit,
621 sd_bus_error *error) {
622
623 Unit *u;
624 int r;
625
626 assert(m);
627 assert(message);
628 assert(name);
629
630 r = manager_load_unit(m, name, NULL, error, &u);
631 if (r < 0)
632 return r;
633
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);
637
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);
641 if (r < 0)
642 return r;
643
644 /* Set our properties */
645 r = bus_unit_set_properties(u, message, UNIT_RUNTIME, false, error);
646 if (r < 0)
647 return r;
648
649 *unit = u;
650
651 return 0;
652 }
653
654 static int transient_aux_units_from_message(
655 Manager *m,
656 sd_bus_message *message,
657 sd_bus_error *error) {
658
659 Unit *u;
660 char *name = NULL;
661 int r;
662
663 assert(m);
664 assert(message);
665
666 r = sd_bus_message_enter_container(message, 'a', "(sa(sv))");
667 if (r < 0)
668 return r;
669
670 while ((r = sd_bus_message_enter_container(message, 'r', "sa(sv)")) > 0) {
671 r = sd_bus_message_read(message, "s", &name);
672 if (r < 0)
673 return r;
674
675 r = transient_unit_from_message(m, message, name, &u, error);
676 if (r < 0 && r != -EEXIST)
677 return r;
678
679 if (r != -EEXIST) {
680 r = unit_load(u);
681 if (r < 0)
682 return r;
683 }
684
685 r = sd_bus_message_exit_container(message);
686 if (r < 0)
687 return r;
688 }
689 if (r < 0)
690 return r;
691
692 r = sd_bus_message_exit_container(message);
693 if (r < 0)
694 return r;
695
696 return 0;
697 }
698
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;
702 JobMode mode;
703 UnitType t;
704 Unit *u;
705 int r;
706
707 assert(message);
708 assert(m);
709
710 r = mac_selinux_access_check(message, "start", error);
711 if (r < 0)
712 return r;
713
714 r = sd_bus_message_read(message, "ss", &name, &smode);
715 if (r < 0)
716 return r;
717
718 t = unit_name_to_type(name);
719 if (t < 0)
720 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit type.");
721
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));
724
725 mode = job_mode_from_string(smode);
726 if (mode < 0)
727 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s is invalid.", smode);
728
729 r = bus_verify_manage_units_async(m, message, error);
730 if (r < 0)
731 return r;
732 if (r == 0)
733 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
734
735 r = transient_unit_from_message(m, message, name, &u, error);
736 if (r < 0)
737 return r;
738
739 r = transient_aux_units_from_message(m, message, error);
740 if (r < 0)
741 return r;
742
743 /* And load this stub fully */
744 r = unit_load(u);
745 if (r < 0)
746 return r;
747
748 manager_dispatch_load_queue(m);
749
750 /* Finally, start it */
751 return bus_unit_queue_job(message, u, JOB_START, mode, false, error);
752 }
753
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;
757 uint32_t id;
758 Job *j;
759 int r;
760
761 assert(message);
762 assert(m);
763
764 /* Anyone can call this method */
765
766 r = sd_bus_message_read(message, "u", &id);
767 if (r < 0)
768 return r;
769
770 j = manager_get_job(m, id);
771 if (!j)
772 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
773
774 r = mac_selinux_unit_access_check(j->unit, message, "status", error);
775 if (r < 0)
776 return r;
777
778 path = job_dbus_path(j);
779 if (!path)
780 return -ENOMEM;
781
782 return sd_bus_reply_method_return(message, "o", path);
783 }
784
785 static int method_cancel_job(sd_bus_message *message, void *userdata, sd_bus_error *error) {
786 Manager *m = userdata;
787 uint32_t id;
788 Job *j;
789 int r;
790
791 assert(message);
792 assert(m);
793
794 r = sd_bus_message_read(message, "u", &id);
795 if (r < 0)
796 return r;
797
798 j = manager_get_job(m, id);
799 if (!j)
800 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
801
802 return bus_job_method_cancel(message, j, error);
803 }
804
805 static int method_clear_jobs(sd_bus_message *message, void *userdata, sd_bus_error *error) {
806 Manager *m = userdata;
807 int r;
808
809 assert(message);
810 assert(m);
811
812 r = mac_selinux_access_check(message, "reload", error);
813 if (r < 0)
814 return r;
815
816 r = bus_verify_manage_units_async(m, message, error);
817 if (r < 0)
818 return r;
819 if (r == 0)
820 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
821
822 manager_clear_jobs(m);
823
824 return sd_bus_reply_method_return(message, NULL);
825 }
826
827 static int method_reset_failed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
828 Manager *m = userdata;
829 int r;
830
831 assert(message);
832 assert(m);
833
834 r = mac_selinux_access_check(message, "reload", error);
835 if (r < 0)
836 return r;
837
838 r = bus_verify_manage_units_async(m, message, error);
839 if (r < 0)
840 return r;
841 if (r == 0)
842 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
843
844 manager_reset_failed(m);
845
846 return sd_bus_reply_method_return(message, NULL);
847 }
848
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;
852 const char *k;
853 Iterator i;
854 Unit *u;
855 int r;
856
857 assert(message);
858 assert(m);
859
860 /* Anyone can call this method */
861
862 r = mac_selinux_access_check(message, "status", error);
863 if (r < 0)
864 return r;
865
866 r = sd_bus_message_new_method_return(message, &reply);
867 if (r < 0)
868 return r;
869
870 r = sd_bus_message_open_container(reply, 'a', "(ssssssouso)");
871 if (r < 0)
872 return r;
873
874 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
875 _cleanup_free_ char *unit_path = NULL, *job_path = NULL;
876 Unit *following;
877
878 if (k != u->id)
879 continue;
880
881 following = unit_following(u);
882
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)))
887 continue;
888
889 unit_path = unit_dbus_path(u);
890 if (!unit_path)
891 return -ENOMEM;
892
893 if (u->job) {
894 job_path = job_dbus_path(u->job);
895 if (!job_path)
896 return -ENOMEM;
897 }
898
899 r = sd_bus_message_append(
900 reply, "(ssssssouso)",
901 u->id,
902 unit_description(u),
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 : "",
907 unit_path,
908 u->job ? u->job->id : 0,
909 u->job ? job_type_to_string(u->job->type) : "",
910 job_path ? job_path : "/");
911 if (r < 0)
912 return r;
913 }
914
915 r = sd_bus_message_close_container(reply);
916 if (r < 0)
917 return r;
918
919 return sd_bus_send(NULL, reply, NULL);
920 }
921
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);
924 }
925
926 static int method_list_units_filtered(sd_bus_message *message, void *userdata, sd_bus_error *error) {
927 _cleanup_strv_free_ char **states = NULL;
928 int r;
929
930 r = sd_bus_message_read_strv(message, &states);
931 if (r < 0)
932 return r;
933
934 return list_units_filtered(message, userdata, error, states);
935 }
936
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;
940 Iterator i;
941 Job *j;
942 int r;
943
944 assert(message);
945 assert(m);
946
947 /* Anyone can call this method */
948
949 r = mac_selinux_access_check(message, "status", error);
950 if (r < 0)
951 return r;
952
953 r = sd_bus_message_new_method_return(message, &reply);
954 if (r < 0)
955 return r;
956
957 r = sd_bus_message_open_container(reply, 'a', "(usssoo)");
958 if (r < 0)
959 return r;
960
961 HASHMAP_FOREACH(j, m->jobs, i) {
962 _cleanup_free_ char *unit_path = NULL, *job_path = NULL;
963
964 job_path = job_dbus_path(j);
965 if (!job_path)
966 return -ENOMEM;
967
968 unit_path = unit_dbus_path(j->unit);
969 if (!unit_path)
970 return -ENOMEM;
971
972 r = sd_bus_message_append(
973 reply, "(usssoo)",
974 j->id,
975 j->unit->id,
976 job_type_to_string(j->type),
977 job_state_to_string(j->state),
978 job_path,
979 unit_path);
980 if (r < 0)
981 return r;
982 }
983
984 r = sd_bus_message_close_container(reply);
985 if (r < 0)
986 return r;
987
988 return sd_bus_send(NULL, reply, NULL);
989 }
990
991 static int method_subscribe(sd_bus_message *message, void *userdata, sd_bus_error *error) {
992 Manager *m = userdata;
993 int r;
994
995 assert(message);
996 assert(m);
997
998 /* Anyone can call this method */
999
1000 r = mac_selinux_access_check(message, "status", error);
1001 if (r < 0)
1002 return r;
1003
1004 if (sd_bus_message_get_bus(message) == m->api_bus) {
1005
1006 /* Note that direct bus connection subscribe by
1007 * default, we only track peers on the API bus here */
1008
1009 if (!m->subscribed) {
1010 r = sd_bus_track_new(sd_bus_message_get_bus(message), &m->subscribed, NULL, NULL);
1011 if (r < 0)
1012 return r;
1013 }
1014
1015 r = sd_bus_track_add_sender(m->subscribed, message);
1016 if (r < 0)
1017 return r;
1018 if (r == 0)
1019 return sd_bus_error_setf(error, BUS_ERROR_ALREADY_SUBSCRIBED, "Client is already subscribed.");
1020 }
1021
1022 return sd_bus_reply_method_return(message, NULL);
1023 }
1024
1025 static int method_unsubscribe(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1026 Manager *m = userdata;
1027 int r;
1028
1029 assert(message);
1030 assert(m);
1031
1032 /* Anyone can call this method */
1033
1034 r = mac_selinux_access_check(message, "status", error);
1035 if (r < 0)
1036 return r;
1037
1038 if (sd_bus_message_get_bus(message) == m->api_bus) {
1039 r = sd_bus_track_remove_sender(m->subscribed, message);
1040 if (r < 0)
1041 return r;
1042 if (r == 0)
1043 return sd_bus_error_setf(error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
1044 }
1045
1046 return sd_bus_reply_method_return(message, NULL);
1047 }
1048
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;
1053 size_t size;
1054 int r;
1055
1056 assert(message);
1057 assert(m);
1058
1059 /* Anyone can call this method */
1060
1061 r = mac_selinux_access_check(message, "status", error);
1062 if (r < 0)
1063 return r;
1064
1065 f = open_memstream(&dump, &size);
1066 if (!f)
1067 return -ENOMEM;
1068
1069 manager_dump_units(m, f, NULL);
1070 manager_dump_jobs(m, f, NULL);
1071
1072 fflush(f);
1073
1074 if (ferror(f))
1075 return -ENOMEM;
1076
1077 return sd_bus_reply_method_return(message, "s", dump);
1078 }
1079
1080 static int method_create_snapshot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1081 _cleanup_free_ char *path = NULL;
1082 Manager *m = userdata;
1083 const char *name;
1084 int cleanup;
1085 Snapshot *s = NULL;
1086 int r;
1087
1088 assert(message);
1089 assert(m);
1090
1091 r = mac_selinux_access_check(message, "start", error);
1092 if (r < 0)
1093 return r;
1094
1095 r = sd_bus_message_read(message, "sb", &name, &cleanup);
1096 if (r < 0)
1097 return r;
1098
1099 if (isempty(name))
1100 name = NULL;
1101
1102 r = bus_verify_manage_units_async(m, message, error);
1103 if (r < 0)
1104 return r;
1105 if (r == 0)
1106 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1107
1108 r = snapshot_create(m, name, cleanup, error, &s);
1109 if (r < 0)
1110 return r;
1111
1112 path = unit_dbus_path(UNIT(s));
1113 if (!path)
1114 return -ENOMEM;
1115
1116 return sd_bus_reply_method_return(message, "o", path);
1117 }
1118
1119 static int method_remove_snapshot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1120 Manager *m = userdata;
1121 const char *name;
1122 Unit *u;
1123 int r;
1124
1125 assert(message);
1126 assert(m);
1127
1128 r = sd_bus_message_read(message, "s", &name);
1129 if (r < 0)
1130 return r;
1131
1132 u = manager_get_unit(m, name);
1133 if (!u)
1134 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s does not exist.", name);
1135
1136 if (u->type != UNIT_SNAPSHOT)
1137 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not a snapshot", name);
1138
1139 return bus_snapshot_method_remove(message, u, error);
1140 }
1141
1142 static int method_reload(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1143 Manager *m = userdata;
1144 int r;
1145
1146 assert(message);
1147 assert(m);
1148
1149 r = mac_selinux_access_check(message, "reload", error);
1150 if (r < 0)
1151 return r;
1152
1153 r = bus_verify_reload_daemon_async(m, message, error);
1154 if (r < 0)
1155 return r;
1156 if (r == 0)
1157 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1158
1159 /* Instead of sending the reply back right away, we just
1160 * remember that we need to and then send it after the reload
1161 * is finished. That way the caller knows when the reload
1162 * finished. */
1163
1164 assert(!m->queued_message);
1165 r = sd_bus_message_new_method_return(message, &m->queued_message);
1166 if (r < 0)
1167 return r;
1168
1169 m->exit_code = MANAGER_RELOAD;
1170
1171 return 1;
1172 }
1173
1174 static int method_reexecute(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1175 Manager *m = userdata;
1176 int r;
1177
1178 assert(message);
1179 assert(m);
1180
1181 r = mac_selinux_access_check(message, "reload", error);
1182 if (r < 0)
1183 return r;
1184
1185 r = bus_verify_reload_daemon_async(m, message, error);
1186 if (r < 0)
1187 return r;
1188 if (r == 0)
1189 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1190
1191 /* We don't send a reply back here, the client should
1192 * just wait for us disconnecting. */
1193
1194 m->exit_code = MANAGER_REEXECUTE;
1195 return 1;
1196 }
1197
1198 static int method_exit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1199 Manager *m = userdata;
1200 int r;
1201
1202 assert(message);
1203 assert(m);
1204
1205 r = mac_selinux_access_check(message, "halt", error);
1206 if (r < 0)
1207 return r;
1208
1209 if (m->running_as == MANAGER_SYSTEM)
1210 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
1211
1212 m->exit_code = MANAGER_EXIT;
1213
1214 return sd_bus_reply_method_return(message, NULL);
1215 }
1216
1217 static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1218 Manager *m = userdata;
1219 int r;
1220
1221 assert(message);
1222 assert(m);
1223
1224 r = mac_selinux_access_check(message, "reboot", error);
1225 if (r < 0)
1226 return r;
1227
1228 if (m->running_as != MANAGER_SYSTEM)
1229 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
1230
1231 m->exit_code = MANAGER_REBOOT;
1232
1233 return sd_bus_reply_method_return(message, NULL);
1234 }
1235
1236 static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1237 Manager *m = userdata;
1238 int r;
1239
1240 assert(message);
1241 assert(m);
1242
1243 r = mac_selinux_access_check(message, "halt", error);
1244 if (r < 0)
1245 return r;
1246
1247 if (m->running_as != MANAGER_SYSTEM)
1248 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
1249
1250 m->exit_code = MANAGER_POWEROFF;
1251
1252 return sd_bus_reply_method_return(message, NULL);
1253 }
1254
1255 static int method_halt(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1256 Manager *m = userdata;
1257 int r;
1258
1259 assert(message);
1260 assert(m);
1261
1262 r = mac_selinux_access_check(message, "halt", error);
1263 if (r < 0)
1264 return r;
1265
1266 if (m->running_as != MANAGER_SYSTEM)
1267 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Halt is only supported for system managers.");
1268
1269 m->exit_code = MANAGER_HALT;
1270
1271 return sd_bus_reply_method_return(message, NULL);
1272 }
1273
1274 static int method_kexec(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1275 Manager *m = userdata;
1276 int r;
1277
1278 assert(message);
1279 assert(m);
1280
1281 r = mac_selinux_access_check(message, "reboot", error);
1282 if (r < 0)
1283 return r;
1284
1285 if (m->running_as != MANAGER_SYSTEM)
1286 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "KExec is only supported for system managers.");
1287
1288 m->exit_code = MANAGER_KEXEC;
1289
1290 return sd_bus_reply_method_return(message, NULL);
1291 }
1292
1293 static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1294 char *ri = NULL, *rt = NULL;
1295 const char *root, *init;
1296 Manager *m = userdata;
1297 int r;
1298
1299 assert(message);
1300 assert(m);
1301
1302 r = mac_selinux_access_check(message, "reboot", error);
1303 if (r < 0)
1304 return r;
1305
1306 if (m->running_as != MANAGER_SYSTEM)
1307 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Root switching is only supported by system manager.");
1308
1309 r = sd_bus_message_read(message, "ss", &root, &init);
1310 if (r < 0)
1311 return r;
1312
1313 if (path_equal(root, "/") || !path_is_absolute(root))
1314 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid switch root path %s", root);
1315
1316 /* Safety check */
1317 if (isempty(init)) {
1318 if (!path_is_os_tree(root))
1319 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 } else {
1321 _cleanup_free_ char *p = NULL;
1322
1323 if (!path_is_absolute(init))
1324 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid init path %s", init);
1325
1326 p = strappend(root, init);
1327 if (!p)
1328 return -ENOMEM;
1329
1330 if (access(p, X_OK) < 0)
1331 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified init binary %s does not exist.", p);
1332 }
1333
1334 rt = strdup(root);
1335 if (!rt)
1336 return -ENOMEM;
1337
1338 if (!isempty(init)) {
1339 ri = strdup(init);
1340 if (!ri) {
1341 free(rt);
1342 return -ENOMEM;
1343 }
1344 }
1345
1346 free(m->switch_root);
1347 m->switch_root = rt;
1348
1349 free(m->switch_root_init);
1350 m->switch_root_init = ri;
1351
1352 m->exit_code = MANAGER_SWITCH_ROOT;
1353
1354 return sd_bus_reply_method_return(message, NULL);
1355 }
1356
1357 static int method_set_environment(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1358 _cleanup_strv_free_ char **plus = NULL;
1359 Manager *m = userdata;
1360 int r;
1361
1362 assert(message);
1363 assert(m);
1364
1365 r = mac_selinux_access_check(message, "reload", error);
1366 if (r < 0)
1367 return r;
1368
1369 r = sd_bus_message_read_strv(message, &plus);
1370 if (r < 0)
1371 return r;
1372 if (!strv_env_is_valid(plus))
1373 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
1374
1375 r = bus_verify_set_environment_async(m, message, error);
1376 if (r < 0)
1377 return r;
1378 if (r == 0)
1379 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1380
1381 r = manager_environment_add(m, NULL, plus);
1382 if (r < 0)
1383 return r;
1384
1385 return sd_bus_reply_method_return(message, NULL);
1386 }
1387
1388 static int method_unset_environment(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1389 _cleanup_strv_free_ char **minus = NULL;
1390 Manager *m = userdata;
1391 int r;
1392
1393 assert(message);
1394 assert(m);
1395
1396 r = mac_selinux_access_check(message, "reload", error);
1397 if (r < 0)
1398 return r;
1399
1400 r = sd_bus_message_read_strv(message, &minus);
1401 if (r < 0)
1402 return r;
1403
1404 if (!strv_env_name_or_assignment_is_valid(minus))
1405 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment variable names or assignments");
1406
1407 r = bus_verify_set_environment_async(m, message, error);
1408 if (r < 0)
1409 return r;
1410 if (r == 0)
1411 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1412
1413 r = manager_environment_add(m, minus, NULL);
1414 if (r < 0)
1415 return r;
1416
1417 return sd_bus_reply_method_return(message, NULL);
1418 }
1419
1420 static int method_unset_and_set_environment(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1421 _cleanup_strv_free_ char **minus = NULL, **plus = NULL;
1422 Manager *m = userdata;
1423 int r;
1424
1425 assert(message);
1426 assert(m);
1427
1428 r = mac_selinux_access_check(message, "reload", error);
1429 if (r < 0)
1430 return r;
1431
1432 r = sd_bus_message_read_strv(message, &minus);
1433 if (r < 0)
1434 return r;
1435
1436 r = sd_bus_message_read_strv(message, &plus);
1437 if (r < 0)
1438 return r;
1439
1440 if (!strv_env_name_or_assignment_is_valid(minus))
1441 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment variable names or assignments");
1442 if (!strv_env_is_valid(plus))
1443 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
1444
1445 r = bus_verify_set_environment_async(m, message, error);
1446 if (r < 0)
1447 return r;
1448 if (r == 0)
1449 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1450
1451 r = manager_environment_add(m, minus, plus);
1452 if (r < 0)
1453 return r;
1454
1455 return sd_bus_reply_method_return(message, NULL);
1456 }
1457
1458 static int method_list_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1459 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1460 Manager *m = userdata;
1461 UnitFileList *item;
1462 Hashmap *h;
1463 Iterator i;
1464 int r;
1465
1466 assert(message);
1467 assert(m);
1468
1469 /* Anyone can call this method */
1470
1471 r = mac_selinux_access_check(message, "status", error);
1472 if (r < 0)
1473 return r;
1474
1475 r = sd_bus_message_new_method_return(message, &reply);
1476 if (r < 0)
1477 return r;
1478
1479 h = hashmap_new(&string_hash_ops);
1480 if (!h)
1481 return -ENOMEM;
1482
1483 r = unit_file_get_list(m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
1484 if (r < 0)
1485 goto fail;
1486
1487 r = sd_bus_message_open_container(reply, 'a', "(ss)");
1488 if (r < 0)
1489 goto fail;
1490
1491 HASHMAP_FOREACH(item, h, i) {
1492
1493 r = sd_bus_message_append(reply, "(ss)", item->path, unit_file_state_to_string(item->state));
1494 if (r < 0)
1495 goto fail;
1496 }
1497
1498 unit_file_list_free(h);
1499
1500 r = sd_bus_message_close_container(reply);
1501 if (r < 0)
1502 return r;
1503
1504 return sd_bus_send(NULL, reply, NULL);
1505
1506 fail:
1507 unit_file_list_free(h);
1508 return r;
1509 }
1510
1511 static int method_get_unit_file_state(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1512 Manager *m = userdata;
1513 const char *name;
1514 UnitFileState state;
1515 UnitFileScope scope;
1516 int r;
1517
1518 assert(message);
1519 assert(m);
1520
1521 /* Anyone can call this method */
1522
1523 r = mac_selinux_access_check(message, "status", error);
1524 if (r < 0)
1525 return r;
1526
1527 r = sd_bus_message_read(message, "s", &name);
1528 if (r < 0)
1529 return r;
1530
1531 scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1532
1533 state = unit_file_get_state(scope, NULL, name);
1534 if (state < 0)
1535 return state;
1536
1537 return sd_bus_reply_method_return(message, "s", unit_file_state_to_string(state));
1538 }
1539
1540 static int method_get_default_target(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1541 _cleanup_free_ char *default_target = NULL;
1542 Manager *m = userdata;
1543 UnitFileScope scope;
1544 int r;
1545
1546 assert(message);
1547 assert(m);
1548
1549 /* Anyone can call this method */
1550
1551 r = mac_selinux_access_check(message, "status", error);
1552 if (r < 0)
1553 return r;
1554
1555 scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1556
1557 r = unit_file_get_default(scope, NULL, &default_target);
1558 if (r < 0)
1559 return r;
1560
1561 return sd_bus_reply_method_return(message, "s", default_target);
1562 }
1563
1564 static int send_unit_files_changed(sd_bus *bus, void *userdata) {
1565 _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
1566 int r;
1567
1568 assert(bus);
1569
1570 r = sd_bus_message_new_signal(bus, &message, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged");
1571 if (r < 0)
1572 return r;
1573
1574 return sd_bus_send(bus, message, NULL);
1575 }
1576
1577 static int reply_unit_file_changes_and_free(
1578 Manager *m,
1579 sd_bus_message *message,
1580 int carries_install_info,
1581 UnitFileChange *changes,
1582 unsigned n_changes) {
1583
1584 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1585 unsigned i;
1586 int r;
1587
1588 if (n_changes > 0) {
1589 r = bus_foreach_bus(m, NULL, send_unit_files_changed, NULL);
1590 if (r < 0)
1591 log_debug_errno(r, "Failed to send UnitFilesChanged signal: %m");
1592 }
1593
1594 r = sd_bus_message_new_method_return(message, &reply);
1595 if (r < 0)
1596 goto fail;
1597
1598 if (carries_install_info >= 0) {
1599 r = sd_bus_message_append(reply, "b", carries_install_info);
1600 if (r < 0)
1601 goto fail;
1602 }
1603
1604 r = sd_bus_message_open_container(reply, 'a', "(sss)");
1605 if (r < 0)
1606 goto fail;
1607
1608 for (i = 0; i < n_changes; i++) {
1609 r = sd_bus_message_append(
1610 reply, "(sss)",
1611 unit_file_change_type_to_string(changes[i].type),
1612 changes[i].path,
1613 changes[i].source);
1614 if (r < 0)
1615 goto fail;
1616 }
1617
1618 r = sd_bus_message_close_container(reply);
1619 if (r < 0)
1620 goto fail;
1621
1622 return sd_bus_send(NULL, reply, NULL);
1623
1624 fail:
1625 unit_file_changes_free(changes, n_changes);
1626 return r;
1627 }
1628
1629 static int method_enable_unit_files_generic(
1630 sd_bus_message *message,
1631 Manager *m,
1632 const char *verb,
1633 int (*call)(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes),
1634 bool carries_install_info,
1635 sd_bus_error *error) {
1636
1637 _cleanup_strv_free_ char **l = NULL;
1638 UnitFileChange *changes = NULL;
1639 unsigned n_changes = 0;
1640 UnitFileScope scope;
1641 int runtime, force, r;
1642
1643 assert(message);
1644 assert(m);
1645
1646 r = sd_bus_message_read_strv(message, &l);
1647 if (r < 0)
1648 return r;
1649
1650 r = sd_bus_message_read(message, "bb", &runtime, &force);
1651 if (r < 0)
1652 return r;
1653
1654 r = mac_selinux_unit_access_check_strv(l, message, m, verb, error);
1655 if (r < 0)
1656 return r;
1657
1658 r = bus_verify_manage_unit_files_async(m, message, error);
1659 if (r < 0)
1660 return r;
1661 if (r == 0)
1662 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1663
1664 scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1665
1666 r = call(scope, runtime, NULL, l, force, &changes, &n_changes);
1667 if (r < 0)
1668 return r;
1669
1670 return reply_unit_file_changes_and_free(m, message, carries_install_info ? r : -1, changes, n_changes);
1671 }
1672
1673 static int method_enable_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1674 return method_enable_unit_files_generic(message, userdata, "enable", unit_file_enable, true, error);
1675 }
1676
1677 static int method_reenable_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1678 return method_enable_unit_files_generic(message, userdata, "enable", unit_file_reenable, true, error);
1679 }
1680
1681 static int method_link_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1682 return method_enable_unit_files_generic(message, userdata, "enable", unit_file_link, false, error);
1683 }
1684
1685 static int unit_file_preset_without_mode(UnitFileScope scope, bool runtime, const char *root_dir, char **files, bool force, UnitFileChange **changes, unsigned *n_changes) {
1686 return unit_file_preset(scope, runtime, root_dir, files, UNIT_FILE_PRESET_FULL, force, changes, n_changes);
1687 }
1688
1689 static int method_preset_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1690 return method_enable_unit_files_generic(message, userdata, "enable", unit_file_preset_without_mode, true, error);
1691 }
1692
1693 static int method_mask_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1694 return method_enable_unit_files_generic(message, userdata, "disable", unit_file_mask, false, error);
1695 }
1696
1697 static int method_preset_unit_files_with_mode(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1698
1699 _cleanup_strv_free_ char **l = NULL;
1700 UnitFileChange *changes = NULL;
1701 unsigned n_changes = 0;
1702 Manager *m = userdata;
1703 UnitFilePresetMode mm;
1704 UnitFileScope scope;
1705 int runtime, force, r;
1706 const char *mode;
1707
1708 assert(message);
1709 assert(m);
1710
1711 r = sd_bus_message_read_strv(message, &l);
1712 if (r < 0)
1713 return r;
1714
1715 r = sd_bus_message_read(message, "sbb", &mode, &runtime, &force);
1716 if (r < 0)
1717 return r;
1718
1719 if (isempty(mode))
1720 mm = UNIT_FILE_PRESET_FULL;
1721 else {
1722 mm = unit_file_preset_mode_from_string(mode);
1723 if (mm < 0)
1724 return -EINVAL;
1725 }
1726
1727 r = mac_selinux_unit_access_check_strv(l, message, m, "enable", error);
1728 if (r < 0)
1729 return r;
1730
1731 r = bus_verify_manage_unit_files_async(m, message, error);
1732 if (r < 0)
1733 return r;
1734 if (r == 0)
1735 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1736
1737 scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1738
1739 r = unit_file_preset(scope, runtime, NULL, l, mm, force, &changes, &n_changes);
1740 if (r < 0)
1741 return r;
1742
1743 return reply_unit_file_changes_and_free(m, message, r, changes, n_changes);
1744 }
1745
1746 static int method_disable_unit_files_generic(
1747 sd_bus_message *message,
1748 Manager *m, const
1749 char *verb,
1750 int (*call)(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], UnitFileChange **changes, unsigned *n_changes),
1751 sd_bus_error *error) {
1752
1753 _cleanup_strv_free_ char **l = NULL;
1754 UnitFileChange *changes = NULL;
1755 unsigned n_changes = 0;
1756 UnitFileScope scope;
1757 int r, runtime;
1758
1759 assert(message);
1760 assert(m);
1761
1762 r = sd_bus_message_read_strv(message, &l);
1763 if (r < 0)
1764 return r;
1765
1766 r = sd_bus_message_read(message, "b", &runtime);
1767 if (r < 0)
1768 return r;
1769
1770 r = mac_selinux_unit_access_check_strv(l, message, m, verb, error);
1771 if (r < 0)
1772 return r;
1773
1774 scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1775
1776 r = bus_verify_manage_unit_files_async(m, message, error);
1777 if (r < 0)
1778 return r;
1779 if (r == 0)
1780 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1781
1782 r = call(scope, runtime, NULL, l, &changes, &n_changes);
1783 if (r < 0)
1784 return r;
1785
1786 return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes);
1787 }
1788
1789 static int method_disable_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1790 return method_disable_unit_files_generic(message, userdata, "disable", unit_file_disable, error);
1791 }
1792
1793 static int method_unmask_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1794 return method_disable_unit_files_generic(message, userdata, "enable", unit_file_unmask, error);
1795 }
1796
1797 static int method_set_default_target(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1798 UnitFileChange *changes = NULL;
1799 unsigned n_changes = 0;
1800 Manager *m = userdata;
1801 UnitFileScope scope;
1802 const char *name;
1803 int force, r;
1804
1805 assert(message);
1806 assert(m);
1807
1808 r = mac_selinux_access_check(message, "enable", error);
1809 if (r < 0)
1810 return r;
1811
1812 r = sd_bus_message_read(message, "sb", &name, &force);
1813 if (r < 0)
1814 return r;
1815
1816 r = bus_verify_manage_unit_files_async(m, message, error);
1817 if (r < 0)
1818 return r;
1819 if (r == 0)
1820 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1821
1822 scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1823
1824 r = unit_file_set_default(scope, NULL, name, force, &changes, &n_changes);
1825 if (r < 0)
1826 return r;
1827
1828 return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes);
1829 }
1830
1831 static int method_preset_all_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1832 UnitFileChange *changes = NULL;
1833 unsigned n_changes = 0;
1834 Manager *m = userdata;
1835 UnitFilePresetMode mm;
1836 UnitFileScope scope;
1837 const char *mode;
1838 int force, runtime, r;
1839
1840 assert(message);
1841 assert(m);
1842
1843 r = mac_selinux_access_check(message, "enable", error);
1844 if (r < 0)
1845 return r;
1846
1847 r = sd_bus_message_read(message, "sbb", &mode, &runtime, &force);
1848 if (r < 0)
1849 return r;
1850
1851 if (isempty(mode))
1852 mm = UNIT_FILE_PRESET_FULL;
1853 else {
1854 mm = unit_file_preset_mode_from_string(mode);
1855 if (mm < 0)
1856 return -EINVAL;
1857 }
1858
1859 r = bus_verify_manage_unit_files_async(m, message, error);
1860 if (r < 0)
1861 return r;
1862 if (r == 0)
1863 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1864
1865 scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1866
1867 r = unit_file_preset_all(scope, runtime, NULL, mm, force, &changes, &n_changes);
1868 if (r < 0)
1869 return r;
1870
1871 return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes);
1872 }
1873
1874 static int method_add_dependency_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1875 _cleanup_strv_free_ char **l = NULL;
1876 Manager *m = userdata;
1877 UnitFileChange *changes = NULL;
1878 unsigned n_changes = 0;
1879 UnitFileScope scope;
1880 int runtime, force, r;
1881 char *target;
1882 char *type;
1883 UnitDependency dep;
1884
1885 assert(message);
1886 assert(m);
1887
1888 r = bus_verify_manage_unit_files_async(m, message, error);
1889 if (r < 0)
1890 return r;
1891 if (r == 0)
1892 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1893
1894 r = sd_bus_message_read_strv(message, &l);
1895 if (r < 0)
1896 return r;
1897
1898 r = sd_bus_message_read(message, "ssbb", &target, &type, &runtime, &force);
1899 if (r < 0)
1900 return r;
1901
1902 dep = unit_dependency_from_string(type);
1903 if (dep < 0)
1904 return -EINVAL;
1905
1906 r = mac_selinux_unit_access_check_strv(l, message, m, "enable", error);
1907 if (r < 0)
1908 return r;
1909
1910 scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1911
1912 r = unit_file_add_dependency(scope, runtime, NULL, l, target, dep, force, &changes, &n_changes);
1913 if (r < 0)
1914 return r;
1915
1916 return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes);
1917 }
1918
1919 const sd_bus_vtable bus_manager_vtable[] = {
1920 SD_BUS_VTABLE_START(0),
1921
1922 SD_BUS_PROPERTY("Version", "s", property_get_version, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1923 SD_BUS_PROPERTY("Features", "s", property_get_features, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1924 SD_BUS_PROPERTY("Virtualization", "s", property_get_virtualization, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1925 SD_BUS_PROPERTY("Architecture", "s", property_get_architecture, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1926 SD_BUS_PROPERTY("Tainted", "s", property_get_tainted, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1927 BUS_PROPERTY_DUAL_TIMESTAMP("FirmwareTimestamp", offsetof(Manager, firmware_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1928 BUS_PROPERTY_DUAL_TIMESTAMP("LoaderTimestamp", offsetof(Manager, loader_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1929 BUS_PROPERTY_DUAL_TIMESTAMP("KernelTimestamp", offsetof(Manager, kernel_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1930 BUS_PROPERTY_DUAL_TIMESTAMP("InitRDTimestamp", offsetof(Manager, initrd_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1931 BUS_PROPERTY_DUAL_TIMESTAMP("UserspaceTimestamp", offsetof(Manager, userspace_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1932 BUS_PROPERTY_DUAL_TIMESTAMP("FinishTimestamp", offsetof(Manager, finish_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1933 BUS_PROPERTY_DUAL_TIMESTAMP("SecurityStartTimestamp", offsetof(Manager, security_start_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1934 BUS_PROPERTY_DUAL_TIMESTAMP("SecurityFinishTimestamp", offsetof(Manager, security_finish_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1935 BUS_PROPERTY_DUAL_TIMESTAMP("GeneratorsStartTimestamp", offsetof(Manager, generators_start_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1936 BUS_PROPERTY_DUAL_TIMESTAMP("GeneratorsFinishTimestamp", offsetof(Manager, generators_finish_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1937 BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadStartTimestamp", offsetof(Manager, units_load_start_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1938 BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadFinishTimestamp", offsetof(Manager, units_load_finish_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1939 SD_BUS_WRITABLE_PROPERTY("LogLevel", "s", property_get_log_level, property_set_log_level, 0, 0),
1940 SD_BUS_WRITABLE_PROPERTY("LogTarget", "s", property_get_log_target, property_set_log_target, 0, 0),
1941 SD_BUS_PROPERTY("NNames", "u", property_get_n_names, 0, 0),
1942 SD_BUS_PROPERTY("NFailedUnits", "u", property_get_n_failed_units, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1943 SD_BUS_PROPERTY("NJobs", "u", property_get_n_jobs, 0, 0),
1944 SD_BUS_PROPERTY("NInstalledJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_installed_jobs), 0),
1945 SD_BUS_PROPERTY("NFailedJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_failed_jobs), 0),
1946 SD_BUS_PROPERTY("Progress", "d", property_get_progress, 0, 0),
1947 SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(Manager, environment), 0),
1948 SD_BUS_PROPERTY("ConfirmSpawn", "b", bus_property_get_bool, offsetof(Manager, confirm_spawn), SD_BUS_VTABLE_PROPERTY_CONST),
1949 SD_BUS_PROPERTY("ShowStatus", "b", bus_property_get_bool, offsetof(Manager, show_status), SD_BUS_VTABLE_PROPERTY_CONST),
1950 SD_BUS_PROPERTY("UnitPath", "as", NULL, offsetof(Manager, lookup_paths.unit_path), SD_BUS_VTABLE_PROPERTY_CONST),
1951 SD_BUS_PROPERTY("DefaultStandardOutput", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), SD_BUS_VTABLE_PROPERTY_CONST),
1952 SD_BUS_PROPERTY("DefaultStandardError", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), SD_BUS_VTABLE_PROPERTY_CONST),
1953 SD_BUS_WRITABLE_PROPERTY("RuntimeWatchdogUSec", "t", bus_property_get_usec, property_set_runtime_watchdog, offsetof(Manager, runtime_watchdog), 0),
1954 SD_BUS_WRITABLE_PROPERTY("ShutdownWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, shutdown_watchdog), 0),
1955 SD_BUS_PROPERTY("ControlGroup", "s", NULL, offsetof(Manager, cgroup_root), 0),
1956 SD_BUS_PROPERTY("SystemState", "s", property_get_system_state, 0, 0),
1957
1958 SD_BUS_METHOD("GetUnit", "s", "o", method_get_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1959 SD_BUS_METHOD("GetUnitByPID", "u", "o", method_get_unit_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
1960 SD_BUS_METHOD("LoadUnit", "s", "o", method_load_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1961 SD_BUS_METHOD("StartUnit", "ss", "o", method_start_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1962 SD_BUS_METHOD("StartUnitReplace", "sss", "o", method_start_unit_replace, SD_BUS_VTABLE_UNPRIVILEGED),
1963 SD_BUS_METHOD("StopUnit", "ss", "o", method_stop_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1964 SD_BUS_METHOD("ReloadUnit", "ss", "o", method_reload_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1965 SD_BUS_METHOD("RestartUnit", "ss", "o", method_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1966 SD_BUS_METHOD("TryRestartUnit", "ss", "o", method_try_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1967 SD_BUS_METHOD("ReloadOrRestartUnit", "ss", "o", method_reload_or_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1968 SD_BUS_METHOD("ReloadOrTryRestartUnit", "ss", "o", method_reload_or_try_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1969 SD_BUS_METHOD("KillUnit", "ssi", NULL, method_kill_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1970 SD_BUS_METHOD("ResetFailedUnit", "s", NULL, method_reset_failed_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1971 SD_BUS_METHOD("SetUnitProperties", "sba(sv)", NULL, method_set_unit_properties, SD_BUS_VTABLE_UNPRIVILEGED),
1972 SD_BUS_METHOD("StartTransientUnit", "ssa(sv)a(sa(sv))", "o", method_start_transient_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1973 SD_BUS_METHOD("GetJob", "u", "o", method_get_job, SD_BUS_VTABLE_UNPRIVILEGED),
1974 SD_BUS_METHOD("CancelJob", "u", NULL, method_cancel_job, SD_BUS_VTABLE_UNPRIVILEGED),
1975 SD_BUS_METHOD("ClearJobs", NULL, NULL, method_clear_jobs, SD_BUS_VTABLE_UNPRIVILEGED),
1976 SD_BUS_METHOD("ResetFailed", NULL, NULL, method_reset_failed, SD_BUS_VTABLE_UNPRIVILEGED),
1977 SD_BUS_METHOD("ListUnits", NULL, "a(ssssssouso)", method_list_units, SD_BUS_VTABLE_UNPRIVILEGED),
1978 SD_BUS_METHOD("ListUnitsFiltered", "as", "a(ssssssouso)", method_list_units_filtered, SD_BUS_VTABLE_UNPRIVILEGED),
1979 SD_BUS_METHOD("ListJobs", NULL, "a(usssoo)", method_list_jobs, SD_BUS_VTABLE_UNPRIVILEGED),
1980 SD_BUS_METHOD("Subscribe", NULL, NULL, method_subscribe, SD_BUS_VTABLE_UNPRIVILEGED),
1981 SD_BUS_METHOD("Unsubscribe", NULL, NULL, method_unsubscribe, SD_BUS_VTABLE_UNPRIVILEGED),
1982 SD_BUS_METHOD("Dump", NULL, "s", method_dump, SD_BUS_VTABLE_UNPRIVILEGED),
1983 SD_BUS_METHOD("CreateSnapshot", "sb", "o", method_create_snapshot, SD_BUS_VTABLE_UNPRIVILEGED),
1984 SD_BUS_METHOD("RemoveSnapshot", "s", NULL, method_remove_snapshot, SD_BUS_VTABLE_UNPRIVILEGED),
1985 SD_BUS_METHOD("Reload", NULL, NULL, method_reload, SD_BUS_VTABLE_UNPRIVILEGED),
1986 SD_BUS_METHOD("Reexecute", NULL, NULL, method_reexecute, SD_BUS_VTABLE_UNPRIVILEGED),
1987 SD_BUS_METHOD("Exit", NULL, NULL, method_exit, 0),
1988 SD_BUS_METHOD("Reboot", NULL, NULL, method_reboot, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
1989 SD_BUS_METHOD("PowerOff", NULL, NULL, method_poweroff, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
1990 SD_BUS_METHOD("Halt", NULL, NULL, method_halt, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
1991 SD_BUS_METHOD("KExec", NULL, NULL, method_kexec, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
1992 SD_BUS_METHOD("SwitchRoot", "ss", NULL, method_switch_root, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
1993 SD_BUS_METHOD("SetEnvironment", "as", NULL, method_set_environment, SD_BUS_VTABLE_UNPRIVILEGED),
1994 SD_BUS_METHOD("UnsetEnvironment", "as", NULL, method_unset_environment, SD_BUS_VTABLE_UNPRIVILEGED),
1995 SD_BUS_METHOD("UnsetAndSetEnvironment", "asas", NULL, method_unset_and_set_environment, SD_BUS_VTABLE_UNPRIVILEGED),
1996 SD_BUS_METHOD("ListUnitFiles", NULL, "a(ss)", method_list_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
1997 SD_BUS_METHOD("GetUnitFileState", "s", "s", method_get_unit_file_state, SD_BUS_VTABLE_UNPRIVILEGED),
1998 SD_BUS_METHOD("EnableUnitFiles", "asbb", "ba(sss)", method_enable_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
1999 SD_BUS_METHOD("DisableUnitFiles", "asb", "a(sss)", method_disable_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2000 SD_BUS_METHOD("ReenableUnitFiles", "asbb", "ba(sss)", method_reenable_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2001 SD_BUS_METHOD("LinkUnitFiles", "asbb", "a(sss)", method_link_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2002 SD_BUS_METHOD("PresetUnitFiles", "asbb", "ba(sss)", method_preset_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2003 SD_BUS_METHOD("PresetUnitFilesWithMode", "assbb", "ba(sss)", method_preset_unit_files_with_mode, SD_BUS_VTABLE_UNPRIVILEGED),
2004 SD_BUS_METHOD("MaskUnitFiles", "asbb", "a(sss)", method_mask_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2005 SD_BUS_METHOD("UnmaskUnitFiles", "asb", "a(sss)", method_unmask_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2006 SD_BUS_METHOD("SetDefaultTarget", "sb", "a(sss)", method_set_default_target, SD_BUS_VTABLE_UNPRIVILEGED),
2007 SD_BUS_METHOD("GetDefaultTarget", NULL, "s", method_get_default_target, SD_BUS_VTABLE_UNPRIVILEGED),
2008 SD_BUS_METHOD("PresetAllUnitFiles", "sbb", "a(sss)", method_preset_all_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2009 SD_BUS_METHOD("AddDependencyUnitFiles", "asssbb", "a(sss)", method_add_dependency_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2010
2011 SD_BUS_SIGNAL("UnitNew", "so", 0),
2012 SD_BUS_SIGNAL("UnitRemoved", "so", 0),
2013 SD_BUS_SIGNAL("JobNew", "uos", 0),
2014 SD_BUS_SIGNAL("JobRemoved", "uoss", 0),
2015 SD_BUS_SIGNAL("StartupFinished", "tttttt", 0),
2016 SD_BUS_SIGNAL("UnitFilesChanged", NULL, 0),
2017 SD_BUS_SIGNAL("Reloading", "b", 0),
2018
2019 SD_BUS_VTABLE_END
2020 };
2021
2022 static int send_finished(sd_bus *bus, void *userdata) {
2023 _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
2024 usec_t *times = userdata;
2025 int r;
2026
2027 assert(bus);
2028 assert(times);
2029
2030 r = sd_bus_message_new_signal(bus, &message, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished");
2031 if (r < 0)
2032 return r;
2033
2034 r = sd_bus_message_append(message, "tttttt", times[0], times[1], times[2], times[3], times[4], times[5]);
2035 if (r < 0)
2036 return r;
2037
2038 return sd_bus_send(bus, message, NULL);
2039 }
2040
2041 void bus_manager_send_finished(
2042 Manager *m,
2043 usec_t firmware_usec,
2044 usec_t loader_usec,
2045 usec_t kernel_usec,
2046 usec_t initrd_usec,
2047 usec_t userspace_usec,
2048 usec_t total_usec) {
2049
2050 int r;
2051
2052 assert(m);
2053
2054 r = bus_foreach_bus(
2055 m,
2056 NULL,
2057 send_finished,
2058 (usec_t[6]) {
2059 firmware_usec,
2060 loader_usec,
2061 kernel_usec,
2062 initrd_usec,
2063 userspace_usec,
2064 total_usec
2065 });
2066 if (r < 0)
2067 log_debug_errno(r, "Failed to send finished signal: %m");
2068 }
2069
2070 static int send_reloading(sd_bus *bus, void *userdata) {
2071 _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
2072 int r;
2073
2074 assert(bus);
2075
2076 r = sd_bus_message_new_signal(bus, &message, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "Reloading");
2077 if (r < 0)
2078 return r;
2079
2080 r = sd_bus_message_append(message, "b", PTR_TO_INT(userdata));
2081 if (r < 0)
2082 return r;
2083
2084 return sd_bus_send(bus, message, NULL);
2085 }
2086
2087 void bus_manager_send_reloading(Manager *m, bool active) {
2088 int r;
2089
2090 assert(m);
2091
2092 r = bus_foreach_bus(m, NULL, send_reloading, INT_TO_PTR(active));
2093 if (r < 0)
2094 log_debug_errno(r, "Failed to send reloading signal: %m");
2095 }
2096
2097 static int send_changed_signal(sd_bus *bus, void *userdata) {
2098 assert(bus);
2099
2100 return sd_bus_emit_properties_changed_strv(bus,
2101 "/org/freedesktop/systemd1",
2102 "org.freedesktop.systemd1.Manager",
2103 NULL);
2104 }
2105
2106 void bus_manager_send_change_signal(Manager *m) {
2107 int r;
2108
2109 assert(m);
2110
2111 r = bus_foreach_bus(m, NULL, send_changed_signal, NULL);
2112 if (r < 0)
2113 log_debug_errno(r, "Failed to send manager change signal: %m");
2114 }