chiark / gitweb /
bc0c3109e393f41a3d6cda7d4eb9753ea3221b15
[elogind.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 }