chiark / gitweb /
core: fix serilization of ListJobs() response
[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 = selinux_access_check(bus, message, "start", error);
551         if (r < 0)
552                 return r;
553
554         r = manager_load_unit(m, name, NULL, error, &u);
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                                 j->unit->id,
778                                 job_type_to_string(j->type),
779                                 job_state_to_string(j->state),
780                                 job_path,
781                                 unit_path);
782                 if (r < 0)
783                         return r;
784         }
785
786         r = sd_bus_message_close_container(reply);
787         if (r < 0)
788                 return r;
789
790         return sd_bus_send(bus, reply, NULL);
791 }
792
793 static int method_subscribe(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
794         Manager *m = userdata;
795         int r;
796
797         assert(bus);
798         assert(message);
799         assert(m);
800
801         r = selinux_access_check(bus, message, "status", error);
802         if (r < 0)
803                 return r;
804
805         r = bus_client_track(&m->subscribed, bus, sd_bus_message_get_sender(message));
806         if (r < 0)
807                 return r;
808         if (r == 0)
809                 return sd_bus_error_setf(error, BUS_ERROR_ALREADY_SUBSCRIBED, "Client is already subscribed.");
810
811         return sd_bus_reply_method_return(message, NULL);
812 }
813
814 static int method_unsubscribe(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
815         Manager *m = userdata;
816         int r;
817
818         assert(bus);
819         assert(message);
820         assert(m);
821
822         r = selinux_access_check(bus, message, "status", error);
823         if (r < 0)
824                 return r;
825
826         r = bus_client_untrack(m->subscribed, bus, sd_bus_message_get_sender(message));
827         if (r < 0)
828                 return r;
829         if (r == 0)
830                 return sd_bus_error_setf(error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
831
832         return sd_bus_reply_method_return(message, NULL);
833 }
834
835 static int method_dump(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
836         _cleanup_free_ char *dump = NULL;
837         _cleanup_fclose_ FILE *f = NULL;
838         Manager *m = userdata;
839         size_t size;
840         int r;
841
842         assert(bus);
843         assert(message);
844         assert(m);
845
846         r = selinux_access_check(bus, message, "status", error);
847         if (r < 0)
848                 return r;
849
850         f = open_memstream(&dump, &size);
851         if (!f)
852                 return -ENOMEM;
853
854         manager_dump_units(m, f, NULL);
855         manager_dump_jobs(m, f, NULL);
856
857         fflush(f);
858
859         if (ferror(f))
860                 return -ENOMEM;
861
862         return sd_bus_reply_method_return(message, "s", dump);
863 }
864
865 static int method_create_snapshot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
866         _cleanup_free_ char *path = NULL;
867         Manager *m = userdata;
868         const char *name;
869         int cleanup;
870         Snapshot *s;
871         int r;
872
873         assert(bus);
874         assert(message);
875         assert(m);
876
877         r = selinux_access_check(bus, message, "start", error);
878         if (r < 0)
879                 return r;
880
881         r = sd_bus_message_read(message, "sb", &name, &cleanup);
882         if (r < 0)
883                 return r;
884
885         if (isempty(name))
886                 name = NULL;
887
888         r = snapshot_create(m, name, cleanup, error, &s);
889         if (r < 0)
890                 return r;
891
892         path = unit_dbus_path(UNIT(s));
893         if (!path)
894                 return -ENOMEM;
895
896         return sd_bus_reply_method_return(message, "o", path);
897 }
898
899 static int method_remove_snapshot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
900         Manager *m = userdata;
901         const char *name;
902         Unit *u;
903         int r;
904
905         assert(bus);
906         assert(message);
907         assert(m);
908
909         r = selinux_access_check(bus, message, "stop", error);
910         if (r < 0)
911                 return r;
912
913         r = sd_bus_message_read(message, "s", &name);
914         if (r < 0)
915                 return r;
916
917         u = manager_get_unit(m, name);
918         if (!u)
919                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s does not exist.", name);
920
921         if (u->type != UNIT_SNAPSHOT)
922                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not a snapshot", name);
923
924         return bus_snapshot_method_remove(bus, message, u, error);
925 }
926
927 static int method_reload(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
928         Manager *m = userdata;
929         int r;
930
931         assert(bus);
932         assert(message);
933         assert(m);
934
935         r = selinux_access_check(bus, message, "reload", error);
936         if (r < 0)
937                 return r;
938
939         /* Instead of sending the reply back right away, we just
940          * remember that we need to and then send it after the reload
941          * is finished. That way the caller knows when the reload
942          * finished. */
943
944         assert(!m->queued_message);
945         r = sd_bus_message_new_method_return(message, &m->queued_message);
946         if (r < 0)
947                 return r;
948
949         m->queued_message_bus = sd_bus_ref(bus);
950         m->exit_code = MANAGER_RELOAD;
951
952         return 1;
953 }
954
955 static int method_reexecute(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
956         Manager *m = userdata;
957         int r;
958
959         assert(bus);
960         assert(message);
961         assert(m);
962
963         r = selinux_access_check(bus, message, "reload", error);
964         if (r < 0)
965                 return r;
966
967         /* We don't send a reply back here, the client should
968          * just wait for us disconnecting. */
969
970         m->exit_code = MANAGER_REEXECUTE;
971         return 1;
972 }
973
974 static int method_exit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
975         Manager *m = userdata;
976         int r;
977
978         assert(bus);
979         assert(message);
980         assert(m);
981
982         r = selinux_access_check(bus, message, "halt", error);
983         if (r < 0)
984                 return r;
985
986         if (m->running_as == SYSTEMD_SYSTEM)
987                 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
988
989         m->exit_code = MANAGER_EXIT;
990
991         return sd_bus_reply_method_return(message, NULL);
992 }
993
994 static int method_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
995         Manager *m = userdata;
996         int r;
997
998         assert(bus);
999         assert(message);
1000         assert(m);
1001
1002         r = selinux_access_check(bus, message, "reboot", error);
1003         if (r < 0)
1004                 return r;
1005
1006         if (m->running_as != SYSTEMD_SYSTEM)
1007                 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
1008
1009         m->exit_code = MANAGER_REBOOT;
1010
1011         return sd_bus_reply_method_return(message, NULL);
1012 }
1013
1014
1015 static int method_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1016         Manager *m = userdata;
1017         int r;
1018
1019         assert(bus);
1020         assert(message);
1021         assert(m);
1022
1023         r = selinux_access_check(bus, message, "halt", error);
1024         if (r < 0)
1025                 return r;
1026
1027         if (m->running_as != SYSTEMD_SYSTEM)
1028                 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
1029
1030         m->exit_code = MANAGER_POWEROFF;
1031
1032         return sd_bus_reply_method_return(message, NULL);
1033 }
1034
1035 static int method_halt(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1036         Manager *m = userdata;
1037         int r;
1038
1039         assert(bus);
1040         assert(message);
1041         assert(m);
1042
1043         r = selinux_access_check(bus, message, "halt", error);
1044         if (r < 0)
1045                 return r;
1046
1047         if (m->running_as != SYSTEMD_SYSTEM)
1048                 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Halt is only supported for system managers.");
1049
1050         m->exit_code = MANAGER_HALT;
1051
1052         return sd_bus_reply_method_return(message, NULL);
1053 }
1054
1055 static int method_kexec(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1056         Manager *m = userdata;
1057         int r;
1058
1059         assert(bus);
1060         assert(message);
1061         assert(m);
1062
1063         r = selinux_access_check(bus, message, "reboot", error);
1064         if (r < 0)
1065                 return r;
1066
1067         if (m->running_as != SYSTEMD_SYSTEM)
1068                 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "KExec is only supported for system managers.");
1069
1070         m->exit_code = MANAGER_KEXEC;
1071
1072         return sd_bus_reply_method_return(message, NULL);
1073 }
1074
1075 static int method_switch_root(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1076         char *ri = NULL, *rt = NULL;
1077         const char *root, *init;
1078         Manager *m = userdata;
1079         int r;
1080
1081         assert(bus);
1082         assert(message);
1083         assert(m);
1084
1085         r = selinux_access_check(bus, message, "reboot", error);
1086         if (r < 0)
1087                 return r;
1088
1089         if (m->running_as != SYSTEMD_SYSTEM)
1090                 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "KExec is only supported for system managers.");
1091
1092         r = sd_bus_message_read(message, "ss", &root, &init);
1093         if (r < 0)
1094                 return r;
1095
1096         if (path_equal(root, "/") || !path_is_absolute(root))
1097                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid switch root path %s", root);
1098
1099         /* Safety check */
1100         if (isempty(init)) {
1101                 if (! path_is_os_tree(root))
1102                         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);
1103         } else {
1104                 _cleanup_free_ char *p = NULL;
1105
1106                 if (!path_is_absolute(init))
1107                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid init path %s", init);
1108
1109                 p = strappend(root, init);
1110                 if (!p)
1111                         return -ENOMEM;
1112
1113                 if (access(p, X_OK) < 0)
1114                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified init binary %s does not exist.", p);
1115         }
1116
1117         rt = strdup(root);
1118         if (!rt)
1119                 return -ENOMEM;
1120
1121         if (!isempty(init)) {
1122                 ri = strdup(init);
1123                 if (!ri) {
1124                         free(ri);
1125                         return -ENOMEM;
1126                 }
1127         }
1128
1129         free(m->switch_root);
1130         m->switch_root = rt;
1131
1132         free(m->switch_root_init);
1133         m->switch_root_init = ri;
1134
1135         return sd_bus_reply_method_return(message, NULL);
1136 }
1137
1138 static int method_set_environment(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1139         _cleanup_strv_free_ char **plus = NULL;
1140         Manager *m = userdata;
1141         int r;
1142
1143         assert(bus);
1144         assert(message);
1145         assert(m);
1146
1147         r = selinux_access_check(bus, message, "reload", error);
1148         if (r < 0)
1149                 return r;
1150
1151         r = sd_bus_message_read_strv(message, &plus);
1152         if (r < 0)
1153                 return r;
1154         if (!strv_env_is_valid(plus))
1155                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
1156
1157         r = manager_environment_add(m, NULL, plus);
1158         if (r < 0)
1159                 return r;
1160
1161         return sd_bus_reply_method_return(message, NULL);
1162 }
1163
1164 static int method_unset_environment(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1165         _cleanup_strv_free_ char **minus = NULL;
1166         Manager *m = userdata;
1167         int r;
1168
1169         assert(bus);
1170         assert(message);
1171         assert(m);
1172
1173         r = selinux_access_check(bus, message, "reload", error);
1174         if (r < 0)
1175                 return r;
1176
1177         r = sd_bus_message_read_strv(message, &minus);
1178         if (r < 0)
1179                 return r;
1180
1181         if (!strv_env_name_or_assignment_is_valid(minus))
1182                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment variable names or assignments");
1183
1184         r = manager_environment_add(m, minus, NULL);
1185         if (r < 0)
1186                 return r;
1187
1188         return sd_bus_reply_method_return(message, NULL);
1189 }
1190
1191 static int method_unset_and_set_environment(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1192         _cleanup_strv_free_ char **minus = NULL, **plus = NULL;
1193         Manager *m = userdata;
1194         int r;
1195
1196         assert(bus);
1197         assert(message);
1198         assert(m);
1199
1200         r = selinux_access_check(bus, message, "reload", error);
1201         if (r < 0)
1202                 return r;
1203
1204         r = sd_bus_message_read_strv(message, &plus);
1205         if (r < 0)
1206                 return r;
1207
1208         r = sd_bus_message_read_strv(message, &minus);
1209         if (r < 0)
1210                 return r;
1211
1212         if (!strv_env_is_valid(plus))
1213                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
1214         if (!strv_env_name_or_assignment_is_valid(minus))
1215                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment variable names or assignments");
1216
1217         r = manager_environment_add(m, minus, plus);
1218         if (r < 0)
1219                 return r;
1220
1221         return sd_bus_reply_method_return(message, NULL);
1222 }
1223
1224 static int method_list_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1225         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1226         Manager *m = userdata;
1227         UnitFileList *item;
1228         Hashmap *h;
1229         Iterator i;
1230         int r;
1231
1232         assert(bus);
1233         assert(message);
1234         assert(m);
1235
1236         r = selinux_access_check(bus, message, "status", error);
1237         if (r < 0)
1238                 return r;
1239
1240         r = sd_bus_message_new_method_return(message, &reply);
1241         if (r < 0)
1242                 return r;
1243
1244         h = hashmap_new(string_hash_func, string_compare_func);
1245         if (!h)
1246                 return -ENOMEM;
1247
1248         r = unit_file_get_list(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
1249         if (r < 0)
1250                 goto fail;
1251
1252         r = sd_bus_message_open_container(reply, 'a', "(ss)");
1253         if (r < 0)
1254                 goto fail;
1255
1256         HASHMAP_FOREACH(item, h, i) {
1257
1258                 r = sd_bus_message_append(reply, "(ss)", item->path, unit_file_state_to_string(item->state));
1259                 if (r < 0)
1260                         goto fail;
1261         }
1262
1263         unit_file_list_free(h);
1264
1265         r = sd_bus_message_close_container(reply);
1266         if (r < 0)
1267                 return r;
1268
1269         return sd_bus_send(bus, reply, NULL);
1270
1271 fail:
1272         unit_file_list_free(h);
1273         return r;
1274 }
1275
1276 static int method_get_unit_file_state(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1277         Manager *m = userdata;
1278         const char *name;
1279         UnitFileState state;
1280         UnitFileScope scope;
1281         int r;
1282
1283         assert(bus);
1284         assert(message);
1285         assert(m);
1286
1287         r = selinux_access_check(bus, message, "status", error);
1288         if (r < 0)
1289                 return r;
1290
1291         r = sd_bus_message_read(message, "s", &name);
1292         if (r < 0)
1293                 return r;
1294
1295         scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1296
1297         state = unit_file_get_state(scope, NULL, name);
1298         if (state < 0)
1299                 return state;
1300
1301         return sd_bus_reply_method_return(message, "s", unit_file_state_to_string(state));
1302 }
1303
1304 static int method_get_default_target(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1305         _cleanup_free_ char *default_target = NULL;
1306         Manager *m = userdata;
1307         UnitFileScope scope;
1308         int r;
1309
1310         assert(bus);
1311         assert(message);
1312         assert(m);
1313
1314         r = selinux_access_check(bus, message, "status", error);
1315         if (r < 0)
1316                 return r;
1317
1318         scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1319
1320         r = unit_file_get_default(scope, NULL, &default_target);
1321         if (r < 0)
1322                 return r;
1323
1324         return sd_bus_reply_method_return(message, "s", default_target);
1325 }
1326
1327 static int send_unit_files_changed(sd_bus *bus, const char *destination, void *userdata) {
1328         _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
1329         int r;
1330
1331         assert(bus);
1332
1333         r = sd_bus_message_new_signal(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged", &message);
1334         if (r < 0)
1335                 return r;
1336
1337         return sd_bus_send_to(bus, message, destination, NULL);
1338 }
1339
1340 static int reply_unit_file_changes_and_free(
1341                 Manager *m,
1342                 sd_bus *bus,
1343                 sd_bus_message *message,
1344                 int carries_install_info,
1345                 UnitFileChange *changes,
1346                 unsigned n_changes) {
1347
1348         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1349         unsigned i;
1350         int r;
1351
1352         if (n_changes > 0)
1353                 bus_manager_foreach_client(m, send_unit_files_changed, NULL);
1354
1355         r = sd_bus_message_new_method_return(message, &reply);
1356         if (r < 0)
1357                 goto fail;
1358
1359         if (carries_install_info >= 0) {
1360                 r = sd_bus_message_append(reply, "b", carries_install_info);
1361                 if (r < 0)
1362                         goto fail;
1363         }
1364
1365         r = sd_bus_message_open_container(reply, 'a', "(sss)");
1366         if (r < 0)
1367                 goto fail;
1368
1369         for (i = 0; i < n_changes; i++) {
1370                 r = sd_bus_message_append(
1371                                 reply, "(sss)",
1372                                 unit_file_change_type_to_string(changes[i].type),
1373                                 changes[i].path,
1374                                 changes[i].source);
1375                 if (r < 0)
1376                         goto fail;
1377         }
1378
1379         r = sd_bus_message_close_container(reply);
1380         if (r < 0)
1381                 goto fail;
1382
1383         return sd_bus_send(bus, reply, NULL);
1384
1385 fail:
1386         unit_file_changes_free(changes, n_changes);
1387         return r;
1388 }
1389
1390 static int method_enable_unit_files_generic(
1391                 sd_bus *bus,
1392                 sd_bus_message *message,
1393                 Manager *m, const
1394                 char *verb,
1395                 int (*call)(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes),
1396                 bool carries_install_info,
1397                 sd_bus_error *error) {
1398
1399         _cleanup_strv_free_ char **l = NULL;
1400         UnitFileChange *changes = NULL;
1401         unsigned n_changes = 0;
1402         UnitFileScope scope;
1403         int runtime, force, r;
1404
1405         assert(bus);
1406         assert(message);
1407         assert(m);
1408
1409         r = selinux_access_check(bus, message, verb, error);
1410         if (r < 0)
1411                 return r;
1412
1413         r = sd_bus_message_read_strv(message, &l);
1414         if (r < 0)
1415                 return r;
1416
1417         r = sd_bus_message_read(message, "bb", &runtime, &force);
1418         if (r < 0)
1419                 return r;
1420
1421         scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1422
1423         r = call(scope, runtime, NULL, l, force, &changes, &n_changes);
1424         if (r < 0)
1425                 return r;
1426
1427         return reply_unit_file_changes_and_free(m, bus, message, carries_install_info ? r : -1, changes, n_changes);
1428 }
1429
1430 static int method_enable_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1431         return method_enable_unit_files_generic(bus, message, userdata, "enable", unit_file_enable, true, error);
1432 }
1433
1434 static int method_reenable_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1435         return method_enable_unit_files_generic(bus, message, userdata, "enable", unit_file_reenable, true, error);
1436 }
1437
1438 static int method_link_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1439         return method_enable_unit_files_generic(bus, message, userdata, "enable", unit_file_link, false, error);
1440 }
1441
1442 static int method_preset_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1443         return method_enable_unit_files_generic(bus, message, userdata, "enable", unit_file_preset, true, error);
1444 }
1445
1446 static int method_mask_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1447         return method_enable_unit_files_generic(bus, message, userdata, "disable", unit_file_mask, false, error);
1448 }
1449
1450 static int method_disable_unit_files_generic(
1451                 sd_bus *bus,
1452                 sd_bus_message *message,
1453                 Manager *m, const
1454                 char *verb,
1455                 int (*call)(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], UnitFileChange **changes, unsigned *n_changes),
1456                 sd_bus_error *error) {
1457
1458         _cleanup_strv_free_ char **l = NULL;
1459         UnitFileChange *changes = NULL;
1460         unsigned n_changes = 0;
1461         UnitFileScope scope;
1462         int r, runtime;
1463
1464         assert(bus);
1465         assert(message);
1466         assert(m);
1467
1468         r = selinux_access_check(bus, message, verb, error);
1469         if (r < 0)
1470                 return r;
1471
1472         r = sd_bus_message_read_strv(message, &l);
1473         if (r < 0)
1474                 return r;
1475
1476         r = sd_bus_message_read(message, "b", &runtime);
1477         if (r < 0)
1478                 return r;
1479
1480         scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1481
1482         r = call(scope, runtime, NULL, l, &changes, &n_changes);
1483         if (r < 0)
1484                 return r;
1485
1486         return reply_unit_file_changes_and_free(m, bus, message, -1, changes, n_changes);
1487 }
1488
1489 static int method_disable_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1490         return method_disable_unit_files_generic(bus, message, userdata, "disable", unit_file_disable, error);
1491 }
1492
1493 static int method_unmask_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1494         return method_disable_unit_files_generic(bus, message, userdata, "enable", unit_file_unmask, error);
1495 }
1496
1497 static int method_set_default_target(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1498         UnitFileChange *changes = NULL;
1499         unsigned n_changes = 0;
1500         Manager *m = userdata;
1501         UnitFileScope scope;
1502         const char *name;
1503         int force, r;
1504
1505         assert(bus);
1506         assert(message);
1507         assert(m);
1508
1509         r = selinux_access_check(bus, message, "enable", error);
1510         if (r < 0)
1511                 return r;
1512
1513         r = sd_bus_message_read(message, "sb", &name, &force);
1514         if (r < 0)
1515                 return r;
1516
1517         scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1518
1519         r = unit_file_set_default(scope, NULL, name, force, &changes, &n_changes);
1520         if (r < 0)
1521                 return r;
1522
1523         return reply_unit_file_changes_and_free(m, bus, message, -1, changes, n_changes);
1524 }
1525
1526 const sd_bus_vtable bus_manager_vtable[] = {
1527         SD_BUS_VTABLE_START(0),
1528
1529         SD_BUS_PROPERTY("Version", "s", property_get_version, 0, 0),
1530         SD_BUS_PROPERTY("Features", "s", property_get_features, 0, 0),
1531         SD_BUS_PROPERTY("Virtualization", "s", property_get_virtualization, 0, 0),
1532         SD_BUS_PROPERTY("Tainted", "s", property_get_tainted, 0, 0),
1533         BUS_PROPERTY_DUAL_TIMESTAMP("FirmwareTimestamp", offsetof(Manager, firmware_timestamp), 0),
1534         BUS_PROPERTY_DUAL_TIMESTAMP("LoaderTimestamp", offsetof(Manager, loader_timestamp), 0),
1535         BUS_PROPERTY_DUAL_TIMESTAMP("KernelTimestamp", offsetof(Manager, firmware_timestamp), 0),
1536         BUS_PROPERTY_DUAL_TIMESTAMP("InitRDTimestamp", offsetof(Manager, initrd_timestamp), 0),
1537         BUS_PROPERTY_DUAL_TIMESTAMP("UserspaceTimestamp", offsetof(Manager, userspace_timestamp), 0),
1538         BUS_PROPERTY_DUAL_TIMESTAMP("FinishTimestamp", offsetof(Manager, finish_timestamp), 0),
1539         BUS_PROPERTY_DUAL_TIMESTAMP("SecurityStartTimestamp", offsetof(Manager, security_start_timestamp), 0),
1540         BUS_PROPERTY_DUAL_TIMESTAMP("SecurityFinishTimestamp", offsetof(Manager, security_finish_timestamp), 0),
1541         BUS_PROPERTY_DUAL_TIMESTAMP("GeneratorsStartTimestamp", offsetof(Manager, generators_start_timestamp), 0),
1542         BUS_PROPERTY_DUAL_TIMESTAMP("GeneratorsFinishTimestamp", offsetof(Manager, generators_finish_timestamp), 0),
1543         BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadStartTimestamp", offsetof(Manager, units_load_start_timestamp), 0),
1544         BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadFinishTimestamp", offsetof(Manager, units_load_finish_timestamp), 0),
1545         SD_BUS_WRITABLE_PROPERTY("LogLevel", "s", property_get_log_level, property_set_log_level, 0, 0),
1546         SD_BUS_WRITABLE_PROPERTY("LogTarget", "s", property_get_log_target, property_set_log_target, 0, 0),
1547         SD_BUS_PROPERTY("NNames", "u", property_get_n_names, 0, 0),
1548         SD_BUS_PROPERTY("NJobs", "u", property_get_n_jobs, 0, 0),
1549         SD_BUS_PROPERTY("NInstalledJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_installed_jobs), 0),
1550         SD_BUS_PROPERTY("NFailedJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_failed_jobs), 0),
1551         SD_BUS_PROPERTY("Progress", "d", property_get_progress, 0, 0),
1552         SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(Manager, environment), 0),
1553         SD_BUS_PROPERTY("ConfirmSpawn", "b", bus_property_get_bool, offsetof(Manager, confirm_spawn), 0),
1554         SD_BUS_PROPERTY("ShowStatus", "b", bus_property_get_bool, offsetof(Manager, show_status), 0),
1555         SD_BUS_PROPERTY("UnitPath", "as", NULL, offsetof(Manager, lookup_paths.unit_path), 0),
1556         SD_BUS_PROPERTY("DefaultStandardOutput", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), 0),
1557         SD_BUS_PROPERTY("DefaultStandardError", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), 0),
1558         SD_BUS_WRITABLE_PROPERTY("RuntimeWatchdogUSec", "t", bus_property_get_usec, property_set_runtime_watchdog, offsetof(Manager, runtime_watchdog), 0),
1559         SD_BUS_WRITABLE_PROPERTY("ShutdownWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, shutdown_watchdog), 0),
1560
1561         SD_BUS_METHOD("GetUnit", "s", "o", method_get_unit, 0),
1562         SD_BUS_METHOD("GetUnitByPID", "u", "o", method_get_unit_by_pid, 0),
1563         SD_BUS_METHOD("LoadUnit", "s", "o", method_load_unit, 0),
1564         SD_BUS_METHOD("StartUnit", "ss", "o", method_start_unit, 0),
1565         SD_BUS_METHOD("StartUnitReplace", "sss", "o", method_start_unit_replace, 0),
1566         SD_BUS_METHOD("StopUnit", "ss", "o", method_stop_unit, 0),
1567         SD_BUS_METHOD("ReloadUnit", "ss", "o", method_reload_unit, 0),
1568         SD_BUS_METHOD("RestartUnit", "ss", "o", method_restart_unit, 0),
1569         SD_BUS_METHOD("TryRestartUnit", "ss", "o", method_try_restart_unit, 0),
1570         SD_BUS_METHOD("ReloadOrRestartUnit", "ss", "o", method_reload_or_restart_unit, 0),
1571         SD_BUS_METHOD("ReloadOrTryRestartUnit", "ss", "o", method_reload_or_try_restart_unit, 0),
1572         SD_BUS_METHOD("KillUnit", "ssi", NULL, method_kill_unit, 0),
1573         SD_BUS_METHOD("ResetFailedUnit", "s", NULL, method_reset_failed_unit, 0),
1574         SD_BUS_METHOD("SetUnitProperties", "sb", "a(sv)", method_set_unit_properties, 0),
1575         SD_BUS_METHOD("StartTransientUnit", "ssa(sv)a(sa(sv))", "o", method_start_transient_unit, 0),
1576         SD_BUS_METHOD("GetJob", "u", "o", method_get_job, 0),
1577         SD_BUS_METHOD("CancelJob", "u", NULL, method_cancel_job, 0),
1578         SD_BUS_METHOD("ClearJobs", NULL, NULL, method_clear_jobs, 0),
1579         SD_BUS_METHOD("ResetFailed", NULL, NULL, method_reset_failed, 0),
1580         SD_BUS_METHOD("ListUnits", NULL, "a(ssssssouso)", method_list_units, 0),
1581         SD_BUS_METHOD("ListJobs", NULL, "a(usssoo)", method_list_jobs, 0),
1582         SD_BUS_METHOD("Subscribe", NULL, NULL, method_subscribe, 0),
1583         SD_BUS_METHOD("Unsubscribe", NULL, NULL, method_unsubscribe, 0),
1584         SD_BUS_METHOD("Dump", NULL, "s", method_dump, 0),
1585         SD_BUS_METHOD("CreateSnapshot", "sb", "o", method_create_snapshot, 0),
1586         SD_BUS_METHOD("RemoveSnapshot", "s", NULL, method_remove_snapshot, 0),
1587         SD_BUS_METHOD("Reload", NULL, NULL, method_reload, 0),
1588         SD_BUS_METHOD("Reexecute", NULL, NULL, method_reexecute, 0),
1589         SD_BUS_METHOD("Exit", NULL, NULL, method_exit, 0),
1590         SD_BUS_METHOD("Reboot", NULL, NULL, method_reboot, 0),
1591         SD_BUS_METHOD("PowerOff", NULL, NULL, method_poweroff, 0),
1592         SD_BUS_METHOD("Halt", NULL, NULL, method_halt, 0),
1593         SD_BUS_METHOD("KExec", NULL, NULL, method_kexec, 0),
1594         SD_BUS_METHOD("SwitchRoot", "ss", NULL, method_switch_root, 0),
1595         SD_BUS_METHOD("SetEnvironment", "as", NULL, method_set_environment, 0),
1596         SD_BUS_METHOD("UnsetEnvironment", "as", NULL, method_unset_environment, 0),
1597         SD_BUS_METHOD("UnsetAndSetEnvironment", "asas", NULL, method_unset_and_set_environment, 0),
1598         SD_BUS_METHOD("ListUnitFiles", NULL, "a(ss)", method_list_unit_files, 0),
1599         SD_BUS_METHOD("GetUnitFileState", "s", "s", method_get_unit_file_state, 0),
1600         SD_BUS_METHOD("EnableUnitFiles", "asbb", "ba(sss)", method_enable_unit_files, 0),
1601         SD_BUS_METHOD("DisableUnitFiles", "asb", "a(sss)", method_disable_unit_files, 0),
1602         SD_BUS_METHOD("ReenableUnitFiles", "asbb", "ba(sss)", method_reenable_unit_files, 0),
1603         SD_BUS_METHOD("LinkUnitFiles", "asbb", "a(sss)", method_link_unit_files, 0),
1604         SD_BUS_METHOD("PresetUnitFiles", "asbb", "ba(sss)", method_preset_unit_files, 0),
1605         SD_BUS_METHOD("MaskUnitFiles", "asbb", "a(sss)", method_mask_unit_files, 0),
1606         SD_BUS_METHOD("UnmaskUnitFiles", "asb", "a(sss)", method_unmask_unit_files, 0),
1607         SD_BUS_METHOD("SetDefaultTarget", "sb", "a(sss)", method_set_default_target, 0),
1608         SD_BUS_METHOD("GetDefaultTarget", NULL, "s", method_get_default_target, 0),
1609
1610         SD_BUS_SIGNAL("UnitNew", "so", 0),
1611         SD_BUS_SIGNAL("UnitRemoved", "so", 0),
1612         SD_BUS_SIGNAL("JobNew", "uos", 0),
1613         SD_BUS_SIGNAL("JobRemoved", "uoss", 0),
1614         SD_BUS_SIGNAL("StartupFinished", "tttttt", 0),
1615         SD_BUS_SIGNAL("UnitFilesChanged", NULL, 0),
1616         SD_BUS_SIGNAL("Reloading", "b", 0),
1617
1618         SD_BUS_VTABLE_END
1619 };
1620
1621 int bus_manager_foreach_client(Manager *m, int (*send_message)(sd_bus *bus, const char *destination, void *userdata), void *userdata) {
1622         Iterator i;
1623         sd_bus *b;
1624         unsigned n;
1625         int r;
1626
1627         n = set_size(m->subscribed);
1628         if (n <= 0)
1629                 return 0;
1630         if (n == 1) {
1631                 BusTrackedClient *d;
1632
1633                 assert_se(d = set_first(m->subscribed));
1634                 return send_message(d->bus, isempty(d->name) ? NULL : d->name, userdata);
1635         }
1636
1637         /* Send to everybody */
1638         SET_FOREACH(b, m->private_buses, i) {
1639                 r = send_message(b, NULL, userdata);
1640                 if (r < 0)
1641                         return r;
1642         }
1643
1644         if (m->api_bus)
1645                 return send_message(m->api_bus, NULL, userdata);
1646
1647         return 0;
1648 }
1649
1650 static int send_finished(sd_bus *bus, const char *destination, void *userdata) {
1651         _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
1652         usec_t *times = userdata;
1653         int r;
1654
1655         assert(bus);
1656         assert(times);
1657
1658         r = sd_bus_message_new_signal(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished", &message);
1659         if (r < 0)
1660                 return r;
1661
1662         r = sd_bus_message_append(message, "tttttt", times[0], times[1], times[2], times[3], times[4], times[5]);
1663         if (r < 0)
1664                 return r;
1665
1666         return sd_bus_send_to(bus, message, destination, NULL);
1667 }
1668
1669 int bus_manager_send_finished(
1670                 Manager *m,
1671                 usec_t firmware_usec,
1672                 usec_t loader_usec,
1673                 usec_t kernel_usec,
1674                 usec_t initrd_usec,
1675                 usec_t userspace_usec,
1676                 usec_t total_usec) {
1677
1678         assert(m);
1679
1680         return bus_manager_foreach_client(m, send_finished,
1681                         (usec_t[6]) { firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec });
1682 }
1683
1684 static int send_reloading(sd_bus *bus, const char *destination, void *userdata) {
1685         _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
1686         int r;
1687
1688         assert(bus);
1689
1690         r = sd_bus_message_new_signal(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "Reloading", &message);
1691         if (r < 0)
1692                 return r;
1693
1694         r = sd_bus_message_append(message, "b", PTR_TO_INT(userdata));
1695         if (r < 0)
1696                 return r;
1697
1698         return sd_bus_send_to(bus, message, destination, NULL);
1699 }
1700
1701 int bus_manager_send_reloading(Manager *m, bool active) {
1702         assert(m);
1703
1704         return bus_manager_foreach_client(m, send_reloading, INT_TO_PTR(active));
1705 }