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