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