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