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