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