]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dbus-manager.c
sd-bus: drop bus parameter from message callback prototype
[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(sd_bus_message_get_bus(reply), 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(sd_bus_message_get_bus(reply), 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->queued_message_bus = sd_bus_ref(sd_bus_message_get_bus(message));
1170 m->exit_code = MANAGER_RELOAD;
1171
1172 return 1;
1173 }
1174
1175 static int method_reexecute(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1176 Manager *m = userdata;
1177 int r;
1178
1179 assert(message);
1180 assert(m);
1181
1182 r = mac_selinux_access_check(message, "reload", error);
1183 if (r < 0)
1184 return r;
1185
1186 r = bus_verify_reload_daemon_async(m, message, error);
1187 if (r < 0)
1188 return r;
1189 if (r == 0)
1190 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1191
1192 /* We don't send a reply back here, the client should
1193 * just wait for us disconnecting. */
1194
1195 m->exit_code = MANAGER_REEXECUTE;
1196 return 1;
1197 }
1198
1199 static int method_exit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1200 Manager *m = userdata;
1201 int r;
1202
1203 assert(message);
1204 assert(m);
1205
1206 r = mac_selinux_access_check(message, "halt", error);
1207 if (r < 0)
1208 return r;
1209
1210 if (m->running_as == SYSTEMD_SYSTEM)
1211 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
1212
1213 m->exit_code = MANAGER_EXIT;
1214
1215 return sd_bus_reply_method_return(message, NULL);
1216 }
1217
1218 static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1219 Manager *m = userdata;
1220 int r;
1221
1222 assert(message);
1223 assert(m);
1224
1225 r = mac_selinux_access_check(message, "reboot", error);
1226 if (r < 0)
1227 return r;
1228
1229 if (m->running_as != SYSTEMD_SYSTEM)
1230 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
1231
1232 m->exit_code = MANAGER_REBOOT;
1233
1234 return sd_bus_reply_method_return(message, NULL);
1235 }
1236
1237 static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1238 Manager *m = userdata;
1239 int r;
1240
1241 assert(message);
1242 assert(m);
1243
1244 r = mac_selinux_access_check(message, "halt", error);
1245 if (r < 0)
1246 return r;
1247
1248 if (m->running_as != SYSTEMD_SYSTEM)
1249 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
1250
1251 m->exit_code = MANAGER_POWEROFF;
1252
1253 return sd_bus_reply_method_return(message, NULL);
1254 }
1255
1256 static int method_halt(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1257 Manager *m = userdata;
1258 int r;
1259
1260 assert(message);
1261 assert(m);
1262
1263 r = mac_selinux_access_check(message, "halt", error);
1264 if (r < 0)
1265 return r;
1266
1267 if (m->running_as != SYSTEMD_SYSTEM)
1268 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Halt is only supported for system managers.");
1269
1270 m->exit_code = MANAGER_HALT;
1271
1272 return sd_bus_reply_method_return(message, NULL);
1273 }
1274
1275 static int method_kexec(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1276 Manager *m = userdata;
1277 int r;
1278
1279 assert(message);
1280 assert(m);
1281
1282 r = mac_selinux_access_check(message, "reboot", error);
1283 if (r < 0)
1284 return r;
1285
1286 if (m->running_as != SYSTEMD_SYSTEM)
1287 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "KExec is only supported for system managers.");
1288
1289 m->exit_code = MANAGER_KEXEC;
1290
1291 return sd_bus_reply_method_return(message, NULL);
1292 }
1293
1294 static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1295 char *ri = NULL, *rt = NULL;
1296 const char *root, *init;
1297 Manager *m = userdata;
1298 int r;
1299
1300 assert(message);
1301 assert(m);
1302
1303 r = mac_selinux_access_check(message, "reboot", error);
1304 if (r < 0)
1305 return r;
1306
1307 if (m->running_as != SYSTEMD_SYSTEM)
1308 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Root switching is only supported by system manager.");
1309
1310 r = sd_bus_message_read(message, "ss", &root, &init);
1311 if (r < 0)
1312 return r;
1313
1314 if (path_equal(root, "/") || !path_is_absolute(root))
1315 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid switch root path %s", root);
1316
1317 /* Safety check */
1318 if (isempty(init)) {
1319 if (!path_is_os_tree(root))
1320 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);
1321 } else {
1322 _cleanup_free_ char *p = NULL;
1323
1324 if (!path_is_absolute(init))
1325 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid init path %s", init);
1326
1327 p = strappend(root, init);
1328 if (!p)
1329 return -ENOMEM;
1330
1331 if (access(p, X_OK) < 0)
1332 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified init binary %s does not exist.", p);
1333 }
1334
1335 rt = strdup(root);
1336 if (!rt)
1337 return -ENOMEM;
1338
1339 if (!isempty(init)) {
1340 ri = strdup(init);
1341 if (!ri) {
1342 free(rt);
1343 return -ENOMEM;
1344 }
1345 }
1346
1347 free(m->switch_root);
1348 m->switch_root = rt;
1349
1350 free(m->switch_root_init);
1351 m->switch_root_init = ri;
1352
1353 m->exit_code = MANAGER_SWITCH_ROOT;
1354
1355 return sd_bus_reply_method_return(message, NULL);
1356 }
1357
1358 static int method_set_environment(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1359 _cleanup_strv_free_ char **plus = NULL;
1360 Manager *m = userdata;
1361 int r;
1362
1363 assert(message);
1364 assert(m);
1365
1366 r = mac_selinux_access_check(message, "reload", error);
1367 if (r < 0)
1368 return r;
1369
1370 r = sd_bus_message_read_strv(message, &plus);
1371 if (r < 0)
1372 return r;
1373 if (!strv_env_is_valid(plus))
1374 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
1375
1376 r = bus_verify_set_environment_async(m, message, error);
1377 if (r < 0)
1378 return r;
1379 if (r == 0)
1380 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1381
1382 r = manager_environment_add(m, NULL, plus);
1383 if (r < 0)
1384 return r;
1385
1386 return sd_bus_reply_method_return(message, NULL);
1387 }
1388
1389 static int method_unset_environment(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1390 _cleanup_strv_free_ char **minus = NULL;
1391 Manager *m = userdata;
1392 int r;
1393
1394 assert(message);
1395 assert(m);
1396
1397 r = mac_selinux_access_check(message, "reload", error);
1398 if (r < 0)
1399 return r;
1400
1401 r = sd_bus_message_read_strv(message, &minus);
1402 if (r < 0)
1403 return r;
1404
1405 if (!strv_env_name_or_assignment_is_valid(minus))
1406 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment variable names or assignments");
1407
1408 r = bus_verify_set_environment_async(m, message, error);
1409 if (r < 0)
1410 return r;
1411 if (r == 0)
1412 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1413
1414 r = manager_environment_add(m, minus, NULL);
1415 if (r < 0)
1416 return r;
1417
1418 return sd_bus_reply_method_return(message, NULL);
1419 }
1420
1421 static int method_unset_and_set_environment(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1422 _cleanup_strv_free_ char **minus = NULL, **plus = NULL;
1423 Manager *m = userdata;
1424 int r;
1425
1426 assert(message);
1427 assert(m);
1428
1429 r = mac_selinux_access_check(message, "reload", error);
1430 if (r < 0)
1431 return r;
1432
1433 r = sd_bus_message_read_strv(message, &minus);
1434 if (r < 0)
1435 return r;
1436
1437 r = sd_bus_message_read_strv(message, &plus);
1438 if (r < 0)
1439 return r;
1440
1441 if (!strv_env_name_or_assignment_is_valid(minus))
1442 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment variable names or assignments");
1443 if (!strv_env_is_valid(plus))
1444 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
1445
1446 r = bus_verify_set_environment_async(m, message, error);
1447 if (r < 0)
1448 return r;
1449 if (r == 0)
1450 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1451
1452 r = manager_environment_add(m, minus, plus);
1453 if (r < 0)
1454 return r;
1455
1456 return sd_bus_reply_method_return(message, NULL);
1457 }
1458
1459 static int method_list_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1460 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1461 Manager *m = userdata;
1462 UnitFileList *item;
1463 Hashmap *h;
1464 Iterator i;
1465 int r;
1466
1467 assert(message);
1468 assert(m);
1469
1470 /* Anyone can call this method */
1471
1472 r = mac_selinux_access_check(message, "status", error);
1473 if (r < 0)
1474 return r;
1475
1476 r = sd_bus_message_new_method_return(message, &reply);
1477 if (r < 0)
1478 return r;
1479
1480 h = hashmap_new(&string_hash_ops);
1481 if (!h)
1482 return -ENOMEM;
1483
1484 r = unit_file_get_list(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
1485 if (r < 0)
1486 goto fail;
1487
1488 r = sd_bus_message_open_container(reply, 'a', "(ss)");
1489 if (r < 0)
1490 goto fail;
1491
1492 HASHMAP_FOREACH(item, h, i) {
1493
1494 r = sd_bus_message_append(reply, "(ss)", item->path, unit_file_state_to_string(item->state));
1495 if (r < 0)
1496 goto fail;
1497 }
1498
1499 unit_file_list_free(h);
1500
1501 r = sd_bus_message_close_container(reply);
1502 if (r < 0)
1503 return r;
1504
1505 return sd_bus_send(sd_bus_message_get_bus(reply), reply, NULL);
1506
1507 fail:
1508 unit_file_list_free(h);
1509 return r;
1510 }
1511
1512 static int method_get_unit_file_state(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1513 Manager *m = userdata;
1514 const char *name;
1515 UnitFileState state;
1516 UnitFileScope scope;
1517 int r;
1518
1519 assert(message);
1520 assert(m);
1521
1522 /* Anyone can call this method */
1523
1524 r = mac_selinux_access_check(message, "status", error);
1525 if (r < 0)
1526 return r;
1527
1528 r = sd_bus_message_read(message, "s", &name);
1529 if (r < 0)
1530 return r;
1531
1532 scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1533
1534 state = unit_file_get_state(scope, NULL, name);
1535 if (state < 0)
1536 return state;
1537
1538 return sd_bus_reply_method_return(message, "s", unit_file_state_to_string(state));
1539 }
1540
1541 static int method_get_default_target(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1542 _cleanup_free_ char *default_target = NULL;
1543 Manager *m = userdata;
1544 UnitFileScope scope;
1545 int r;
1546
1547 assert(message);
1548 assert(m);
1549
1550 /* Anyone can call this method */
1551
1552 r = mac_selinux_access_check(message, "status", error);
1553 if (r < 0)
1554 return r;
1555
1556 scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1557
1558 r = unit_file_get_default(scope, NULL, &default_target);
1559 if (r < 0)
1560 return r;
1561
1562 return sd_bus_reply_method_return(message, "s", default_target);
1563 }
1564
1565 static int send_unit_files_changed(sd_bus *bus, void *userdata) {
1566 _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
1567 int r;
1568
1569 assert(bus);
1570
1571 r = sd_bus_message_new_signal(bus, &message, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged");
1572 if (r < 0)
1573 return r;
1574
1575 return sd_bus_send(bus, message, NULL);
1576 }
1577
1578 static int reply_unit_file_changes_and_free(
1579 Manager *m,
1580 sd_bus_message *message,
1581 int carries_install_info,
1582 UnitFileChange *changes,
1583 unsigned n_changes) {
1584
1585 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1586 unsigned i;
1587 int r;
1588
1589 if (n_changes > 0) {
1590 r = bus_foreach_bus(m, NULL, send_unit_files_changed, NULL);
1591 if (r < 0)
1592 log_debug_errno(r, "Failed to send UnitFilesChanged signal: %m");
1593 }
1594
1595 r = sd_bus_message_new_method_return(message, &reply);
1596 if (r < 0)
1597 goto fail;
1598
1599 if (carries_install_info >= 0) {
1600 r = sd_bus_message_append(reply, "b", carries_install_info);
1601 if (r < 0)
1602 goto fail;
1603 }
1604
1605 r = sd_bus_message_open_container(reply, 'a', "(sss)");
1606 if (r < 0)
1607 goto fail;
1608
1609 for (i = 0; i < n_changes; i++) {
1610 r = sd_bus_message_append(
1611 reply, "(sss)",
1612 unit_file_change_type_to_string(changes[i].type),
1613 changes[i].path,
1614 changes[i].source);
1615 if (r < 0)
1616 goto fail;
1617 }
1618
1619 r = sd_bus_message_close_container(reply);
1620 if (r < 0)
1621 goto fail;
1622
1623 return sd_bus_send(sd_bus_message_get_bus(message), reply, NULL);
1624
1625 fail:
1626 unit_file_changes_free(changes, n_changes);
1627 return r;
1628 }
1629
1630 static int method_enable_unit_files_generic(
1631 sd_bus_message *message,
1632 Manager *m,
1633 const char *verb,
1634 int (*call)(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes),
1635 bool carries_install_info,
1636 sd_bus_error *error) {
1637
1638 _cleanup_strv_free_ char **l = NULL;
1639 UnitFileChange *changes = NULL;
1640 unsigned n_changes = 0;
1641 UnitFileScope scope;
1642 int runtime, force, r;
1643
1644 assert(message);
1645 assert(m);
1646
1647 r = sd_bus_message_read_strv(message, &l);
1648 if (r < 0)
1649 return r;
1650
1651 r = sd_bus_message_read(message, "bb", &runtime, &force);
1652 if (r < 0)
1653 return r;
1654
1655 r = mac_selinux_unit_access_check_strv(l, message, m, verb, error);
1656 if (r < 0)
1657 return r;
1658
1659 r = bus_verify_manage_unit_files_async(m, message, error);
1660 if (r < 0)
1661 return r;
1662 if (r == 0)
1663 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1664
1665 scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1666
1667 r = call(scope, runtime, NULL, l, force, &changes, &n_changes);
1668 if (r < 0)
1669 return r;
1670
1671 return reply_unit_file_changes_and_free(m, message, carries_install_info ? r : -1, changes, n_changes);
1672 }
1673
1674 static int method_enable_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1675 return method_enable_unit_files_generic(message, userdata, "enable", unit_file_enable, true, error);
1676 }
1677
1678 static int method_reenable_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1679 return method_enable_unit_files_generic(message, userdata, "enable", unit_file_reenable, true, error);
1680 }
1681
1682 static int method_link_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1683 return method_enable_unit_files_generic(message, userdata, "enable", unit_file_link, false, error);
1684 }
1685
1686 static int unit_file_preset_without_mode(UnitFileScope scope, bool runtime, const char *root_dir, char **files, bool force, UnitFileChange **changes, unsigned *n_changes) {
1687 return unit_file_preset(scope, runtime, root_dir, files, UNIT_FILE_PRESET_FULL, force, changes, n_changes);
1688 }
1689
1690 static int method_preset_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1691 return method_enable_unit_files_generic(message, userdata, "enable", unit_file_preset_without_mode, true, error);
1692 }
1693
1694 static int method_mask_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1695 return method_enable_unit_files_generic(message, userdata, "disable", unit_file_mask, false, error);
1696 }
1697
1698 static int method_preset_unit_files_with_mode(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1699
1700 _cleanup_strv_free_ char **l = NULL;
1701 UnitFileChange *changes = NULL;
1702 unsigned n_changes = 0;
1703 Manager *m = userdata;
1704 UnitFilePresetMode mm;
1705 UnitFileScope scope;
1706 int runtime, force, r;
1707 const char *mode;
1708
1709 assert(message);
1710 assert(m);
1711
1712 r = sd_bus_message_read_strv(message, &l);
1713 if (r < 0)
1714 return r;
1715
1716 r = sd_bus_message_read(message, "sbb", &mode, &runtime, &force);
1717 if (r < 0)
1718 return r;
1719
1720 if (isempty(mode))
1721 mm = UNIT_FILE_PRESET_FULL;
1722 else {
1723 mm = unit_file_preset_mode_from_string(mode);
1724 if (mm < 0)
1725 return -EINVAL;
1726 }
1727
1728 r = mac_selinux_unit_access_check_strv(l, message, m, "enable", error);
1729 if (r < 0)
1730 return r;
1731
1732 r = bus_verify_manage_unit_files_async(m, message, error);
1733 if (r < 0)
1734 return r;
1735 if (r == 0)
1736 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1737
1738 scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1739
1740 r = unit_file_preset(scope, runtime, NULL, l, mm, force, &changes, &n_changes);
1741 if (r < 0)
1742 return r;
1743
1744 return reply_unit_file_changes_and_free(m, message, r, changes, n_changes);
1745 }
1746
1747 static int method_disable_unit_files_generic(
1748 sd_bus_message *message,
1749 Manager *m, const
1750 char *verb,
1751 int (*call)(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], UnitFileChange **changes, unsigned *n_changes),
1752 sd_bus_error *error) {
1753
1754 _cleanup_strv_free_ char **l = NULL;
1755 UnitFileChange *changes = NULL;
1756 unsigned n_changes = 0;
1757 UnitFileScope scope;
1758 int r, runtime;
1759
1760 assert(message);
1761 assert(m);
1762
1763 r = sd_bus_message_read_strv(message, &l);
1764 if (r < 0)
1765 return r;
1766
1767 r = sd_bus_message_read(message, "b", &runtime);
1768 if (r < 0)
1769 return r;
1770
1771 r = mac_selinux_unit_access_check_strv(l, message, m, verb, error);
1772 if (r < 0)
1773 return r;
1774
1775 scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1776
1777 r = bus_verify_manage_unit_files_async(m, message, error);
1778 if (r < 0)
1779 return r;
1780 if (r == 0)
1781 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1782
1783 r = call(scope, runtime, NULL, l, &changes, &n_changes);
1784 if (r < 0)
1785 return r;
1786
1787 return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes);
1788 }
1789
1790 static int method_disable_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1791 return method_disable_unit_files_generic(message, userdata, "disable", unit_file_disable, error);
1792 }
1793
1794 static int method_unmask_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1795 return method_disable_unit_files_generic(message, userdata, "enable", unit_file_unmask, error);
1796 }
1797
1798 static int method_set_default_target(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1799 UnitFileChange *changes = NULL;
1800 unsigned n_changes = 0;
1801 Manager *m = userdata;
1802 UnitFileScope scope;
1803 const char *name;
1804 int force, r;
1805
1806 assert(message);
1807 assert(m);
1808
1809 r = mac_selinux_access_check(message, "enable", error);
1810 if (r < 0)
1811 return r;
1812
1813 r = sd_bus_message_read(message, "sb", &name, &force);
1814 if (r < 0)
1815 return r;
1816
1817 r = bus_verify_manage_unit_files_async(m, message, error);
1818 if (r < 0)
1819 return r;
1820 if (r == 0)
1821 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1822
1823 scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1824
1825 r = unit_file_set_default(scope, NULL, name, force, &changes, &n_changes);
1826 if (r < 0)
1827 return r;
1828
1829 return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes);
1830 }
1831
1832 static int method_preset_all_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1833 UnitFileChange *changes = NULL;
1834 unsigned n_changes = 0;
1835 Manager *m = userdata;
1836 UnitFilePresetMode mm;
1837 UnitFileScope scope;
1838 const char *mode;
1839 int force, runtime, r;
1840
1841 assert(message);
1842 assert(m);
1843
1844 r = mac_selinux_access_check(message, "enable", error);
1845 if (r < 0)
1846 return r;
1847
1848 r = sd_bus_message_read(message, "sbb", &mode, &runtime, &force);
1849 if (r < 0)
1850 return r;
1851
1852 if (isempty(mode))
1853 mm = UNIT_FILE_PRESET_FULL;
1854 else {
1855 mm = unit_file_preset_mode_from_string(mode);
1856 if (mm < 0)
1857 return -EINVAL;
1858 }
1859
1860 r = bus_verify_manage_unit_files_async(m, message, error);
1861 if (r < 0)
1862 return r;
1863 if (r == 0)
1864 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1865
1866 scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1867
1868 r = unit_file_preset_all(scope, runtime, NULL, mm, force, &changes, &n_changes);
1869 if (r < 0)
1870 return r;
1871
1872 return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes);
1873 }
1874
1875 static int method_add_dependency_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1876 _cleanup_strv_free_ char **l = NULL;
1877 Manager *m = userdata;
1878 UnitFileChange *changes = NULL;
1879 unsigned n_changes = 0;
1880 UnitFileScope scope;
1881 int runtime, force, r;
1882 char *target;
1883 char *type;
1884 UnitDependency dep;
1885
1886 assert(message);
1887 assert(m);
1888
1889 r = bus_verify_manage_unit_files_async(m, message, error);
1890 if (r < 0)
1891 return r;
1892 if (r == 0)
1893 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1894
1895 r = sd_bus_message_read_strv(message, &l);
1896 if (r < 0)
1897 return r;
1898
1899 r = sd_bus_message_read(message, "ssbb", &target, &type, &runtime, &force);
1900 if (r < 0)
1901 return r;
1902
1903 dep = unit_dependency_from_string(type);
1904 if (dep < 0)
1905 return -EINVAL;
1906
1907 r = mac_selinux_unit_access_check_strv(l, message, m, "enable", error);
1908 if (r < 0)
1909 return r;
1910
1911 scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1912
1913 r = unit_file_add_dependency(scope, runtime, NULL, l, target, dep, force, &changes, &n_changes);
1914 if (r < 0)
1915 return r;
1916
1917 return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes);
1918 }
1919
1920 const sd_bus_vtable bus_manager_vtable[] = {
1921 SD_BUS_VTABLE_START(0),
1922
1923 SD_BUS_PROPERTY("Version", "s", property_get_version, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1924 SD_BUS_PROPERTY("Features", "s", property_get_features, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1925 SD_BUS_PROPERTY("Virtualization", "s", property_get_virtualization, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1926 SD_BUS_PROPERTY("Architecture", "s", property_get_architecture, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1927 SD_BUS_PROPERTY("Tainted", "s", property_get_tainted, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1928 BUS_PROPERTY_DUAL_TIMESTAMP("FirmwareTimestamp", offsetof(Manager, firmware_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1929 BUS_PROPERTY_DUAL_TIMESTAMP("LoaderTimestamp", offsetof(Manager, loader_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1930 BUS_PROPERTY_DUAL_TIMESTAMP("KernelTimestamp", offsetof(Manager, kernel_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1931 BUS_PROPERTY_DUAL_TIMESTAMP("InitRDTimestamp", offsetof(Manager, initrd_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1932 BUS_PROPERTY_DUAL_TIMESTAMP("UserspaceTimestamp", offsetof(Manager, userspace_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1933 BUS_PROPERTY_DUAL_TIMESTAMP("FinishTimestamp", offsetof(Manager, finish_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1934 BUS_PROPERTY_DUAL_TIMESTAMP("SecurityStartTimestamp", offsetof(Manager, security_start_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1935 BUS_PROPERTY_DUAL_TIMESTAMP("SecurityFinishTimestamp", offsetof(Manager, security_finish_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1936 BUS_PROPERTY_DUAL_TIMESTAMP("GeneratorsStartTimestamp", offsetof(Manager, generators_start_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1937 BUS_PROPERTY_DUAL_TIMESTAMP("GeneratorsFinishTimestamp", offsetof(Manager, generators_finish_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1938 BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadStartTimestamp", offsetof(Manager, units_load_start_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1939 BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadFinishTimestamp", offsetof(Manager, units_load_finish_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1940 SD_BUS_WRITABLE_PROPERTY("LogLevel", "s", property_get_log_level, property_set_log_level, 0, 0),
1941 SD_BUS_WRITABLE_PROPERTY("LogTarget", "s", property_get_log_target, property_set_log_target, 0, 0),
1942 SD_BUS_PROPERTY("NNames", "u", property_get_n_names, 0, 0),
1943 SD_BUS_PROPERTY("NFailedUnits", "u", property_get_n_failed_units, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1944 SD_BUS_PROPERTY("NJobs", "u", property_get_n_jobs, 0, 0),
1945 SD_BUS_PROPERTY("NInstalledJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_installed_jobs), 0),
1946 SD_BUS_PROPERTY("NFailedJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_failed_jobs), 0),
1947 SD_BUS_PROPERTY("Progress", "d", property_get_progress, 0, 0),
1948 SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(Manager, environment), 0),
1949 SD_BUS_PROPERTY("ConfirmSpawn", "b", bus_property_get_bool, offsetof(Manager, confirm_spawn), SD_BUS_VTABLE_PROPERTY_CONST),
1950 SD_BUS_PROPERTY("ShowStatus", "b", bus_property_get_bool, offsetof(Manager, show_status), SD_BUS_VTABLE_PROPERTY_CONST),
1951 SD_BUS_PROPERTY("UnitPath", "as", NULL, offsetof(Manager, lookup_paths.unit_path), SD_BUS_VTABLE_PROPERTY_CONST),
1952 SD_BUS_PROPERTY("DefaultStandardOutput", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), SD_BUS_VTABLE_PROPERTY_CONST),
1953 SD_BUS_PROPERTY("DefaultStandardError", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), SD_BUS_VTABLE_PROPERTY_CONST),
1954 SD_BUS_WRITABLE_PROPERTY("RuntimeWatchdogUSec", "t", bus_property_get_usec, property_set_runtime_watchdog, offsetof(Manager, runtime_watchdog), 0),
1955 SD_BUS_WRITABLE_PROPERTY("ShutdownWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, shutdown_watchdog), 0),
1956 SD_BUS_PROPERTY("ControlGroup", "s", NULL, offsetof(Manager, cgroup_root), 0),
1957 SD_BUS_PROPERTY("SystemState", "s", property_get_system_state, 0, 0),
1958
1959 SD_BUS_METHOD("GetUnit", "s", "o", method_get_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1960 SD_BUS_METHOD("GetUnitByPID", "u", "o", method_get_unit_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
1961 SD_BUS_METHOD("LoadUnit", "s", "o", method_load_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1962 SD_BUS_METHOD("StartUnit", "ss", "o", method_start_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1963 SD_BUS_METHOD("StartUnitReplace", "sss", "o", method_start_unit_replace, SD_BUS_VTABLE_UNPRIVILEGED),
1964 SD_BUS_METHOD("StopUnit", "ss", "o", method_stop_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1965 SD_BUS_METHOD("ReloadUnit", "ss", "o", method_reload_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1966 SD_BUS_METHOD("RestartUnit", "ss", "o", method_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1967 SD_BUS_METHOD("TryRestartUnit", "ss", "o", method_try_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1968 SD_BUS_METHOD("ReloadOrRestartUnit", "ss", "o", method_reload_or_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1969 SD_BUS_METHOD("ReloadOrTryRestartUnit", "ss", "o", method_reload_or_try_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1970 SD_BUS_METHOD("KillUnit", "ssi", NULL, method_kill_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1971 SD_BUS_METHOD("ResetFailedUnit", "s", NULL, method_reset_failed_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1972 SD_BUS_METHOD("SetUnitProperties", "sba(sv)", NULL, method_set_unit_properties, SD_BUS_VTABLE_UNPRIVILEGED),
1973 SD_BUS_METHOD("StartTransientUnit", "ssa(sv)a(sa(sv))", "o", method_start_transient_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1974 SD_BUS_METHOD("GetJob", "u", "o", method_get_job, SD_BUS_VTABLE_UNPRIVILEGED),
1975 SD_BUS_METHOD("CancelJob", "u", NULL, method_cancel_job, SD_BUS_VTABLE_UNPRIVILEGED),
1976 SD_BUS_METHOD("ClearJobs", NULL, NULL, method_clear_jobs, SD_BUS_VTABLE_UNPRIVILEGED),
1977 SD_BUS_METHOD("ResetFailed", NULL, NULL, method_reset_failed, SD_BUS_VTABLE_UNPRIVILEGED),
1978 SD_BUS_METHOD("ListUnits", NULL, "a(ssssssouso)", method_list_units, SD_BUS_VTABLE_UNPRIVILEGED),
1979 SD_BUS_METHOD("ListUnitsFiltered", "as", "a(ssssssouso)", method_list_units_filtered, SD_BUS_VTABLE_UNPRIVILEGED),
1980 SD_BUS_METHOD("ListJobs", NULL, "a(usssoo)", method_list_jobs, SD_BUS_VTABLE_UNPRIVILEGED),
1981 SD_BUS_METHOD("Subscribe", NULL, NULL, method_subscribe, SD_BUS_VTABLE_UNPRIVILEGED),
1982 SD_BUS_METHOD("Unsubscribe", NULL, NULL, method_unsubscribe, SD_BUS_VTABLE_UNPRIVILEGED),
1983 SD_BUS_METHOD("Dump", NULL, "s", method_dump, SD_BUS_VTABLE_UNPRIVILEGED),
1984 SD_BUS_METHOD("CreateSnapshot", "sb", "o", method_create_snapshot, SD_BUS_VTABLE_UNPRIVILEGED),
1985 SD_BUS_METHOD("RemoveSnapshot", "s", NULL, method_remove_snapshot, SD_BUS_VTABLE_UNPRIVILEGED),
1986 SD_BUS_METHOD("Reload", NULL, NULL, method_reload, SD_BUS_VTABLE_UNPRIVILEGED),
1987 SD_BUS_METHOD("Reexecute", NULL, NULL, method_reexecute, SD_BUS_VTABLE_UNPRIVILEGED),
1988 SD_BUS_METHOD("Exit", NULL, NULL, method_exit, 0),
1989 SD_BUS_METHOD("Reboot", NULL, NULL, method_reboot, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
1990 SD_BUS_METHOD("PowerOff", NULL, NULL, method_poweroff, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
1991 SD_BUS_METHOD("Halt", NULL, NULL, method_halt, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
1992 SD_BUS_METHOD("KExec", NULL, NULL, method_kexec, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
1993 SD_BUS_METHOD("SwitchRoot", "ss", NULL, method_switch_root, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
1994 SD_BUS_METHOD("SetEnvironment", "as", NULL, method_set_environment, SD_BUS_VTABLE_UNPRIVILEGED),
1995 SD_BUS_METHOD("UnsetEnvironment", "as", NULL, method_unset_environment, SD_BUS_VTABLE_UNPRIVILEGED),
1996 SD_BUS_METHOD("UnsetAndSetEnvironment", "asas", NULL, method_unset_and_set_environment, SD_BUS_VTABLE_UNPRIVILEGED),
1997 SD_BUS_METHOD("ListUnitFiles", NULL, "a(ss)", method_list_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
1998 SD_BUS_METHOD("GetUnitFileState", "s", "s", method_get_unit_file_state, SD_BUS_VTABLE_UNPRIVILEGED),
1999 SD_BUS_METHOD("EnableUnitFiles", "asbb", "ba(sss)", method_enable_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2000 SD_BUS_METHOD("DisableUnitFiles", "asb", "a(sss)", method_disable_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2001 SD_BUS_METHOD("ReenableUnitFiles", "asbb", "ba(sss)", method_reenable_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2002 SD_BUS_METHOD("LinkUnitFiles", "asbb", "a(sss)", method_link_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2003 SD_BUS_METHOD("PresetUnitFiles", "asbb", "ba(sss)", method_preset_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2004 SD_BUS_METHOD("PresetUnitFilesWithMode", "assbb", "ba(sss)", method_preset_unit_files_with_mode, SD_BUS_VTABLE_UNPRIVILEGED),
2005 SD_BUS_METHOD("MaskUnitFiles", "asbb", "a(sss)", method_mask_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2006 SD_BUS_METHOD("UnmaskUnitFiles", "asb", "a(sss)", method_unmask_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2007 SD_BUS_METHOD("SetDefaultTarget", "sb", "a(sss)", method_set_default_target, SD_BUS_VTABLE_UNPRIVILEGED),
2008 SD_BUS_METHOD("GetDefaultTarget", NULL, "s", method_get_default_target, SD_BUS_VTABLE_UNPRIVILEGED),
2009 SD_BUS_METHOD("PresetAllUnitFiles", "sbb", "a(sss)", method_preset_all_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2010 SD_BUS_METHOD("AddDependencyUnitFiles", "asssbb", "a(sss)", method_add_dependency_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2011
2012 SD_BUS_SIGNAL("UnitNew", "so", 0),
2013 SD_BUS_SIGNAL("UnitRemoved", "so", 0),
2014 SD_BUS_SIGNAL("JobNew", "uos", 0),
2015 SD_BUS_SIGNAL("JobRemoved", "uoss", 0),
2016 SD_BUS_SIGNAL("StartupFinished", "tttttt", 0),
2017 SD_BUS_SIGNAL("UnitFilesChanged", NULL, 0),
2018 SD_BUS_SIGNAL("Reloading", "b", 0),
2019
2020 SD_BUS_VTABLE_END
2021 };
2022
2023 static int send_finished(sd_bus *bus, void *userdata) {
2024 _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
2025 usec_t *times = userdata;
2026 int r;
2027
2028 assert(bus);
2029 assert(times);
2030
2031 r = sd_bus_message_new_signal(bus, &message, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished");
2032 if (r < 0)
2033 return r;
2034
2035 r = sd_bus_message_append(message, "tttttt", times[0], times[1], times[2], times[3], times[4], times[5]);
2036 if (r < 0)
2037 return r;
2038
2039 return sd_bus_send(bus, message, NULL);
2040 }
2041
2042 void bus_manager_send_finished(
2043 Manager *m,
2044 usec_t firmware_usec,
2045 usec_t loader_usec,
2046 usec_t kernel_usec,
2047 usec_t initrd_usec,
2048 usec_t userspace_usec,
2049 usec_t total_usec) {
2050
2051 int r;
2052
2053 assert(m);
2054
2055 r = bus_foreach_bus(
2056 m,
2057 NULL,
2058 send_finished,
2059 (usec_t[6]) {
2060 firmware_usec,
2061 loader_usec,
2062 kernel_usec,
2063 initrd_usec,
2064 userspace_usec,
2065 total_usec
2066 });
2067 if (r < 0)
2068 log_debug_errno(r, "Failed to send finished signal: %m");
2069 }
2070
2071 static int send_reloading(sd_bus *bus, void *userdata) {
2072 _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
2073 int r;
2074
2075 assert(bus);
2076
2077 r = sd_bus_message_new_signal(bus, &message, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "Reloading");
2078 if (r < 0)
2079 return r;
2080
2081 r = sd_bus_message_append(message, "b", PTR_TO_INT(userdata));
2082 if (r < 0)
2083 return r;
2084
2085 return sd_bus_send(bus, message, NULL);
2086 }
2087
2088 void bus_manager_send_reloading(Manager *m, bool active) {
2089 int r;
2090
2091 assert(m);
2092
2093 r = bus_foreach_bus(m, NULL, send_reloading, INT_TO_PTR(active));
2094 if (r < 0)
2095 log_debug_errno(r, "Failed to send reloading signal: %m");
2096 }
2097
2098 static int send_changed_signal(sd_bus *bus, void *userdata) {
2099 assert(bus);
2100
2101 return sd_bus_emit_properties_changed_strv(bus,
2102 "/org/freedesktop/systemd1",
2103 "org.freedesktop.systemd1.Manager",
2104 NULL);
2105 }
2106
2107 void bus_manager_send_change_signal(Manager *m) {
2108 int r;
2109
2110 assert(m);
2111
2112 r = bus_foreach_bus(m, NULL, send_changed_signal, NULL);
2113 if (r < 0)
2114 log_debug_errno(r, "Failed to send manager change signal: %m");
2115 }