]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dbus-manager.c
bus: properly serialize unit file change list
[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 "hwclock.h"
32 #include "path-util.h"
33 #include "virt.h"
34 #include "env-util.h"
35 #include "dbus.h"
36 #include "dbus-manager.h"
37 #include "dbus-unit.h"
38 #include "dbus-snapshot.h"
39 #include "dbus-client-track.h"
40 #include "dbus-execute.h"
41 #include "bus-errors.h"
42
43 static int property_get_version(
44 sd_bus *bus,
45 const char *path,
46 const char *interface,
47 const char *property,
48 sd_bus_message *reply,
49 void *userdata,
50 sd_bus_error *error) {
51
52 assert(bus);
53 assert(reply);
54
55 return sd_bus_message_append(reply, "s", PACKAGE_VERSION);
56 }
57
58 static int property_get_features(
59 sd_bus *bus,
60 const char *path,
61 const char *interface,
62 const char *property,
63 sd_bus_message *reply,
64 void *userdata,
65 sd_bus_error *error) {
66
67 assert(bus);
68 assert(reply);
69
70 return sd_bus_message_append(reply, "s", SYSTEMD_FEATURES);
71 }
72
73 static int property_get_virtualization(
74 sd_bus *bus,
75 const char *path,
76 const char *interface,
77 const char *property,
78 sd_bus_message *reply,
79 void *userdata,
80 sd_bus_error *error) {
81
82 const char *id = NULL;
83
84 assert(bus);
85 assert(reply);
86
87 detect_virtualization(&id);
88
89 return sd_bus_message_append(reply, "s", id);
90 }
91
92 static int property_get_tainted(
93 sd_bus *bus,
94 const char *path,
95 const char *interface,
96 const char *property,
97 sd_bus_message *reply,
98 void *userdata,
99 sd_bus_error *error) {
100
101 char buf[sizeof("split-usr:mtab-not-symlink:cgroups-missing:local-hwclock:")] = "", *e = buf;
102 _cleanup_free_ char *p = NULL;
103 Manager *m = userdata;
104
105 assert(bus);
106 assert(reply);
107 assert(m);
108
109 if (m->taint_usr)
110 e = stpcpy(e, "split-usr:");
111
112 if (readlink_malloc("/etc/mtab", &p) < 0)
113 e = stpcpy(e, "mtab-not-symlink:");
114
115 if (access("/proc/cgroups", F_OK) < 0)
116 e = stpcpy(e, "cgroups-missing:");
117
118 if (hwclock_is_localtime() > 0)
119 e = stpcpy(e, "local-hwclock:");
120
121 /* remove the last ':' */
122 if (e != buf)
123 e[-1] = 0;
124
125 return sd_bus_message_append(reply, "s", buf);
126 }
127
128 static int property_get_log_target(
129 sd_bus *bus,
130 const char *path,
131 const char *interface,
132 const char *property,
133 sd_bus_message *reply,
134 void *userdata,
135 sd_bus_error *error) {
136
137 assert(bus);
138 assert(reply);
139
140 return sd_bus_message_append(reply, "s", log_target_to_string(log_get_target()));
141 }
142
143 static int property_set_log_target(
144 sd_bus *bus,
145 const char *path,
146 const char *interface,
147 const char *property,
148 sd_bus_message *value,
149 void *userdata,
150 sd_bus_error *error) {
151
152 const char *t;
153 int r;
154
155 assert(bus);
156 assert(value);
157
158 r = sd_bus_message_read(value, "s", &t);
159 if (r < 0)
160 return r;
161
162 return log_set_target_from_string(t);
163 }
164
165 static int property_get_log_level(
166 sd_bus *bus,
167 const char *path,
168 const char *interface,
169 const char *property,
170 sd_bus_message *reply,
171 void *userdata,
172 sd_bus_error *error) {
173
174 _cleanup_free_ char *t = NULL;
175 int r;
176
177 assert(bus);
178 assert(reply);
179
180 r = log_level_to_string_alloc(log_get_max_level(), &t);
181 if (r < 0)
182 return r;
183
184 return sd_bus_message_append(reply, "s", t);
185 }
186
187 static int property_set_log_level(
188 sd_bus *bus,
189 const char *path,
190 const char *interface,
191 const char *property,
192 sd_bus_message *value,
193 void *userdata,
194 sd_bus_error *error) {
195
196 const char *t;
197 int r;
198
199 assert(bus);
200 assert(value);
201
202 r = sd_bus_message_read(value, "s", &t);
203 if (r < 0)
204 return r;
205
206 return log_set_max_level_from_string(t);
207 }
208
209 static int property_get_n_names(
210 sd_bus *bus,
211 const char *path,
212 const char *interface,
213 const char *property,
214 sd_bus_message *reply,
215 void *userdata,
216 sd_bus_error *error) {
217
218 Manager *m = userdata;
219
220 assert(bus);
221 assert(reply);
222 assert(m);
223
224 return sd_bus_message_append(reply, "u", (uint32_t) hashmap_size(m->units));
225 }
226
227 static int property_get_n_jobs(
228 sd_bus *bus,
229 const char *path,
230 const char *interface,
231 const char *property,
232 sd_bus_message *reply,
233 void *userdata,
234 sd_bus_error *error) {
235
236 Manager *m = userdata;
237
238 assert(bus);
239 assert(reply);
240 assert(m);
241
242 return sd_bus_message_append(reply, "u", (uint32_t) hashmap_size(m->jobs));
243 }
244
245 static int property_get_progress(
246 sd_bus *bus,
247 const char *path,
248 const char *interface,
249 const char *property,
250 sd_bus_message *reply,
251 void *userdata,
252 sd_bus_error *error) {
253
254 Manager *m = userdata;
255 double d;
256
257 assert(bus);
258 assert(reply);
259 assert(m);
260
261 if (dual_timestamp_is_set(&m->finish_timestamp))
262 d = 1.0;
263 else
264 d = 1.0 - ((double) hashmap_size(m->jobs) / (double) m->n_installed_jobs);
265
266 return sd_bus_message_append(reply, "d", d);
267 }
268
269 static int property_set_runtime_watchdog(
270 sd_bus *bus,
271 const char *path,
272 const char *interface,
273 const char *property,
274 sd_bus_message *value,
275 void *userdata,
276 sd_bus_error *error) {
277
278 usec_t *t = userdata;
279 int r;
280
281 assert(bus);
282 assert(value);
283
284 assert_cc(sizeof(usec_t) == sizeof(uint64_t));
285
286 r = sd_bus_message_read(value, "t", t);
287 if (r < 0)
288 return r;
289
290 return watchdog_set_timeout(t);
291 }
292
293 static int method_get_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
294 _cleanup_free_ char *path = NULL;
295 Manager *m = userdata;
296 const char *name;
297 Unit *u;
298 int r;
299
300 assert(bus);
301 assert(message);
302 assert(m);
303
304 r = sd_bus_message_read(message, "s", &name);
305 if (r < 0)
306 return r;
307
308 u = manager_get_unit(m, name);
309 if (!u)
310 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", name);
311
312 r = selinux_unit_access_check(u, bus, message, "status", error);
313 if (r < 0)
314 return r;
315
316 path = unit_dbus_path(u);
317 if (!path)
318 return -ENOMEM;
319
320 return sd_bus_reply_method_return(message, "o", path);
321 }
322
323 static int method_get_unit_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
324 _cleanup_free_ char *path = NULL;
325 Manager *m = userdata;
326 pid_t pid;
327 Unit *u;
328 int r;
329
330 assert(bus);
331 assert(message);
332 assert(m);
333
334 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
335
336 r = sd_bus_message_read(message, "u", &pid);
337 if (r < 0)
338 return r;
339
340 if (pid == 0) {
341 r = sd_bus_get_owner_pid(bus, sd_bus_message_get_sender(message), &pid);
342 if (r < 0)
343 return r;
344 }
345
346 u = manager_get_unit_by_pid(m, pid);
347 if (!u)
348 return sd_bus_error_setf(error, BUS_ERROR_NO_UNIT_FOR_PID, "PID %u does not belong to any loaded unit.", pid);
349
350 r = selinux_unit_access_check(u, bus, message, "status", error);
351 if (r < 0)
352 return r;
353
354 path = unit_dbus_path(u);
355 if (!path)
356 return -ENOMEM;
357
358 return sd_bus_reply_method_return(message, "o", path);
359 }
360
361 static int method_load_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
362 _cleanup_free_ char *path = NULL;
363 Manager *m = userdata;
364 const char *name;
365 Unit *u;
366 int r;
367
368 assert(bus);
369 assert(message);
370 assert(m);
371
372 r = sd_bus_message_read(message, "s", &name);
373 if (r < 0)
374 return r;
375
376 r = manager_load_unit(m, name, NULL, error, &u);
377 if (r < 0)
378 return r;
379
380 r = selinux_unit_access_check(u, bus, message, "status", error);
381 if (r < 0)
382 return r;
383
384 path = unit_dbus_path(u);
385 if (!path)
386 return -ENOMEM;
387
388 return sd_bus_reply_method_return(message, "o", path);
389 }
390
391 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) {
392 const char *name;
393 Unit *u;
394 int r;
395
396 assert(bus);
397 assert(message);
398 assert(m);
399
400 r = sd_bus_message_read(message, "s", &name);
401 if (r < 0)
402 return r;
403
404 r = manager_load_unit(m, name, NULL, error, &u);
405 if (r < 0)
406 return r;
407
408 return bus_unit_method_start_generic(bus, message, u, job_type, reload_if_possible, error);
409 }
410
411 static int method_start_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
412 return method_start_unit_generic(bus, message, userdata, JOB_START, false, error);
413 }
414
415 static int method_stop_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
416 return method_start_unit_generic(bus, message, userdata, JOB_STOP, false, error);
417 }
418
419 static int method_reload_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
420 return method_start_unit_generic(bus, message, userdata, JOB_RELOAD, false, error);
421 }
422
423 static int method_restart_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
424 return method_start_unit_generic(bus, message, userdata, JOB_RESTART, false, error);
425 }
426
427 static int method_try_restart_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
428 return method_start_unit_generic(bus, message, userdata, JOB_TRY_RESTART, false, error);
429 }
430
431 static int method_reload_or_restart_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
432 return method_start_unit_generic(bus, message, userdata, JOB_RESTART, true, error);
433 }
434
435 static int method_reload_or_try_restart_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
436 return method_start_unit_generic(bus, message, userdata, JOB_TRY_RESTART, true, error);
437 }
438
439 static int method_start_unit_replace(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
440 Manager *m = userdata;
441 const char *old_name;
442 Unit *u;
443 int r;
444
445 assert(bus);
446 assert(message);
447 assert(m);
448
449 r = sd_bus_message_read(message, "s", &old_name);
450 if (r < 0)
451 return r;
452
453 u = manager_get_unit(m, old_name);
454 if (!u || !u->job || u->job->type != JOB_START)
455 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
456
457 return method_start_unit_generic(bus, message, m, JOB_START, false, error);
458 }
459
460 static int method_kill_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
461 Manager *m = userdata;
462 const char *name;
463 Unit *u;
464 int r;
465
466 assert(bus);
467 assert(message);
468 assert(m);
469
470 r = sd_bus_message_read(message, "s", &name);
471 if (r < 0)
472 return r;
473
474 u = manager_get_unit(m, name);
475 if (!u)
476 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
477
478 return bus_unit_method_kill(bus, message, u, error);
479 }
480
481 static int method_reset_failed_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
482 Manager *m = userdata;
483 const char *name;
484 Unit *u;
485 int r;
486
487 assert(bus);
488 assert(message);
489 assert(m);
490
491 r = sd_bus_message_read(message, "s", &name);
492 if (r < 0)
493 return r;
494
495 u = manager_get_unit(m, name);
496 if (!u)
497 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
498
499 return bus_unit_method_reset_failed(bus, message, u, error);
500 }
501
502 static int method_set_unit_properties(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
503 Manager *m = userdata;
504 const char *name;
505 Unit *u;
506 int r;
507
508 assert(bus);
509 assert(message);
510 assert(m);
511
512 r = sd_bus_message_read(message, "s", &name);
513 if (r < 0)
514 return r;
515
516 u = manager_get_unit(m, name);
517 if (!u)
518 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
519
520 return bus_unit_method_set_properties(bus, message, u, error);
521 }
522
523 static int method_start_transient_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
524 const char *name, *smode;
525 Manager *m = userdata;
526 JobMode mode;
527 UnitType t;
528 Unit *u;
529 int r;
530
531 assert(bus);
532 assert(message);
533 assert(m);
534
535 r = sd_bus_message_read(message, "ss", &name, &smode);
536 if (r < 0)
537 return r;
538
539 t = unit_name_to_type(name);
540 if (t < 0)
541 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit type.");
542
543 if (!unit_vtable[t]->can_transient)
544 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit type %s does not support transient units.");
545
546 mode = job_mode_from_string(smode);
547 if (mode < 0)
548 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s is invalid.", smode);
549
550 r = manager_load_unit(m, name, NULL, error, &u);
551 if (r < 0)
552 return r;
553
554 r = selinux_unit_access_check(u, bus, message, "start", error);
555 if (r < 0)
556 return r;
557
558 if (u->load_state != UNIT_NOT_FOUND || set_size(u->dependencies[UNIT_REFERENCED_BY]) > 0)
559 return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit %s already exists.", name);
560
561 /* OK, the unit failed to load and is unreferenced, now let's
562 * fill in the transient data instead */
563 r = unit_make_transient(u);
564 if (r < 0)
565 return r;
566
567 /* Set our properties */
568 r = bus_unit_set_properties(u, message, UNIT_RUNTIME, false, error);
569 if (r < 0)
570 return r;
571
572 /* And load this stub fully */
573 r = unit_load(u);
574 if (r < 0)
575 return r;
576
577 manager_dispatch_load_queue(m);
578
579 /* Finally, start it */
580 return bus_unit_queue_job(bus, message, u, JOB_START, mode, false, error);
581 }
582
583 static int method_get_job(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
584 _cleanup_free_ char *path = NULL;
585 Manager *m = userdata;
586 uint32_t id;
587 Job *j;
588 int r;
589
590 assert(bus);
591 assert(message);
592 assert(m);
593
594 r = sd_bus_message_read(message, "u", &id);
595 if (r < 0)
596 return r;
597
598 j = manager_get_job(m, id);
599 if (!j)
600 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
601
602 r = selinux_unit_access_check(j->unit, bus, message, "status", error);
603 if (r < 0)
604 return r;
605
606 path = job_dbus_path(j);
607 if (!path)
608 return -ENOMEM;
609
610 return sd_bus_reply_method_return(message, "o", path);
611 }
612
613 static int method_cancel_job(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
614 Manager *m = userdata;
615 uint32_t id;
616 Job *j;
617 int r;
618
619 assert(bus);
620 assert(message);
621 assert(m);
622
623 r = sd_bus_message_read(message, "u", &id);
624 if (r < 0)
625 return r;
626
627 j = manager_get_job(m, id);
628 if (!j)
629 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
630
631 r = selinux_unit_access_check(j->unit, bus, message, "stop", error);
632 if (r < 0)
633 return r;
634
635 job_finish_and_invalidate(j, JOB_CANCELED, true);
636
637 return sd_bus_reply_method_return(message, NULL);
638 }
639
640 static int method_clear_jobs(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
641 Manager *m = userdata;
642 int r;
643
644 assert(bus);
645 assert(message);
646 assert(m);
647
648 r = selinux_access_check(bus, message, "reboot", error);
649 if (r < 0)
650 return r;
651
652 manager_clear_jobs(m);
653
654 return sd_bus_reply_method_return(message, NULL);
655 }
656
657 static int method_reset_failed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
658 Manager *m = userdata;
659 int r;
660
661 assert(bus);
662 assert(message);
663 assert(m);
664
665 r = selinux_access_check(bus, message, "reload", error);
666 if (r < 0)
667 return r;
668
669 manager_reset_failed(m);
670
671 return sd_bus_reply_method_return(message, NULL);
672 }
673
674 static int method_list_units(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
675 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
676 Manager *m = userdata;
677 const char *k;
678 Iterator i;
679 Unit *u;
680 int r;
681
682 assert(bus);
683 assert(message);
684 assert(m);
685
686 r = selinux_access_check(bus, message, "status", error);
687 if (r < 0)
688 return r;
689
690 r = sd_bus_message_new_method_return(message, &reply);
691 if (r < 0)
692 return r;
693
694 r = sd_bus_message_open_container(reply, 'a', "(ssssssouso)");
695 if (r < 0)
696 return r;
697
698 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
699 _cleanup_free_ char *unit_path = NULL, *job_path = NULL;
700 Unit *following;
701
702 if (k != u->id)
703 continue;
704
705 following = unit_following(u);
706
707 unit_path = unit_dbus_path(u);
708 if (!unit_path)
709 return -ENOMEM;
710
711 if (u->job) {
712 job_path = job_dbus_path(u->job);
713 if (!job_path)
714 return -ENOMEM;
715 }
716
717 r = sd_bus_message_append(
718 reply, "(ssssssouso)",
719 u->id,
720 unit_description(u),
721 unit_load_state_to_string(u->load_state),
722 unit_active_state_to_string(unit_active_state(u)),
723 unit_sub_state_to_string(u),
724 following ? following->id : "",
725 unit_path,
726 u->job ? u->job->id : 0,
727 u->job ? job_type_to_string(u->job->type) : "",
728 job_path ? job_path : "/");
729 if (r < 0)
730 return r;
731 }
732
733 r = sd_bus_message_close_container(reply);
734 if (r < 0)
735 return r;
736
737 return sd_bus_send(bus, reply, NULL);
738 }
739
740 static int method_list_jobs(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
741 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
742 Manager *m = userdata;
743 Iterator i;
744 Job *j;
745 int r;
746
747 assert(bus);
748 assert(message);
749 assert(m);
750
751 r = selinux_access_check(bus, message, "status", error);
752 if (r < 0)
753 return r;
754
755 r = sd_bus_message_new_method_return(message, &reply);
756 if (r < 0)
757 return r;
758
759 r = sd_bus_message_open_container(reply, 'a', "(usssoo)");
760 if (r < 0)
761 return r;
762
763 HASHMAP_FOREACH(j, m->jobs, i) {
764 _cleanup_free_ char *unit_path = NULL, *job_path = NULL;
765
766 job_path = job_dbus_path(j);
767 if (!job_path)
768 return -ENOMEM;
769
770 unit_path = unit_dbus_path(j->unit);
771 if (!unit_path)
772 return -ENOMEM;
773
774 r = sd_bus_message_append(
775 reply, "(usssoo)",
776 j->id,
777 job_state_to_string(j->state),
778 job_type_to_string(j->type),
779 job_path,
780 unit_path);
781 if (r < 0)
782 return r;
783 }
784
785 r = sd_bus_message_close_container(reply);
786 if (r < 0)
787 return r;
788
789 return sd_bus_send(bus, reply, NULL);
790 }
791
792 static int method_subscribe(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
793 Manager *m = userdata;
794 int r;
795
796 assert(bus);
797 assert(message);
798 assert(m);
799
800 r = selinux_access_check(bus, message, "status", error);
801 if (r < 0)
802 return r;
803
804 r = bus_client_track(&m->subscribed, bus, sd_bus_message_get_sender(message));
805 if (r < 0)
806 return r;
807 if (r == 0)
808 return sd_bus_error_setf(error, BUS_ERROR_ALREADY_SUBSCRIBED, "Client is already subscribed.");
809
810 return sd_bus_reply_method_return(message, NULL);
811 }
812
813 static int method_unsubscribe(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 = selinux_access_check(bus, message, "status", error);
822 if (r < 0)
823 return r;
824
825 r = bus_client_untrack(m->subscribed, bus, sd_bus_message_get_sender(message));
826 if (r < 0)
827 return r;
828 if (r == 0)
829 return sd_bus_error_setf(error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
830
831 return sd_bus_reply_method_return(message, NULL);
832 }
833
834 static int method_dump(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
835 _cleanup_free_ char *dump = NULL;
836 _cleanup_fclose_ FILE *f = NULL;
837 Manager *m = userdata;
838 size_t size;
839 int r;
840
841 assert(bus);
842 assert(message);
843 assert(m);
844
845 r = selinux_access_check(bus, message, "status", error);
846 if (r < 0)
847 return r;
848
849 f = open_memstream(&dump, &size);
850 if (!f)
851 return -ENOMEM;
852
853 manager_dump_units(m, f, NULL);
854 manager_dump_jobs(m, f, NULL);
855
856 fflush(f);
857
858 if (ferror(f))
859 return -ENOMEM;
860
861 return sd_bus_reply_method_return(message, "s", dump);
862 }
863
864 static int method_create_snapshot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
865 _cleanup_free_ char *path = NULL;
866 Manager *m = userdata;
867 const char *name;
868 int cleanup;
869 Snapshot *s;
870 int r;
871
872 assert(bus);
873 assert(message);
874 assert(m);
875
876 r = selinux_access_check(bus, message, "start", error);
877 if (r < 0)
878 return r;
879
880 r = sd_bus_message_read(message, "sb", &name, &cleanup);
881 if (r < 0)
882 return r;
883
884 if (isempty(name))
885 name = NULL;
886
887 r = snapshot_create(m, name, cleanup, error, &s);
888 if (r < 0)
889 return r;
890
891 path = unit_dbus_path(UNIT(s));
892 if (!path)
893 return -ENOMEM;
894
895 return sd_bus_reply_method_return(message, "o", path);
896 }
897
898 static int method_remove_snapshot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
899 Manager *m = userdata;
900 const char *name;
901 Unit *u;
902 int r;
903
904 assert(bus);
905 assert(message);
906 assert(m);
907
908 r = selinux_access_check(bus, message, "stop", error);
909 if (r < 0)
910 return r;
911
912 r = sd_bus_message_read(message, "s", &name);
913 if (r < 0)
914 return r;
915
916 u = manager_get_unit(m, name);
917 if (!u)
918 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s does not exist.", name);
919
920 if (u->type != UNIT_SNAPSHOT)
921 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not a snapshot", name);
922
923 return bus_snapshot_method_remove(bus, message, u, error);
924 }
925
926 static int method_reload(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
927 Manager *m = userdata;
928 int r;
929
930 assert(bus);
931 assert(message);
932 assert(m);
933
934 r = selinux_access_check(bus, message, "reload", error);
935 if (r < 0)
936 return r;
937
938 /* Instead of sending the reply back right away, we just
939 * remember that we need to and then send it after the reload
940 * is finished. That way the caller knows when the reload
941 * finished. */
942
943 assert(!m->queued_message);
944 r = sd_bus_message_new_method_return(message, &m->queued_message);
945 if (r < 0)
946 return r;
947
948 m->queued_message_bus = sd_bus_ref(bus);
949 m->exit_code = MANAGER_RELOAD;
950
951 return 1;
952 }
953
954 static int method_reexecute(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
955 Manager *m = userdata;
956 int r;
957
958 assert(bus);
959 assert(message);
960 assert(m);
961
962 r = selinux_access_check(bus, message, "reload", error);
963 if (r < 0)
964 return r;
965
966 /* We don't send a reply back here, the client should
967 * just wait for us disconnecting. */
968
969 m->exit_code = MANAGER_REEXECUTE;
970 return 1;
971 }
972
973 static int method_exit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
974 Manager *m = userdata;
975 int r;
976
977 assert(bus);
978 assert(message);
979 assert(m);
980
981 r = selinux_access_check(bus, message, "halt", error);
982 if (r < 0)
983 return r;
984
985 if (m->running_as == SYSTEMD_SYSTEM)
986 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
987
988 m->exit_code = MANAGER_EXIT;
989
990 return sd_bus_reply_method_return(message, NULL);
991 }
992
993 static int method_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
994 Manager *m = userdata;
995 int r;
996
997 assert(bus);
998 assert(message);
999 assert(m);
1000
1001 r = selinux_access_check(bus, message, "reboot", error);
1002 if (r < 0)
1003 return r;
1004
1005 if (m->running_as != SYSTEMD_SYSTEM)
1006 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
1007
1008 m->exit_code = MANAGER_REBOOT;
1009
1010 return sd_bus_reply_method_return(message, NULL);
1011 }
1012
1013
1014 static int method_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1015 Manager *m = userdata;
1016 int r;
1017
1018 assert(bus);
1019 assert(message);
1020 assert(m);
1021
1022 r = selinux_access_check(bus, message, "halt", error);
1023 if (r < 0)
1024 return r;
1025
1026 if (m->running_as != SYSTEMD_SYSTEM)
1027 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
1028
1029 m->exit_code = MANAGER_POWEROFF;
1030
1031 return sd_bus_reply_method_return(message, NULL);
1032 }
1033
1034 static int method_halt(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1035 Manager *m = userdata;
1036 int r;
1037
1038 assert(bus);
1039 assert(message);
1040 assert(m);
1041
1042 r = selinux_access_check(bus, message, "halt", error);
1043 if (r < 0)
1044 return r;
1045
1046 if (m->running_as != SYSTEMD_SYSTEM)
1047 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Halt is only supported for system managers.");
1048
1049 m->exit_code = MANAGER_HALT;
1050
1051 return sd_bus_reply_method_return(message, NULL);
1052 }
1053
1054 static int method_kexec(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1055 Manager *m = userdata;
1056 int r;
1057
1058 assert(bus);
1059 assert(message);
1060 assert(m);
1061
1062 r = selinux_access_check(bus, message, "reboot", error);
1063 if (r < 0)
1064 return r;
1065
1066 if (m->running_as != SYSTEMD_SYSTEM)
1067 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "KExec is only supported for system managers.");
1068
1069 m->exit_code = MANAGER_KEXEC;
1070
1071 return sd_bus_reply_method_return(message, NULL);
1072 }
1073
1074 static int method_switch_root(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1075 char *ri = NULL, *rt = NULL;
1076 const char *root, *init;
1077 Manager *m = userdata;
1078 int r;
1079
1080 assert(bus);
1081 assert(message);
1082 assert(m);
1083
1084 r = selinux_access_check(bus, message, "reboot", error);
1085 if (r < 0)
1086 return r;
1087
1088 if (m->running_as != SYSTEMD_SYSTEM)
1089 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "KExec is only supported for system managers.");
1090
1091 r = sd_bus_message_read(message, "ss", &root, &init);
1092 if (r < 0)
1093 return r;
1094
1095 if (path_equal(root, "/") || !path_is_absolute(root))
1096 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid switch root path %s", root);
1097
1098 /* Safety check */
1099 if (isempty(init)) {
1100 if (! path_is_os_tree(root))
1101 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified switch root path %s does not seem to be an OS tree. /etc/os-release is missing.", root);
1102 } else {
1103 _cleanup_free_ char *p = NULL;
1104
1105 if (!path_is_absolute(init))
1106 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid init path %s", init);
1107
1108 p = strappend(root, init);
1109 if (!p)
1110 return -ENOMEM;
1111
1112 if (access(p, X_OK) < 0)
1113 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified init binary %s does not exist.", p);
1114 }
1115
1116 rt = strdup(root);
1117 if (!rt)
1118 return -ENOMEM;
1119
1120 if (!isempty(init)) {
1121 ri = strdup(init);
1122 if (!ri) {
1123 free(ri);
1124 return -ENOMEM;
1125 }
1126 }
1127
1128 free(m->switch_root);
1129 m->switch_root = rt;
1130
1131 free(m->switch_root_init);
1132 m->switch_root_init = ri;
1133
1134 return sd_bus_reply_method_return(message, NULL);
1135 }
1136
1137 static int method_set_environment(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1138 _cleanup_strv_free_ char **plus = NULL;
1139 Manager *m = userdata;
1140 int r;
1141
1142 assert(bus);
1143 assert(message);
1144 assert(m);
1145
1146 r = selinux_access_check(bus, message, "reload", error);
1147 if (r < 0)
1148 return r;
1149
1150 r = sd_bus_message_read_strv(message, &plus);
1151 if (r < 0)
1152 return r;
1153 if (!strv_env_is_valid(plus))
1154 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
1155
1156 r = manager_environment_add(m, NULL, plus);
1157 if (r < 0)
1158 return r;
1159
1160 return sd_bus_reply_method_return(message, NULL);
1161 }
1162
1163 static int method_unset_environment(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1164 _cleanup_strv_free_ char **minus = NULL;
1165 Manager *m = userdata;
1166 int r;
1167
1168 assert(bus);
1169 assert(message);
1170 assert(m);
1171
1172 r = selinux_access_check(bus, message, "reload", error);
1173 if (r < 0)
1174 return r;
1175
1176 r = sd_bus_message_read_strv(message, &minus);
1177 if (r < 0)
1178 return r;
1179
1180 if (!strv_env_name_or_assignment_is_valid(minus))
1181 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment variable names or assignments");
1182
1183 r = manager_environment_add(m, minus, NULL);
1184 if (r < 0)
1185 return r;
1186
1187 return sd_bus_reply_method_return(message, NULL);
1188 }
1189
1190 static int method_unset_and_set_environment(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1191 _cleanup_strv_free_ char **minus = NULL, **plus = NULL;
1192 Manager *m = userdata;
1193 int r;
1194
1195 assert(bus);
1196 assert(message);
1197 assert(m);
1198
1199 r = selinux_access_check(bus, message, "reload", error);
1200 if (r < 0)
1201 return r;
1202
1203 r = sd_bus_message_read_strv(message, &plus);
1204 if (r < 0)
1205 return r;
1206
1207 r = sd_bus_message_read_strv(message, &minus);
1208 if (r < 0)
1209 return r;
1210
1211 if (!strv_env_is_valid(plus))
1212 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
1213 if (!strv_env_name_or_assignment_is_valid(minus))
1214 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment variable names or assignments");
1215
1216 r = manager_environment_add(m, minus, plus);
1217 if (r < 0)
1218 return r;
1219
1220 return sd_bus_reply_method_return(message, NULL);
1221 }
1222
1223 static int method_list_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1224 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1225 Manager *m = userdata;
1226 UnitFileList *item;
1227 Hashmap *h;
1228 Iterator i;
1229 int r;
1230
1231 assert(bus);
1232 assert(message);
1233 assert(m);
1234
1235 r = selinux_access_check(bus, message, "status", error);
1236 if (r < 0)
1237 return r;
1238
1239 r = sd_bus_message_new_method_return(message, &reply);
1240 if (r < 0)
1241 return r;
1242
1243 h = hashmap_new(string_hash_func, string_compare_func);
1244 if (!h)
1245 return -ENOMEM;
1246
1247 r = unit_file_get_list(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
1248 if (r < 0)
1249 goto fail;
1250
1251 r = sd_bus_message_open_container(reply, 'a', "(ss)");
1252 if (r < 0)
1253 goto fail;
1254
1255 HASHMAP_FOREACH(item, h, i) {
1256
1257 r = sd_bus_message_append(reply, "(ss)", item->path, unit_file_state_to_string(item->state));
1258 if (r < 0)
1259 goto fail;
1260 }
1261
1262 unit_file_list_free(h);
1263
1264 r = sd_bus_message_close_container(reply);
1265 if (r < 0)
1266 return r;
1267
1268 return sd_bus_send(bus, reply, NULL);
1269
1270 fail:
1271 unit_file_list_free(h);
1272 return r;
1273 }
1274
1275 static int method_get_unit_file_state(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1276 Manager *m = userdata;
1277 const char *name;
1278 UnitFileState state;
1279 UnitFileScope scope;
1280 int r;
1281
1282 assert(bus);
1283 assert(message);
1284 assert(m);
1285
1286 r = selinux_access_check(bus, message, "status", error);
1287 if (r < 0)
1288 return r;
1289
1290 r = sd_bus_message_read(message, "s", &name);
1291 if (r < 0)
1292 return r;
1293
1294 scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1295
1296 state = unit_file_get_state(scope, NULL, name);
1297 if (state < 0)
1298 return state;
1299
1300 return sd_bus_reply_method_return(message, "s", unit_file_state_to_string(state));
1301 }
1302
1303 static int method_get_default_target(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1304 _cleanup_free_ char *default_target = NULL;
1305 Manager *m = userdata;
1306 UnitFileScope scope;
1307 int r;
1308
1309 assert(bus);
1310 assert(message);
1311 assert(m);
1312
1313 r = selinux_access_check(bus, message, "status", error);
1314 if (r < 0)
1315 return r;
1316
1317 scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1318
1319 r = unit_file_get_default(scope, NULL, &default_target);
1320 if (r < 0)
1321 return r;
1322
1323 return sd_bus_reply_method_return(message, "s", default_target);
1324 }
1325
1326 static int send_unit_files_changed(sd_bus *bus, const char *destination, void *userdata) {
1327 _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
1328 int r;
1329
1330 assert(bus);
1331
1332 r = sd_bus_message_new_signal(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged", &message);
1333 if (r < 0)
1334 return r;
1335
1336 return sd_bus_send_to(bus, message, destination, NULL);
1337 }
1338
1339 static int reply_unit_file_changes_and_free(
1340 Manager *m,
1341 sd_bus *bus,
1342 sd_bus_message *message,
1343 int carries_install_info,
1344 UnitFileChange *changes,
1345 unsigned n_changes) {
1346
1347 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1348 unsigned i;
1349 int r;
1350
1351 if (n_changes > 0)
1352 bus_manager_foreach_client(m, send_unit_files_changed, NULL);
1353
1354 r = sd_bus_message_new_method_return(message, &reply);
1355 if (r < 0)
1356 goto fail;
1357
1358 if (carries_install_info >= 0) {
1359 r = sd_bus_message_append(reply, "b", carries_install_info);
1360 if (r < 0)
1361 goto fail;
1362 }
1363
1364 r = sd_bus_message_open_container(reply, 'a', "(sss)");
1365 if (r < 0)
1366 goto fail;
1367
1368 for (i = 0; i < n_changes; i++) {
1369 r = sd_bus_message_append(
1370 reply, "(sss)",
1371 unit_file_change_type_to_string(changes[i].type),
1372 changes[i].path,
1373 changes[i].source);
1374 if (r < 0)
1375 goto fail;
1376 }
1377
1378 r = sd_bus_message_close_container(reply);
1379 if (r < 0)
1380 goto fail;
1381
1382 return sd_bus_send(bus, reply, NULL);
1383
1384 fail:
1385 unit_file_changes_free(changes, n_changes);
1386 return r;
1387 }
1388
1389 static int method_enable_unit_files_generic(
1390 sd_bus *bus,
1391 sd_bus_message *message,
1392 Manager *m, const
1393 char *verb,
1394 int (*call)(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes),
1395 bool carries_install_info,
1396 sd_bus_error *error) {
1397
1398 _cleanup_strv_free_ char **l = NULL;
1399 UnitFileChange *changes = NULL;
1400 unsigned n_changes = 0;
1401 UnitFileScope scope;
1402 int runtime, force, r;
1403
1404 assert(bus);
1405 assert(message);
1406 assert(m);
1407
1408 r = selinux_access_check(bus, message, verb, error);
1409 if (r < 0)
1410 return r;
1411
1412 r = sd_bus_message_read_strv(message, &l);
1413 if (r < 0)
1414 return r;
1415
1416 r = sd_bus_message_read(message, "bb", &runtime, &force);
1417 if (r < 0)
1418 return r;
1419
1420 scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1421
1422 r = call(scope, runtime, NULL, l, force, &changes, &n_changes);
1423 if (r < 0)
1424 return r;
1425
1426 return reply_unit_file_changes_and_free(m, bus, message, carries_install_info ? r : -1, changes, n_changes);
1427 }
1428
1429 static int method_enable_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1430 return method_enable_unit_files_generic(bus, message, userdata, "enable", unit_file_enable, true, error);
1431 }
1432
1433 static int method_reenable_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1434 return method_enable_unit_files_generic(bus, message, userdata, "enable", unit_file_reenable, true, error);
1435 }
1436
1437 static int method_link_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1438 return method_enable_unit_files_generic(bus, message, userdata, "enable", unit_file_link, false, error);
1439 }
1440
1441 static int method_preset_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1442 return method_enable_unit_files_generic(bus, message, userdata, "enable", unit_file_preset, true, error);
1443 }
1444
1445 static int method_mask_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1446 return method_enable_unit_files_generic(bus, message, userdata, "disable", unit_file_mask, false, error);
1447 }
1448
1449 static int method_disable_unit_files_generic(
1450 sd_bus *bus,
1451 sd_bus_message *message,
1452 Manager *m, const
1453 char *verb,
1454 int (*call)(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], UnitFileChange **changes, unsigned *n_changes),
1455 sd_bus_error *error) {
1456
1457 _cleanup_strv_free_ char **l = NULL;
1458 UnitFileChange *changes = NULL;
1459 unsigned n_changes = 0;
1460 UnitFileScope scope;
1461 int r, runtime;
1462
1463 assert(bus);
1464 assert(message);
1465 assert(m);
1466
1467 r = selinux_access_check(bus, message, verb, error);
1468 if (r < 0)
1469 return r;
1470
1471 r = sd_bus_message_read_strv(message, &l);
1472 if (r < 0)
1473 return r;
1474
1475 r = sd_bus_message_read(message, "b", &runtime);
1476 if (r < 0)
1477 return r;
1478
1479 scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1480
1481 r = call(scope, runtime, NULL, l, &changes, &n_changes);
1482 if (r < 0)
1483 return r;
1484
1485 return reply_unit_file_changes_and_free(m, bus, message, -1, changes, n_changes);
1486 }
1487
1488 static int method_disable_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1489 return method_disable_unit_files_generic(bus, message, userdata, "disable", unit_file_disable, error);
1490 }
1491
1492 static int method_unmask_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1493 return method_disable_unit_files_generic(bus, message, userdata, "enable", unit_file_unmask, error);
1494 }
1495
1496 static int method_set_default_target(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1497 UnitFileChange *changes = NULL;
1498 unsigned n_changes = 0;
1499 Manager *m = userdata;
1500 UnitFileScope scope;
1501 const char *name;
1502 int force, r;
1503
1504 assert(bus);
1505 assert(message);
1506 assert(m);
1507
1508 r = selinux_access_check(bus, message, "enable", error);
1509 if (r < 0)
1510 return r;
1511
1512 r = sd_bus_message_read(message, "sb", &name, &force);
1513 if (r < 0)
1514 return r;
1515
1516 scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1517
1518 r = unit_file_set_default(scope, NULL, name, force, &changes, &n_changes);
1519 if (r < 0)
1520 return r;
1521
1522 return reply_unit_file_changes_and_free(m, bus, message, -1, changes, n_changes);
1523 }
1524
1525 const sd_bus_vtable bus_manager_vtable[] = {
1526 SD_BUS_VTABLE_START(0),
1527
1528 SD_BUS_PROPERTY("Version", "s", property_get_version, 0, 0),
1529 SD_BUS_PROPERTY("Features", "s", property_get_features, 0, 0),
1530 SD_BUS_PROPERTY("Virtualization", "s", property_get_virtualization, 0, 0),
1531 SD_BUS_PROPERTY("Tainted", "s", property_get_tainted, 0, 0),
1532 BUS_PROPERTY_DUAL_TIMESTAMP("FirmwareTimestamp", offsetof(Manager, firmware_timestamp), 0),
1533 BUS_PROPERTY_DUAL_TIMESTAMP("LoaderTimestamp", offsetof(Manager, loader_timestamp), 0),
1534 BUS_PROPERTY_DUAL_TIMESTAMP("KernelTimestamp", offsetof(Manager, firmware_timestamp), 0),
1535 BUS_PROPERTY_DUAL_TIMESTAMP("InitRDTimestamp", offsetof(Manager, initrd_timestamp), 0),
1536 BUS_PROPERTY_DUAL_TIMESTAMP("UserspaceTimestamp", offsetof(Manager, userspace_timestamp), 0),
1537 BUS_PROPERTY_DUAL_TIMESTAMP("FinishTimestamp", offsetof(Manager, finish_timestamp), 0),
1538 BUS_PROPERTY_DUAL_TIMESTAMP("SecurityStartTimestamp", offsetof(Manager, security_start_timestamp), 0),
1539 BUS_PROPERTY_DUAL_TIMESTAMP("SecurityFinishTimestamp", offsetof(Manager, security_finish_timestamp), 0),
1540 BUS_PROPERTY_DUAL_TIMESTAMP("GeneratorsStartTimestamp", offsetof(Manager, generators_start_timestamp), 0),
1541 BUS_PROPERTY_DUAL_TIMESTAMP("GeneratorsFinishTimestamp", offsetof(Manager, generators_finish_timestamp), 0),
1542 BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadStartTimestamp", offsetof(Manager, units_load_start_timestamp), 0),
1543 BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadFinishTimestamp", offsetof(Manager, units_load_finish_timestamp), 0),
1544 SD_BUS_WRITABLE_PROPERTY("LogLevel", "s", property_get_log_level, property_set_log_level, 0, 0),
1545 SD_BUS_WRITABLE_PROPERTY("LogTarget", "s", property_get_log_target, property_set_log_target, 0, 0),
1546 SD_BUS_PROPERTY("NNames", "u", property_get_n_names, 0, 0),
1547 SD_BUS_PROPERTY("NJobs", "u", property_get_n_jobs, 0, 0),
1548 SD_BUS_PROPERTY("NInstalledJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_installed_jobs), 0),
1549 SD_BUS_PROPERTY("NFailedJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_failed_jobs), 0),
1550 SD_BUS_PROPERTY("Progress", "d", property_get_progress, 0, 0),
1551 SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(Manager, environment), 0),
1552 SD_BUS_PROPERTY("ConfirmSpawn", "b", bus_property_get_bool, offsetof(Manager, confirm_spawn), 0),
1553 SD_BUS_PROPERTY("ShowStatus", "b", bus_property_get_bool, offsetof(Manager, show_status), 0),
1554 SD_BUS_PROPERTY("UnitPath", "as", NULL, offsetof(Manager, lookup_paths.unit_path), 0),
1555 SD_BUS_PROPERTY("DefaultStandardOutput", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), 0),
1556 SD_BUS_PROPERTY("DefaultStandardError", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), 0),
1557 SD_BUS_WRITABLE_PROPERTY("RuntimeWatchdogUSec", "t", bus_property_get_usec, property_set_runtime_watchdog, offsetof(Manager, runtime_watchdog), 0),
1558 SD_BUS_WRITABLE_PROPERTY("ShutdownWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, shutdown_watchdog), 0),
1559
1560 SD_BUS_METHOD("GetUnit", "s", "o", method_get_unit, 0),
1561 SD_BUS_METHOD("GetUnitByPID", "u", "o", method_get_unit_by_pid, 0),
1562 SD_BUS_METHOD("LoadUnit", "s", "o", method_load_unit, 0),
1563 SD_BUS_METHOD("StartUnit", "ss", "o", method_start_unit, 0),
1564 SD_BUS_METHOD("StartUnitReplace", "sss", "o", method_start_unit_replace, 0),
1565 SD_BUS_METHOD("StopUnit", "ss", "o", method_stop_unit, 0),
1566 SD_BUS_METHOD("ReloadUnit", "ss", "o", method_reload_unit, 0),
1567 SD_BUS_METHOD("RestartUnit", "ss", "o", method_restart_unit, 0),
1568 SD_BUS_METHOD("TryRestartUnit", "ss", "o", method_try_restart_unit, 0),
1569 SD_BUS_METHOD("ReloadOrRestartUnit", "ss", "o", method_reload_or_restart_unit, 0),
1570 SD_BUS_METHOD("ReloadOrTryRestartUnit", "ss", "o", method_reload_or_try_restart_unit, 0),
1571 SD_BUS_METHOD("KillUnit", "ssi", NULL, method_kill_unit, 0),
1572 SD_BUS_METHOD("ResetFailedUnit", "s", NULL, method_reset_failed_unit, 0),
1573 SD_BUS_METHOD("SetUnitProperties", "sb", "a(sv)", method_set_unit_properties, 0),
1574 SD_BUS_METHOD("StartTransientUnit", "ssa(sv)a(sa(sv))", "o", method_start_transient_unit, 0),
1575 SD_BUS_METHOD("GetJob", "u", "o", method_get_job, 0),
1576 SD_BUS_METHOD("CancelJob", "u", NULL, method_cancel_job, 0),
1577 SD_BUS_METHOD("ClearJobs", NULL, NULL, method_clear_jobs, 0),
1578 SD_BUS_METHOD("ResetFailed", NULL, NULL, method_reset_failed, 0),
1579 SD_BUS_METHOD("ListUnits", NULL, "a(ssssssouso)", method_list_units, 0),
1580 SD_BUS_METHOD("ListJobs", NULL, "a(usssoo)", method_list_jobs, 0),
1581 SD_BUS_METHOD("Subscribe", NULL, NULL, method_subscribe, 0),
1582 SD_BUS_METHOD("Unsubscribe", NULL, NULL, method_unsubscribe, 0),
1583 SD_BUS_METHOD("Dump", NULL, "s", method_dump, 0),
1584 SD_BUS_METHOD("CreateSnapshot", "sb", "o", method_create_snapshot, 0),
1585 SD_BUS_METHOD("RemoveSnapshot", "s", NULL, method_remove_snapshot, 0),
1586 SD_BUS_METHOD("Reload", NULL, NULL, method_reload, 0),
1587 SD_BUS_METHOD("Reexecute", NULL, NULL, method_reexecute, 0),
1588 SD_BUS_METHOD("Exit", NULL, NULL, method_exit, 0),
1589 SD_BUS_METHOD("Reboot", NULL, NULL, method_reboot, 0),
1590 SD_BUS_METHOD("PowerOff", NULL, NULL, method_poweroff, 0),
1591 SD_BUS_METHOD("Halt", NULL, NULL, method_halt, 0),
1592 SD_BUS_METHOD("KExec", NULL, NULL, method_kexec, 0),
1593 SD_BUS_METHOD("SwitchRoot", "ss", NULL, method_switch_root, 0),
1594 SD_BUS_METHOD("SetEnvironment", "as", NULL, method_set_environment, 0),
1595 SD_BUS_METHOD("UnsetEnvironment", "as", NULL, method_unset_environment, 0),
1596 SD_BUS_METHOD("UnsetAndSetEnvironment", "asas", NULL, method_unset_and_set_environment, 0),
1597 SD_BUS_METHOD("ListUnitFiles", NULL, "a(ss)", method_list_unit_files, 0),
1598 SD_BUS_METHOD("GetUnitFileState", "s", "s", method_get_unit_file_state, 0),
1599 SD_BUS_METHOD("EnableUnitFiles", "asbb", "ba(sss)", method_enable_unit_files, 0),
1600 SD_BUS_METHOD("DisableUnitFiles", "asb", "a(sss)", method_disable_unit_files, 0),
1601 SD_BUS_METHOD("ReenableUnitFiles", "asbb", "ba(sss)", method_reenable_unit_files, 0),
1602 SD_BUS_METHOD("LinkUnitFiles", "asbb", "a(sss)", method_link_unit_files, 0),
1603 SD_BUS_METHOD("PresetUnitFiles", "asbb", "ba(sss)", method_preset_unit_files, 0),
1604 SD_BUS_METHOD("MaskUnitFiles", "asbb", "a(sss)", method_mask_unit_files, 0),
1605 SD_BUS_METHOD("UnmaskUnitFiles", "asb", "a(sss)", method_unmask_unit_files, 0),
1606 SD_BUS_METHOD("SetDefaultTarget", "sb", "a(sss)", method_set_default_target, 0),
1607 SD_BUS_METHOD("GetDefaultTarget", NULL, "s", method_get_default_target, 0),
1608
1609 SD_BUS_SIGNAL("UnitNew", "so", 0),
1610 SD_BUS_SIGNAL("UnitRemoved", "so", 0),
1611 SD_BUS_SIGNAL("JobNew", "uos", 0),
1612 SD_BUS_SIGNAL("JobRemoved", "uoss", 0),
1613 SD_BUS_SIGNAL("StartupFinished", "tttttt", 0),
1614 SD_BUS_SIGNAL("UnitFilesChanged", NULL, 0),
1615 SD_BUS_SIGNAL("Reloading", "b", 0),
1616
1617 SD_BUS_VTABLE_END
1618 };
1619
1620 int bus_manager_foreach_client(Manager *m, int (*send_message)(sd_bus *bus, const char *destination, void *userdata), void *userdata) {
1621 Iterator i;
1622 sd_bus *b;
1623 unsigned n;
1624 int r;
1625
1626 n = set_size(m->subscribed);
1627 if (n <= 0)
1628 return 0;
1629 if (n == 1) {
1630 BusTrackedClient *d;
1631
1632 assert_se(d = set_first(m->subscribed));
1633 return send_message(d->bus, isempty(d->name) ? NULL : d->name, userdata);
1634 }
1635
1636 /* Send to everybody */
1637 SET_FOREACH(b, m->private_buses, i) {
1638 r = send_message(b, NULL, userdata);
1639 if (r < 0)
1640 return r;
1641 }
1642
1643 if (m->api_bus)
1644 return send_message(m->api_bus, NULL, userdata);
1645
1646 return 0;
1647 }
1648
1649 static int send_finished(sd_bus *bus, const char *destination, void *userdata) {
1650 _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
1651 usec_t *times = userdata;
1652 int r;
1653
1654 assert(bus);
1655 assert(times);
1656
1657 r = sd_bus_message_new_signal(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished", &message);
1658 if (r < 0)
1659 return r;
1660
1661 r = sd_bus_message_append(message, "tttttt", times[0], times[1], times[2], times[3], times[4], times[5]);
1662 if (r < 0)
1663 return r;
1664
1665 return sd_bus_send_to(bus, message, destination, NULL);
1666 }
1667
1668 int bus_manager_send_finished(
1669 Manager *m,
1670 usec_t firmware_usec,
1671 usec_t loader_usec,
1672 usec_t kernel_usec,
1673 usec_t initrd_usec,
1674 usec_t userspace_usec,
1675 usec_t total_usec) {
1676
1677 assert(m);
1678
1679 return bus_manager_foreach_client(m, send_finished,
1680 (usec_t[6]) { firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec });
1681 }
1682
1683 static int send_reloading(sd_bus *bus, const char *destination, void *userdata) {
1684 _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
1685 int r;
1686
1687 assert(bus);
1688
1689 r = sd_bus_message_new_signal(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "Reloading", &message);
1690 if (r < 0)
1691 return r;
1692
1693 r = sd_bus_message_append(message, "b", PTR_TO_INT(userdata));
1694 if (r < 0)
1695 return r;
1696
1697 return sd_bus_send_to(bus, message, destination, NULL);
1698 }
1699
1700 int bus_manager_send_reloading(Manager *m, bool active) {
1701 assert(m);
1702
1703 return bus_manager_foreach_client(m, send_reloading, INT_TO_PTR(active));
1704 }