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