]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dbus-unit.c
core: improve error message when RefuseManualStart(Stop) is hit (#5132)
[thirdparty/systemd.git] / src / core / dbus-unit.c
1 /***
2 This file is part of systemd.
3
4 Copyright 2010 Lennart Poettering
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include "sd-bus.h"
21
22 #include "alloc-util.h"
23 #include "bus-common-errors.h"
24 #include "cgroup-util.h"
25 #include "dbus-job.h"
26 #include "dbus-unit.h"
27 #include "dbus.h"
28 #include "fd-util.h"
29 #include "locale-util.h"
30 #include "log.h"
31 #include "process-util.h"
32 #include "selinux-access.h"
33 #include "signal-util.h"
34 #include "special.h"
35 #include "string-util.h"
36 #include "strv.h"
37 #include "user-util.h"
38
39 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_load_state, unit_load_state, UnitLoadState);
40 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_job_mode, job_mode, JobMode);
41 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_emergency_action, emergency_action, EmergencyAction);
42
43 static int property_get_names(
44 sd_bus *bus,
45 const char *path,
46 const char *interface,
47 const char *property,
48 sd_bus_message *reply,
49 void *userdata,
50 sd_bus_error *error) {
51
52 Unit *u = userdata;
53 Iterator i;
54 const char *t;
55 int r;
56
57 assert(bus);
58 assert(reply);
59 assert(u);
60
61 r = sd_bus_message_open_container(reply, 'a', "s");
62 if (r < 0)
63 return r;
64
65 SET_FOREACH(t, u->names, i) {
66 r = sd_bus_message_append(reply, "s", t);
67 if (r < 0)
68 return r;
69 }
70
71 return sd_bus_message_close_container(reply);
72 }
73
74 static int property_get_following(
75 sd_bus *bus,
76 const char *path,
77 const char *interface,
78 const char *property,
79 sd_bus_message *reply,
80 void *userdata,
81 sd_bus_error *error) {
82
83 Unit *u = userdata, *f;
84
85 assert(bus);
86 assert(reply);
87 assert(u);
88
89 f = unit_following(u);
90 return sd_bus_message_append(reply, "s", f ? f->id : "");
91 }
92
93 static int property_get_dependencies(
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 Set *s = *(Set**) userdata;
103 Iterator j;
104 Unit *u;
105 int r;
106
107 assert(bus);
108 assert(reply);
109
110 r = sd_bus_message_open_container(reply, 'a', "s");
111 if (r < 0)
112 return r;
113
114 SET_FOREACH(u, s, j) {
115 r = sd_bus_message_append(reply, "s", u->id);
116 if (r < 0)
117 return r;
118 }
119
120 return sd_bus_message_close_container(reply);
121 }
122
123 static int property_get_obsolete_dependencies(
124 sd_bus *bus,
125 const char *path,
126 const char *interface,
127 const char *property,
128 sd_bus_message *reply,
129 void *userdata,
130 sd_bus_error *error) {
131
132 assert(bus);
133 assert(reply);
134
135 /* For dependency types we don't support anymore always return an empty array */
136 return sd_bus_message_append(reply, "as", 0);
137 }
138
139 static int property_get_description(
140 sd_bus *bus,
141 const char *path,
142 const char *interface,
143 const char *property,
144 sd_bus_message *reply,
145 void *userdata,
146 sd_bus_error *error) {
147
148 Unit *u = userdata;
149
150 assert(bus);
151 assert(reply);
152 assert(u);
153
154 return sd_bus_message_append(reply, "s", unit_description(u));
155 }
156
157 static int property_get_active_state(
158 sd_bus *bus,
159 const char *path,
160 const char *interface,
161 const char *property,
162 sd_bus_message *reply,
163 void *userdata,
164 sd_bus_error *error) {
165
166 Unit *u = userdata;
167
168 assert(bus);
169 assert(reply);
170 assert(u);
171
172 return sd_bus_message_append(reply, "s", unit_active_state_to_string(unit_active_state(u)));
173 }
174
175 static int property_get_sub_state(
176 sd_bus *bus,
177 const char *path,
178 const char *interface,
179 const char *property,
180 sd_bus_message *reply,
181 void *userdata,
182 sd_bus_error *error) {
183
184 Unit *u = userdata;
185
186 assert(bus);
187 assert(reply);
188 assert(u);
189
190 return sd_bus_message_append(reply, "s", unit_sub_state_to_string(u));
191 }
192
193 static int property_get_unit_file_preset(
194 sd_bus *bus,
195 const char *path,
196 const char *interface,
197 const char *property,
198 sd_bus_message *reply,
199 void *userdata,
200 sd_bus_error *error) {
201
202 Unit *u = userdata;
203 int r;
204
205 assert(bus);
206 assert(reply);
207 assert(u);
208
209 r = unit_get_unit_file_preset(u);
210
211 return sd_bus_message_append(reply, "s",
212 r < 0 ? "":
213 r > 0 ? "enabled" : "disabled");
214 }
215
216 static int property_get_unit_file_state(
217 sd_bus *bus,
218 const char *path,
219 const char *interface,
220 const char *property,
221 sd_bus_message *reply,
222 void *userdata,
223 sd_bus_error *error) {
224
225 Unit *u = userdata;
226
227 assert(bus);
228 assert(reply);
229 assert(u);
230
231 return sd_bus_message_append(reply, "s", unit_file_state_to_string(unit_get_unit_file_state(u)));
232 }
233
234 static int property_get_can_start(
235 sd_bus *bus,
236 const char *path,
237 const char *interface,
238 const char *property,
239 sd_bus_message *reply,
240 void *userdata,
241 sd_bus_error *error) {
242
243 Unit *u = userdata;
244
245 assert(bus);
246 assert(reply);
247 assert(u);
248
249 return sd_bus_message_append(reply, "b", unit_can_start(u) && !u->refuse_manual_start);
250 }
251
252 static int property_get_can_stop(
253 sd_bus *bus,
254 const char *path,
255 const char *interface,
256 const char *property,
257 sd_bus_message *reply,
258 void *userdata,
259 sd_bus_error *error) {
260
261 Unit *u = userdata;
262
263 assert(bus);
264 assert(reply);
265 assert(u);
266
267 return sd_bus_message_append(reply, "b", unit_can_stop(u) && !u->refuse_manual_stop);
268 }
269
270 static int property_get_can_reload(
271 sd_bus *bus,
272 const char *path,
273 const char *interface,
274 const char *property,
275 sd_bus_message *reply,
276 void *userdata,
277 sd_bus_error *error) {
278
279 Unit *u = userdata;
280
281 assert(bus);
282 assert(reply);
283 assert(u);
284
285 return sd_bus_message_append(reply, "b", unit_can_reload(u));
286 }
287
288 static int property_get_can_isolate(
289 sd_bus *bus,
290 const char *path,
291 const char *interface,
292 const char *property,
293 sd_bus_message *reply,
294 void *userdata,
295 sd_bus_error *error) {
296
297 Unit *u = userdata;
298
299 assert(bus);
300 assert(reply);
301 assert(u);
302
303 return sd_bus_message_append(reply, "b", unit_can_isolate(u) && !u->refuse_manual_start);
304 }
305
306 static int property_get_job(
307 sd_bus *bus,
308 const char *path,
309 const char *interface,
310 const char *property,
311 sd_bus_message *reply,
312 void *userdata,
313 sd_bus_error *error) {
314
315 _cleanup_free_ char *p = NULL;
316 Unit *u = userdata;
317
318 assert(bus);
319 assert(reply);
320 assert(u);
321
322 if (!u->job)
323 return sd_bus_message_append(reply, "(uo)", 0, "/");
324
325 p = job_dbus_path(u->job);
326 if (!p)
327 return -ENOMEM;
328
329 return sd_bus_message_append(reply, "(uo)", u->job->id, p);
330 }
331
332 static int property_get_need_daemon_reload(
333 sd_bus *bus,
334 const char *path,
335 const char *interface,
336 const char *property,
337 sd_bus_message *reply,
338 void *userdata,
339 sd_bus_error *error) {
340
341 Unit *u = userdata;
342
343 assert(bus);
344 assert(reply);
345 assert(u);
346
347 return sd_bus_message_append(reply, "b", unit_need_daemon_reload(u));
348 }
349
350 static int property_get_conditions(
351 sd_bus *bus,
352 const char *path,
353 const char *interface,
354 const char *property,
355 sd_bus_message *reply,
356 void *userdata,
357 sd_bus_error *error) {
358
359 const char *(*to_string)(ConditionType type) = NULL;
360 Condition **list = userdata, *c;
361 int r;
362
363 assert(bus);
364 assert(reply);
365 assert(list);
366
367 to_string = streq(property, "Asserts") ? assert_type_to_string : condition_type_to_string;
368
369 r = sd_bus_message_open_container(reply, 'a', "(sbbsi)");
370 if (r < 0)
371 return r;
372
373 LIST_FOREACH(conditions, c, *list) {
374 int tristate;
375
376 tristate =
377 c->result == CONDITION_UNTESTED ? 0 :
378 c->result == CONDITION_SUCCEEDED ? 1 : -1;
379
380 r = sd_bus_message_append(reply, "(sbbsi)",
381 to_string(c->type),
382 c->trigger, c->negate,
383 c->parameter, tristate);
384 if (r < 0)
385 return r;
386
387 }
388
389 return sd_bus_message_close_container(reply);
390 }
391
392 static int property_get_load_error(
393 sd_bus *bus,
394 const char *path,
395 const char *interface,
396 const char *property,
397 sd_bus_message *reply,
398 void *userdata,
399 sd_bus_error *error) {
400
401 _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
402 Unit *u = userdata;
403
404 assert(bus);
405 assert(reply);
406 assert(u);
407
408 if (u->load_error != 0)
409 sd_bus_error_set_errno(&e, u->load_error);
410
411 return sd_bus_message_append(reply, "(ss)", e.name, e.message);
412 }
413
414 static int bus_verify_manage_units_async_full(
415 Unit *u,
416 const char *verb,
417 int capability,
418 const char *polkit_message,
419 bool interactive,
420 sd_bus_message *call,
421 sd_bus_error *error) {
422
423 const char *details[9] = {
424 "unit", u->id,
425 "verb", verb,
426 };
427
428 if (polkit_message) {
429 details[4] = "polkit.message";
430 details[5] = polkit_message;
431 details[6] = "polkit.gettext_domain";
432 details[7] = GETTEXT_PACKAGE;
433 }
434
435 return bus_verify_polkit_async(
436 call,
437 capability,
438 "org.freedesktop.systemd1.manage-units",
439 details,
440 interactive,
441 UID_INVALID,
442 &u->manager->polkit_registry,
443 error);
444 }
445
446 int bus_unit_method_start_generic(
447 sd_bus_message *message,
448 Unit *u,
449 JobType job_type,
450 bool reload_if_possible,
451 sd_bus_error *error) {
452
453 const char *smode;
454 JobMode mode;
455 _cleanup_free_ char *verb = NULL;
456 static const char *const polkit_message_for_job[_JOB_TYPE_MAX] = {
457 [JOB_START] = N_("Authentication is required to start '$(unit)'."),
458 [JOB_STOP] = N_("Authentication is required to stop '$(unit)'."),
459 [JOB_RELOAD] = N_("Authentication is required to reload '$(unit)'."),
460 [JOB_RESTART] = N_("Authentication is required to restart '$(unit)'."),
461 [JOB_TRY_RESTART] = N_("Authentication is required to restart '$(unit)'."),
462 };
463 int r;
464
465 assert(message);
466 assert(u);
467 assert(job_type >= 0 && job_type < _JOB_TYPE_MAX);
468
469 r = mac_selinux_unit_access_check(
470 u, message,
471 job_type_to_access_method(job_type),
472 error);
473 if (r < 0)
474 return r;
475
476 r = sd_bus_message_read(message, "s", &smode);
477 if (r < 0)
478 return r;
479
480 mode = job_mode_from_string(smode);
481 if (mode < 0)
482 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s invalid", smode);
483
484 if (reload_if_possible)
485 verb = strjoin("reload-or-", job_type_to_string(job_type));
486 else
487 verb = strdup(job_type_to_string(job_type));
488 if (!verb)
489 return -ENOMEM;
490
491 r = bus_verify_manage_units_async_full(
492 u,
493 verb,
494 CAP_SYS_ADMIN,
495 job_type < _JOB_TYPE_MAX ? polkit_message_for_job[job_type] : NULL,
496 true,
497 message,
498 error);
499 if (r < 0)
500 return r;
501 if (r == 0)
502 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
503
504 return bus_unit_queue_job(message, u, job_type, mode, reload_if_possible, error);
505 }
506
507 static int method_start(sd_bus_message *message, void *userdata, sd_bus_error *error) {
508 return bus_unit_method_start_generic(message, userdata, JOB_START, false, error);
509 }
510
511 static int method_stop(sd_bus_message *message, void *userdata, sd_bus_error *error) {
512 return bus_unit_method_start_generic(message, userdata, JOB_STOP, false, error);
513 }
514
515 static int method_reload(sd_bus_message *message, void *userdata, sd_bus_error *error) {
516 return bus_unit_method_start_generic(message, userdata, JOB_RELOAD, false, error);
517 }
518
519 static int method_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) {
520 return bus_unit_method_start_generic(message, userdata, JOB_RESTART, false, error);
521 }
522
523 static int method_try_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) {
524 return bus_unit_method_start_generic(message, userdata, JOB_TRY_RESTART, false, error);
525 }
526
527 static int method_reload_or_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) {
528 return bus_unit_method_start_generic(message, userdata, JOB_RESTART, true, error);
529 }
530
531 static int method_reload_or_try_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) {
532 return bus_unit_method_start_generic(message, userdata, JOB_TRY_RESTART, true, error);
533 }
534
535 int bus_unit_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error) {
536 Unit *u = userdata;
537 const char *swho;
538 int32_t signo;
539 KillWho who;
540 int r;
541
542 assert(message);
543 assert(u);
544
545 r = mac_selinux_unit_access_check(u, message, "stop", error);
546 if (r < 0)
547 return r;
548
549 r = sd_bus_message_read(message, "si", &swho, &signo);
550 if (r < 0)
551 return r;
552
553 if (isempty(swho))
554 who = KILL_ALL;
555 else {
556 who = kill_who_from_string(swho);
557 if (who < 0)
558 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid who argument %s", swho);
559 }
560
561 if (!SIGNAL_VALID(signo))
562 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Signal number out of range.");
563
564 r = bus_verify_manage_units_async_full(
565 u,
566 "kill",
567 CAP_KILL,
568 N_("Authentication is required to kill '$(unit)'."),
569 true,
570 message,
571 error);
572 if (r < 0)
573 return r;
574 if (r == 0)
575 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
576
577 r = unit_kill(u, who, signo, error);
578 if (r < 0)
579 return r;
580
581 return sd_bus_reply_method_return(message, NULL);
582 }
583
584 int bus_unit_method_reset_failed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
585 Unit *u = userdata;
586 int r;
587
588 assert(message);
589 assert(u);
590
591 r = mac_selinux_unit_access_check(u, message, "reload", error);
592 if (r < 0)
593 return r;
594
595 r = bus_verify_manage_units_async_full(
596 u,
597 "reset-failed",
598 CAP_SYS_ADMIN,
599 N_("Authentication is required to reset the \"failed\" state of '$(unit)'."),
600 true,
601 message,
602 error);
603 if (r < 0)
604 return r;
605 if (r == 0)
606 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
607
608 unit_reset_failed(u);
609
610 return sd_bus_reply_method_return(message, NULL);
611 }
612
613 int bus_unit_method_set_properties(sd_bus_message *message, void *userdata, sd_bus_error *error) {
614 Unit *u = userdata;
615 int runtime, r;
616
617 assert(message);
618 assert(u);
619
620 r = mac_selinux_unit_access_check(u, message, "start", error);
621 if (r < 0)
622 return r;
623
624 r = sd_bus_message_read(message, "b", &runtime);
625 if (r < 0)
626 return r;
627
628 r = bus_verify_manage_units_async_full(
629 u,
630 "set-property",
631 CAP_SYS_ADMIN,
632 N_("Authentication is required to set properties on '$(unit)'."),
633 true,
634 message,
635 error);
636 if (r < 0)
637 return r;
638 if (r == 0)
639 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
640
641 r = bus_unit_set_properties(u, message, runtime ? UNIT_RUNTIME : UNIT_PERSISTENT, true, error);
642 if (r < 0)
643 return r;
644
645 return sd_bus_reply_method_return(message, NULL);
646 }
647
648 int bus_unit_method_ref(sd_bus_message *message, void *userdata, sd_bus_error *error) {
649 Unit *u = userdata;
650 int r;
651
652 assert(message);
653 assert(u);
654
655 r = mac_selinux_unit_access_check(u, message, "start", error);
656 if (r < 0)
657 return r;
658
659 r = bus_verify_manage_units_async_full(
660 u,
661 "ref",
662 CAP_SYS_ADMIN,
663 NULL,
664 false,
665 message,
666 error);
667 if (r < 0)
668 return r;
669 if (r == 0)
670 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
671
672 r = bus_unit_track_add_sender(u, message);
673 if (r < 0)
674 return r;
675
676 return sd_bus_reply_method_return(message, NULL);
677 }
678
679 int bus_unit_method_unref(sd_bus_message *message, void *userdata, sd_bus_error *error) {
680 Unit *u = userdata;
681 int r;
682
683 assert(message);
684 assert(u);
685
686 r = bus_unit_track_remove_sender(u, message);
687 if (r == -EUNATCH)
688 return sd_bus_error_setf(error, BUS_ERROR_NOT_REFERENCED, "Unit has not been referenced yet.");
689 if (r < 0)
690 return r;
691
692 return sd_bus_reply_method_return(message, NULL);
693 }
694
695 const sd_bus_vtable bus_unit_vtable[] = {
696 SD_BUS_VTABLE_START(0),
697
698 SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Unit, id), SD_BUS_VTABLE_PROPERTY_CONST),
699 SD_BUS_PROPERTY("Names", "as", property_get_names, 0, SD_BUS_VTABLE_PROPERTY_CONST),
700 SD_BUS_PROPERTY("Following", "s", property_get_following, 0, 0),
701 SD_BUS_PROPERTY("Requires", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRES]), SD_BUS_VTABLE_PROPERTY_CONST),
702 SD_BUS_PROPERTY("Requisite", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE]), SD_BUS_VTABLE_PROPERTY_CONST),
703 SD_BUS_PROPERTY("Wants", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_WANTS]), SD_BUS_VTABLE_PROPERTY_CONST),
704 SD_BUS_PROPERTY("BindsTo", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BINDS_TO]), SD_BUS_VTABLE_PROPERTY_CONST),
705 SD_BUS_PROPERTY("PartOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_PART_OF]), SD_BUS_VTABLE_PROPERTY_CONST),
706 SD_BUS_PROPERTY("RequiredBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRED_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
707 SD_BUS_PROPERTY("RequisiteOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE_OF]), SD_BUS_VTABLE_PROPERTY_CONST),
708 SD_BUS_PROPERTY("WantedBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_WANTED_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
709 SD_BUS_PROPERTY("BoundBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BOUND_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
710 SD_BUS_PROPERTY("ConsistsOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONSISTS_OF]), SD_BUS_VTABLE_PROPERTY_CONST),
711 SD_BUS_PROPERTY("Conflicts", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONFLICTS]), SD_BUS_VTABLE_PROPERTY_CONST),
712 SD_BUS_PROPERTY("ConflictedBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONFLICTED_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
713 SD_BUS_PROPERTY("Before", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BEFORE]), SD_BUS_VTABLE_PROPERTY_CONST),
714 SD_BUS_PROPERTY("After", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_AFTER]), SD_BUS_VTABLE_PROPERTY_CONST),
715 SD_BUS_PROPERTY("OnFailure", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_ON_FAILURE]), SD_BUS_VTABLE_PROPERTY_CONST),
716 SD_BUS_PROPERTY("Triggers", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_TRIGGERS]), SD_BUS_VTABLE_PROPERTY_CONST),
717 SD_BUS_PROPERTY("TriggeredBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_TRIGGERED_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
718 SD_BUS_PROPERTY("PropagatesReloadTo", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_PROPAGATES_RELOAD_TO]), SD_BUS_VTABLE_PROPERTY_CONST),
719 SD_BUS_PROPERTY("ReloadPropagatedFrom", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_RELOAD_PROPAGATED_FROM]), SD_BUS_VTABLE_PROPERTY_CONST),
720 SD_BUS_PROPERTY("JoinsNamespaceOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_JOINS_NAMESPACE_OF]), SD_BUS_VTABLE_PROPERTY_CONST),
721 SD_BUS_PROPERTY("RequiresMountsFor", "as", NULL, offsetof(Unit, requires_mounts_for), SD_BUS_VTABLE_PROPERTY_CONST),
722 SD_BUS_PROPERTY("Documentation", "as", NULL, offsetof(Unit, documentation), SD_BUS_VTABLE_PROPERTY_CONST),
723 SD_BUS_PROPERTY("Description", "s", property_get_description, 0, SD_BUS_VTABLE_PROPERTY_CONST),
724 SD_BUS_PROPERTY("LoadState", "s", property_get_load_state, offsetof(Unit, load_state), SD_BUS_VTABLE_PROPERTY_CONST),
725 SD_BUS_PROPERTY("ActiveState", "s", property_get_active_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
726 SD_BUS_PROPERTY("SubState", "s", property_get_sub_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
727 SD_BUS_PROPERTY("FragmentPath", "s", NULL, offsetof(Unit, fragment_path), SD_BUS_VTABLE_PROPERTY_CONST),
728 SD_BUS_PROPERTY("SourcePath", "s", NULL, offsetof(Unit, source_path), SD_BUS_VTABLE_PROPERTY_CONST),
729 SD_BUS_PROPERTY("DropInPaths", "as", NULL, offsetof(Unit, dropin_paths), SD_BUS_VTABLE_PROPERTY_CONST),
730 SD_BUS_PROPERTY("UnitFileState", "s", property_get_unit_file_state, 0, 0),
731 SD_BUS_PROPERTY("UnitFilePreset", "s", property_get_unit_file_preset, 0, 0),
732 BUS_PROPERTY_DUAL_TIMESTAMP("StateChangeTimestamp", offsetof(Unit, state_change_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
733 BUS_PROPERTY_DUAL_TIMESTAMP("InactiveExitTimestamp", offsetof(Unit, inactive_exit_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
734 BUS_PROPERTY_DUAL_TIMESTAMP("ActiveEnterTimestamp", offsetof(Unit, active_enter_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
735 BUS_PROPERTY_DUAL_TIMESTAMP("ActiveExitTimestamp", offsetof(Unit, active_exit_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
736 BUS_PROPERTY_DUAL_TIMESTAMP("InactiveEnterTimestamp", offsetof(Unit, inactive_enter_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
737 SD_BUS_PROPERTY("CanStart", "b", property_get_can_start, 0, SD_BUS_VTABLE_PROPERTY_CONST),
738 SD_BUS_PROPERTY("CanStop", "b", property_get_can_stop, 0, SD_BUS_VTABLE_PROPERTY_CONST),
739 SD_BUS_PROPERTY("CanReload", "b", property_get_can_reload, 0, SD_BUS_VTABLE_PROPERTY_CONST),
740 SD_BUS_PROPERTY("CanIsolate", "b", property_get_can_isolate, 0, SD_BUS_VTABLE_PROPERTY_CONST),
741 SD_BUS_PROPERTY("Job", "(uo)", property_get_job, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
742 SD_BUS_PROPERTY("StopWhenUnneeded", "b", bus_property_get_bool, offsetof(Unit, stop_when_unneeded), SD_BUS_VTABLE_PROPERTY_CONST),
743 SD_BUS_PROPERTY("RefuseManualStart", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_start), SD_BUS_VTABLE_PROPERTY_CONST),
744 SD_BUS_PROPERTY("RefuseManualStop", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_stop), SD_BUS_VTABLE_PROPERTY_CONST),
745 SD_BUS_PROPERTY("AllowIsolate", "b", bus_property_get_bool, offsetof(Unit, allow_isolate), SD_BUS_VTABLE_PROPERTY_CONST),
746 SD_BUS_PROPERTY("DefaultDependencies", "b", bus_property_get_bool, offsetof(Unit, default_dependencies), SD_BUS_VTABLE_PROPERTY_CONST),
747 SD_BUS_PROPERTY("OnFailureJobMode", "s", property_get_job_mode, offsetof(Unit, on_failure_job_mode), SD_BUS_VTABLE_PROPERTY_CONST),
748 SD_BUS_PROPERTY("IgnoreOnIsolate", "b", bus_property_get_bool, offsetof(Unit, ignore_on_isolate), SD_BUS_VTABLE_PROPERTY_CONST),
749 SD_BUS_PROPERTY("NeedDaemonReload", "b", property_get_need_daemon_reload, 0, SD_BUS_VTABLE_PROPERTY_CONST),
750 SD_BUS_PROPERTY("JobTimeoutUSec", "t", bus_property_get_usec, offsetof(Unit, job_timeout), SD_BUS_VTABLE_PROPERTY_CONST),
751 SD_BUS_PROPERTY("JobTimeoutAction", "s", property_get_emergency_action, offsetof(Unit, job_timeout_action), SD_BUS_VTABLE_PROPERTY_CONST),
752 SD_BUS_PROPERTY("JobTimeoutRebootArgument", "s", NULL, offsetof(Unit, job_timeout_reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST),
753 SD_BUS_PROPERTY("ConditionResult", "b", bus_property_get_bool, offsetof(Unit, condition_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
754 SD_BUS_PROPERTY("AssertResult", "b", bus_property_get_bool, offsetof(Unit, assert_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
755 BUS_PROPERTY_DUAL_TIMESTAMP("ConditionTimestamp", offsetof(Unit, condition_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
756 BUS_PROPERTY_DUAL_TIMESTAMP("AssertTimestamp", offsetof(Unit, assert_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
757 SD_BUS_PROPERTY("Conditions", "a(sbbsi)", property_get_conditions, offsetof(Unit, conditions), 0),
758 SD_BUS_PROPERTY("Asserts", "a(sbbsi)", property_get_conditions, offsetof(Unit, asserts), 0),
759 SD_BUS_PROPERTY("LoadError", "(ss)", property_get_load_error, 0, SD_BUS_VTABLE_PROPERTY_CONST),
760 SD_BUS_PROPERTY("Transient", "b", bus_property_get_bool, offsetof(Unit, transient), SD_BUS_VTABLE_PROPERTY_CONST),
761 SD_BUS_PROPERTY("Perpetual", "b", bus_property_get_bool, offsetof(Unit, perpetual), SD_BUS_VTABLE_PROPERTY_CONST),
762 SD_BUS_PROPERTY("StartLimitIntervalSec", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST),
763 SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST),
764 SD_BUS_PROPERTY("StartLimitAction", "s", property_get_emergency_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST),
765 SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST),
766 SD_BUS_PROPERTY("InvocationID", "ay", bus_property_get_id128, offsetof(Unit, invocation_id), 0),
767
768 SD_BUS_METHOD("Start", "s", "o", method_start, SD_BUS_VTABLE_UNPRIVILEGED),
769 SD_BUS_METHOD("Stop", "s", "o", method_stop, SD_BUS_VTABLE_UNPRIVILEGED),
770 SD_BUS_METHOD("Reload", "s", "o", method_reload, SD_BUS_VTABLE_UNPRIVILEGED),
771 SD_BUS_METHOD("Restart", "s", "o", method_restart, SD_BUS_VTABLE_UNPRIVILEGED),
772 SD_BUS_METHOD("TryRestart", "s", "o", method_try_restart, SD_BUS_VTABLE_UNPRIVILEGED),
773 SD_BUS_METHOD("ReloadOrRestart", "s", "o", method_reload_or_restart, SD_BUS_VTABLE_UNPRIVILEGED),
774 SD_BUS_METHOD("ReloadOrTryRestart", "s", "o", method_reload_or_try_restart, SD_BUS_VTABLE_UNPRIVILEGED),
775 SD_BUS_METHOD("Kill", "si", NULL, bus_unit_method_kill, SD_BUS_VTABLE_UNPRIVILEGED),
776 SD_BUS_METHOD("ResetFailed", NULL, NULL, bus_unit_method_reset_failed, SD_BUS_VTABLE_UNPRIVILEGED),
777 SD_BUS_METHOD("SetProperties", "ba(sv)", NULL, bus_unit_method_set_properties, SD_BUS_VTABLE_UNPRIVILEGED),
778 SD_BUS_METHOD("Ref", NULL, NULL, bus_unit_method_ref, SD_BUS_VTABLE_UNPRIVILEGED),
779 SD_BUS_METHOD("Unref", NULL, NULL, bus_unit_method_unref, SD_BUS_VTABLE_UNPRIVILEGED),
780
781 /* Obsolete properties or obsolete alias names */
782 SD_BUS_PROPERTY("RequiresOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN),
783 SD_BUS_PROPERTY("RequisiteOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN),
784 SD_BUS_PROPERTY("RequiredByOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN),
785 SD_BUS_PROPERTY("RequisiteOfOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN),
786 SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
787 SD_BUS_VTABLE_END
788 };
789
790 static int property_get_slice(
791 sd_bus *bus,
792 const char *path,
793 const char *interface,
794 const char *property,
795 sd_bus_message *reply,
796 void *userdata,
797 sd_bus_error *error) {
798
799 Unit *u = userdata;
800
801 assert(bus);
802 assert(reply);
803 assert(u);
804
805 return sd_bus_message_append(reply, "s", unit_slice_name(u));
806 }
807
808 static int property_get_current_memory(
809 sd_bus *bus,
810 const char *path,
811 const char *interface,
812 const char *property,
813 sd_bus_message *reply,
814 void *userdata,
815 sd_bus_error *error) {
816
817 uint64_t sz = (uint64_t) -1;
818 Unit *u = userdata;
819 int r;
820
821 assert(bus);
822 assert(reply);
823 assert(u);
824
825 r = unit_get_memory_current(u, &sz);
826 if (r < 0 && r != -ENODATA)
827 log_unit_warning_errno(u, r, "Failed to get memory.usage_in_bytes attribute: %m");
828
829 return sd_bus_message_append(reply, "t", sz);
830 }
831
832 static int property_get_current_tasks(
833 sd_bus *bus,
834 const char *path,
835 const char *interface,
836 const char *property,
837 sd_bus_message *reply,
838 void *userdata,
839 sd_bus_error *error) {
840
841 uint64_t cn = (uint64_t) -1;
842 Unit *u = userdata;
843 int r;
844
845 assert(bus);
846 assert(reply);
847 assert(u);
848
849 r = unit_get_tasks_current(u, &cn);
850 if (r < 0 && r != -ENODATA)
851 log_unit_warning_errno(u, r, "Failed to get pids.current attribute: %m");
852
853 return sd_bus_message_append(reply, "t", cn);
854 }
855
856 static int property_get_cpu_usage(
857 sd_bus *bus,
858 const char *path,
859 const char *interface,
860 const char *property,
861 sd_bus_message *reply,
862 void *userdata,
863 sd_bus_error *error) {
864
865 nsec_t ns = (nsec_t) -1;
866 Unit *u = userdata;
867 int r;
868
869 assert(bus);
870 assert(reply);
871 assert(u);
872
873 r = unit_get_cpu_usage(u, &ns);
874 if (r < 0 && r != -ENODATA)
875 log_unit_warning_errno(u, r, "Failed to get cpuacct.usage attribute: %m");
876
877 return sd_bus_message_append(reply, "t", ns);
878 }
879
880 static int property_get_cgroup(
881 sd_bus *bus,
882 const char *path,
883 const char *interface,
884 const char *property,
885 sd_bus_message *reply,
886 void *userdata,
887 sd_bus_error *error) {
888
889 Unit *u = userdata;
890 const char *t;
891
892 assert(bus);
893 assert(reply);
894 assert(u);
895
896 /* Three cases: a) u->cgroup_path is NULL, in which case the
897 * unit has no control group, which we report as the empty
898 * string. b) u->cgroup_path is the empty string, which
899 * indicates the root cgroup, which we report as "/". c) all
900 * other cases we report as-is. */
901
902 if (u->cgroup_path)
903 t = isempty(u->cgroup_path) ? "/" : u->cgroup_path;
904 else
905 t = "";
906
907 return sd_bus_message_append(reply, "s", t);
908 }
909
910 static int append_process(sd_bus_message *reply, const char *p, pid_t pid, Set *pids) {
911 _cleanup_free_ char *buf = NULL, *cmdline = NULL;
912 int r;
913
914 assert(reply);
915 assert(pid > 0);
916
917 r = set_put(pids, PID_TO_PTR(pid));
918 if (r == -EEXIST || r == 0)
919 return 0;
920 if (r < 0)
921 return r;
922
923 if (!p) {
924 r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &buf);
925 if (r == -ESRCH)
926 return 0;
927 if (r < 0)
928 return r;
929
930 p = buf;
931 }
932
933 (void) get_process_cmdline(pid, 0, true, &cmdline);
934
935 return sd_bus_message_append(reply,
936 "(sus)",
937 p,
938 (uint32_t) pid,
939 cmdline);
940 }
941
942 static int append_cgroup(sd_bus_message *reply, const char *p, Set *pids) {
943 _cleanup_closedir_ DIR *d = NULL;
944 _cleanup_fclose_ FILE *f = NULL;
945 int r;
946
947 assert(reply);
948 assert(p);
949
950 r = cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, p, &f);
951 if (r == ENOENT)
952 return 0;
953 if (r < 0)
954 return r;
955
956 for (;;) {
957 pid_t pid;
958
959 r = cg_read_pid(f, &pid);
960 if (r < 0)
961 return r;
962 if (r == 0)
963 break;
964
965 if (is_kernel_thread(pid) > 0)
966 continue;
967
968 r = append_process(reply, p, pid, pids);
969 if (r < 0)
970 return r;
971 }
972
973 r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, p, &d);
974 if (r == -ENOENT)
975 return 0;
976 if (r < 0)
977 return r;
978
979 for (;;) {
980 _cleanup_free_ char *g = NULL, *j = NULL;
981
982 r = cg_read_subgroup(d, &g);
983 if (r < 0)
984 return r;
985 if (r == 0)
986 break;
987
988 j = strjoin(p, "/", g);
989 if (!j)
990 return -ENOMEM;
991
992 r = append_cgroup(reply, j, pids);
993 if (r < 0)
994 return r;
995 }
996
997 return 0;
998 }
999
1000 int bus_unit_method_get_processes(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1001 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1002 _cleanup_(set_freep) Set *pids = NULL;
1003 Unit *u = userdata;
1004 pid_t pid;
1005 int r;
1006
1007 assert(message);
1008
1009 pids = set_new(NULL);
1010 if (!pids)
1011 return -ENOMEM;
1012
1013 r = sd_bus_message_new_method_return(message, &reply);
1014 if (r < 0)
1015 return r;
1016
1017 r = sd_bus_message_open_container(reply, 'a', "(sus)");
1018 if (r < 0)
1019 return r;
1020
1021 if (u->cgroup_path) {
1022 r = append_cgroup(reply, u->cgroup_path, pids);
1023 if (r < 0)
1024 return r;
1025 }
1026
1027 /* The main and control pids might live outside of the cgroup, hence fetch them separately */
1028 pid = unit_main_pid(u);
1029 if (pid > 0) {
1030 r = append_process(reply, NULL, pid, pids);
1031 if (r < 0)
1032 return r;
1033 }
1034
1035 pid = unit_control_pid(u);
1036 if (pid > 0) {
1037 r = append_process(reply, NULL, pid, pids);
1038 if (r < 0)
1039 return r;
1040 }
1041
1042 r = sd_bus_message_close_container(reply);
1043 if (r < 0)
1044 return r;
1045
1046 return sd_bus_send(NULL, reply, NULL);
1047 }
1048
1049 const sd_bus_vtable bus_unit_cgroup_vtable[] = {
1050 SD_BUS_VTABLE_START(0),
1051 SD_BUS_PROPERTY("Slice", "s", property_get_slice, 0, 0),
1052 SD_BUS_PROPERTY("ControlGroup", "s", property_get_cgroup, 0, 0),
1053 SD_BUS_PROPERTY("MemoryCurrent", "t", property_get_current_memory, 0, 0),
1054 SD_BUS_PROPERTY("CPUUsageNSec", "t", property_get_cpu_usage, 0, 0),
1055 SD_BUS_PROPERTY("TasksCurrent", "t", property_get_current_tasks, 0, 0),
1056 SD_BUS_METHOD("GetProcesses", NULL, "a(sus)", bus_unit_method_get_processes, SD_BUS_VTABLE_UNPRIVILEGED),
1057 SD_BUS_VTABLE_END
1058 };
1059
1060 static int send_new_signal(sd_bus *bus, void *userdata) {
1061 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
1062 _cleanup_free_ char *p = NULL;
1063 Unit *u = userdata;
1064 int r;
1065
1066 assert(bus);
1067 assert(u);
1068
1069 p = unit_dbus_path(u);
1070 if (!p)
1071 return -ENOMEM;
1072
1073 r = sd_bus_message_new_signal(
1074 bus,
1075 &m,
1076 "/org/freedesktop/systemd1",
1077 "org.freedesktop.systemd1.Manager",
1078 "UnitNew");
1079 if (r < 0)
1080 return r;
1081
1082 r = sd_bus_message_append(m, "so", u->id, p);
1083 if (r < 0)
1084 return r;
1085
1086 return sd_bus_send(bus, m, NULL);
1087 }
1088
1089 static int send_changed_signal(sd_bus *bus, void *userdata) {
1090 _cleanup_free_ char *p = NULL;
1091 Unit *u = userdata;
1092 int r;
1093
1094 assert(bus);
1095 assert(u);
1096
1097 p = unit_dbus_path(u);
1098 if (!p)
1099 return -ENOMEM;
1100
1101 /* Send a properties changed signal. First for the specific
1102 * type, then for the generic unit. The clients may rely on
1103 * this order to get atomic behavior if needed. */
1104
1105 r = sd_bus_emit_properties_changed_strv(
1106 bus, p,
1107 unit_dbus_interface_from_type(u->type),
1108 NULL);
1109 if (r < 0)
1110 return r;
1111
1112 return sd_bus_emit_properties_changed_strv(
1113 bus, p,
1114 "org.freedesktop.systemd1.Unit",
1115 NULL);
1116 }
1117
1118 void bus_unit_send_change_signal(Unit *u) {
1119 int r;
1120 assert(u);
1121
1122 if (u->in_dbus_queue) {
1123 LIST_REMOVE(dbus_queue, u->manager->dbus_unit_queue, u);
1124 u->in_dbus_queue = false;
1125 }
1126
1127 if (!u->id)
1128 return;
1129
1130 r = bus_foreach_bus(u->manager, NULL, u->sent_dbus_new_signal ? send_changed_signal : send_new_signal, u);
1131 if (r < 0)
1132 log_unit_debug_errno(u, r, "Failed to send unit change signal for %s: %m", u->id);
1133
1134 u->sent_dbus_new_signal = true;
1135 }
1136
1137 static int send_removed_signal(sd_bus *bus, void *userdata) {
1138 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
1139 _cleanup_free_ char *p = NULL;
1140 Unit *u = userdata;
1141 int r;
1142
1143 assert(bus);
1144 assert(u);
1145
1146 p = unit_dbus_path(u);
1147 if (!p)
1148 return -ENOMEM;
1149
1150 r = sd_bus_message_new_signal(
1151 bus,
1152 &m,
1153 "/org/freedesktop/systemd1",
1154 "org.freedesktop.systemd1.Manager",
1155 "UnitRemoved");
1156 if (r < 0)
1157 return r;
1158
1159 r = sd_bus_message_append(m, "so", u->id, p);
1160 if (r < 0)
1161 return r;
1162
1163 return sd_bus_send(bus, m, NULL);
1164 }
1165
1166 void bus_unit_send_removed_signal(Unit *u) {
1167 int r;
1168 assert(u);
1169
1170 if (!u->sent_dbus_new_signal || u->in_dbus_queue)
1171 bus_unit_send_change_signal(u);
1172
1173 if (!u->id)
1174 return;
1175
1176 r = bus_foreach_bus(u->manager, NULL, send_removed_signal, u);
1177 if (r < 0)
1178 log_unit_debug_errno(u, r, "Failed to send unit remove signal for %s: %m", u->id);
1179 }
1180
1181 int bus_unit_queue_job(
1182 sd_bus_message *message,
1183 Unit *u,
1184 JobType type,
1185 JobMode mode,
1186 bool reload_if_possible,
1187 sd_bus_error *error) {
1188
1189 _cleanup_free_ char *path = NULL;
1190 Job *j;
1191 int r;
1192
1193 assert(message);
1194 assert(u);
1195 assert(type >= 0 && type < _JOB_TYPE_MAX);
1196 assert(mode >= 0 && mode < _JOB_MODE_MAX);
1197
1198 r = mac_selinux_unit_access_check(
1199 u, message,
1200 job_type_to_access_method(type),
1201 error);
1202 if (r < 0)
1203 return r;
1204
1205 if (reload_if_possible && unit_can_reload(u)) {
1206 if (type == JOB_RESTART)
1207 type = JOB_RELOAD_OR_START;
1208 else if (type == JOB_TRY_RESTART)
1209 type = JOB_TRY_RELOAD;
1210 }
1211
1212 if (type == JOB_STOP &&
1213 (u->load_state == UNIT_NOT_FOUND || u->load_state == UNIT_ERROR) &&
1214 unit_active_state(u) == UNIT_INACTIVE)
1215 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", u->id);
1216
1217 if ((type == JOB_START && u->refuse_manual_start) ||
1218 (type == JOB_STOP && u->refuse_manual_stop) ||
1219 ((type == JOB_RESTART || type == JOB_TRY_RESTART) && (u->refuse_manual_start || u->refuse_manual_stop)) ||
1220 (type == JOB_RELOAD_OR_START && job_type_collapse(type, u) == JOB_START && u->refuse_manual_start))
1221 return sd_bus_error_setf(error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, unit %s may be requested by dependency only (it is configured to refuse manual start/stop).", u->id);
1222
1223 r = manager_add_job(u->manager, type, u, mode, error, &j);
1224 if (r < 0)
1225 return r;
1226
1227 r = bus_job_track_sender(j, message);
1228 if (r < 0)
1229 return r;
1230
1231 path = job_dbus_path(j);
1232 if (!path)
1233 return -ENOMEM;
1234
1235 return sd_bus_reply_method_return(message, "o", path);
1236 }
1237
1238 static int bus_unit_set_transient_property(
1239 Unit *u,
1240 const char *name,
1241 sd_bus_message *message,
1242 UnitSetPropertiesMode mode,
1243 sd_bus_error *error) {
1244
1245 int r;
1246
1247 assert(u);
1248 assert(name);
1249 assert(message);
1250
1251 if (streq(name, "Description")) {
1252 const char *d;
1253
1254 r = sd_bus_message_read(message, "s", &d);
1255 if (r < 0)
1256 return r;
1257
1258 if (mode != UNIT_CHECK) {
1259 r = unit_set_description(u, d);
1260 if (r < 0)
1261 return r;
1262
1263 unit_write_drop_in_format(u, mode, name, "[Unit]\nDescription=%s", d);
1264 }
1265
1266 return 1;
1267
1268 } else if (streq(name, "DefaultDependencies")) {
1269 int b;
1270
1271 r = sd_bus_message_read(message, "b", &b);
1272 if (r < 0)
1273 return r;
1274
1275 if (mode != UNIT_CHECK) {
1276 u->default_dependencies = b;
1277 unit_write_drop_in_format(u, mode, name, "[Unit]\nDefaultDependencies=%s", yes_no(b));
1278 }
1279
1280 return 1;
1281
1282 } else if (streq(name, "Slice")) {
1283 Unit *slice;
1284 const char *s;
1285
1286 if (!UNIT_HAS_CGROUP_CONTEXT(u))
1287 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "The slice property is only available for units with control groups.");
1288 if (u->type == UNIT_SLICE)
1289 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Slice may not be set for slice units.");
1290 if (unit_has_name(u, SPECIAL_INIT_SCOPE))
1291 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot set slice for init.scope");
1292
1293 r = sd_bus_message_read(message, "s", &s);
1294 if (r < 0)
1295 return r;
1296
1297 if (!unit_name_is_valid(s, UNIT_NAME_PLAIN))
1298 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit name '%s'", s);
1299
1300 /* Note that we do not dispatch the load queue here yet, as we don't want our own transient unit to be
1301 * loaded while we are still setting it up. Or in other words, we use manager_load_unit_prepare()
1302 * instead of manager_load_unit() on purpose, here. */
1303 r = manager_load_unit_prepare(u->manager, s, NULL, error, &slice);
1304 if (r < 0)
1305 return r;
1306
1307 if (slice->type != UNIT_SLICE)
1308 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit name '%s' is not a slice", s);
1309
1310 if (mode != UNIT_CHECK) {
1311 r = unit_set_slice(u, slice);
1312 if (r < 0)
1313 return r;
1314
1315 unit_write_drop_in_private_format(u, mode, name, "Slice=%s", s);
1316 }
1317
1318 return 1;
1319
1320 } else if (STR_IN_SET(name,
1321 "Requires", "RequiresOverridable",
1322 "Requisite", "RequisiteOverridable",
1323 "Wants",
1324 "BindsTo",
1325 "Conflicts",
1326 "Before", "After",
1327 "OnFailure",
1328 "PropagatesReloadTo", "ReloadPropagatedFrom",
1329 "PartOf")) {
1330
1331 UnitDependency d;
1332 const char *other;
1333
1334 if (streq(name, "RequiresOverridable"))
1335 d = UNIT_REQUIRES; /* redirect for obsolete unit dependency type */
1336 else if (streq(name, "RequisiteOverridable"))
1337 d = UNIT_REQUISITE; /* same here */
1338 else {
1339 d = unit_dependency_from_string(name);
1340 if (d < 0)
1341 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit dependency: %s", name);
1342 }
1343
1344 r = sd_bus_message_enter_container(message, 'a', "s");
1345 if (r < 0)
1346 return r;
1347
1348 while ((r = sd_bus_message_read(message, "s", &other)) > 0) {
1349 if (!unit_name_is_valid(other, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE))
1350 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit name %s", other);
1351
1352 if (mode != UNIT_CHECK) {
1353 _cleanup_free_ char *label = NULL;
1354
1355 r = unit_add_dependency_by_name(u, d, other, NULL, true);
1356 if (r < 0)
1357 return r;
1358
1359 label = strjoin(name, "-", other);
1360 if (!label)
1361 return -ENOMEM;
1362
1363 unit_write_drop_in_format(u, mode, label, "[Unit]\n%s=%s", name, other);
1364 }
1365
1366 }
1367 if (r < 0)
1368 return r;
1369
1370 r = sd_bus_message_exit_container(message);
1371 if (r < 0)
1372 return r;
1373
1374 return 1;
1375
1376 } else if (streq(name, "AddRef")) {
1377
1378 int b;
1379
1380 /* Why is this called "AddRef" rather than just "Ref", or "Reference"? There's already a "Ref()" method
1381 * on the Unit interface, and it's probably not a good idea to expose a property and a method on the
1382 * same interface (well, strictly speaking AddRef isn't exposed as full property, we just read it for
1383 * transient units, but still). And "References" and "ReferencedBy" is already used as unit reference
1384 * dependency type, hence let's not confuse things with that.
1385 *
1386 * Note that we don't acually add the reference to the bus track. We do that only after the setup of
1387 * the transient unit is complete, so that setting this property multiple times in the same transient
1388 * unit creation call doesn't count as individual references. */
1389
1390 r = sd_bus_message_read(message, "b", &b);
1391 if (r < 0)
1392 return r;
1393
1394 if (mode != UNIT_CHECK)
1395 u->bus_track_add = b;
1396
1397 return 1;
1398 }
1399
1400 return 0;
1401 }
1402
1403 int bus_unit_set_properties(
1404 Unit *u,
1405 sd_bus_message *message,
1406 UnitSetPropertiesMode mode,
1407 bool commit,
1408 sd_bus_error *error) {
1409
1410 bool for_real = false;
1411 unsigned n = 0;
1412 int r;
1413
1414 assert(u);
1415 assert(message);
1416
1417 /* We iterate through the array twice. First run we just check
1418 * if all passed data is valid, second run actually applies
1419 * it. This is to implement transaction-like behaviour without
1420 * actually providing full transactions. */
1421
1422 r = sd_bus_message_enter_container(message, 'a', "(sv)");
1423 if (r < 0)
1424 return r;
1425
1426 for (;;) {
1427 const char *name;
1428
1429 r = sd_bus_message_enter_container(message, 'r', "sv");
1430 if (r < 0)
1431 return r;
1432 if (r == 0) {
1433 if (for_real || mode == UNIT_CHECK)
1434 break;
1435
1436 /* Reached EOF. Let's try again, and this time for realz... */
1437 r = sd_bus_message_rewind(message, false);
1438 if (r < 0)
1439 return r;
1440
1441 for_real = true;
1442 continue;
1443 }
1444
1445 r = sd_bus_message_read(message, "s", &name);
1446 if (r < 0)
1447 return r;
1448
1449 if (!UNIT_VTABLE(u)->bus_set_property)
1450 return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Objects of this type do not support setting properties.");
1451
1452 r = sd_bus_message_enter_container(message, 'v', NULL);
1453 if (r < 0)
1454 return r;
1455
1456 r = UNIT_VTABLE(u)->bus_set_property(u, name, message, for_real ? mode : UNIT_CHECK, error);
1457 if (r == 0 && u->transient && u->load_state == UNIT_STUB)
1458 r = bus_unit_set_transient_property(u, name, message, for_real ? mode : UNIT_CHECK, error);
1459 if (r < 0)
1460 return r;
1461 if (r == 0)
1462 return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Cannot set property %s, or unknown property.", name);
1463
1464 r = sd_bus_message_exit_container(message);
1465 if (r < 0)
1466 return r;
1467
1468 r = sd_bus_message_exit_container(message);
1469 if (r < 0)
1470 return r;
1471
1472 n += for_real;
1473 }
1474
1475 r = sd_bus_message_exit_container(message);
1476 if (r < 0)
1477 return r;
1478
1479 if (commit && n > 0 && UNIT_VTABLE(u)->bus_commit_properties)
1480 UNIT_VTABLE(u)->bus_commit_properties(u);
1481
1482 return n;
1483 }
1484
1485 int bus_unit_check_load_state(Unit *u, sd_bus_error *error) {
1486 assert(u);
1487
1488 if (u->load_state == UNIT_LOADED)
1489 return 0;
1490
1491 /* Give a better description of the unit error when
1492 * possible. Note that in the case of UNIT_MASKED, load_error
1493 * is not set. */
1494 if (u->load_state == UNIT_MASKED)
1495 return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit %s is masked.", u->id);
1496
1497 if (u->load_state == UNIT_NOT_FOUND)
1498 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not found.", u->id);
1499
1500 return sd_bus_error_set_errnof(error, u->load_error, "Unit %s is not loaded properly: %m.", u->id);
1501 }
1502
1503 static int bus_unit_track_handler(sd_bus_track *t, void *userdata) {
1504 Unit *u = userdata;
1505
1506 assert(t);
1507 assert(u);
1508
1509 u->bus_track = sd_bus_track_unref(u->bus_track); /* make sure we aren't called again */
1510
1511 unit_add_to_gc_queue(u);
1512 return 0;
1513 }
1514
1515 static int bus_unit_allocate_bus_track(Unit *u) {
1516 int r;
1517
1518 assert(u);
1519
1520 if (u->bus_track)
1521 return 0;
1522
1523 r = sd_bus_track_new(u->manager->api_bus, &u->bus_track, bus_unit_track_handler, u);
1524 if (r < 0)
1525 return r;
1526
1527 r = sd_bus_track_set_recursive(u->bus_track, true);
1528 if (r < 0) {
1529 u->bus_track = sd_bus_track_unref(u->bus_track);
1530 return r;
1531 }
1532
1533 return 0;
1534 }
1535
1536 int bus_unit_track_add_name(Unit *u, const char *name) {
1537 int r;
1538
1539 assert(u);
1540
1541 r = bus_unit_allocate_bus_track(u);
1542 if (r < 0)
1543 return r;
1544
1545 return sd_bus_track_add_name(u->bus_track, name);
1546 }
1547
1548 int bus_unit_track_add_sender(Unit *u, sd_bus_message *m) {
1549 int r;
1550
1551 assert(u);
1552
1553 r = bus_unit_allocate_bus_track(u);
1554 if (r < 0)
1555 return r;
1556
1557 return sd_bus_track_add_sender(u->bus_track, m);
1558 }
1559
1560 int bus_unit_track_remove_sender(Unit *u, sd_bus_message *m) {
1561 assert(u);
1562
1563 /* If we haven't allocated the bus track object yet, then there's definitely no reference taken yet, return an
1564 * error */
1565 if (!u->bus_track)
1566 return -EUNATCH;
1567
1568 return sd_bus_track_remove_sender(u->bus_track, m);
1569 }