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