]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-manager.c
core: generate nice error messages for auxiliary transient units, too
[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
06cc6afa 647 UnitType t;
ab31f6b8
WC
648 Unit *u;
649 int r;
650
651 assert(m);
652 assert(message);
653 assert(name);
654
06cc6afa
LP
655 t = unit_name_to_type(name);
656 if (t < 0)
657 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit name or type.");
658
659 if (!unit_vtable[t]->can_transient)
660 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit type %s does not support transient units.", unit_type_to_string(t));
661
ab31f6b8
WC
662 r = manager_load_unit(m, name, NULL, error, &u);
663 if (r < 0)
664 return r;
665
17f62e9b
LP
666 /* Check if the unit already exists or is already referenced,
667 * in a number of different ways. Note that to cater for unit
668 * types such as slice, we are generally fine with units that
669 * are marked UNIT_LOADED even even though nothing was
670 * actually loaded, as those unit types don't require a file
671 * on disk to validly load. */
672
673 if (!IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_LOADED) ||
674 u->fragment_path ||
675 u->source_path ||
676 !strv_isempty(u->dropin_paths) ||
677 u->refs ||
ab31f6b8
WC
678 set_size(u->dependencies[UNIT_REFERENCED_BY]) > 0)
679 return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit %s already exists.", name);
680
681 /* OK, the unit failed to load and is unreferenced, now let's
682 * fill in the transient data instead */
683 r = unit_make_transient(u);
684 if (r < 0)
685 return r;
686
687 /* Set our properties */
688 r = bus_unit_set_properties(u, message, UNIT_RUNTIME, false, error);
689 if (r < 0)
690 return r;
691
692 *unit = u;
693
694 return 0;
695}
696
697static int transient_aux_units_from_message(
698 Manager *m,
699 sd_bus_message *message,
700 sd_bus_error *error) {
701
702 Unit *u;
703 char *name = NULL;
704 int r;
705
706 assert(m);
707 assert(message);
708
709 r = sd_bus_message_enter_container(message, 'a', "(sa(sv))");
710 if (r < 0)
711 return r;
712
713 while ((r = sd_bus_message_enter_container(message, 'r', "sa(sv)")) > 0) {
ab31f6b8
WC
714 r = sd_bus_message_read(message, "s", &name);
715 if (r < 0)
716 return r;
717
718 r = transient_unit_from_message(m, message, name, &u, error);
719 if (r < 0 && r != -EEXIST)
720 return r;
721
4c213d6c
WC
722 if (r != -EEXIST) {
723 r = unit_load(u);
724 if (r < 0)
725 return r;
726 }
ab31f6b8
WC
727
728 r = sd_bus_message_exit_container(message);
729 if (r < 0)
730 return r;
731 }
732 if (r < 0)
733 return r;
734
735 r = sd_bus_message_exit_container(message);
736 if (r < 0)
737 return r;
738
739 return 0;
740}
741
19070062 742static int method_start_transient_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
743 const char *name, *smode;
744 Manager *m = userdata;
745 JobMode mode;
718db961
LP
746 Unit *u;
747 int r;
ea430986 748
718db961
LP
749 assert(message);
750 assert(m);
ea430986 751
1d22e906 752 r = mac_selinux_access_check(message, "start", error);
283868e1
SW
753 if (r < 0)
754 return r;
283868e1 755
718db961
LP
756 r = sd_bus_message_read(message, "ss", &name, &smode);
757 if (r < 0)
ebcf1f97 758 return r;
5632e374 759
718db961
LP
760 mode = job_mode_from_string(smode);
761 if (mode < 0)
ebcf1f97 762 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s is invalid.", smode);
5632e374 763
1d22e906 764 r = bus_verify_manage_units_async(m, message, error);
718db961 765 if (r < 0)
ebcf1f97 766 return r;
1d22e906
LP
767 if (r == 0)
768 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
5632e374 769
ab31f6b8 770 r = transient_unit_from_message(m, message, name, &u, error);
ebcf1f97
LP
771 if (r < 0)
772 return r;
5632e374 773
ab31f6b8 774 r = transient_aux_units_from_message(m, message, error);
718db961 775 if (r < 0)
ebcf1f97 776 return r;
ea430986 777
718db961
LP
778 /* And load this stub fully */
779 r = unit_load(u);
780 if (r < 0)
ebcf1f97 781 return r;
ea430986 782
718db961 783 manager_dispatch_load_queue(m);
cad45ba1 784
718db961 785 /* Finally, start it */
19070062 786 return bus_unit_queue_job(message, u, JOB_START, mode, false, error);
718db961 787}
ea430986 788
19070062 789static int method_get_job(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
790 _cleanup_free_ char *path = NULL;
791 Manager *m = userdata;
792 uint32_t id;
793 Job *j;
794 int r;
ea430986 795
718db961
LP
796 assert(message);
797 assert(m);
ea430986 798
283868e1
SW
799 /* Anyone can call this method */
800
718db961
LP
801 r = sd_bus_message_read(message, "u", &id);
802 if (r < 0)
ebcf1f97 803 return r;
ea430986 804
718db961
LP
805 j = manager_get_job(m, id);
806 if (!j)
ebcf1f97 807 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
ea430986 808
8a188de9 809 r = mac_selinux_unit_access_check(j->unit, message, "status", error);
ebcf1f97
LP
810 if (r < 0)
811 return r;
ea430986 812
718db961
LP
813 path = job_dbus_path(j);
814 if (!path)
ebcf1f97 815 return -ENOMEM;
ea430986 816
df2d202e 817 return sd_bus_reply_method_return(message, "o", path);
718db961 818}
ea430986 819
19070062 820static int method_cancel_job(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
821 Manager *m = userdata;
822 uint32_t id;
823 Job *j;
824 int r;
ea430986 825
718db961
LP
826 assert(message);
827 assert(m);
ea430986 828
718db961
LP
829 r = sd_bus_message_read(message, "u", &id);
830 if (r < 0)
ebcf1f97 831 return r;
ea430986 832
718db961
LP
833 j = manager_get_job(m, id);
834 if (!j)
ebcf1f97 835 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
ea430986 836
19070062 837 return bus_job_method_cancel(message, j, error);
718db961 838}
c1e1601e 839
19070062 840static int method_clear_jobs(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961 841 Manager *m = userdata;
ebcf1f97 842 int r;
c1e1601e 843
718db961
LP
844 assert(message);
845 assert(m);
c1e1601e 846
1d22e906 847 r = mac_selinux_access_check(message, "reload", error);
ebcf1f97
LP
848 if (r < 0)
849 return r;
850
1d22e906
LP
851 r = bus_verify_manage_units_async(m, message, error);
852 if (r < 0)
853 return r;
854 if (r == 0)
855 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
856
718db961 857 manager_clear_jobs(m);
c1e1601e 858
df2d202e 859 return sd_bus_reply_method_return(message, NULL);
718db961 860}
c1e1601e 861
19070062 862static int method_reset_failed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961 863 Manager *m = userdata;
ebcf1f97 864 int r;
cad45ba1 865
718db961
LP
866 assert(message);
867 assert(m);
868
8a188de9 869 r = mac_selinux_access_check(message, "reload", error);
ebcf1f97
LP
870 if (r < 0)
871 return r;
872
1d22e906
LP
873 r = bus_verify_manage_units_async(m, message, error);
874 if (r < 0)
875 return r;
876 if (r == 0)
877 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
878
718db961 879 manager_reset_failed(m);
c1e1601e 880
df2d202e 881 return sd_bus_reply_method_return(message, NULL);
718db961 882}
c1e1601e 883
19070062 884static int list_units_filtered(sd_bus_message *message, void *userdata, sd_bus_error *error, char **states) {
718db961
LP
885 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
886 Manager *m = userdata;
887 const char *k;
888 Iterator i;
889 Unit *u;
890 int r;
c1e1601e 891
718db961
LP
892 assert(message);
893 assert(m);
b152adec 894
283868e1
SW
895 /* Anyone can call this method */
896
8a188de9 897 r = mac_selinux_access_check(message, "status", error);
ebcf1f97
LP
898 if (r < 0)
899 return r;
cad45ba1 900
df2d202e 901 r = sd_bus_message_new_method_return(message, &reply);
718db961 902 if (r < 0)
ebcf1f97 903 return r;
b152adec 904
718db961
LP
905 r = sd_bus_message_open_container(reply, 'a', "(ssssssouso)");
906 if (r < 0)
ebcf1f97 907 return r;
b152adec 908
718db961
LP
909 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
910 _cleanup_free_ char *unit_path = NULL, *job_path = NULL;
911 Unit *following;
b152adec 912
718db961
LP
913 if (k != u->id)
914 continue;
b152adec 915
718db961 916 following = unit_following(u);
b152adec 917
cdc06ed7
DS
918 if (!strv_isempty(states) &&
919 !strv_contains(states, unit_load_state_to_string(u->load_state)) &&
920 !strv_contains(states, unit_active_state_to_string(unit_active_state(u))) &&
921 !strv_contains(states, unit_sub_state_to_string(u)))
922 continue;
923
718db961
LP
924 unit_path = unit_dbus_path(u);
925 if (!unit_path)
ebcf1f97 926 return -ENOMEM;
718db961
LP
927
928 if (u->job) {
929 job_path = job_dbus_path(u->job);
930 if (!job_path)
ebcf1f97 931 return -ENOMEM;
b152adec
LP
932 }
933
718db961
LP
934 r = sd_bus_message_append(
935 reply, "(ssssssouso)",
936 u->id,
937 unit_description(u),
938 unit_load_state_to_string(u->load_state),
939 unit_active_state_to_string(unit_active_state(u)),
940 unit_sub_state_to_string(u),
941 following ? following->id : "",
942 unit_path,
943 u->job ? u->job->id : 0,
944 u->job ? job_type_to_string(u->job->type) : "",
945 job_path ? job_path : "/");
946 if (r < 0)
ebcf1f97 947 return r;
718db961 948 }
4139c1b2 949
718db961
LP
950 r = sd_bus_message_close_container(reply);
951 if (r < 0)
ebcf1f97 952 return r;
cad45ba1 953
9030ca46 954 return sd_bus_send(NULL, reply, NULL);
718db961 955}
4139c1b2 956
19070062
LP
957static int method_list_units(sd_bus_message *message, void *userdata, sd_bus_error *error) {
958 return list_units_filtered(message, userdata, error, NULL);
cdc06ed7
DS
959}
960
19070062 961static int method_list_units_filtered(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cdc06ed7
DS
962 _cleanup_strv_free_ char **states = NULL;
963 int r;
964
965 r = sd_bus_message_read_strv(message, &states);
966 if (r < 0)
967 return r;
968
19070062 969 return list_units_filtered(message, userdata, error, states);
cdc06ed7
DS
970}
971
19070062 972static int method_list_jobs(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
973 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
974 Manager *m = userdata;
975 Iterator i;
976 Job *j;
977 int r;
4139c1b2 978
718db961
LP
979 assert(message);
980 assert(m);
981
283868e1
SW
982 /* Anyone can call this method */
983
8a188de9 984 r = mac_selinux_access_check(message, "status", error);
ebcf1f97
LP
985 if (r < 0)
986 return r;
718db961 987
df2d202e 988 r = sd_bus_message_new_method_return(message, &reply);
718db961 989 if (r < 0)
ebcf1f97 990 return r;
718db961
LP
991
992 r = sd_bus_message_open_container(reply, 'a', "(usssoo)");
993 if (r < 0)
ebcf1f97 994 return r;
718db961
LP
995
996 HASHMAP_FOREACH(j, m->jobs, i) {
997 _cleanup_free_ char *unit_path = NULL, *job_path = NULL;
998
999 job_path = job_dbus_path(j);
1000 if (!job_path)
ebcf1f97 1001 return -ENOMEM;
718db961
LP
1002
1003 unit_path = unit_dbus_path(j->unit);
1004 if (!unit_path)
ebcf1f97 1005 return -ENOMEM;
718db961
LP
1006
1007 r = sd_bus_message_append(
1008 reply, "(usssoo)",
1009 j->id,
1302759d 1010 j->unit->id,
718db961 1011 job_type_to_string(j->type),
1302759d 1012 job_state_to_string(j->state),
718db961
LP
1013 job_path,
1014 unit_path);
cad45ba1 1015 if (r < 0)
ebcf1f97 1016 return r;
718db961 1017 }
5dd9014f 1018
718db961
LP
1019 r = sd_bus_message_close_container(reply);
1020 if (r < 0)
ebcf1f97 1021 return r;
5dd9014f 1022
9030ca46 1023 return sd_bus_send(NULL, reply, NULL);
718db961 1024}
5dd9014f 1025
19070062 1026static int method_subscribe(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
1027 Manager *m = userdata;
1028 int r;
5dd9014f 1029
718db961
LP
1030 assert(message);
1031 assert(m);
ea430986 1032
283868e1
SW
1033 /* Anyone can call this method */
1034
8a188de9 1035 r = mac_selinux_access_check(message, "status", error);
ebcf1f97
LP
1036 if (r < 0)
1037 return r;
cad45ba1 1038
19070062 1039 if (sd_bus_message_get_bus(message) == m->api_bus) {
8f8f05a9
LP
1040
1041 /* Note that direct bus connection subscribe by
1042 * default, we only track peers on the API bus here */
1043
1044 if (!m->subscribed) {
19070062 1045 r = sd_bus_track_new(sd_bus_message_get_bus(message), &m->subscribed, NULL, NULL);
8f8f05a9
LP
1046 if (r < 0)
1047 return r;
1048 }
1049
1050 r = sd_bus_track_add_sender(m->subscribed, message);
1051 if (r < 0)
1052 return r;
1053 if (r == 0)
1054 return sd_bus_error_setf(error, BUS_ERROR_ALREADY_SUBSCRIBED, "Client is already subscribed.");
1055 }
ea430986 1056
df2d202e 1057 return sd_bus_reply_method_return(message, NULL);
718db961 1058}
ea430986 1059
19070062 1060static int method_unsubscribe(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
1061 Manager *m = userdata;
1062 int r;
ea430986 1063
718db961
LP
1064 assert(message);
1065 assert(m);
ea430986 1066
283868e1
SW
1067 /* Anyone can call this method */
1068
8a188de9 1069 r = mac_selinux_access_check(message, "status", error);
ebcf1f97
LP
1070 if (r < 0)
1071 return r;
ea430986 1072
19070062 1073 if (sd_bus_message_get_bus(message) == m->api_bus) {
8f8f05a9
LP
1074 r = sd_bus_track_remove_sender(m->subscribed, message);
1075 if (r < 0)
1076 return r;
1077 if (r == 0)
1078 return sd_bus_error_setf(error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
1079 }
ea430986 1080
df2d202e 1081 return sd_bus_reply_method_return(message, NULL);
718db961 1082}
ea430986 1083
19070062 1084static int method_dump(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
1085 _cleanup_free_ char *dump = NULL;
1086 _cleanup_fclose_ FILE *f = NULL;
1087 Manager *m = userdata;
1088 size_t size;
ebcf1f97 1089 int r;
ea430986 1090
718db961
LP
1091 assert(message);
1092 assert(m);
ea430986 1093
283868e1
SW
1094 /* Anyone can call this method */
1095
8a188de9 1096 r = mac_selinux_access_check(message, "status", error);
ebcf1f97
LP
1097 if (r < 0)
1098 return r;
ea430986 1099
718db961
LP
1100 f = open_memstream(&dump, &size);
1101 if (!f)
ebcf1f97 1102 return -ENOMEM;
ea430986 1103
718db961
LP
1104 manager_dump_units(m, f, NULL);
1105 manager_dump_jobs(m, f, NULL);
ea430986 1106
dacd6cee
LP
1107 r = fflush_and_check(f);
1108 if (r < 0)
1109 return r;
a16e1123 1110
df2d202e 1111 return sd_bus_reply_method_return(message, "s", dump);
718db961 1112}
cad45ba1 1113
36b4a7ba
ZJS
1114static int method_refuse_snapshot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1115 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Support for snapshots has been removed.");
718db961 1116}
cad45ba1 1117
19070062 1118static int method_reload(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
1119 Manager *m = userdata;
1120 int r;
6652a2b9 1121
718db961
LP
1122 assert(message);
1123 assert(m);
6652a2b9 1124
1d22e906 1125 r = mac_selinux_access_check(message, "reload", error);
283868e1
SW
1126 if (r < 0)
1127 return r;
283868e1 1128
1d22e906 1129 r = bus_verify_reload_daemon_async(m, message, error);
ebcf1f97
LP
1130 if (r < 0)
1131 return r;
1d22e906
LP
1132 if (r == 0)
1133 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
6652a2b9 1134
718db961
LP
1135 /* Instead of sending the reply back right away, we just
1136 * remember that we need to and then send it after the reload
1137 * is finished. That way the caller knows when the reload
1138 * finished. */
6652a2b9 1139
718db961 1140 assert(!m->queued_message);
df2d202e 1141 r = sd_bus_message_new_method_return(message, &m->queued_message);
718db961 1142 if (r < 0)
ebcf1f97 1143 return r;
cad45ba1 1144
718db961 1145 m->exit_code = MANAGER_RELOAD;
6652a2b9 1146
718db961
LP
1147 return 1;
1148}
6652a2b9 1149
19070062 1150static int method_reexecute(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961 1151 Manager *m = userdata;
ebcf1f97 1152 int r;
6652a2b9 1153
718db961
LP
1154 assert(message);
1155 assert(m);
6652a2b9 1156
1d22e906 1157 r = mac_selinux_access_check(message, "reload", error);
283868e1
SW
1158 if (r < 0)
1159 return r;
283868e1 1160
1d22e906 1161 r = bus_verify_reload_daemon_async(m, message, error);
ebcf1f97
LP
1162 if (r < 0)
1163 return r;
1d22e906
LP
1164 if (r == 0)
1165 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
cad45ba1 1166
718db961
LP
1167 /* We don't send a reply back here, the client should
1168 * just wait for us disconnecting. */
6652a2b9 1169
718db961
LP
1170 m->exit_code = MANAGER_REEXECUTE;
1171 return 1;
1172}
6652a2b9 1173
19070062 1174static int method_exit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961 1175 Manager *m = userdata;
ebcf1f97 1176 int r;
6652a2b9 1177
718db961
LP
1178 assert(message);
1179 assert(m);
6652a2b9 1180
8a188de9 1181 r = mac_selinux_access_check(message, "halt", error);
ebcf1f97
LP
1182 if (r < 0)
1183 return r;
cad45ba1 1184
287419c1
AC
1185 /* Exit() (in contrast to SetExitCode()) is actually allowed even if
1186 * we are running on the host. It will fall back on reboot() in
1187 * systemd-shutdown if it cannot do the exit() because it isn't a
1188 * container. */
6652a2b9 1189
718db961 1190 m->exit_code = MANAGER_EXIT;
6652a2b9 1191
df2d202e 1192 return sd_bus_reply_method_return(message, NULL);
718db961 1193}
6652a2b9 1194
19070062 1195static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961 1196 Manager *m = userdata;
ebcf1f97 1197 int r;
664f88a7 1198
718db961
LP
1199 assert(message);
1200 assert(m);
cad45ba1 1201
8a188de9 1202 r = mac_selinux_access_check(message, "reboot", error);
ebcf1f97
LP
1203 if (r < 0)
1204 return r;
664f88a7 1205
b2c23da8 1206 if (m->running_as != MANAGER_SYSTEM)
ebcf1f97 1207 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
664f88a7 1208
718db961 1209 m->exit_code = MANAGER_REBOOT;
664f88a7 1210
df2d202e 1211 return sd_bus_reply_method_return(message, NULL);
718db961 1212}
664f88a7 1213
19070062 1214static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961 1215 Manager *m = userdata;
ebcf1f97 1216 int r;
50913bc0 1217
718db961
LP
1218 assert(message);
1219 assert(m);
1137a57c 1220
8a188de9 1221 r = mac_selinux_access_check(message, "halt", error);
ebcf1f97
LP
1222 if (r < 0)
1223 return r;
1137a57c 1224
b2c23da8 1225 if (m->running_as != MANAGER_SYSTEM)
ebcf1f97 1226 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
1137a57c 1227
718db961 1228 m->exit_code = MANAGER_POWEROFF;
1137a57c 1229
df2d202e 1230 return sd_bus_reply_method_return(message, NULL);
718db961 1231}
1137a57c 1232
19070062 1233static int method_halt(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961 1234 Manager *m = userdata;
ebcf1f97 1235 int r;
1137a57c 1236
718db961
LP
1237 assert(message);
1238 assert(m);
8d0e38a2 1239
8a188de9 1240 r = mac_selinux_access_check(message, "halt", error);
ebcf1f97
LP
1241 if (r < 0)
1242 return r;
cad45ba1 1243
b2c23da8 1244 if (m->running_as != MANAGER_SYSTEM)
ebcf1f97 1245 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Halt is only supported for system managers.");
8d0e38a2 1246
718db961 1247 m->exit_code = MANAGER_HALT;
8d0e38a2 1248
df2d202e 1249 return sd_bus_reply_method_return(message, NULL);
718db961 1250}
8d0e38a2 1251
19070062 1252static int method_kexec(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961 1253 Manager *m = userdata;
ebcf1f97 1254 int r;
8d0e38a2 1255
718db961
LP
1256 assert(message);
1257 assert(m);
c0576cd6 1258
8a188de9 1259 r = mac_selinux_access_check(message, "reboot", error);
ebcf1f97
LP
1260 if (r < 0)
1261 return r;
cad45ba1 1262
b2c23da8 1263 if (m->running_as != MANAGER_SYSTEM)
ebcf1f97 1264 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "KExec is only supported for system managers.");
c0576cd6 1265
718db961 1266 m->exit_code = MANAGER_KEXEC;
c0576cd6 1267
df2d202e 1268 return sd_bus_reply_method_return(message, NULL);
718db961 1269}
c0576cd6 1270
19070062 1271static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
1272 char *ri = NULL, *rt = NULL;
1273 const char *root, *init;
1274 Manager *m = userdata;
1275 int r;
c0576cd6 1276
718db961
LP
1277 assert(message);
1278 assert(m);
c0576cd6 1279
8a188de9 1280 r = mac_selinux_access_check(message, "reboot", error);
ebcf1f97
LP
1281 if (r < 0)
1282 return r;
c0576cd6 1283
b2c23da8 1284 if (m->running_as != MANAGER_SYSTEM)
6ad3b2b6 1285 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Root switching is only supported by system manager.");
c0576cd6 1286
718db961
LP
1287 r = sd_bus_message_read(message, "ss", &root, &init);
1288 if (r < 0)
ebcf1f97 1289 return r;
c0576cd6 1290
718db961 1291 if (path_equal(root, "/") || !path_is_absolute(root))
ebcf1f97 1292 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid switch root path %s", root);
c0576cd6 1293
718db961
LP
1294 /* Safety check */
1295 if (isempty(init)) {
6ad3b2b6 1296 if (!path_is_os_tree(root))
5ae4d543 1297 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
1298 } else {
1299 _cleanup_free_ char *p = NULL;
c0576cd6 1300
718db961 1301 if (!path_is_absolute(init))
ebcf1f97 1302 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid init path %s", init);
c0576cd6 1303
718db961
LP
1304 p = strappend(root, init);
1305 if (!p)
ebcf1f97 1306 return -ENOMEM;
c0576cd6 1307
718db961 1308 if (access(p, X_OK) < 0)
ebcf1f97 1309 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified init binary %s does not exist.", p);
718db961
LP
1310 }
1311
1312 rt = strdup(root);
1313 if (!rt)
ebcf1f97 1314 return -ENOMEM;
718db961
LP
1315
1316 if (!isempty(init)) {
1317 ri = strdup(init);
1318 if (!ri) {
92b315df 1319 free(rt);
ebcf1f97 1320 return -ENOMEM;
c0576cd6 1321 }
718db961 1322 }
c0576cd6 1323
718db961
LP
1324 free(m->switch_root);
1325 m->switch_root = rt;
c0576cd6 1326
718db961
LP
1327 free(m->switch_root_init);
1328 m->switch_root_init = ri;
c0576cd6 1329
92b315df
LP
1330 m->exit_code = MANAGER_SWITCH_ROOT;
1331
df2d202e 1332 return sd_bus_reply_method_return(message, NULL);
718db961 1333}
c0576cd6 1334
19070062 1335static int method_set_environment(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
1336 _cleanup_strv_free_ char **plus = NULL;
1337 Manager *m = userdata;
1338 int r;
c0576cd6 1339
718db961
LP
1340 assert(message);
1341 assert(m);
cad45ba1 1342
8a188de9 1343 r = mac_selinux_access_check(message, "reload", error);
ebcf1f97
LP
1344 if (r < 0)
1345 return r;
c0576cd6 1346
718db961
LP
1347 r = sd_bus_message_read_strv(message, &plus);
1348 if (r < 0)
ebcf1f97 1349 return r;
718db961 1350 if (!strv_env_is_valid(plus))
ebcf1f97 1351 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
c0576cd6 1352
1d22e906
LP
1353 r = bus_verify_set_environment_async(m, message, error);
1354 if (r < 0)
1355 return r;
1356 if (r == 0)
1357 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1358
718db961
LP
1359 r = manager_environment_add(m, NULL, plus);
1360 if (r < 0)
ebcf1f97 1361 return r;
c0576cd6 1362
df2d202e 1363 return sd_bus_reply_method_return(message, NULL);
718db961
LP
1364}
1365
19070062 1366static int method_unset_environment(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
1367 _cleanup_strv_free_ char **minus = NULL;
1368 Manager *m = userdata;
1369 int r;
1370
718db961
LP
1371 assert(message);
1372 assert(m);
1373
8a188de9 1374 r = mac_selinux_access_check(message, "reload", error);
ebcf1f97
LP
1375 if (r < 0)
1376 return r;
c0576cd6 1377
718db961
LP
1378 r = sd_bus_message_read_strv(message, &minus);
1379 if (r < 0)
ebcf1f97 1380 return r;
718db961
LP
1381
1382 if (!strv_env_name_or_assignment_is_valid(minus))
ebcf1f97 1383 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment variable names or assignments");
718db961 1384
1d22e906
LP
1385 r = bus_verify_set_environment_async(m, message, error);
1386 if (r < 0)
1387 return r;
1388 if (r == 0)
1389 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1390
718db961
LP
1391 r = manager_environment_add(m, minus, NULL);
1392 if (r < 0)
ebcf1f97 1393 return r;
718db961 1394
df2d202e 1395 return sd_bus_reply_method_return(message, NULL);
718db961
LP
1396}
1397
19070062 1398static int method_unset_and_set_environment(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
1399 _cleanup_strv_free_ char **minus = NULL, **plus = NULL;
1400 Manager *m = userdata;
1401 int r;
1402
718db961
LP
1403 assert(message);
1404 assert(m);
1405
8a188de9 1406 r = mac_selinux_access_check(message, "reload", error);
ebcf1f97
LP
1407 if (r < 0)
1408 return r;
718db961 1409
eb6c7d20 1410 r = sd_bus_message_read_strv(message, &minus);
718db961 1411 if (r < 0)
ebcf1f97 1412 return r;
718db961 1413
eb6c7d20 1414 r = sd_bus_message_read_strv(message, &plus);
718db961 1415 if (r < 0)
ebcf1f97 1416 return r;
718db961 1417
718db961 1418 if (!strv_env_name_or_assignment_is_valid(minus))
ebcf1f97 1419 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment variable names or assignments");
eb6c7d20
ZJS
1420 if (!strv_env_is_valid(plus))
1421 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
718db961 1422
1d22e906
LP
1423 r = bus_verify_set_environment_async(m, message, error);
1424 if (r < 0)
1425 return r;
1426 if (r == 0)
1427 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1428
718db961
LP
1429 r = manager_environment_add(m, minus, plus);
1430 if (r < 0)
ebcf1f97 1431 return r;
718db961 1432
df2d202e 1433 return sd_bus_reply_method_return(message, NULL);
718db961
LP
1434}
1435
287419c1
AC
1436static int method_set_exit_code(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1437 uint8_t code;
1438 Manager *m = userdata;
1439 int r;
1440
1441 assert(message);
1442 assert(m);
1443
1444 r = mac_selinux_access_check(message, "exit", error);
1445 if (r < 0)
1446 return r;
1447
1448 r = sd_bus_message_read_basic(message, 'y', &code);
1449 if (r < 0)
1450 return r;
1451
1452 if (m->running_as == MANAGER_SYSTEM && detect_container() <= 0)
1453 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "ExitCode can only be set for user service managers or in containers.");
1454
1455 m->return_value = code;
1456
1457 return sd_bus_reply_method_return(message, NULL);
1458}
1459
19070062 1460static int method_list_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
1461 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1462 Manager *m = userdata;
1463 UnitFileList *item;
1464 Hashmap *h;
1465 Iterator i;
1466 int r;
1467
718db961
LP
1468 assert(message);
1469 assert(m);
1470
283868e1
SW
1471 /* Anyone can call this method */
1472
8a188de9 1473 r = mac_selinux_access_check(message, "status", error);
ebcf1f97
LP
1474 if (r < 0)
1475 return r;
718db961 1476
df2d202e 1477 r = sd_bus_message_new_method_return(message, &reply);
718db961 1478 if (r < 0)
ebcf1f97 1479 return r;
c0576cd6 1480
d5099efc 1481 h = hashmap_new(&string_hash_ops);
718db961 1482 if (!h)
ebcf1f97 1483 return -ENOMEM;
c0576cd6 1484
b2c23da8 1485 r = unit_file_get_list(m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
ebcf1f97 1486 if (r < 0)
718db961 1487 goto fail;
718db961
LP
1488
1489 r = sd_bus_message_open_container(reply, 'a', "(ss)");
ebcf1f97 1490 if (r < 0)
718db961 1491 goto fail;
718db961
LP
1492
1493 HASHMAP_FOREACH(item, h, i) {
1494
1495 r = sd_bus_message_append(reply, "(ss)", item->path, unit_file_state_to_string(item->state));
ebcf1f97 1496 if (r < 0)
718db961 1497 goto fail;
718db961 1498 }
c0576cd6 1499
718db961 1500 unit_file_list_free(h);
c0576cd6 1501
718db961
LP
1502 r = sd_bus_message_close_container(reply);
1503 if (r < 0)
ebcf1f97 1504 return r;
8d0e38a2 1505
9030ca46 1506 return sd_bus_send(NULL, reply, NULL);
99504dd4 1507
718db961
LP
1508fail:
1509 unit_file_list_free(h);
1510 return r;
1511}
99504dd4 1512
19070062 1513static int method_get_unit_file_state(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
1514 Manager *m = userdata;
1515 const char *name;
1516 UnitFileState state;
1517 UnitFileScope scope;
1518 int r;
99504dd4 1519
718db961
LP
1520 assert(message);
1521 assert(m);
8e2af478 1522
283868e1
SW
1523 /* Anyone can call this method */
1524
8a188de9 1525 r = mac_selinux_access_check(message, "status", error);
ebcf1f97
LP
1526 if (r < 0)
1527 return r;
8e2af478 1528
718db961
LP
1529 r = sd_bus_message_read(message, "s", &name);
1530 if (r < 0)
ebcf1f97 1531 return r;
8e2af478 1532
b2c23da8 1533 scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
8e2af478 1534
0ec0deaa
LP
1535 r = unit_file_get_state(scope, NULL, name, &state);
1536 if (r < 0)
1537 return r;
8e2af478 1538
df2d202e 1539 return sd_bus_reply_method_return(message, "s", unit_file_state_to_string(state));
718db961 1540}
8e2af478 1541
19070062 1542static int method_get_default_target(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
1543 _cleanup_free_ char *default_target = NULL;
1544 Manager *m = userdata;
1545 UnitFileScope scope;
1546 int r;
c2756a68 1547
718db961
LP
1548 assert(message);
1549 assert(m);
c2756a68 1550
283868e1
SW
1551 /* Anyone can call this method */
1552
8a188de9 1553 r = mac_selinux_access_check(message, "status", error);
ebcf1f97
LP
1554 if (r < 0)
1555 return r;
c2756a68 1556
b2c23da8 1557 scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
c2756a68 1558
718db961
LP
1559 r = unit_file_get_default(scope, NULL, &default_target);
1560 if (r < 0)
ebcf1f97 1561 return r;
c2756a68 1562
df2d202e 1563 return sd_bus_reply_method_return(message, "s", default_target);
718db961 1564}
c2756a68 1565
8f8f05a9 1566static int send_unit_files_changed(sd_bus *bus, void *userdata) {
718db961
LP
1567 _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
1568 int r;
1569
1570 assert(bus);
1571
151b9b96 1572 r = sd_bus_message_new_signal(bus, &message, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged");
718db961
LP
1573 if (r < 0)
1574 return r;
1575
8f8f05a9 1576 return sd_bus_send(bus, message, NULL);
718db961
LP
1577}
1578
1579static int reply_unit_file_changes_and_free(
1580 Manager *m,
718db961
LP
1581 sd_bus_message *message,
1582 int carries_install_info,
1583 UnitFileChange *changes,
1584 unsigned n_changes) {
1585
1586 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1587 unsigned i;
1588 int r;
1589
fe7f06f1
LP
1590 if (n_changes > 0) {
1591 r = bus_foreach_bus(m, NULL, send_unit_files_changed, NULL);
1592 if (r < 0)
da927ba9 1593 log_debug_errno(r, "Failed to send UnitFilesChanged signal: %m");
fe7f06f1 1594 }
718db961 1595
df2d202e 1596 r = sd_bus_message_new_method_return(message, &reply);
718db961
LP
1597 if (r < 0)
1598 goto fail;
1599
1600 if (carries_install_info >= 0) {
1601 r = sd_bus_message_append(reply, "b", carries_install_info);
c2756a68 1602 if (r < 0)
718db961
LP
1603 goto fail;
1604 }
1605
1606 r = sd_bus_message_open_container(reply, 'a', "(sss)");
1607 if (r < 0)
1608 goto fail;
c2756a68 1609
718db961
LP
1610 for (i = 0; i < n_changes; i++) {
1611 r = sd_bus_message_append(
21586b77 1612 reply, "(sss)",
718db961
LP
1613 unit_file_change_type_to_string(changes[i].type),
1614 changes[i].path,
1615 changes[i].source);
c2756a68 1616 if (r < 0)
718db961
LP
1617 goto fail;
1618 }
c2756a68 1619
718db961
LP
1620 r = sd_bus_message_close_container(reply);
1621 if (r < 0)
1622 goto fail;
c2756a68 1623
9030ca46 1624 return sd_bus_send(NULL, reply, NULL);
c2756a68 1625
718db961
LP
1626fail:
1627 unit_file_changes_free(changes, n_changes);
ebcf1f97 1628 return r;
718db961 1629}
cad45ba1 1630
718db961 1631static int method_enable_unit_files_generic(
718db961 1632 sd_bus_message *message,
d309c1c3
LP
1633 Manager *m,
1634 const char *verb,
718db961 1635 int (*call)(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes),
ebcf1f97
LP
1636 bool carries_install_info,
1637 sd_bus_error *error) {
718db961
LP
1638
1639 _cleanup_strv_free_ char **l = NULL;
1640 UnitFileChange *changes = NULL;
1641 unsigned n_changes = 0;
1642 UnitFileScope scope;
1643 int runtime, force, r;
1644
718db961
LP
1645 assert(message);
1646 assert(m);
cad45ba1 1647
718db961
LP
1648 r = sd_bus_message_read_strv(message, &l);
1649 if (r < 0)
ebcf1f97 1650 return r;
90bb85e1 1651
d309c1c3
LP
1652 r = sd_bus_message_read(message, "bb", &runtime, &force);
1653 if (r < 0)
1654 return r;
1655
1d22e906
LP
1656 r = bus_verify_manage_unit_files_async(m, message, error);
1657 if (r < 0)
1658 return r;
1659 if (r == 0)
1660 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1661
b2c23da8 1662 scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
c87eba54 1663
718db961 1664 r = call(scope, runtime, NULL, l, force, &changes, &n_changes);
d073dea0
LP
1665 if (r == -ESHUTDOWN)
1666 return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit file is masked");
718db961 1667 if (r < 0)
ebcf1f97 1668 return r;
718db961 1669
19070062 1670 return reply_unit_file_changes_and_free(m, message, carries_install_info ? r : -1, changes, n_changes);
718db961 1671}
c87eba54 1672
19070062
LP
1673static int method_enable_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1674 return method_enable_unit_files_generic(message, userdata, "enable", unit_file_enable, true, error);
718db961 1675}
ea430986 1676
19070062
LP
1677static int method_reenable_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1678 return method_enable_unit_files_generic(message, userdata, "enable", unit_file_reenable, true, error);
718db961
LP
1679}
1680
19070062
LP
1681static int method_link_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1682 return method_enable_unit_files_generic(message, userdata, "enable", unit_file_link, false, error);
718db961
LP
1683}
1684
d309c1c3
LP
1685static int unit_file_preset_without_mode(UnitFileScope scope, bool runtime, const char *root_dir, char **files, bool force, UnitFileChange **changes, unsigned *n_changes) {
1686 return unit_file_preset(scope, runtime, root_dir, files, UNIT_FILE_PRESET_FULL, force, changes, n_changes);
1687}
1688
19070062
LP
1689static int method_preset_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1690 return method_enable_unit_files_generic(message, userdata, "enable", unit_file_preset_without_mode, true, error);
718db961
LP
1691}
1692
19070062
LP
1693static int method_mask_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1694 return method_enable_unit_files_generic(message, userdata, "disable", unit_file_mask, false, error);
718db961 1695}
ea430986 1696
19070062 1697static int method_preset_unit_files_with_mode(sd_bus_message *message, void *userdata, sd_bus_error *error) {
d309c1c3
LP
1698
1699 _cleanup_strv_free_ char **l = NULL;
d309c1c3
LP
1700 UnitFileChange *changes = NULL;
1701 unsigned n_changes = 0;
1702 Manager *m = userdata;
1703 UnitFilePresetMode mm;
1704 UnitFileScope scope;
1705 int runtime, force, r;
1706 const char *mode;
1707
d309c1c3
LP
1708 assert(message);
1709 assert(m);
1710
1711 r = sd_bus_message_read_strv(message, &l);
1712 if (r < 0)
1713 return r;
1714
1715 r = sd_bus_message_read(message, "sbb", &mode, &runtime, &force);
1716 if (r < 0)
1717 return r;
1718
1719 if (isempty(mode))
1720 mm = UNIT_FILE_PRESET_FULL;
1721 else {
1722 mm = unit_file_preset_mode_from_string(mode);
1723 if (mm < 0)
1724 return -EINVAL;
1725 }
1726
1d22e906
LP
1727 r = bus_verify_manage_unit_files_async(m, message, error);
1728 if (r < 0)
1729 return r;
1730 if (r == 0)
1731 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1732
b2c23da8 1733 scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
d309c1c3
LP
1734
1735 r = unit_file_preset(scope, runtime, NULL, l, mm, force, &changes, &n_changes);
1736 if (r < 0)
1737 return r;
1738
19070062 1739 return reply_unit_file_changes_and_free(m, message, r, changes, n_changes);
d309c1c3
LP
1740}
1741
718db961 1742static int method_disable_unit_files_generic(
718db961
LP
1743 sd_bus_message *message,
1744 Manager *m, const
1745 char *verb,
ebcf1f97
LP
1746 int (*call)(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], UnitFileChange **changes, unsigned *n_changes),
1747 sd_bus_error *error) {
718db961
LP
1748
1749 _cleanup_strv_free_ char **l = NULL;
1750 UnitFileChange *changes = NULL;
1751 unsigned n_changes = 0;
1752 UnitFileScope scope;
1753 int r, runtime;
1754
718db961
LP
1755 assert(message);
1756 assert(m);
1757
df823e23 1758 r = sd_bus_message_read_strv(message, &l);
ebcf1f97
LP
1759 if (r < 0)
1760 return r;
718db961 1761
df823e23 1762 r = sd_bus_message_read(message, "b", &runtime);
718db961 1763 if (r < 0)
ebcf1f97 1764 return r;
718db961 1765
b2c23da8 1766 scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
718db961 1767
1d22e906
LP
1768 r = bus_verify_manage_unit_files_async(m, message, error);
1769 if (r < 0)
1770 return r;
1771 if (r == 0)
1772 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1773
718db961
LP
1774 r = call(scope, runtime, NULL, l, &changes, &n_changes);
1775 if (r < 0)
ebcf1f97 1776 return r;
718db961 1777
19070062 1778 return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes);
718db961 1779}
ea430986 1780
19070062
LP
1781static int method_disable_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1782 return method_disable_unit_files_generic(message, userdata, "disable", unit_file_disable, error);
ea430986
LP
1783}
1784
19070062
LP
1785static int method_unmask_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1786 return method_disable_unit_files_generic(message, userdata, "enable", unit_file_unmask, error);
718db961
LP
1787}
1788
19070062 1789static int method_set_default_target(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
1790 UnitFileChange *changes = NULL;
1791 unsigned n_changes = 0;
1792 Manager *m = userdata;
1793 UnitFileScope scope;
1794 const char *name;
1795 int force, r;
1796
718db961
LP
1797 assert(message);
1798 assert(m);
1799
1d22e906 1800 r = mac_selinux_access_check(message, "enable", error);
283868e1
SW
1801 if (r < 0)
1802 return r;
283868e1 1803
1d22e906 1804 r = sd_bus_message_read(message, "sb", &name, &force);
ebcf1f97
LP
1805 if (r < 0)
1806 return r;
718db961 1807
1d22e906 1808 r = bus_verify_manage_unit_files_async(m, message, error);
718db961 1809 if (r < 0)
ebcf1f97 1810 return r;
1d22e906
LP
1811 if (r == 0)
1812 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
718db961 1813
b2c23da8 1814 scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
718db961
LP
1815
1816 r = unit_file_set_default(scope, NULL, name, force, &changes, &n_changes);
1817 if (r < 0)
ebcf1f97 1818 return r;
718db961 1819
19070062 1820 return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes);
718db961
LP
1821}
1822
19070062 1823static int method_preset_all_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
d309c1c3
LP
1824 UnitFileChange *changes = NULL;
1825 unsigned n_changes = 0;
1826 Manager *m = userdata;
1827 UnitFilePresetMode mm;
1828 UnitFileScope scope;
1829 const char *mode;
1830 int force, runtime, r;
1831
d309c1c3
LP
1832 assert(message);
1833 assert(m);
1834
8a188de9 1835 r = mac_selinux_access_check(message, "enable", error);
d309c1c3
LP
1836 if (r < 0)
1837 return r;
1838
1839 r = sd_bus_message_read(message, "sbb", &mode, &runtime, &force);
1840 if (r < 0)
1841 return r;
1842
1843 if (isempty(mode))
1844 mm = UNIT_FILE_PRESET_FULL;
1845 else {
1846 mm = unit_file_preset_mode_from_string(mode);
1847 if (mm < 0)
1848 return -EINVAL;
1849 }
1850
1d22e906
LP
1851 r = bus_verify_manage_unit_files_async(m, message, error);
1852 if (r < 0)
1853 return r;
1854 if (r == 0)
1855 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1856
b2c23da8 1857 scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
d309c1c3
LP
1858
1859 r = unit_file_preset_all(scope, runtime, NULL, mm, force, &changes, &n_changes);
1860 if (r < 0)
1861 return r;
1862
19070062 1863 return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes);
d309c1c3
LP
1864}
1865
19070062 1866static int method_add_dependency_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
e94937df
LN
1867 _cleanup_strv_free_ char **l = NULL;
1868 Manager *m = userdata;
1869 UnitFileChange *changes = NULL;
1870 unsigned n_changes = 0;
1871 UnitFileScope scope;
1872 int runtime, force, r;
1873 char *target;
1874 char *type;
1875 UnitDependency dep;
1876
e94937df
LN
1877 assert(message);
1878 assert(m);
1879
1880 r = bus_verify_manage_unit_files_async(m, message, error);
1881 if (r < 0)
1882 return r;
1883 if (r == 0)
1884 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1885
1886 r = sd_bus_message_read_strv(message, &l);
1887 if (r < 0)
1888 return r;
1889
1890 r = sd_bus_message_read(message, "ssbb", &target, &type, &runtime, &force);
1891 if (r < 0)
1892 return r;
1893
1894 dep = unit_dependency_from_string(type);
1895 if (dep < 0)
1896 return -EINVAL;
1897
b2c23da8 1898 scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
e94937df
LN
1899
1900 r = unit_file_add_dependency(scope, runtime, NULL, l, target, dep, force, &changes, &n_changes);
d073dea0
LP
1901 if (r == -ESHUTDOWN)
1902 return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit file is masked");
e94937df
LN
1903 if (r < 0)
1904 return r;
1905
19070062 1906 return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes);
e94937df
LN
1907}
1908
718db961
LP
1909const sd_bus_vtable bus_manager_vtable[] = {
1910 SD_BUS_VTABLE_START(0),
1911
556089dc
LP
1912 SD_BUS_PROPERTY("Version", "s", property_get_version, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1913 SD_BUS_PROPERTY("Features", "s", property_get_features, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1914 SD_BUS_PROPERTY("Virtualization", "s", property_get_virtualization, 0, SD_BUS_VTABLE_PROPERTY_CONST),
7452394e 1915 SD_BUS_PROPERTY("Architecture", "s", property_get_architecture, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
1916 SD_BUS_PROPERTY("Tainted", "s", property_get_tainted, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1917 BUS_PROPERTY_DUAL_TIMESTAMP("FirmwareTimestamp", offsetof(Manager, firmware_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1918 BUS_PROPERTY_DUAL_TIMESTAMP("LoaderTimestamp", offsetof(Manager, loader_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1919 BUS_PROPERTY_DUAL_TIMESTAMP("KernelTimestamp", offsetof(Manager, kernel_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1920 BUS_PROPERTY_DUAL_TIMESTAMP("InitRDTimestamp", offsetof(Manager, initrd_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1921 BUS_PROPERTY_DUAL_TIMESTAMP("UserspaceTimestamp", offsetof(Manager, userspace_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1922 BUS_PROPERTY_DUAL_TIMESTAMP("FinishTimestamp", offsetof(Manager, finish_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1923 BUS_PROPERTY_DUAL_TIMESTAMP("SecurityStartTimestamp", offsetof(Manager, security_start_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1924 BUS_PROPERTY_DUAL_TIMESTAMP("SecurityFinishTimestamp", offsetof(Manager, security_finish_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1925 BUS_PROPERTY_DUAL_TIMESTAMP("GeneratorsStartTimestamp", offsetof(Manager, generators_start_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1926 BUS_PROPERTY_DUAL_TIMESTAMP("GeneratorsFinishTimestamp", offsetof(Manager, generators_finish_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1927 BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadStartTimestamp", offsetof(Manager, units_load_start_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1928 BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadFinishTimestamp", offsetof(Manager, units_load_finish_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
718db961
LP
1929 SD_BUS_WRITABLE_PROPERTY("LogLevel", "s", property_get_log_level, property_set_log_level, 0, 0),
1930 SD_BUS_WRITABLE_PROPERTY("LogTarget", "s", property_get_log_target, property_set_log_target, 0, 0),
1931 SD_BUS_PROPERTY("NNames", "u", property_get_n_names, 0, 0),
03455c28 1932 SD_BUS_PROPERTY("NFailedUnits", "u", property_get_n_failed_units, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
718db961
LP
1933 SD_BUS_PROPERTY("NJobs", "u", property_get_n_jobs, 0, 0),
1934 SD_BUS_PROPERTY("NInstalledJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_installed_jobs), 0),
1935 SD_BUS_PROPERTY("NFailedJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_failed_jobs), 0),
1936 SD_BUS_PROPERTY("Progress", "d", property_get_progress, 0, 0),
1937 SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(Manager, environment), 0),
556089dc
LP
1938 SD_BUS_PROPERTY("ConfirmSpawn", "b", bus_property_get_bool, offsetof(Manager, confirm_spawn), SD_BUS_VTABLE_PROPERTY_CONST),
1939 SD_BUS_PROPERTY("ShowStatus", "b", bus_property_get_bool, offsetof(Manager, show_status), SD_BUS_VTABLE_PROPERTY_CONST),
1940 SD_BUS_PROPERTY("UnitPath", "as", NULL, offsetof(Manager, lookup_paths.unit_path), SD_BUS_VTABLE_PROPERTY_CONST),
1941 SD_BUS_PROPERTY("DefaultStandardOutput", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), SD_BUS_VTABLE_PROPERTY_CONST),
1942 SD_BUS_PROPERTY("DefaultStandardError", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), SD_BUS_VTABLE_PROPERTY_CONST),
4c3f1641
LP
1943 SD_BUS_WRITABLE_PROPERTY("RuntimeWatchdogUSec", "t", bus_property_get_usec, property_set_runtime_watchdog, offsetof(Manager, runtime_watchdog), 0),
1944 SD_BUS_WRITABLE_PROPERTY("ShutdownWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, shutdown_watchdog), 0),
b272b74d 1945 SD_BUS_PROPERTY("ControlGroup", "s", NULL, offsetof(Manager, cgroup_root), 0),
f755e3b7 1946 SD_BUS_PROPERTY("SystemState", "s", property_get_system_state, 0, 0),
287419c1 1947 SD_BUS_PROPERTY("ExitCode", "y", bus_property_get_unsigned, offsetof(Manager, return_value), 0),
670a3efe
EV
1948 SD_BUS_PROPERTY("DefaultTimerAccuracyUSec", "t", bus_property_get_usec, offsetof(Manager, default_timer_accuracy_usec), SD_BUS_VTABLE_PROPERTY_CONST),
1949 SD_BUS_PROPERTY("DefaultTimeoutStartUSec", "t", bus_property_get_usec, offsetof(Manager, default_timeout_start_usec), SD_BUS_VTABLE_PROPERTY_CONST),
1950 SD_BUS_PROPERTY("DefaultTimeoutStopUSec", "t", bus_property_get_usec, offsetof(Manager, default_timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST),
1951 SD_BUS_PROPERTY("DefaultRestartUSec", "t", bus_property_get_usec, offsetof(Manager, default_restart_usec), SD_BUS_VTABLE_PROPERTY_CONST),
1952 SD_BUS_PROPERTY("DefaultStartLimitInterval", "t", bus_property_get_usec, offsetof(Manager, default_start_limit_interval), SD_BUS_VTABLE_PROPERTY_CONST),
1953 SD_BUS_PROPERTY("DefaultStartLimitBurst", "u", bus_property_get_unsigned, offsetof(Manager, default_start_limit_burst), SD_BUS_VTABLE_PROPERTY_CONST),
1954 SD_BUS_PROPERTY("DefaultCPUAccounting", "b", bus_property_get_bool, offsetof(Manager, default_cpu_accounting), SD_BUS_VTABLE_PROPERTY_CONST),
1955 SD_BUS_PROPERTY("DefaultBlockIOAccounting", "b", bus_property_get_bool, offsetof(Manager, default_blockio_accounting), SD_BUS_VTABLE_PROPERTY_CONST),
1956 SD_BUS_PROPERTY("DefaultMemoryAccounting", "b", bus_property_get_bool, offsetof(Manager, default_memory_accounting), SD_BUS_VTABLE_PROPERTY_CONST),
1957 SD_BUS_PROPERTY("DefaultTasksAccounting", "b", bus_property_get_bool, offsetof(Manager, default_tasks_accounting), SD_BUS_VTABLE_PROPERTY_CONST),
97eb4231
EV
1958 SD_BUS_PROPERTY("DefaultLimitCPU", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
1959 SD_BUS_PROPERTY("DefaultLimitFSIZE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
1960 SD_BUS_PROPERTY("DefaultLimitDATA", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
1961 SD_BUS_PROPERTY("DefaultLimitSTACK", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
1962 SD_BUS_PROPERTY("DefaultLimitCORE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
1963 SD_BUS_PROPERTY("DefaultLimitRSS", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
1964 SD_BUS_PROPERTY("DefaultLimitNOFILE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
1965 SD_BUS_PROPERTY("DefaultLimitAS", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
1966 SD_BUS_PROPERTY("DefaultLimitNPROC", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
1967 SD_BUS_PROPERTY("DefaultLimitMEMLOCK", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
1968 SD_BUS_PROPERTY("DefaultLimitLOCKS", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
1969 SD_BUS_PROPERTY("DefaultLimitSIGPENDING", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
1970 SD_BUS_PROPERTY("DefaultLimitMSGQUEUE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
1971 SD_BUS_PROPERTY("DefaultLimitNICE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
1972 SD_BUS_PROPERTY("DefaultLimitRTPRIO", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
1973 SD_BUS_PROPERTY("DefaultLimitRTTIME", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
0af20ea2 1974 SD_BUS_PROPERTY("DefaultTasksMax", "t", NULL, offsetof(Manager, default_tasks_max), SD_BUS_VTABLE_PROPERTY_CONST),
eed67a30 1975 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
718db961 1976
adacb957
LP
1977 SD_BUS_METHOD("GetUnit", "s", "o", method_get_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1978 SD_BUS_METHOD("GetUnitByPID", "u", "o", method_get_unit_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
1979 SD_BUS_METHOD("LoadUnit", "s", "o", method_load_unit, SD_BUS_VTABLE_UNPRIVILEGED),
283868e1
SW
1980 SD_BUS_METHOD("StartUnit", "ss", "o", method_start_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1981 SD_BUS_METHOD("StartUnitReplace", "sss", "o", method_start_unit_replace, SD_BUS_VTABLE_UNPRIVILEGED),
1982 SD_BUS_METHOD("StopUnit", "ss", "o", method_stop_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1983 SD_BUS_METHOD("ReloadUnit", "ss", "o", method_reload_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1984 SD_BUS_METHOD("RestartUnit", "ss", "o", method_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1985 SD_BUS_METHOD("TryRestartUnit", "ss", "o", method_try_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1986 SD_BUS_METHOD("ReloadOrRestartUnit", "ss", "o", method_reload_or_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1987 SD_BUS_METHOD("ReloadOrTryRestartUnit", "ss", "o", method_reload_or_try_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1988 SD_BUS_METHOD("KillUnit", "ssi", NULL, method_kill_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1989 SD_BUS_METHOD("ResetFailedUnit", "s", NULL, method_reset_failed_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1990 SD_BUS_METHOD("SetUnitProperties", "sba(sv)", NULL, method_set_unit_properties, SD_BUS_VTABLE_UNPRIVILEGED),
1991 SD_BUS_METHOD("StartTransientUnit", "ssa(sv)a(sa(sv))", "o", method_start_transient_unit, SD_BUS_VTABLE_UNPRIVILEGED),
adacb957 1992 SD_BUS_METHOD("GetJob", "u", "o", method_get_job, SD_BUS_VTABLE_UNPRIVILEGED),
283868e1 1993 SD_BUS_METHOD("CancelJob", "u", NULL, method_cancel_job, SD_BUS_VTABLE_UNPRIVILEGED),
1d22e906
LP
1994 SD_BUS_METHOD("ClearJobs", NULL, NULL, method_clear_jobs, SD_BUS_VTABLE_UNPRIVILEGED),
1995 SD_BUS_METHOD("ResetFailed", NULL, NULL, method_reset_failed, SD_BUS_VTABLE_UNPRIVILEGED),
adacb957 1996 SD_BUS_METHOD("ListUnits", NULL, "a(ssssssouso)", method_list_units, SD_BUS_VTABLE_UNPRIVILEGED),
cdc06ed7 1997 SD_BUS_METHOD("ListUnitsFiltered", "as", "a(ssssssouso)", method_list_units_filtered, SD_BUS_VTABLE_UNPRIVILEGED),
adacb957
LP
1998 SD_BUS_METHOD("ListJobs", NULL, "a(usssoo)", method_list_jobs, SD_BUS_VTABLE_UNPRIVILEGED),
1999 SD_BUS_METHOD("Subscribe", NULL, NULL, method_subscribe, SD_BUS_VTABLE_UNPRIVILEGED),
2000 SD_BUS_METHOD("Unsubscribe", NULL, NULL, method_unsubscribe, SD_BUS_VTABLE_UNPRIVILEGED),
2001 SD_BUS_METHOD("Dump", NULL, "s", method_dump, SD_BUS_VTABLE_UNPRIVILEGED),
36b4a7ba
ZJS
2002 SD_BUS_METHOD("CreateSnapshot", "sb", "o", method_refuse_snapshot, SD_BUS_VTABLE_UNPRIVILEGED),
2003 SD_BUS_METHOD("RemoveSnapshot", "s", NULL, method_refuse_snapshot, SD_BUS_VTABLE_UNPRIVILEGED),
283868e1
SW
2004 SD_BUS_METHOD("Reload", NULL, NULL, method_reload, SD_BUS_VTABLE_UNPRIVILEGED),
2005 SD_BUS_METHOD("Reexecute", NULL, NULL, method_reexecute, SD_BUS_VTABLE_UNPRIVILEGED),
718db961 2006 SD_BUS_METHOD("Exit", NULL, NULL, method_exit, 0),
adacb957
LP
2007 SD_BUS_METHOD("Reboot", NULL, NULL, method_reboot, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
2008 SD_BUS_METHOD("PowerOff", NULL, NULL, method_poweroff, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
2009 SD_BUS_METHOD("Halt", NULL, NULL, method_halt, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
2010 SD_BUS_METHOD("KExec", NULL, NULL, method_kexec, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
2011 SD_BUS_METHOD("SwitchRoot", "ss", NULL, method_switch_root, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
1d22e906
LP
2012 SD_BUS_METHOD("SetEnvironment", "as", NULL, method_set_environment, SD_BUS_VTABLE_UNPRIVILEGED),
2013 SD_BUS_METHOD("UnsetEnvironment", "as", NULL, method_unset_environment, SD_BUS_VTABLE_UNPRIVILEGED),
2014 SD_BUS_METHOD("UnsetAndSetEnvironment", "asas", NULL, method_unset_and_set_environment, SD_BUS_VTABLE_UNPRIVILEGED),
adacb957
LP
2015 SD_BUS_METHOD("ListUnitFiles", NULL, "a(ss)", method_list_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2016 SD_BUS_METHOD("GetUnitFileState", "s", "s", method_get_unit_file_state, SD_BUS_VTABLE_UNPRIVILEGED),
283868e1
SW
2017 SD_BUS_METHOD("EnableUnitFiles", "asbb", "ba(sss)", method_enable_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2018 SD_BUS_METHOD("DisableUnitFiles", "asb", "a(sss)", method_disable_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2019 SD_BUS_METHOD("ReenableUnitFiles", "asbb", "ba(sss)", method_reenable_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2020 SD_BUS_METHOD("LinkUnitFiles", "asbb", "a(sss)", method_link_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2021 SD_BUS_METHOD("PresetUnitFiles", "asbb", "ba(sss)", method_preset_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2022 SD_BUS_METHOD("PresetUnitFilesWithMode", "assbb", "ba(sss)", method_preset_unit_files_with_mode, SD_BUS_VTABLE_UNPRIVILEGED),
2023 SD_BUS_METHOD("MaskUnitFiles", "asbb", "a(sss)", method_mask_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2024 SD_BUS_METHOD("UnmaskUnitFiles", "asb", "a(sss)", method_unmask_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2025 SD_BUS_METHOD("SetDefaultTarget", "sb", "a(sss)", method_set_default_target, SD_BUS_VTABLE_UNPRIVILEGED),
adacb957 2026 SD_BUS_METHOD("GetDefaultTarget", NULL, "s", method_get_default_target, SD_BUS_VTABLE_UNPRIVILEGED),
283868e1 2027 SD_BUS_METHOD("PresetAllUnitFiles", "sbb", "a(sss)", method_preset_all_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
e94937df 2028 SD_BUS_METHOD("AddDependencyUnitFiles", "asssbb", "a(sss)", method_add_dependency_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
287419c1 2029 SD_BUS_METHOD("SetExitCode", "y", NULL, method_set_exit_code, SD_BUS_VTABLE_UNPRIVILEGED),
718db961
LP
2030
2031 SD_BUS_SIGNAL("UnitNew", "so", 0),
2032 SD_BUS_SIGNAL("UnitRemoved", "so", 0),
2033 SD_BUS_SIGNAL("JobNew", "uos", 0),
2034 SD_BUS_SIGNAL("JobRemoved", "uoss", 0),
2035 SD_BUS_SIGNAL("StartupFinished", "tttttt", 0),
2036 SD_BUS_SIGNAL("UnitFilesChanged", NULL, 0),
2037 SD_BUS_SIGNAL("Reloading", "b", 0),
2038
2039 SD_BUS_VTABLE_END
ea430986 2040};
718db961 2041
8f8f05a9 2042static int send_finished(sd_bus *bus, void *userdata) {
718db961
LP
2043 _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
2044 usec_t *times = userdata;
2045 int r;
2046
2047 assert(bus);
2048 assert(times);
2049
151b9b96 2050 r = sd_bus_message_new_signal(bus, &message, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished");
718db961
LP
2051 if (r < 0)
2052 return r;
2053
2054 r = sd_bus_message_append(message, "tttttt", times[0], times[1], times[2], times[3], times[4], times[5]);
2055 if (r < 0)
2056 return r;
2057
8f8f05a9 2058 return sd_bus_send(bus, message, NULL);
718db961
LP
2059}
2060
39abcaee 2061void bus_manager_send_finished(
718db961
LP
2062 Manager *m,
2063 usec_t firmware_usec,
2064 usec_t loader_usec,
2065 usec_t kernel_usec,
2066 usec_t initrd_usec,
2067 usec_t userspace_usec,
2068 usec_t total_usec) {
2069
39abcaee
LP
2070 int r;
2071
718db961
LP
2072 assert(m);
2073
8f8f05a9
LP
2074 r = bus_foreach_bus(
2075 m,
2076 NULL,
2077 send_finished,
2078 (usec_t[6]) {
2079 firmware_usec,
2080 loader_usec,
2081 kernel_usec,
2082 initrd_usec,
2083 userspace_usec,
2084 total_usec
2085 });
39abcaee 2086 if (r < 0)
da927ba9 2087 log_debug_errno(r, "Failed to send finished signal: %m");
718db961
LP
2088}
2089
8f8f05a9 2090static int send_reloading(sd_bus *bus, void *userdata) {
718db961
LP
2091 _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
2092 int r;
2093
2094 assert(bus);
2095
151b9b96 2096 r = sd_bus_message_new_signal(bus, &message, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "Reloading");
718db961
LP
2097 if (r < 0)
2098 return r;
2099
2100 r = sd_bus_message_append(message, "b", PTR_TO_INT(userdata));
2101 if (r < 0)
2102 return r;
2103
8f8f05a9 2104 return sd_bus_send(bus, message, NULL);
718db961
LP
2105}
2106
39abcaee
LP
2107void bus_manager_send_reloading(Manager *m, bool active) {
2108 int r;
2109
718db961
LP
2110 assert(m);
2111
8f8f05a9 2112 r = bus_foreach_bus(m, NULL, send_reloading, INT_TO_PTR(active));
39abcaee 2113 if (r < 0)
da927ba9 2114 log_debug_errno(r, "Failed to send reloading signal: %m");
03455c28
LDM
2115}
2116
2117static int send_changed_signal(sd_bus *bus, void *userdata) {
2118 assert(bus);
2119
2120 return sd_bus_emit_properties_changed_strv(bus,
2121 "/org/freedesktop/systemd1",
2122 "org.freedesktop.systemd1.Manager",
2123 NULL);
2124}
39abcaee 2125
03455c28
LDM
2126void bus_manager_send_change_signal(Manager *m) {
2127 int r;
2128
2129 assert(m);
2130
2131 r = bus_foreach_bus(m, NULL, send_changed_signal, NULL);
2132 if (r < 0)
2133 log_debug_errno(r, "Failed to send manager change signal: %m");
718db961 2134}