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