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