]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dbus-manager.c
5722e3c2bbf37798898d05a0be821197aa114bc9
[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 r = fflush_and_check(f);
1073 if (r < 0)
1074 return r;
1075
1076 return sd_bus_reply_method_return(message, "s", dump);
1077 }
1078
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;
1082 const char *name;
1083 int cleanup;
1084 Snapshot *s = NULL;
1085 int r;
1086
1087 assert(message);
1088 assert(m);
1089
1090 r = mac_selinux_access_check(message, "start", error);
1091 if (r < 0)
1092 return r;
1093
1094 r = sd_bus_message_read(message, "sb", &name, &cleanup);
1095 if (r < 0)
1096 return r;
1097
1098 if (isempty(name))
1099 name = NULL;
1100
1101 r = bus_verify_manage_units_async(m, message, error);
1102 if (r < 0)
1103 return r;
1104 if (r == 0)
1105 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1106
1107 r = snapshot_create(m, name, cleanup, error, &s);
1108 if (r < 0)
1109 return r;
1110
1111 path = unit_dbus_path(UNIT(s));
1112 if (!path)
1113 return -ENOMEM;
1114
1115 return sd_bus_reply_method_return(message, "o", path);
1116 }
1117
1118 static int method_remove_snapshot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1119 Manager *m = userdata;
1120 const char *name;
1121 Unit *u;
1122 int r;
1123
1124 assert(message);
1125 assert(m);
1126
1127 r = sd_bus_message_read(message, "s", &name);
1128 if (r < 0)
1129 return r;
1130
1131 u = manager_get_unit(m, name);
1132 if (!u)
1133 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s does not exist.", name);
1134
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);
1137
1138 return bus_snapshot_method_remove(message, u, error);
1139 }
1140
1141 static int method_reload(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1142 Manager *m = userdata;
1143 int r;
1144
1145 assert(message);
1146 assert(m);
1147
1148 r = mac_selinux_access_check(message, "reload", error);
1149 if (r < 0)
1150 return r;
1151
1152 r = bus_verify_reload_daemon_async(m, message, error);
1153 if (r < 0)
1154 return r;
1155 if (r == 0)
1156 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1157
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
1161 * finished. */
1162
1163 assert(!m->queued_message);
1164 r = sd_bus_message_new_method_return(message, &m->queued_message);
1165 if (r < 0)
1166 return r;
1167
1168 m->exit_code = MANAGER_RELOAD;
1169
1170 return 1;
1171 }
1172
1173 static int method_reexecute(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1174 Manager *m = userdata;
1175 int r;
1176
1177 assert(message);
1178 assert(m);
1179
1180 r = mac_selinux_access_check(message, "reload", error);
1181 if (r < 0)
1182 return r;
1183
1184 r = bus_verify_reload_daemon_async(m, message, error);
1185 if (r < 0)
1186 return r;
1187 if (r == 0)
1188 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1189
1190 /* We don't send a reply back here, the client should
1191 * just wait for us disconnecting. */
1192
1193 m->exit_code = MANAGER_REEXECUTE;
1194 return 1;
1195 }
1196
1197 static int method_exit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1198 Manager *m = userdata;
1199 int r;
1200
1201 assert(message);
1202 assert(m);
1203
1204 r = mac_selinux_access_check(message, "halt", error);
1205 if (r < 0)
1206 return r;
1207
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.");
1210
1211 m->exit_code = MANAGER_EXIT;
1212
1213 return sd_bus_reply_method_return(message, NULL);
1214 }
1215
1216 static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1217 Manager *m = userdata;
1218 int r;
1219
1220 assert(message);
1221 assert(m);
1222
1223 r = mac_selinux_access_check(message, "reboot", error);
1224 if (r < 0)
1225 return r;
1226
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.");
1229
1230 m->exit_code = MANAGER_REBOOT;
1231
1232 return sd_bus_reply_method_return(message, NULL);
1233 }
1234
1235 static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1236 Manager *m = userdata;
1237 int r;
1238
1239 assert(message);
1240 assert(m);
1241
1242 r = mac_selinux_access_check(message, "halt", error);
1243 if (r < 0)
1244 return r;
1245
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.");
1248
1249 m->exit_code = MANAGER_POWEROFF;
1250
1251 return sd_bus_reply_method_return(message, NULL);
1252 }
1253
1254 static int method_halt(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1255 Manager *m = userdata;
1256 int r;
1257
1258 assert(message);
1259 assert(m);
1260
1261 r = mac_selinux_access_check(message, "halt", error);
1262 if (r < 0)
1263 return r;
1264
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.");
1267
1268 m->exit_code = MANAGER_HALT;
1269
1270 return sd_bus_reply_method_return(message, NULL);
1271 }
1272
1273 static int method_kexec(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1274 Manager *m = userdata;
1275 int r;
1276
1277 assert(message);
1278 assert(m);
1279
1280 r = mac_selinux_access_check(message, "reboot", error);
1281 if (r < 0)
1282 return r;
1283
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.");
1286
1287 m->exit_code = MANAGER_KEXEC;
1288
1289 return sd_bus_reply_method_return(message, NULL);
1290 }
1291
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;
1296 int r;
1297
1298 assert(message);
1299 assert(m);
1300
1301 r = mac_selinux_access_check(message, "reboot", error);
1302 if (r < 0)
1303 return r;
1304
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.");
1307
1308 r = sd_bus_message_read(message, "ss", &root, &init);
1309 if (r < 0)
1310 return r;
1311
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);
1314
1315 /* Safety check */
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);
1319 } else {
1320 _cleanup_free_ char *p = NULL;
1321
1322 if (!path_is_absolute(init))
1323 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid init path %s", init);
1324
1325 p = strappend(root, init);
1326 if (!p)
1327 return -ENOMEM;
1328
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);
1331 }
1332
1333 rt = strdup(root);
1334 if (!rt)
1335 return -ENOMEM;
1336
1337 if (!isempty(init)) {
1338 ri = strdup(init);
1339 if (!ri) {
1340 free(rt);
1341 return -ENOMEM;
1342 }
1343 }
1344
1345 free(m->switch_root);
1346 m->switch_root = rt;
1347
1348 free(m->switch_root_init);
1349 m->switch_root_init = ri;
1350
1351 m->exit_code = MANAGER_SWITCH_ROOT;
1352
1353 return sd_bus_reply_method_return(message, NULL);
1354 }
1355
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;
1359 int r;
1360
1361 assert(message);
1362 assert(m);
1363
1364 r = mac_selinux_access_check(message, "reload", error);
1365 if (r < 0)
1366 return r;
1367
1368 r = sd_bus_message_read_strv(message, &plus);
1369 if (r < 0)
1370 return r;
1371 if (!strv_env_is_valid(plus))
1372 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
1373
1374 r = bus_verify_set_environment_async(m, message, error);
1375 if (r < 0)
1376 return r;
1377 if (r == 0)
1378 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1379
1380 r = manager_environment_add(m, NULL, plus);
1381 if (r < 0)
1382 return r;
1383
1384 return sd_bus_reply_method_return(message, NULL);
1385 }
1386
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;
1390 int r;
1391
1392 assert(message);
1393 assert(m);
1394
1395 r = mac_selinux_access_check(message, "reload", error);
1396 if (r < 0)
1397 return r;
1398
1399 r = sd_bus_message_read_strv(message, &minus);
1400 if (r < 0)
1401 return r;
1402
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");
1405
1406 r = bus_verify_set_environment_async(m, message, error);
1407 if (r < 0)
1408 return r;
1409 if (r == 0)
1410 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1411
1412 r = manager_environment_add(m, minus, NULL);
1413 if (r < 0)
1414 return r;
1415
1416 return sd_bus_reply_method_return(message, NULL);
1417 }
1418
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;
1422 int r;
1423
1424 assert(message);
1425 assert(m);
1426
1427 r = mac_selinux_access_check(message, "reload", error);
1428 if (r < 0)
1429 return r;
1430
1431 r = sd_bus_message_read_strv(message, &minus);
1432 if (r < 0)
1433 return r;
1434
1435 r = sd_bus_message_read_strv(message, &plus);
1436 if (r < 0)
1437 return r;
1438
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");
1443
1444 r = bus_verify_set_environment_async(m, message, error);
1445 if (r < 0)
1446 return r;
1447 if (r == 0)
1448 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1449
1450 r = manager_environment_add(m, minus, plus);
1451 if (r < 0)
1452 return r;
1453
1454 return sd_bus_reply_method_return(message, NULL);
1455 }
1456
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;
1460 UnitFileList *item;
1461 Hashmap *h;
1462 Iterator i;
1463 int r;
1464
1465 assert(message);
1466 assert(m);
1467
1468 /* Anyone can call this method */
1469
1470 r = mac_selinux_access_check(message, "status", error);
1471 if (r < 0)
1472 return r;
1473
1474 r = sd_bus_message_new_method_return(message, &reply);
1475 if (r < 0)
1476 return r;
1477
1478 h = hashmap_new(&string_hash_ops);
1479 if (!h)
1480 return -ENOMEM;
1481
1482 r = unit_file_get_list(m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
1483 if (r < 0)
1484 goto fail;
1485
1486 r = sd_bus_message_open_container(reply, 'a', "(ss)");
1487 if (r < 0)
1488 goto fail;
1489
1490 HASHMAP_FOREACH(item, h, i) {
1491
1492 r = sd_bus_message_append(reply, "(ss)", item->path, unit_file_state_to_string(item->state));
1493 if (r < 0)
1494 goto fail;
1495 }
1496
1497 unit_file_list_free(h);
1498
1499 r = sd_bus_message_close_container(reply);
1500 if (r < 0)
1501 return r;
1502
1503 return sd_bus_send(NULL, reply, NULL);
1504
1505 fail:
1506 unit_file_list_free(h);
1507 return r;
1508 }
1509
1510 static int method_get_unit_file_state(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1511 Manager *m = userdata;
1512 const char *name;
1513 UnitFileState state;
1514 UnitFileScope scope;
1515 int r;
1516
1517 assert(message);
1518 assert(m);
1519
1520 /* Anyone can call this method */
1521
1522 r = mac_selinux_access_check(message, "status", error);
1523 if (r < 0)
1524 return r;
1525
1526 r = sd_bus_message_read(message, "s", &name);
1527 if (r < 0)
1528 return r;
1529
1530 scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1531
1532 state = unit_file_get_state(scope, NULL, name);
1533 if (state < 0)
1534 return state;
1535
1536 return sd_bus_reply_method_return(message, "s", unit_file_state_to_string(state));
1537 }
1538
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;
1543 int r;
1544
1545 assert(message);
1546 assert(m);
1547
1548 /* Anyone can call this method */
1549
1550 r = mac_selinux_access_check(message, "status", error);
1551 if (r < 0)
1552 return r;
1553
1554 scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1555
1556 r = unit_file_get_default(scope, NULL, &default_target);
1557 if (r < 0)
1558 return r;
1559
1560 return sd_bus_reply_method_return(message, "s", default_target);
1561 }
1562
1563 static int send_unit_files_changed(sd_bus *bus, void *userdata) {
1564 _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
1565 int r;
1566
1567 assert(bus);
1568
1569 r = sd_bus_message_new_signal(bus, &message, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged");
1570 if (r < 0)
1571 return r;
1572
1573 return sd_bus_send(bus, message, NULL);
1574 }
1575
1576 static int reply_unit_file_changes_and_free(
1577 Manager *m,
1578 sd_bus_message *message,
1579 int carries_install_info,
1580 UnitFileChange *changes,
1581 unsigned n_changes) {
1582
1583 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1584 unsigned i;
1585 int r;
1586
1587 if (n_changes > 0) {
1588 r = bus_foreach_bus(m, NULL, send_unit_files_changed, NULL);
1589 if (r < 0)
1590 log_debug_errno(r, "Failed to send UnitFilesChanged signal: %m");
1591 }
1592
1593 r = sd_bus_message_new_method_return(message, &reply);
1594 if (r < 0)
1595 goto fail;
1596
1597 if (carries_install_info >= 0) {
1598 r = sd_bus_message_append(reply, "b", carries_install_info);
1599 if (r < 0)
1600 goto fail;
1601 }
1602
1603 r = sd_bus_message_open_container(reply, 'a', "(sss)");
1604 if (r < 0)
1605 goto fail;
1606
1607 for (i = 0; i < n_changes; i++) {
1608 r = sd_bus_message_append(
1609 reply, "(sss)",
1610 unit_file_change_type_to_string(changes[i].type),
1611 changes[i].path,
1612 changes[i].source);
1613 if (r < 0)
1614 goto fail;
1615 }
1616
1617 r = sd_bus_message_close_container(reply);
1618 if (r < 0)
1619 goto fail;
1620
1621 return sd_bus_send(NULL, reply, NULL);
1622
1623 fail:
1624 unit_file_changes_free(changes, n_changes);
1625 return r;
1626 }
1627
1628 static int method_enable_unit_files_generic(
1629 sd_bus_message *message,
1630 Manager *m,
1631 const char *verb,
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) {
1635
1636 _cleanup_strv_free_ char **l = NULL;
1637 UnitFileChange *changes = NULL;
1638 unsigned n_changes = 0;
1639 UnitFileScope scope;
1640 int runtime, force, r;
1641
1642 assert(message);
1643 assert(m);
1644
1645 r = sd_bus_message_read_strv(message, &l);
1646 if (r < 0)
1647 return r;
1648
1649 r = sd_bus_message_read(message, "bb", &runtime, &force);
1650 if (r < 0)
1651 return r;
1652
1653 r = mac_selinux_unit_access_check_strv(l, message, m, verb, error);
1654 if (r < 0)
1655 return r;
1656
1657 r = bus_verify_manage_unit_files_async(m, message, error);
1658 if (r < 0)
1659 return r;
1660 if (r == 0)
1661 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1662
1663 scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1664
1665 r = call(scope, runtime, NULL, l, force, &changes, &n_changes);
1666 if (r < 0)
1667 return r;
1668
1669 return reply_unit_file_changes_and_free(m, message, carries_install_info ? r : -1, changes, n_changes);
1670 }
1671
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);
1674 }
1675
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);
1678 }
1679
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);
1682 }
1683
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);
1686 }
1687
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);
1690 }
1691
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);
1694 }
1695
1696 static int method_preset_unit_files_with_mode(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1697
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;
1705 const char *mode;
1706
1707 assert(message);
1708 assert(m);
1709
1710 r = sd_bus_message_read_strv(message, &l);
1711 if (r < 0)
1712 return r;
1713
1714 r = sd_bus_message_read(message, "sbb", &mode, &runtime, &force);
1715 if (r < 0)
1716 return r;
1717
1718 if (isempty(mode))
1719 mm = UNIT_FILE_PRESET_FULL;
1720 else {
1721 mm = unit_file_preset_mode_from_string(mode);
1722 if (mm < 0)
1723 return -EINVAL;
1724 }
1725
1726 r = mac_selinux_unit_access_check_strv(l, message, m, "enable", error);
1727 if (r < 0)
1728 return r;
1729
1730 r = bus_verify_manage_unit_files_async(m, message, error);
1731 if (r < 0)
1732 return r;
1733 if (r == 0)
1734 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1735
1736 scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1737
1738 r = unit_file_preset(scope, runtime, NULL, l, mm, force, &changes, &n_changes);
1739 if (r < 0)
1740 return r;
1741
1742 return reply_unit_file_changes_and_free(m, message, r, changes, n_changes);
1743 }
1744
1745 static int method_disable_unit_files_generic(
1746 sd_bus_message *message,
1747 Manager *m, const
1748 char *verb,
1749 int (*call)(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], UnitFileChange **changes, unsigned *n_changes),
1750 sd_bus_error *error) {
1751
1752 _cleanup_strv_free_ char **l = NULL;
1753 UnitFileChange *changes = NULL;
1754 unsigned n_changes = 0;
1755 UnitFileScope scope;
1756 int r, runtime;
1757
1758 assert(message);
1759 assert(m);
1760
1761 r = sd_bus_message_read_strv(message, &l);
1762 if (r < 0)
1763 return r;
1764
1765 r = sd_bus_message_read(message, "b", &runtime);
1766 if (r < 0)
1767 return r;
1768
1769 r = mac_selinux_unit_access_check_strv(l, message, m, verb, error);
1770 if (r < 0)
1771 return r;
1772
1773 scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1774
1775 r = bus_verify_manage_unit_files_async(m, message, error);
1776 if (r < 0)
1777 return r;
1778 if (r == 0)
1779 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1780
1781 r = call(scope, runtime, NULL, l, &changes, &n_changes);
1782 if (r < 0)
1783 return r;
1784
1785 return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes);
1786 }
1787
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);
1790 }
1791
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);
1794 }
1795
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;
1801 const char *name;
1802 int force, r;
1803
1804 assert(message);
1805 assert(m);
1806
1807 r = mac_selinux_access_check(message, "enable", error);
1808 if (r < 0)
1809 return r;
1810
1811 r = sd_bus_message_read(message, "sb", &name, &force);
1812 if (r < 0)
1813 return r;
1814
1815 r = bus_verify_manage_unit_files_async(m, message, error);
1816 if (r < 0)
1817 return r;
1818 if (r == 0)
1819 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1820
1821 scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1822
1823 r = unit_file_set_default(scope, NULL, name, force, &changes, &n_changes);
1824 if (r < 0)
1825 return r;
1826
1827 return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes);
1828 }
1829
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;
1836 const char *mode;
1837 int force, runtime, r;
1838
1839 assert(message);
1840 assert(m);
1841
1842 r = mac_selinux_access_check(message, "enable", error);
1843 if (r < 0)
1844 return r;
1845
1846 r = sd_bus_message_read(message, "sbb", &mode, &runtime, &force);
1847 if (r < 0)
1848 return r;
1849
1850 if (isempty(mode))
1851 mm = UNIT_FILE_PRESET_FULL;
1852 else {
1853 mm = unit_file_preset_mode_from_string(mode);
1854 if (mm < 0)
1855 return -EINVAL;
1856 }
1857
1858 r = bus_verify_manage_unit_files_async(m, message, error);
1859 if (r < 0)
1860 return r;
1861 if (r == 0)
1862 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1863
1864 scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1865
1866 r = unit_file_preset_all(scope, runtime, NULL, mm, force, &changes, &n_changes);
1867 if (r < 0)
1868 return r;
1869
1870 return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes);
1871 }
1872
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;
1880 char *target;
1881 char *type;
1882 UnitDependency dep;
1883
1884 assert(message);
1885 assert(m);
1886
1887 r = bus_verify_manage_unit_files_async(m, message, error);
1888 if (r < 0)
1889 return r;
1890 if (r == 0)
1891 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1892
1893 r = sd_bus_message_read_strv(message, &l);
1894 if (r < 0)
1895 return r;
1896
1897 r = sd_bus_message_read(message, "ssbb", &target, &type, &runtime, &force);
1898 if (r < 0)
1899 return r;
1900
1901 dep = unit_dependency_from_string(type);
1902 if (dep < 0)
1903 return -EINVAL;
1904
1905 r = mac_selinux_unit_access_check_strv(l, message, m, "enable", error);
1906 if (r < 0)
1907 return r;
1908
1909 scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1910
1911 r = unit_file_add_dependency(scope, runtime, NULL, l, target, dep, force, &changes, &n_changes);
1912 if (r < 0)
1913 return r;
1914
1915 return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes);
1916 }
1917
1918 const sd_bus_vtable bus_manager_vtable[] = {
1919 SD_BUS_VTABLE_START(0),
1920
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),
1956
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),
2009
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),
2017
2018 SD_BUS_VTABLE_END
2019 };
2020
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;
2024 int r;
2025
2026 assert(bus);
2027 assert(times);
2028
2029 r = sd_bus_message_new_signal(bus, &message, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished");
2030 if (r < 0)
2031 return r;
2032
2033 r = sd_bus_message_append(message, "tttttt", times[0], times[1], times[2], times[3], times[4], times[5]);
2034 if (r < 0)
2035 return r;
2036
2037 return sd_bus_send(bus, message, NULL);
2038 }
2039
2040 void bus_manager_send_finished(
2041 Manager *m,
2042 usec_t firmware_usec,
2043 usec_t loader_usec,
2044 usec_t kernel_usec,
2045 usec_t initrd_usec,
2046 usec_t userspace_usec,
2047 usec_t total_usec) {
2048
2049 int r;
2050
2051 assert(m);
2052
2053 r = bus_foreach_bus(
2054 m,
2055 NULL,
2056 send_finished,
2057 (usec_t[6]) {
2058 firmware_usec,
2059 loader_usec,
2060 kernel_usec,
2061 initrd_usec,
2062 userspace_usec,
2063 total_usec
2064 });
2065 if (r < 0)
2066 log_debug_errno(r, "Failed to send finished signal: %m");
2067 }
2068
2069 static int send_reloading(sd_bus *bus, void *userdata) {
2070 _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
2071 int r;
2072
2073 assert(bus);
2074
2075 r = sd_bus_message_new_signal(bus, &message, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "Reloading");
2076 if (r < 0)
2077 return r;
2078
2079 r = sd_bus_message_append(message, "b", PTR_TO_INT(userdata));
2080 if (r < 0)
2081 return r;
2082
2083 return sd_bus_send(bus, message, NULL);
2084 }
2085
2086 void bus_manager_send_reloading(Manager *m, bool active) {
2087 int r;
2088
2089 assert(m);
2090
2091 r = bus_foreach_bus(m, NULL, send_reloading, INT_TO_PTR(active));
2092 if (r < 0)
2093 log_debug_errno(r, "Failed to send reloading signal: %m");
2094 }
2095
2096 static int send_changed_signal(sd_bus *bus, void *userdata) {
2097 assert(bus);
2098
2099 return sd_bus_emit_properties_changed_strv(bus,
2100 "/org/freedesktop/systemd1",
2101 "org.freedesktop.systemd1.Manager",
2102 NULL);
2103 }
2104
2105 void bus_manager_send_change_signal(Manager *m) {
2106 int r;
2107
2108 assert(m);
2109
2110 r = bus_foreach_bus(m, NULL, send_changed_signal, NULL);
2111 if (r < 0)
2112 log_debug_errno(r, "Failed to send manager change signal: %m");
2113 }