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