]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dbus-unit.c
Merge pull request #18863 from keszybz/cmdline-escaping
[thirdparty/systemd.git] / src / core / dbus-unit.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include "sd-bus.h"
4
5 #include "alloc-util.h"
6 #include "bpf-firewall.h"
7 #include "bus-common-errors.h"
8 #include "bus-get-properties.h"
9 #include "bus-polkit.h"
10 #include "cgroup-util.h"
11 #include "condition.h"
12 #include "dbus-job.h"
13 #include "dbus-manager.h"
14 #include "dbus-unit.h"
15 #include "dbus-util.h"
16 #include "dbus.h"
17 #include "fd-util.h"
18 #include "install.h"
19 #include "locale-util.h"
20 #include "log.h"
21 #include "path-util.h"
22 #include "process-util.h"
23 #include "selinux-access.h"
24 #include "signal-util.h"
25 #include "special.h"
26 #include "string-table.h"
27 #include "string-util.h"
28 #include "strv.h"
29 #include "user-util.h"
30 #include "web-util.h"
31
32 static bool unit_can_start_refuse_manual(Unit *u) {
33 return unit_can_start(u) && !u->refuse_manual_start;
34 }
35
36 static bool unit_can_stop_refuse_manual(Unit *u) {
37 return unit_can_stop(u) && !u->refuse_manual_stop;
38 }
39
40 static bool unit_can_isolate_refuse_manual(Unit *u) {
41 return unit_can_isolate(u) && !u->refuse_manual_start;
42 }
43
44 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_collect_mode, collect_mode, CollectMode);
45 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_load_state, unit_load_state, UnitLoadState);
46 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_job_mode, job_mode, JobMode);
47 static BUS_DEFINE_PROPERTY_GET(property_get_description, "s", Unit, unit_description);
48 static BUS_DEFINE_PROPERTY_GET2(property_get_active_state, "s", Unit, unit_active_state, unit_active_state_to_string);
49 static BUS_DEFINE_PROPERTY_GET2(property_get_freezer_state, "s", Unit, unit_freezer_state, freezer_state_to_string);
50 static BUS_DEFINE_PROPERTY_GET(property_get_sub_state, "s", Unit, unit_sub_state_to_string);
51 static BUS_DEFINE_PROPERTY_GET2(property_get_unit_file_state, "s", Unit, unit_get_unit_file_state, unit_file_state_to_string);
52 static BUS_DEFINE_PROPERTY_GET(property_get_can_reload, "b", Unit, unit_can_reload);
53 static BUS_DEFINE_PROPERTY_GET(property_get_can_start, "b", Unit, unit_can_start_refuse_manual);
54 static BUS_DEFINE_PROPERTY_GET(property_get_can_stop, "b", Unit, unit_can_stop_refuse_manual);
55 static BUS_DEFINE_PROPERTY_GET(property_get_can_isolate, "b", Unit, unit_can_isolate_refuse_manual);
56 static BUS_DEFINE_PROPERTY_GET(property_get_can_freeze, "b", Unit, unit_can_freeze);
57 static BUS_DEFINE_PROPERTY_GET(property_get_need_daemon_reload, "b", Unit, unit_need_daemon_reload);
58 static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_empty_strv, "as", 0);
59
60 static int property_get_can_clean(
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 Unit *u = userdata;
70 ExecCleanMask mask;
71 int r;
72
73 assert(bus);
74 assert(reply);
75
76 r = unit_can_clean(u, &mask);
77 if (r < 0)
78 return r;
79
80 r = sd_bus_message_open_container(reply, 'a', "s");
81 if (r < 0)
82 return r;
83
84 for (ExecDirectoryType t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) {
85 if (!FLAGS_SET(mask, 1U << t))
86 continue;
87
88 r = sd_bus_message_append(reply, "s", exec_resource_type_to_string(t));
89 if (r < 0)
90 return r;
91 }
92
93 return sd_bus_message_close_container(reply);
94 }
95
96 static int property_get_names(
97 sd_bus *bus,
98 const char *path,
99 const char *interface,
100 const char *property,
101 sd_bus_message *reply,
102 void *userdata,
103 sd_bus_error *error) {
104
105 Unit *u = userdata;
106 const char *t;
107 int r;
108
109 assert(bus);
110 assert(reply);
111 assert(u);
112
113 r = sd_bus_message_open_container(reply, 'a', "s");
114 if (r < 0)
115 return r;
116
117 r = sd_bus_message_append(reply, "s", u->id);
118 if (r < 0)
119 return r;
120
121 SET_FOREACH(t, u->aliases) {
122 r = sd_bus_message_append(reply, "s", t);
123 if (r < 0)
124 return r;
125 }
126
127 return sd_bus_message_close_container(reply);
128 }
129
130 static int property_get_following(
131 sd_bus *bus,
132 const char *path,
133 const char *interface,
134 const char *property,
135 sd_bus_message *reply,
136 void *userdata,
137 sd_bus_error *error) {
138
139 Unit *u = userdata, *f;
140
141 assert(bus);
142 assert(reply);
143 assert(u);
144
145 f = unit_following(u);
146 return sd_bus_message_append(reply, "s", f ? f->id : NULL);
147 }
148
149 static int property_get_dependencies(
150 sd_bus *bus,
151 const char *path,
152 const char *interface,
153 const char *property,
154 sd_bus_message *reply,
155 void *userdata,
156 sd_bus_error *error) {
157
158 Hashmap **h = userdata;
159 Unit *u;
160 void *v;
161 int r;
162
163 assert(bus);
164 assert(reply);
165 assert(h);
166
167 r = sd_bus_message_open_container(reply, 'a', "s");
168 if (r < 0)
169 return r;
170
171 HASHMAP_FOREACH_KEY(v, u, *h) {
172 r = sd_bus_message_append(reply, "s", u->id);
173 if (r < 0)
174 return r;
175 }
176
177 return sd_bus_message_close_container(reply);
178 }
179
180 static int property_get_requires_mounts_for(
181 sd_bus *bus,
182 const char *path,
183 const char *interface,
184 const char *property,
185 sd_bus_message *reply,
186 void *userdata,
187 sd_bus_error *error) {
188
189 Hashmap **h = userdata;
190 const char *p;
191 void *v;
192 int r;
193
194 assert(bus);
195 assert(reply);
196 assert(h);
197
198 r = sd_bus_message_open_container(reply, 'a', "s");
199 if (r < 0)
200 return r;
201
202 HASHMAP_FOREACH_KEY(v, p, *h) {
203 r = sd_bus_message_append(reply, "s", p);
204 if (r < 0)
205 return r;
206 }
207
208 return sd_bus_message_close_container(reply);
209 }
210
211 static int property_get_unit_file_preset(
212 sd_bus *bus,
213 const char *path,
214 const char *interface,
215 const char *property,
216 sd_bus_message *reply,
217 void *userdata,
218 sd_bus_error *error) {
219
220 Unit *u = userdata;
221 int r;
222
223 assert(bus);
224 assert(reply);
225 assert(u);
226
227 r = unit_get_unit_file_preset(u);
228
229 return sd_bus_message_append(reply, "s",
230 r < 0 ? NULL:
231 r > 0 ? "enabled" : "disabled");
232 }
233
234 static int property_get_job(
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 _cleanup_free_ char *p = NULL;
244 Job **j = userdata;
245
246 assert(bus);
247 assert(reply);
248 assert(j);
249
250 if (!*j)
251 return sd_bus_message_append(reply, "(uo)", 0, "/");
252
253 p = job_dbus_path(*j);
254 if (!p)
255 return -ENOMEM;
256
257 return sd_bus_message_append(reply, "(uo)", (*j)->id, p);
258 }
259
260 static int property_get_conditions(
261 sd_bus *bus,
262 const char *path,
263 const char *interface,
264 const char *property,
265 sd_bus_message *reply,
266 void *userdata,
267 sd_bus_error *error) {
268
269 const char *(*to_string)(ConditionType type) = NULL;
270 Condition **list = userdata, *c;
271 int r;
272
273 assert(bus);
274 assert(reply);
275 assert(list);
276
277 to_string = streq(property, "Asserts") ? assert_type_to_string : condition_type_to_string;
278
279 r = sd_bus_message_open_container(reply, 'a', "(sbbsi)");
280 if (r < 0)
281 return r;
282
283 LIST_FOREACH(conditions, c, *list) {
284 int tristate;
285
286 tristate =
287 c->result == CONDITION_UNTESTED ? 0 :
288 c->result == CONDITION_SUCCEEDED ? 1 : -1;
289
290 r = sd_bus_message_append(reply, "(sbbsi)",
291 to_string(c->type),
292 c->trigger, c->negate,
293 c->parameter, tristate);
294 if (r < 0)
295 return r;
296
297 }
298
299 return sd_bus_message_close_container(reply);
300 }
301
302 static int property_get_load_error(
303 sd_bus *bus,
304 const char *path,
305 const char *interface,
306 const char *property,
307 sd_bus_message *reply,
308 void *userdata,
309 sd_bus_error *error) {
310
311 _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
312 Unit *u = userdata;
313 int r;
314
315 assert(bus);
316 assert(reply);
317 assert(u);
318
319 r = bus_unit_validate_load_state(u, &e);
320 if (r < 0)
321 return sd_bus_message_append(reply, "(ss)", e.name, e.message);
322
323 return sd_bus_message_append(reply, "(ss)", NULL, NULL);
324 }
325
326 static int property_get_markers(
327 sd_bus *bus,
328 const char *path,
329 const char *interface,
330 const char *property,
331 sd_bus_message *reply,
332 void *userdata,
333 sd_bus_error *error) {
334
335 unsigned *markers = userdata;
336 int r;
337
338 assert(bus);
339 assert(reply);
340 assert(markers);
341
342 r = sd_bus_message_open_container(reply, 'a', "s");
343 if (r < 0)
344 return r;
345
346 /* Make sure out values fit in the bitfield. */
347 assert_cc(_UNIT_MARKER_MAX <= sizeof(((Unit){}).markers) * 8);
348
349 for (UnitMarker m = 0; m < _UNIT_MARKER_MAX; m++)
350 if (FLAGS_SET(*markers, 1u << m)) {
351 r = sd_bus_message_append(reply, "s", unit_marker_to_string(m));
352 if (r < 0)
353 return r;
354 }
355
356 return sd_bus_message_close_container(reply);
357 }
358
359 static const char *const polkit_message_for_job[_JOB_TYPE_MAX] = {
360 [JOB_START] = N_("Authentication is required to start '$(unit)'."),
361 [JOB_STOP] = N_("Authentication is required to stop '$(unit)'."),
362 [JOB_RELOAD] = N_("Authentication is required to reload '$(unit)'."),
363 [JOB_RESTART] = N_("Authentication is required to restart '$(unit)'."),
364 [JOB_TRY_RESTART] = N_("Authentication is required to restart '$(unit)'."),
365 };
366
367 int bus_unit_method_start_generic(
368 sd_bus_message *message,
369 Unit *u,
370 JobType job_type,
371 bool reload_if_possible,
372 sd_bus_error *error) {
373
374 const char *smode, *verb;
375 JobMode mode;
376 int r;
377
378 assert(message);
379 assert(u);
380 assert(job_type >= 0 && job_type < _JOB_TYPE_MAX);
381
382 r = mac_selinux_unit_access_check(
383 u, message,
384 job_type_to_access_method(job_type),
385 error);
386 if (r < 0)
387 return r;
388
389 r = sd_bus_message_read(message, "s", &smode);
390 if (r < 0)
391 return r;
392
393 mode = job_mode_from_string(smode);
394 if (mode < 0)
395 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s invalid", smode);
396
397 if (reload_if_possible)
398 verb = strjoina("reload-or-", job_type_to_string(job_type));
399 else
400 verb = job_type_to_string(job_type);
401
402 r = bus_verify_manage_units_async_full(
403 u,
404 verb,
405 CAP_SYS_ADMIN,
406 polkit_message_for_job[job_type],
407 true,
408 message,
409 error);
410 if (r < 0)
411 return r;
412 if (r == 0)
413 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
414
415 return bus_unit_queue_job(message, u, job_type, mode,
416 reload_if_possible ? BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE : 0, error);
417 }
418
419 static int method_start(sd_bus_message *message, void *userdata, sd_bus_error *error) {
420 return bus_unit_method_start_generic(message, userdata, JOB_START, false, error);
421 }
422
423 static int method_stop(sd_bus_message *message, void *userdata, sd_bus_error *error) {
424 return bus_unit_method_start_generic(message, userdata, JOB_STOP, false, error);
425 }
426
427 static int method_reload(sd_bus_message *message, void *userdata, sd_bus_error *error) {
428 return bus_unit_method_start_generic(message, userdata, JOB_RELOAD, false, error);
429 }
430
431 static int method_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) {
432 return bus_unit_method_start_generic(message, userdata, JOB_RESTART, false, error);
433 }
434
435 static int method_try_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) {
436 return bus_unit_method_start_generic(message, userdata, JOB_TRY_RESTART, false, error);
437 }
438
439 static int method_reload_or_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) {
440 return bus_unit_method_start_generic(message, userdata, JOB_RESTART, true, error);
441 }
442
443 static int method_reload_or_try_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) {
444 return bus_unit_method_start_generic(message, userdata, JOB_TRY_RESTART, true, error);
445 }
446
447 int bus_unit_method_enqueue_job(sd_bus_message *message, void *userdata, sd_bus_error *error) {
448 BusUnitQueueFlags flags = BUS_UNIT_QUEUE_VERBOSE_REPLY;
449 const char *jtype, *smode;
450 Unit *u = userdata;
451 JobType type;
452 JobMode mode;
453 int r;
454
455 assert(message);
456 assert(u);
457
458 r = sd_bus_message_read(message, "ss", &jtype, &smode);
459 if (r < 0)
460 return r;
461
462 /* Parse the two magic reload types "reload-or-…" manually */
463 if (streq(jtype, "reload-or-restart")) {
464 type = JOB_RESTART;
465 flags |= BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE;
466 } else if (streq(jtype, "reload-or-try-restart")) {
467 type = JOB_TRY_RESTART;
468 flags |= BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE;
469 } else {
470 /* And the rest generically */
471 type = job_type_from_string(jtype);
472 if (type < 0)
473 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job type %s invalid", jtype);
474 }
475
476 mode = job_mode_from_string(smode);
477 if (mode < 0)
478 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s invalid", smode);
479
480 r = mac_selinux_unit_access_check(
481 u, message,
482 job_type_to_access_method(type),
483 error);
484 if (r < 0)
485 return r;
486
487 r = bus_verify_manage_units_async_full(
488 u,
489 jtype,
490 CAP_SYS_ADMIN,
491 polkit_message_for_job[type],
492 true,
493 message,
494 error);
495 if (r < 0)
496 return r;
497 if (r == 0)
498 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
499
500 return bus_unit_queue_job(message, u, type, mode, flags, error);
501 }
502
503 int bus_unit_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error) {
504 Unit *u = userdata;
505 const char *swho;
506 int32_t signo;
507 KillWho who;
508 int r;
509
510 assert(message);
511 assert(u);
512
513 r = mac_selinux_unit_access_check(u, message, "stop", error);
514 if (r < 0)
515 return r;
516
517 r = sd_bus_message_read(message, "si", &swho, &signo);
518 if (r < 0)
519 return r;
520
521 if (isempty(swho))
522 who = KILL_ALL;
523 else {
524 who = kill_who_from_string(swho);
525 if (who < 0)
526 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid who argument %s", swho);
527 }
528
529 if (!SIGNAL_VALID(signo))
530 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Signal number out of range.");
531
532 r = bus_verify_manage_units_async_full(
533 u,
534 "kill",
535 CAP_KILL,
536 N_("Authentication is required to send a UNIX signal to the processes of '$(unit)'."),
537 true,
538 message,
539 error);
540 if (r < 0)
541 return r;
542 if (r == 0)
543 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
544
545 r = unit_kill(u, who, signo, error);
546 if (r < 0)
547 return r;
548
549 return sd_bus_reply_method_return(message, NULL);
550 }
551
552 int bus_unit_method_reset_failed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
553 Unit *u = userdata;
554 int r;
555
556 assert(message);
557 assert(u);
558
559 r = mac_selinux_unit_access_check(u, message, "reload", error);
560 if (r < 0)
561 return r;
562
563 r = bus_verify_manage_units_async_full(
564 u,
565 "reset-failed",
566 CAP_SYS_ADMIN,
567 N_("Authentication is required to reset the \"failed\" state of '$(unit)'."),
568 true,
569 message,
570 error);
571 if (r < 0)
572 return r;
573 if (r == 0)
574 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
575
576 unit_reset_failed(u);
577
578 return sd_bus_reply_method_return(message, NULL);
579 }
580
581 int bus_unit_method_set_properties(sd_bus_message *message, void *userdata, sd_bus_error *error) {
582 Unit *u = userdata;
583 int runtime, r;
584
585 assert(message);
586 assert(u);
587
588 r = mac_selinux_unit_access_check(u, message, "start", error);
589 if (r < 0)
590 return r;
591
592 r = sd_bus_message_read(message, "b", &runtime);
593 if (r < 0)
594 return r;
595
596 r = bus_verify_manage_units_async_full(
597 u,
598 "set-property",
599 CAP_SYS_ADMIN,
600 N_("Authentication is required to set properties on '$(unit)'."),
601 true,
602 message,
603 error);
604 if (r < 0)
605 return r;
606 if (r == 0)
607 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
608
609 r = bus_unit_set_properties(u, message, runtime ? UNIT_RUNTIME : UNIT_PERSISTENT, true, error);
610 if (r < 0)
611 return r;
612
613 return sd_bus_reply_method_return(message, NULL);
614 }
615
616 int bus_unit_method_ref(sd_bus_message *message, void *userdata, sd_bus_error *error) {
617 Unit *u = userdata;
618 int r;
619
620 assert(message);
621 assert(u);
622
623 r = mac_selinux_unit_access_check(u, message, "start", error);
624 if (r < 0)
625 return r;
626
627 r = bus_verify_manage_units_async_full(
628 u,
629 "ref",
630 CAP_SYS_ADMIN,
631 NULL,
632 false,
633 message,
634 error);
635 if (r < 0)
636 return r;
637 if (r == 0)
638 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
639
640 r = bus_unit_track_add_sender(u, message);
641 if (r < 0)
642 return r;
643
644 return sd_bus_reply_method_return(message, NULL);
645 }
646
647 int bus_unit_method_unref(sd_bus_message *message, void *userdata, sd_bus_error *error) {
648 Unit *u = userdata;
649 int r;
650
651 assert(message);
652 assert(u);
653
654 r = bus_unit_track_remove_sender(u, message);
655 if (r == -EUNATCH)
656 return sd_bus_error_set(error, BUS_ERROR_NOT_REFERENCED, "Unit has not been referenced yet.");
657 if (r < 0)
658 return r;
659
660 return sd_bus_reply_method_return(message, NULL);
661 }
662
663 int bus_unit_method_clean(sd_bus_message *message, void *userdata, sd_bus_error *error) {
664 ExecCleanMask mask = 0;
665 Unit *u = userdata;
666 int r;
667
668 assert(message);
669 assert(u);
670
671 r = mac_selinux_unit_access_check(u, message, "stop", error);
672 if (r < 0)
673 return r;
674
675 r = sd_bus_message_enter_container(message, 'a', "s");
676 if (r < 0)
677 return r;
678
679 for (;;) {
680 const char *i;
681
682 r = sd_bus_message_read(message, "s", &i);
683 if (r < 0)
684 return r;
685 if (r == 0)
686 break;
687
688 if (streq(i, "all"))
689 mask |= EXEC_CLEAN_ALL;
690 else {
691 ExecDirectoryType t;
692
693 t = exec_resource_type_from_string(i);
694 if (t < 0)
695 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid resource type: %s", i);
696
697 mask |= 1U << t;
698 }
699 }
700
701 r = sd_bus_message_exit_container(message);
702 if (r < 0)
703 return r;
704
705 r = bus_verify_manage_units_async_full(
706 u,
707 "clean",
708 CAP_DAC_OVERRIDE,
709 N_("Authentication is required to delete files and directories associated with '$(unit)'."),
710 true,
711 message,
712 error);
713 if (r < 0)
714 return r;
715 if (r == 0)
716 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
717
718 r = unit_clean(u, mask);
719 if (r == -EOPNOTSUPP)
720 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Unit '%s' does not supporting cleaning.", u->id);
721 if (r == -EUNATCH)
722 return sd_bus_error_set(error, BUS_ERROR_NOTHING_TO_CLEAN, "No matching resources found.");
723 if (r == -EBUSY)
724 return sd_bus_error_set(error, BUS_ERROR_UNIT_BUSY, "Unit is not inactive or has pending job.");
725 if (r < 0)
726 return r;
727
728 return sd_bus_reply_method_return(message, NULL);
729 }
730
731 static int bus_unit_method_freezer_generic(sd_bus_message *message, void *userdata, sd_bus_error *error, FreezerAction action) {
732 const char* perm;
733 int (*method)(Unit*);
734 Unit *u = userdata;
735 bool reply_no_delay = false;
736 int r;
737
738 assert(message);
739 assert(u);
740 assert(IN_SET(action, FREEZER_FREEZE, FREEZER_THAW));
741
742 if (action == FREEZER_FREEZE) {
743 perm = "stop";
744 method = unit_freeze;
745 } else {
746 perm = "start";
747 method = unit_thaw;
748 }
749
750 r = mac_selinux_unit_access_check(u, message, perm, error);
751 if (r < 0)
752 return r;
753
754 r = bus_verify_manage_units_async_full(
755 u,
756 perm,
757 CAP_SYS_ADMIN,
758 N_("Authentication is required to freeze or thaw the processes of '$(unit)' unit."),
759 true,
760 message,
761 error);
762 if (r < 0)
763 return r;
764 if (r == 0)
765 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
766
767 r = method(u);
768 if (r == -EOPNOTSUPP)
769 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Unit '%s' does not support freezing.", u->id);
770 if (r == -EBUSY)
771 return sd_bus_error_set(error, BUS_ERROR_UNIT_BUSY, "Unit has a pending job.");
772 if (r == -EHOSTDOWN)
773 return sd_bus_error_set(error, BUS_ERROR_UNIT_INACTIVE, "Unit is inactive.");
774 if (r == -EALREADY)
775 return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Previously requested freezer operation for unit '%s' is still in progress.", u->id);
776 if (r < 0)
777 return r;
778 if (r == 0)
779 reply_no_delay = true;
780
781 assert(!u->pending_freezer_message);
782
783 r = sd_bus_message_new_method_return(message, &u->pending_freezer_message);
784 if (r < 0)
785 return r;
786
787 if (reply_no_delay) {
788 r = bus_unit_send_pending_freezer_message(u);
789 if (r < 0)
790 return r;
791 }
792
793 return 1;
794 }
795
796 int bus_unit_method_thaw(sd_bus_message *message, void *userdata, sd_bus_error *error) {
797 return bus_unit_method_freezer_generic(message, userdata, error, FREEZER_THAW);
798 }
799
800 int bus_unit_method_freeze(sd_bus_message *message, void *userdata, sd_bus_error *error) {
801 return bus_unit_method_freezer_generic(message, userdata, error, FREEZER_FREEZE);
802 }
803
804 static int property_get_refs(
805 sd_bus *bus,
806 const char *path,
807 const char *interface,
808 const char *property,
809 sd_bus_message *reply,
810 void *userdata,
811 sd_bus_error *error) {
812
813 Unit *u = userdata;
814 int r;
815
816 assert(bus);
817 assert(reply);
818
819 r = sd_bus_message_open_container(reply, 'a', "s");
820 if (r < 0)
821 return r;
822
823 for (const char *i = sd_bus_track_first(u->bus_track); i; i = sd_bus_track_next(u->bus_track)) {
824 int c;
825
826 c = sd_bus_track_count_name(u->bus_track, i);
827 if (c < 0)
828 return c;
829
830 /* Add the item multiple times if the ref count for each is above 1 */
831 for (int k = 0; k < c; k++) {
832 r = sd_bus_message_append(reply, "s", i);
833 if (r < 0)
834 return r;
835 }
836 }
837
838 return sd_bus_message_close_container(reply);
839 }
840
841 const sd_bus_vtable bus_unit_vtable[] = {
842 SD_BUS_VTABLE_START(0),
843
844 SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Unit, id), SD_BUS_VTABLE_PROPERTY_CONST),
845 SD_BUS_PROPERTY("Names", "as", property_get_names, 0, SD_BUS_VTABLE_PROPERTY_CONST),
846 SD_BUS_PROPERTY("Following", "s", property_get_following, 0, 0),
847 SD_BUS_PROPERTY("Requires", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRES]), SD_BUS_VTABLE_PROPERTY_CONST),
848 SD_BUS_PROPERTY("Requisite", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE]), SD_BUS_VTABLE_PROPERTY_CONST),
849 SD_BUS_PROPERTY("Wants", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_WANTS]), SD_BUS_VTABLE_PROPERTY_CONST),
850 SD_BUS_PROPERTY("BindsTo", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BINDS_TO]), SD_BUS_VTABLE_PROPERTY_CONST),
851 SD_BUS_PROPERTY("PartOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_PART_OF]), SD_BUS_VTABLE_PROPERTY_CONST),
852 SD_BUS_PROPERTY("RequiredBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRED_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
853 SD_BUS_PROPERTY("RequisiteOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE_OF]), SD_BUS_VTABLE_PROPERTY_CONST),
854 SD_BUS_PROPERTY("WantedBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_WANTED_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
855 SD_BUS_PROPERTY("BoundBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BOUND_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
856 SD_BUS_PROPERTY("ConsistsOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONSISTS_OF]), SD_BUS_VTABLE_PROPERTY_CONST),
857 SD_BUS_PROPERTY("Conflicts", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONFLICTS]), SD_BUS_VTABLE_PROPERTY_CONST),
858 SD_BUS_PROPERTY("ConflictedBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONFLICTED_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
859 SD_BUS_PROPERTY("Before", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BEFORE]), SD_BUS_VTABLE_PROPERTY_CONST),
860 SD_BUS_PROPERTY("After", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_AFTER]), SD_BUS_VTABLE_PROPERTY_CONST),
861 SD_BUS_PROPERTY("OnFailure", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_ON_FAILURE]), SD_BUS_VTABLE_PROPERTY_CONST),
862 SD_BUS_PROPERTY("Triggers", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_TRIGGERS]), SD_BUS_VTABLE_PROPERTY_CONST),
863 SD_BUS_PROPERTY("TriggeredBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_TRIGGERED_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
864 SD_BUS_PROPERTY("PropagatesReloadTo", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_PROPAGATES_RELOAD_TO]), SD_BUS_VTABLE_PROPERTY_CONST),
865 SD_BUS_PROPERTY("ReloadPropagatedFrom", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_RELOAD_PROPAGATED_FROM]), SD_BUS_VTABLE_PROPERTY_CONST),
866 SD_BUS_PROPERTY("JoinsNamespaceOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_JOINS_NAMESPACE_OF]), SD_BUS_VTABLE_PROPERTY_CONST),
867 SD_BUS_PROPERTY("RequiresMountsFor", "as", property_get_requires_mounts_for, offsetof(Unit, requires_mounts_for), SD_BUS_VTABLE_PROPERTY_CONST),
868 SD_BUS_PROPERTY("Documentation", "as", NULL, offsetof(Unit, documentation), SD_BUS_VTABLE_PROPERTY_CONST),
869 SD_BUS_PROPERTY("Description", "s", property_get_description, 0, SD_BUS_VTABLE_PROPERTY_CONST),
870 SD_BUS_PROPERTY("LoadState", "s", property_get_load_state, offsetof(Unit, load_state), SD_BUS_VTABLE_PROPERTY_CONST),
871 SD_BUS_PROPERTY("ActiveState", "s", property_get_active_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
872 SD_BUS_PROPERTY("FreezerState", "s", property_get_freezer_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
873 SD_BUS_PROPERTY("SubState", "s", property_get_sub_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
874 SD_BUS_PROPERTY("FragmentPath", "s", NULL, offsetof(Unit, fragment_path), SD_BUS_VTABLE_PROPERTY_CONST),
875 SD_BUS_PROPERTY("SourcePath", "s", NULL, offsetof(Unit, source_path), SD_BUS_VTABLE_PROPERTY_CONST),
876 SD_BUS_PROPERTY("DropInPaths", "as", NULL, offsetof(Unit, dropin_paths), SD_BUS_VTABLE_PROPERTY_CONST),
877 SD_BUS_PROPERTY("UnitFileState", "s", property_get_unit_file_state, 0, 0),
878 SD_BUS_PROPERTY("UnitFilePreset", "s", property_get_unit_file_preset, 0, 0),
879 BUS_PROPERTY_DUAL_TIMESTAMP("StateChangeTimestamp", offsetof(Unit, state_change_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
880 BUS_PROPERTY_DUAL_TIMESTAMP("InactiveExitTimestamp", offsetof(Unit, inactive_exit_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
881 BUS_PROPERTY_DUAL_TIMESTAMP("ActiveEnterTimestamp", offsetof(Unit, active_enter_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
882 BUS_PROPERTY_DUAL_TIMESTAMP("ActiveExitTimestamp", offsetof(Unit, active_exit_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
883 BUS_PROPERTY_DUAL_TIMESTAMP("InactiveEnterTimestamp", offsetof(Unit, inactive_enter_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
884 SD_BUS_PROPERTY("CanStart", "b", property_get_can_start, 0, SD_BUS_VTABLE_PROPERTY_CONST),
885 SD_BUS_PROPERTY("CanStop", "b", property_get_can_stop, 0, SD_BUS_VTABLE_PROPERTY_CONST),
886 SD_BUS_PROPERTY("CanReload", "b", property_get_can_reload, 0, SD_BUS_VTABLE_PROPERTY_CONST),
887 SD_BUS_PROPERTY("CanIsolate", "b", property_get_can_isolate, 0, SD_BUS_VTABLE_PROPERTY_CONST),
888 SD_BUS_PROPERTY("CanClean", "as", property_get_can_clean, 0, SD_BUS_VTABLE_PROPERTY_CONST),
889 SD_BUS_PROPERTY("CanFreeze", "b", property_get_can_freeze, 0, SD_BUS_VTABLE_PROPERTY_CONST),
890 SD_BUS_PROPERTY("Job", "(uo)", property_get_job, offsetof(Unit, job), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
891 SD_BUS_PROPERTY("StopWhenUnneeded", "b", bus_property_get_bool, offsetof(Unit, stop_when_unneeded), SD_BUS_VTABLE_PROPERTY_CONST),
892 SD_BUS_PROPERTY("RefuseManualStart", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_start), SD_BUS_VTABLE_PROPERTY_CONST),
893 SD_BUS_PROPERTY("RefuseManualStop", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_stop), SD_BUS_VTABLE_PROPERTY_CONST),
894 SD_BUS_PROPERTY("AllowIsolate", "b", bus_property_get_bool, offsetof(Unit, allow_isolate), SD_BUS_VTABLE_PROPERTY_CONST),
895 SD_BUS_PROPERTY("DefaultDependencies", "b", bus_property_get_bool, offsetof(Unit, default_dependencies), SD_BUS_VTABLE_PROPERTY_CONST),
896 SD_BUS_PROPERTY("OnFailureJobMode", "s", property_get_job_mode, offsetof(Unit, on_failure_job_mode), SD_BUS_VTABLE_PROPERTY_CONST),
897 SD_BUS_PROPERTY("IgnoreOnIsolate", "b", bus_property_get_bool, offsetof(Unit, ignore_on_isolate), SD_BUS_VTABLE_PROPERTY_CONST),
898 SD_BUS_PROPERTY("NeedDaemonReload", "b", property_get_need_daemon_reload, 0, SD_BUS_VTABLE_PROPERTY_CONST),
899 SD_BUS_PROPERTY("Markers", "as", property_get_markers, offsetof(Unit, markers), 0),
900 SD_BUS_PROPERTY("JobTimeoutUSec", "t", bus_property_get_usec, offsetof(Unit, job_timeout), SD_BUS_VTABLE_PROPERTY_CONST),
901 SD_BUS_PROPERTY("JobRunningTimeoutUSec", "t", bus_property_get_usec, offsetof(Unit, job_running_timeout), SD_BUS_VTABLE_PROPERTY_CONST),
902 SD_BUS_PROPERTY("JobTimeoutAction", "s", bus_property_get_emergency_action, offsetof(Unit, job_timeout_action), SD_BUS_VTABLE_PROPERTY_CONST),
903 SD_BUS_PROPERTY("JobTimeoutRebootArgument", "s", NULL, offsetof(Unit, job_timeout_reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST),
904 SD_BUS_PROPERTY("ConditionResult", "b", bus_property_get_bool, offsetof(Unit, condition_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
905 SD_BUS_PROPERTY("AssertResult", "b", bus_property_get_bool, offsetof(Unit, assert_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
906 BUS_PROPERTY_DUAL_TIMESTAMP("ConditionTimestamp", offsetof(Unit, condition_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
907 BUS_PROPERTY_DUAL_TIMESTAMP("AssertTimestamp", offsetof(Unit, assert_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
908 SD_BUS_PROPERTY("Conditions", "a(sbbsi)", property_get_conditions, offsetof(Unit, conditions), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
909 SD_BUS_PROPERTY("Asserts", "a(sbbsi)", property_get_conditions, offsetof(Unit, asserts), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
910 SD_BUS_PROPERTY("LoadError", "(ss)", property_get_load_error, 0, SD_BUS_VTABLE_PROPERTY_CONST),
911 SD_BUS_PROPERTY("Transient", "b", bus_property_get_bool, offsetof(Unit, transient), SD_BUS_VTABLE_PROPERTY_CONST),
912 SD_BUS_PROPERTY("Perpetual", "b", bus_property_get_bool, offsetof(Unit, perpetual), SD_BUS_VTABLE_PROPERTY_CONST),
913 SD_BUS_PROPERTY("StartLimitIntervalUSec", "t", bus_property_get_usec, offsetof(Unit, start_ratelimit.interval), SD_BUS_VTABLE_PROPERTY_CONST),
914 SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_ratelimit.burst), SD_BUS_VTABLE_PROPERTY_CONST),
915 SD_BUS_PROPERTY("StartLimitAction", "s", bus_property_get_emergency_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST),
916 SD_BUS_PROPERTY("FailureAction", "s", bus_property_get_emergency_action, offsetof(Unit, failure_action), SD_BUS_VTABLE_PROPERTY_CONST),
917 SD_BUS_PROPERTY("FailureActionExitStatus", "i", bus_property_get_int, offsetof(Unit, failure_action_exit_status), SD_BUS_VTABLE_PROPERTY_CONST),
918 SD_BUS_PROPERTY("SuccessAction", "s", bus_property_get_emergency_action, offsetof(Unit, success_action), SD_BUS_VTABLE_PROPERTY_CONST),
919 SD_BUS_PROPERTY("SuccessActionExitStatus", "i", bus_property_get_int, offsetof(Unit, success_action_exit_status), SD_BUS_VTABLE_PROPERTY_CONST),
920 SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST),
921 SD_BUS_PROPERTY("InvocationID", "ay", bus_property_get_id128, offsetof(Unit, invocation_id), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
922 SD_BUS_PROPERTY("CollectMode", "s", property_get_collect_mode, offsetof(Unit, collect_mode), SD_BUS_VTABLE_PROPERTY_CONST),
923 SD_BUS_PROPERTY("Refs", "as", property_get_refs, 0, 0),
924
925 SD_BUS_METHOD_WITH_NAMES("Start",
926 "s",
927 SD_BUS_PARAM(mode),
928 "o",
929 SD_BUS_PARAM(job),
930 method_start,
931 SD_BUS_VTABLE_UNPRIVILEGED),
932 SD_BUS_METHOD_WITH_NAMES("Stop",
933 "s",
934 SD_BUS_PARAM(mode),
935 "o",
936 SD_BUS_PARAM(job),
937 method_stop,
938 SD_BUS_VTABLE_UNPRIVILEGED),
939 SD_BUS_METHOD_WITH_NAMES("Reload",
940 "s",
941 SD_BUS_PARAM(mode),
942 "o",
943 SD_BUS_PARAM(job),
944 method_reload,
945 SD_BUS_VTABLE_UNPRIVILEGED),
946 SD_BUS_METHOD_WITH_NAMES("Restart",
947 "s",
948 SD_BUS_PARAM(mode),
949 "o",
950 SD_BUS_PARAM(job),
951 method_restart,
952 SD_BUS_VTABLE_UNPRIVILEGED),
953 SD_BUS_METHOD_WITH_NAMES("TryRestart",
954 "s",
955 SD_BUS_PARAM(mode),
956 "o",
957 SD_BUS_PARAM(job),
958 method_try_restart,
959 SD_BUS_VTABLE_UNPRIVILEGED),
960 SD_BUS_METHOD_WITH_NAMES("ReloadOrRestart",
961 "s",
962 SD_BUS_PARAM(mode),
963 "o",
964 SD_BUS_PARAM(job),
965 method_reload_or_restart,
966 SD_BUS_VTABLE_UNPRIVILEGED),
967 SD_BUS_METHOD_WITH_NAMES("ReloadOrTryRestart",
968 "s",
969 SD_BUS_PARAM(mode),
970 "o",
971 SD_BUS_PARAM(job),
972 method_reload_or_try_restart,
973 SD_BUS_VTABLE_UNPRIVILEGED),
974 SD_BUS_METHOD_WITH_NAMES("EnqueueJob",
975 "ss",
976 SD_BUS_PARAM(job_type)
977 SD_BUS_PARAM(job_mode),
978 "uososa(uosos)",
979 SD_BUS_PARAM(job_id)
980 SD_BUS_PARAM(job_path)
981 SD_BUS_PARAM(unit_id)
982 SD_BUS_PARAM(unit_path)
983 SD_BUS_PARAM(job_type)
984 SD_BUS_PARAM(affected_jobs),
985 bus_unit_method_enqueue_job,
986 SD_BUS_VTABLE_UNPRIVILEGED),
987 SD_BUS_METHOD_WITH_NAMES("Kill",
988 "si",
989 SD_BUS_PARAM(whom)
990 SD_BUS_PARAM(signal),
991 NULL,,
992 bus_unit_method_kill,
993 SD_BUS_VTABLE_UNPRIVILEGED),
994 SD_BUS_METHOD("ResetFailed",
995 NULL,
996 NULL,
997 bus_unit_method_reset_failed,
998 SD_BUS_VTABLE_UNPRIVILEGED),
999 SD_BUS_METHOD_WITH_NAMES("SetProperties",
1000 "ba(sv)",
1001 SD_BUS_PARAM(runtime)
1002 SD_BUS_PARAM(properties),
1003 NULL,,
1004 bus_unit_method_set_properties,
1005 SD_BUS_VTABLE_UNPRIVILEGED),
1006 SD_BUS_METHOD("Ref",
1007 NULL,
1008 NULL,
1009 bus_unit_method_ref,
1010 SD_BUS_VTABLE_UNPRIVILEGED),
1011 SD_BUS_METHOD("Unref",
1012 NULL,
1013 NULL,
1014 bus_unit_method_unref,
1015 SD_BUS_VTABLE_UNPRIVILEGED),
1016 SD_BUS_METHOD_WITH_NAMES("Clean",
1017 "as",
1018 SD_BUS_PARAM(mask),
1019 NULL,,
1020 bus_unit_method_clean,
1021 SD_BUS_VTABLE_UNPRIVILEGED),
1022 SD_BUS_METHOD("Freeze",
1023 NULL,
1024 NULL,
1025 bus_unit_method_freeze,
1026 SD_BUS_VTABLE_UNPRIVILEGED),
1027 SD_BUS_METHOD("Thaw",
1028 NULL,
1029 NULL,
1030 bus_unit_method_thaw,
1031 SD_BUS_VTABLE_UNPRIVILEGED),
1032
1033 /* For dependency types we don't support anymore always return an empty array */
1034 SD_BUS_PROPERTY("RequiresOverridable", "as", property_get_empty_strv, 0, SD_BUS_VTABLE_HIDDEN),
1035 SD_BUS_PROPERTY("RequisiteOverridable", "as", property_get_empty_strv, 0, SD_BUS_VTABLE_HIDDEN),
1036 SD_BUS_PROPERTY("RequiredByOverridable", "as", property_get_empty_strv, 0, SD_BUS_VTABLE_HIDDEN),
1037 SD_BUS_PROPERTY("RequisiteOfOverridable", "as", property_get_empty_strv, 0, SD_BUS_VTABLE_HIDDEN),
1038 /* Obsolete alias names */
1039 SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_ratelimit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
1040 SD_BUS_PROPERTY("StartLimitIntervalSec", "t", bus_property_get_usec, offsetof(Unit, start_ratelimit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
1041
1042 SD_BUS_VTABLE_END
1043 };
1044
1045 static int property_get_slice(
1046 sd_bus *bus,
1047 const char *path,
1048 const char *interface,
1049 const char *property,
1050 sd_bus_message *reply,
1051 void *userdata,
1052 sd_bus_error *error) {
1053
1054 Unit *u = userdata;
1055
1056 assert(bus);
1057 assert(reply);
1058 assert(u);
1059
1060 return sd_bus_message_append(reply, "s", unit_slice_name(u));
1061 }
1062
1063 static int property_get_current_memory(
1064 sd_bus *bus,
1065 const char *path,
1066 const char *interface,
1067 const char *property,
1068 sd_bus_message *reply,
1069 void *userdata,
1070 sd_bus_error *error) {
1071
1072 uint64_t sz = UINT64_MAX;
1073 Unit *u = userdata;
1074 int r;
1075
1076 assert(bus);
1077 assert(reply);
1078 assert(u);
1079
1080 r = unit_get_memory_current(u, &sz);
1081 if (r < 0 && r != -ENODATA)
1082 log_unit_warning_errno(u, r, "Failed to get memory.usage_in_bytes attribute: %m");
1083
1084 return sd_bus_message_append(reply, "t", sz);
1085 }
1086
1087 static int property_get_current_tasks(
1088 sd_bus *bus,
1089 const char *path,
1090 const char *interface,
1091 const char *property,
1092 sd_bus_message *reply,
1093 void *userdata,
1094 sd_bus_error *error) {
1095
1096 uint64_t cn = UINT64_MAX;
1097 Unit *u = userdata;
1098 int r;
1099
1100 assert(bus);
1101 assert(reply);
1102 assert(u);
1103
1104 r = unit_get_tasks_current(u, &cn);
1105 if (r < 0 && r != -ENODATA)
1106 log_unit_warning_errno(u, r, "Failed to get pids.current attribute: %m");
1107
1108 return sd_bus_message_append(reply, "t", cn);
1109 }
1110
1111 static int property_get_cpu_usage(
1112 sd_bus *bus,
1113 const char *path,
1114 const char *interface,
1115 const char *property,
1116 sd_bus_message *reply,
1117 void *userdata,
1118 sd_bus_error *error) {
1119
1120 nsec_t ns = NSEC_INFINITY;
1121 Unit *u = userdata;
1122 int r;
1123
1124 assert(bus);
1125 assert(reply);
1126 assert(u);
1127
1128 r = unit_get_cpu_usage(u, &ns);
1129 if (r < 0 && r != -ENODATA)
1130 log_unit_warning_errno(u, r, "Failed to get cpuacct.usage attribute: %m");
1131
1132 return sd_bus_message_append(reply, "t", ns);
1133 }
1134
1135 static int property_get_cpuset_cpus(
1136 sd_bus *bus,
1137 const char *path,
1138 const char *interface,
1139 const char *property,
1140 sd_bus_message *reply,
1141 void *userdata,
1142 sd_bus_error *error) {
1143
1144 Unit *u = userdata;
1145 _cleanup_(cpu_set_reset) CPUSet cpus = {};
1146 _cleanup_free_ uint8_t *array = NULL;
1147 size_t allocated;
1148
1149 assert(bus);
1150 assert(reply);
1151 assert(u);
1152
1153 (void) unit_get_cpuset(u, &cpus, "cpuset.cpus.effective");
1154 (void) cpu_set_to_dbus(&cpus, &array, &allocated);
1155 return sd_bus_message_append_array(reply, 'y', array, allocated);
1156 }
1157
1158 static int property_get_cpuset_mems(
1159 sd_bus *bus,
1160 const char *path,
1161 const char *interface,
1162 const char *property,
1163 sd_bus_message *reply,
1164 void *userdata,
1165 sd_bus_error *error) {
1166
1167 Unit *u = userdata;
1168 _cleanup_(cpu_set_reset) CPUSet mems = {};
1169 _cleanup_free_ uint8_t *array = NULL;
1170 size_t allocated;
1171
1172 assert(bus);
1173 assert(reply);
1174 assert(u);
1175
1176 (void) unit_get_cpuset(u, &mems, "cpuset.mems.effective");
1177 (void) cpu_set_to_dbus(&mems, &array, &allocated);
1178 return sd_bus_message_append_array(reply, 'y', array, allocated);
1179 }
1180
1181 static int property_get_cgroup(
1182 sd_bus *bus,
1183 const char *path,
1184 const char *interface,
1185 const char *property,
1186 sd_bus_message *reply,
1187 void *userdata,
1188 sd_bus_error *error) {
1189
1190 Unit *u = userdata;
1191 const char *t = NULL;
1192
1193 assert(bus);
1194 assert(reply);
1195 assert(u);
1196
1197 /* Three cases: a) u->cgroup_path is NULL, in which case the
1198 * unit has no control group, which we report as the empty
1199 * string. b) u->cgroup_path is the empty string, which
1200 * indicates the root cgroup, which we report as "/". c) all
1201 * other cases we report as-is. */
1202
1203 if (u->cgroup_path)
1204 t = empty_to_root(u->cgroup_path);
1205
1206 return sd_bus_message_append(reply, "s", t);
1207 }
1208
1209 static int append_process(sd_bus_message *reply, const char *p, pid_t pid, Set *pids) {
1210 _cleanup_free_ char *buf = NULL, *cmdline = NULL;
1211 int r;
1212
1213 assert(reply);
1214 assert(pid > 0);
1215
1216 r = set_put(pids, PID_TO_PTR(pid));
1217 if (IN_SET(r, 0, -EEXIST))
1218 return 0;
1219 if (r < 0)
1220 return r;
1221
1222 if (!p) {
1223 r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &buf);
1224 if (r == -ESRCH)
1225 return 0;
1226 if (r < 0)
1227 return r;
1228
1229 p = buf;
1230 }
1231
1232 (void) get_process_cmdline(pid, SIZE_MAX,
1233 PROCESS_CMDLINE_COMM_FALLBACK | PROCESS_CMDLINE_QUOTE,
1234 &cmdline);
1235
1236 return sd_bus_message_append(reply,
1237 "(sus)",
1238 p,
1239 (uint32_t) pid,
1240 cmdline);
1241 }
1242
1243 static int append_cgroup(sd_bus_message *reply, const char *p, Set *pids) {
1244 _cleanup_closedir_ DIR *d = NULL;
1245 _cleanup_fclose_ FILE *f = NULL;
1246 int r;
1247
1248 assert(reply);
1249 assert(p);
1250
1251 r = cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, p, &f);
1252 if (r == -ENOENT)
1253 return 0;
1254 if (r < 0)
1255 return r;
1256
1257 for (;;) {
1258 pid_t pid;
1259
1260 r = cg_read_pid(f, &pid);
1261 if (r < 0)
1262 return r;
1263 if (r == 0)
1264 break;
1265
1266 if (is_kernel_thread(pid) > 0)
1267 continue;
1268
1269 r = append_process(reply, p, pid, pids);
1270 if (r < 0)
1271 return r;
1272 }
1273
1274 r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, p, &d);
1275 if (r == -ENOENT)
1276 return 0;
1277 if (r < 0)
1278 return r;
1279
1280 for (;;) {
1281 _cleanup_free_ char *g = NULL, *j = NULL;
1282
1283 r = cg_read_subgroup(d, &g);
1284 if (r < 0)
1285 return r;
1286 if (r == 0)
1287 break;
1288
1289 j = path_join(empty_to_root(p), g);
1290 if (!j)
1291 return -ENOMEM;
1292
1293 r = append_cgroup(reply, j, pids);
1294 if (r < 0)
1295 return r;
1296 }
1297
1298 return 0;
1299 }
1300
1301 int bus_unit_method_get_processes(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1302 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1303 _cleanup_set_free_ Set *pids = NULL;
1304 Unit *u = userdata;
1305 pid_t pid;
1306 int r;
1307
1308 assert(message);
1309
1310 r = mac_selinux_unit_access_check(u, message, "status", error);
1311 if (r < 0)
1312 return r;
1313
1314 pids = set_new(NULL);
1315 if (!pids)
1316 return -ENOMEM;
1317
1318 r = sd_bus_message_new_method_return(message, &reply);
1319 if (r < 0)
1320 return r;
1321
1322 r = sd_bus_message_open_container(reply, 'a', "(sus)");
1323 if (r < 0)
1324 return r;
1325
1326 if (u->cgroup_path) {
1327 r = append_cgroup(reply, u->cgroup_path, pids);
1328 if (r < 0)
1329 return r;
1330 }
1331
1332 /* The main and control pids might live outside of the cgroup, hence fetch them separately */
1333 pid = unit_main_pid(u);
1334 if (pid > 0) {
1335 r = append_process(reply, NULL, pid, pids);
1336 if (r < 0)
1337 return r;
1338 }
1339
1340 pid = unit_control_pid(u);
1341 if (pid > 0) {
1342 r = append_process(reply, NULL, pid, pids);
1343 if (r < 0)
1344 return r;
1345 }
1346
1347 r = sd_bus_message_close_container(reply);
1348 if (r < 0)
1349 return r;
1350
1351 return sd_bus_send(NULL, reply, NULL);
1352 }
1353
1354 static int property_get_ip_counter(
1355 sd_bus *bus,
1356 const char *path,
1357 const char *interface,
1358 const char *property,
1359 sd_bus_message *reply,
1360 void *userdata,
1361 sd_bus_error *error) {
1362
1363 static const char *const table[_CGROUP_IP_ACCOUNTING_METRIC_MAX] = {
1364 [CGROUP_IP_INGRESS_BYTES] = "IPIngressBytes",
1365 [CGROUP_IP_EGRESS_BYTES] = "IPEgressBytes",
1366 [CGROUP_IP_INGRESS_PACKETS] = "IPIngressPackets",
1367 [CGROUP_IP_EGRESS_PACKETS] = "IPEgressPackets",
1368 };
1369
1370 uint64_t value = UINT64_MAX;
1371 Unit *u = userdata;
1372 ssize_t metric;
1373
1374 assert(bus);
1375 assert(reply);
1376 assert(property);
1377 assert(u);
1378
1379 assert_se((metric = string_table_lookup(table, ELEMENTSOF(table), property)) >= 0);
1380 (void) unit_get_ip_accounting(u, metric, &value);
1381 return sd_bus_message_append(reply, "t", value);
1382 }
1383
1384 static int property_get_io_counter(
1385 sd_bus *bus,
1386 const char *path,
1387 const char *interface,
1388 const char *property,
1389 sd_bus_message *reply,
1390 void *userdata,
1391 sd_bus_error *error) {
1392
1393 static const char *const table[_CGROUP_IO_ACCOUNTING_METRIC_MAX] = {
1394 [CGROUP_IO_READ_BYTES] = "IOReadBytes",
1395 [CGROUP_IO_WRITE_BYTES] = "IOWriteBytes",
1396 [CGROUP_IO_READ_OPERATIONS] = "IOReadOperations",
1397 [CGROUP_IO_WRITE_OPERATIONS] = "IOWriteOperations",
1398 };
1399
1400 uint64_t value = UINT64_MAX;
1401 Unit *u = userdata;
1402 ssize_t metric;
1403
1404 assert(bus);
1405 assert(reply);
1406 assert(property);
1407 assert(u);
1408
1409 assert_se((metric = string_table_lookup(table, ELEMENTSOF(table), property)) >= 0);
1410 (void) unit_get_io_accounting(u, metric, false, &value);
1411 return sd_bus_message_append(reply, "t", value);
1412 }
1413
1414 int bus_unit_method_attach_processes(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1415
1416 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
1417 _cleanup_set_free_ Set *pids = NULL;
1418 Unit *u = userdata;
1419 const char *path;
1420 int r;
1421
1422 assert(message);
1423
1424 /* This migrates the processes with the specified PIDs into the cgroup of this unit, optionally below a
1425 * specified cgroup path. Obviously this only works for units that actually maintain a cgroup
1426 * representation. If a process is already in the cgroup no operation is executed – in this case the specified
1427 * subcgroup path has no effect! */
1428
1429 r = mac_selinux_unit_access_check(u, message, "start", error);
1430 if (r < 0)
1431 return r;
1432
1433 r = sd_bus_message_read(message, "s", &path);
1434 if (r < 0)
1435 return r;
1436
1437 path = empty_to_null(path);
1438 if (path) {
1439 if (!path_is_absolute(path))
1440 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Control group path is not absolute: %s", path);
1441
1442 if (!path_is_normalized(path))
1443 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Control group path is not normalized: %s", path);
1444 }
1445
1446 if (!unit_cgroup_delegate(u))
1447 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Process migration not available on non-delegated units.");
1448
1449 if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(u)))
1450 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Unit is not active, refusing.");
1451
1452 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds);
1453 if (r < 0)
1454 return r;
1455
1456 r = sd_bus_message_enter_container(message, 'a', "u");
1457 if (r < 0)
1458 return r;
1459 for (;;) {
1460 uid_t process_uid, sender_uid;
1461 uint32_t upid;
1462 pid_t pid;
1463
1464 r = sd_bus_message_read(message, "u", &upid);
1465 if (r < 0)
1466 return r;
1467 if (r == 0)
1468 break;
1469
1470 if (upid == 0) {
1471 r = sd_bus_creds_get_pid(creds, &pid);
1472 if (r < 0)
1473 return r;
1474 } else
1475 pid = (uid_t) upid;
1476
1477 /* Filter out duplicates */
1478 if (set_contains(pids, PID_TO_PTR(pid)))
1479 continue;
1480
1481 /* Check if this process is suitable for attaching to this unit */
1482 r = unit_pid_attachable(u, pid, error);
1483 if (r < 0)
1484 return r;
1485
1486 /* Let's query the sender's UID, so that we can make our security decisions */
1487 r = sd_bus_creds_get_euid(creds, &sender_uid);
1488 if (r < 0)
1489 return r;
1490
1491 /* Let's validate security: if the sender is root, then all is OK. If the sender is any other unit,
1492 * then the process' UID and the target unit's UID have to match the sender's UID */
1493 if (sender_uid != 0 && sender_uid != getuid()) {
1494 r = get_process_uid(pid, &process_uid);
1495 if (r < 0)
1496 return sd_bus_error_set_errnof(error, r, "Failed to retrieve process UID: %m");
1497
1498 if (process_uid != sender_uid)
1499 return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Process " PID_FMT " not owned by client's UID. Refusing.", pid);
1500 if (process_uid != u->ref_uid)
1501 return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Process " PID_FMT " not owned by target unit's UID. Refusing.", pid);
1502 }
1503
1504 if (!pids) {
1505 pids = set_new(NULL);
1506 if (!pids)
1507 return -ENOMEM;
1508 }
1509
1510 r = set_put(pids, PID_TO_PTR(pid));
1511 if (r < 0)
1512 return r;
1513 }
1514
1515 r = sd_bus_message_exit_container(message);
1516 if (r < 0)
1517 return r;
1518
1519 r = unit_attach_pids_to_cgroup(u, pids, path);
1520 if (r < 0)
1521 return sd_bus_error_set_errnof(error, r, "Failed to attach processes to control group: %m");
1522
1523 return sd_bus_reply_method_return(message, NULL);
1524 }
1525
1526 const sd_bus_vtable bus_unit_cgroup_vtable[] = {
1527 SD_BUS_VTABLE_START(0),
1528 SD_BUS_PROPERTY("Slice", "s", property_get_slice, 0, 0),
1529 SD_BUS_PROPERTY("ControlGroup", "s", property_get_cgroup, 0, 0),
1530 SD_BUS_PROPERTY("MemoryCurrent", "t", property_get_current_memory, 0, 0),
1531 SD_BUS_PROPERTY("CPUUsageNSec", "t", property_get_cpu_usage, 0, 0),
1532 SD_BUS_PROPERTY("EffectiveCPUs", "ay", property_get_cpuset_cpus, 0, 0),
1533 SD_BUS_PROPERTY("EffectiveMemoryNodes", "ay", property_get_cpuset_mems, 0, 0),
1534 SD_BUS_PROPERTY("TasksCurrent", "t", property_get_current_tasks, 0, 0),
1535 SD_BUS_PROPERTY("IPIngressBytes", "t", property_get_ip_counter, 0, 0),
1536 SD_BUS_PROPERTY("IPIngressPackets", "t", property_get_ip_counter, 0, 0),
1537 SD_BUS_PROPERTY("IPEgressBytes", "t", property_get_ip_counter, 0, 0),
1538 SD_BUS_PROPERTY("IPEgressPackets", "t", property_get_ip_counter, 0, 0),
1539 SD_BUS_PROPERTY("IOReadBytes", "t", property_get_io_counter, 0, 0),
1540 SD_BUS_PROPERTY("IOReadOperations", "t", property_get_io_counter, 0, 0),
1541 SD_BUS_PROPERTY("IOWriteBytes", "t", property_get_io_counter, 0, 0),
1542 SD_BUS_PROPERTY("IOWriteOperations", "t", property_get_io_counter, 0, 0),
1543
1544 SD_BUS_METHOD_WITH_NAMES("GetProcesses",
1545 NULL,,
1546 "a(sus)",
1547 SD_BUS_PARAM(processes),
1548 bus_unit_method_get_processes,
1549 SD_BUS_VTABLE_UNPRIVILEGED),
1550
1551 SD_BUS_METHOD_WITH_NAMES("AttachProcesses",
1552 "sau",
1553 SD_BUS_PARAM(subcgroup)
1554 SD_BUS_PARAM(pids),
1555 NULL,,
1556 bus_unit_method_attach_processes,
1557 SD_BUS_VTABLE_UNPRIVILEGED),
1558
1559 SD_BUS_VTABLE_END
1560 };
1561
1562 static int send_new_signal(sd_bus *bus, void *userdata) {
1563 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
1564 _cleanup_free_ char *p = NULL;
1565 Unit *u = userdata;
1566 int r;
1567
1568 assert(bus);
1569 assert(u);
1570
1571 p = unit_dbus_path(u);
1572 if (!p)
1573 return -ENOMEM;
1574
1575 r = sd_bus_message_new_signal(
1576 bus,
1577 &m,
1578 "/org/freedesktop/systemd1",
1579 "org.freedesktop.systemd1.Manager",
1580 "UnitNew");
1581 if (r < 0)
1582 return r;
1583
1584 r = sd_bus_message_append(m, "so", u->id, p);
1585 if (r < 0)
1586 return r;
1587
1588 return sd_bus_send(bus, m, NULL);
1589 }
1590
1591 static int send_changed_signal(sd_bus *bus, void *userdata) {
1592 _cleanup_free_ char *p = NULL;
1593 Unit *u = userdata;
1594 int r;
1595
1596 assert(bus);
1597 assert(u);
1598
1599 p = unit_dbus_path(u);
1600 if (!p)
1601 return -ENOMEM;
1602
1603 /* Send a properties changed signal. First for the specific
1604 * type, then for the generic unit. The clients may rely on
1605 * this order to get atomic behavior if needed. */
1606
1607 r = sd_bus_emit_properties_changed_strv(
1608 bus, p,
1609 unit_dbus_interface_from_type(u->type),
1610 NULL);
1611 if (r < 0)
1612 return r;
1613
1614 return sd_bus_emit_properties_changed_strv(
1615 bus, p,
1616 "org.freedesktop.systemd1.Unit",
1617 NULL);
1618 }
1619
1620 void bus_unit_send_change_signal(Unit *u) {
1621 int r;
1622 assert(u);
1623
1624 if (u->in_dbus_queue) {
1625 LIST_REMOVE(dbus_queue, u->manager->dbus_unit_queue, u);
1626 u->in_dbus_queue = false;
1627 }
1628
1629 if (!u->id)
1630 return;
1631
1632 r = bus_foreach_bus(u->manager, u->bus_track, u->sent_dbus_new_signal ? send_changed_signal : send_new_signal, u);
1633 if (r < 0)
1634 log_unit_debug_errno(u, r, "Failed to send unit change signal for %s: %m", u->id);
1635
1636 u->sent_dbus_new_signal = true;
1637 }
1638
1639 void bus_unit_send_pending_change_signal(Unit *u, bool including_new) {
1640
1641 /* Sends out any pending change signals, but only if they really are pending. This call is used when we are
1642 * about to change state in order to force out a PropertiesChanged signal beforehand if there was one pending
1643 * so that clients can follow the full state transition */
1644
1645 if (!u->in_dbus_queue) /* If not enqueued, don't bother */
1646 return;
1647
1648 if (!u->sent_dbus_new_signal && !including_new) /* If the unit was never announced, don't bother, it's fine if
1649 * the unit appears in the new state right-away (except if the
1650 * caller explicitly asked us to send it anyway) */
1651 return;
1652
1653 if (MANAGER_IS_RELOADING(u->manager)) /* Don't generate unnecessary PropertiesChanged signals for the same unit
1654 * when we are reloading. */
1655 return;
1656
1657 bus_unit_send_change_signal(u);
1658 }
1659
1660 int bus_unit_send_pending_freezer_message(Unit *u) {
1661 int r;
1662
1663 assert(u);
1664
1665 if (!u->pending_freezer_message)
1666 return 0;
1667
1668 r = sd_bus_send(NULL, u->pending_freezer_message, NULL);
1669 if (r < 0)
1670 log_warning_errno(r, "Failed to send queued message, ignoring: %m");
1671
1672 u->pending_freezer_message = sd_bus_message_unref(u->pending_freezer_message);
1673
1674 return 0;
1675 }
1676
1677 static int send_removed_signal(sd_bus *bus, void *userdata) {
1678 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
1679 _cleanup_free_ char *p = NULL;
1680 Unit *u = userdata;
1681 int r;
1682
1683 assert(bus);
1684 assert(u);
1685
1686 p = unit_dbus_path(u);
1687 if (!p)
1688 return -ENOMEM;
1689
1690 r = sd_bus_message_new_signal(
1691 bus,
1692 &m,
1693 "/org/freedesktop/systemd1",
1694 "org.freedesktop.systemd1.Manager",
1695 "UnitRemoved");
1696 if (r < 0)
1697 return r;
1698
1699 r = sd_bus_message_append(m, "so", u->id, p);
1700 if (r < 0)
1701 return r;
1702
1703 return sd_bus_send(bus, m, NULL);
1704 }
1705
1706 void bus_unit_send_removed_signal(Unit *u) {
1707 int r;
1708 assert(u);
1709
1710 if (!u->sent_dbus_new_signal || u->in_dbus_queue)
1711 bus_unit_send_change_signal(u);
1712
1713 if (!u->id)
1714 return;
1715
1716 r = bus_foreach_bus(u->manager, u->bus_track, send_removed_signal, u);
1717 if (r < 0)
1718 log_unit_debug_errno(u, r, "Failed to send unit remove signal for %s: %m", u->id);
1719 }
1720
1721 int bus_unit_queue_job_one(
1722 sd_bus_message *message,
1723 Unit *u,
1724 JobType type,
1725 JobMode mode,
1726 BusUnitQueueFlags flags,
1727 sd_bus_message *reply,
1728 sd_bus_error *error) {
1729
1730 _cleanup_set_free_ Set *affected = NULL;
1731 _cleanup_free_ char *job_path = NULL, *unit_path = NULL;
1732 Job *j, *a;
1733 int r;
1734
1735 if (FLAGS_SET(flags, BUS_UNIT_QUEUE_VERBOSE_REPLY)) {
1736 affected = set_new(NULL);
1737 if (!affected)
1738 return -ENOMEM;
1739 }
1740
1741 r = manager_add_job(u->manager, type, u, mode, affected, error, &j);
1742 if (r < 0)
1743 return r;
1744
1745 r = bus_job_track_sender(j, message);
1746 if (r < 0)
1747 return r;
1748
1749 /* Before we send the method reply, force out the announcement JobNew for this job */
1750 bus_job_send_pending_change_signal(j, true);
1751
1752 job_path = job_dbus_path(j);
1753 if (!job_path)
1754 return -ENOMEM;
1755
1756 /* The classic response is just a job object path */
1757 if (!FLAGS_SET(flags, BUS_UNIT_QUEUE_VERBOSE_REPLY))
1758 return sd_bus_message_append(reply, "o", job_path);
1759
1760 /* In verbose mode respond with the anchor job plus everything that has been affected */
1761
1762 unit_path = unit_dbus_path(j->unit);
1763 if (!unit_path)
1764 return -ENOMEM;
1765
1766 r = sd_bus_message_append(reply, "uosos",
1767 j->id, job_path,
1768 j->unit->id, unit_path,
1769 job_type_to_string(j->type));
1770 if (r < 0)
1771 return r;
1772
1773 r = sd_bus_message_open_container(reply, 'a', "(uosos)");
1774 if (r < 0)
1775 return r;
1776
1777 SET_FOREACH(a, affected) {
1778 if (a->id == j->id)
1779 continue;
1780
1781 /* Free paths from previous iteration */
1782 job_path = mfree(job_path);
1783 unit_path = mfree(unit_path);
1784
1785 job_path = job_dbus_path(a);
1786 if (!job_path)
1787 return -ENOMEM;
1788
1789 unit_path = unit_dbus_path(a->unit);
1790 if (!unit_path)
1791 return -ENOMEM;
1792
1793 r = sd_bus_message_append(reply, "(uosos)",
1794 a->id, job_path,
1795 a->unit->id, unit_path,
1796 job_type_to_string(a->type));
1797 if (r < 0)
1798 return r;
1799 }
1800
1801 return sd_bus_message_close_container(reply);
1802 }
1803
1804 int bus_unit_queue_job(
1805 sd_bus_message *message,
1806 Unit *u,
1807 JobType type,
1808 JobMode mode,
1809 BusUnitQueueFlags flags,
1810 sd_bus_error *error) {
1811
1812 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1813 int r;
1814
1815 assert(message);
1816 assert(u);
1817 assert(type >= 0 && type < _JOB_TYPE_MAX);
1818 assert(mode >= 0 && mode < _JOB_MODE_MAX);
1819
1820 r = mac_selinux_unit_access_check(
1821 u, message,
1822 job_type_to_access_method(type),
1823 error);
1824 if (r < 0)
1825 return r;
1826
1827 if (FLAGS_SET(flags, BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE) && unit_can_reload(u)) {
1828 if (type == JOB_RESTART)
1829 type = JOB_RELOAD_OR_START;
1830 else if (type == JOB_TRY_RESTART)
1831 type = JOB_TRY_RELOAD;
1832 }
1833
1834 if (type == JOB_STOP &&
1835 IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_ERROR, UNIT_BAD_SETTING) &&
1836 unit_active_state(u) == UNIT_INACTIVE)
1837 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", u->id);
1838
1839 if ((type == JOB_START && u->refuse_manual_start) ||
1840 (type == JOB_STOP && u->refuse_manual_stop) ||
1841 (IN_SET(type, JOB_RESTART, JOB_TRY_RESTART) && (u->refuse_manual_start || u->refuse_manual_stop)) ||
1842 (type == JOB_RELOAD_OR_START && job_type_collapse(type, u) == JOB_START && u->refuse_manual_start))
1843 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);
1844
1845 r = sd_bus_message_new_method_return(message, &reply);
1846 if (r < 0)
1847 return r;
1848
1849 r = bus_unit_queue_job_one(message, u, type, mode, flags, reply, error);
1850 if (r < 0)
1851 return r;
1852
1853 return sd_bus_send(NULL, reply, NULL);
1854 }
1855
1856 static int bus_unit_set_live_property(
1857 Unit *u,
1858 const char *name,
1859 sd_bus_message *message,
1860 UnitWriteFlags flags,
1861 sd_bus_error *error) {
1862
1863 int r;
1864
1865 assert(u);
1866 assert(name);
1867 assert(message);
1868
1869 /* Handles setting properties both "live" (i.e. at any time during runtime), and during creation (for
1870 * transient units that are being created). */
1871
1872 if (streq(name, "Description")) {
1873 const char *d;
1874
1875 r = sd_bus_message_read(message, "s", &d);
1876 if (r < 0)
1877 return r;
1878
1879 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1880 r = unit_set_description(u, d);
1881 if (r < 0)
1882 return r;
1883
1884 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "Description=%s", d);
1885 }
1886
1887 return 1;
1888 }
1889
1890 /* A setting that only applies to active units. We don't actually write this to /run, this state is
1891 * managed internally. "+foo" sets flag foo, "-foo" unsets flag foo, just "foo" resets flags to
1892 * foo. The last type cannot be mixed with "+" or "-". */
1893
1894 if (streq(name, "Markers")) {
1895 unsigned settings = 0, mask = 0;
1896 bool some_plus_minus = false, some_absolute = false;
1897
1898 r = sd_bus_message_enter_container(message, 'a', "s");
1899 if (r < 0)
1900 return r;
1901
1902 for (;;) {
1903 const char *word;
1904 bool b;
1905
1906 r = sd_bus_message_read(message, "s", &word);
1907 if (r < 0)
1908 return r;
1909 if (r == 0)
1910 break;
1911
1912 if (IN_SET(word[0], '+', '-')) {
1913 b = word[0] == '+';
1914 word++;
1915 some_plus_minus = true;
1916 } else {
1917 b = true;
1918 some_absolute = true;
1919 }
1920
1921 UnitMarker m = unit_marker_from_string(word);
1922 if (m < 0)
1923 return sd_bus_error_setf(error, BUS_ERROR_BAD_UNIT_SETTING,
1924 "Unknown marker \"%s\".", word);
1925
1926 SET_FLAG(settings, 1u << m, b);
1927 SET_FLAG(mask, 1u << m, true);
1928 }
1929
1930 r = sd_bus_message_exit_container(message);
1931 if (r < 0)
1932 return r;
1933
1934 if (some_plus_minus && some_absolute)
1935 return sd_bus_error_set(error, BUS_ERROR_BAD_UNIT_SETTING, "Bad marker syntax.");
1936
1937 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1938 if (some_absolute)
1939 u->markers = settings;
1940 else
1941 u->markers = settings | (u->markers & ~mask);
1942 }
1943
1944 return 1;
1945 }
1946
1947 return 0;
1948 }
1949
1950 static int bus_set_transient_emergency_action(
1951 Unit *u,
1952 const char *name,
1953 EmergencyAction *p,
1954 sd_bus_message *message,
1955 UnitWriteFlags flags,
1956 sd_bus_error *error) {
1957
1958 const char *s;
1959 EmergencyAction v;
1960 int r;
1961 bool system;
1962
1963 assert(p);
1964
1965 r = sd_bus_message_read(message, "s", &s);
1966 if (r < 0)
1967 return r;
1968
1969 system = MANAGER_IS_SYSTEM(u->manager);
1970 r = parse_emergency_action(s, system, &v);
1971 if (r < 0)
1972 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
1973 r == -EOPNOTSUPP ? "%s setting invalid for manager type: %s"
1974 : "Invalid %s setting: %s",
1975 name, s);
1976
1977 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1978 *p = v;
1979 unit_write_settingf(u, flags, name,
1980 "%s=%s", name, s);
1981 }
1982
1983 return 1;
1984 }
1985
1986 static int bus_set_transient_exit_status(
1987 Unit *u,
1988 const char *name,
1989 int *p,
1990 sd_bus_message *message,
1991 UnitWriteFlags flags,
1992 sd_bus_error *error) {
1993
1994 int32_t k;
1995 int r;
1996
1997 assert(p);
1998
1999 r = sd_bus_message_read(message, "i", &k);
2000 if (r < 0)
2001 return r;
2002
2003 if (k > 255)
2004 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Exit status must be in range 0…255 or negative.");
2005
2006 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2007 *p = k < 0 ? -1 : k;
2008
2009 if (k < 0)
2010 unit_write_settingf(u, flags, name, "%s=", name);
2011 else
2012 unit_write_settingf(u, flags, name, "%s=%i", name, k);
2013 }
2014
2015 return 1;
2016 }
2017
2018 static BUS_DEFINE_SET_TRANSIENT_PARSE(collect_mode, CollectMode, collect_mode_from_string);
2019 static BUS_DEFINE_SET_TRANSIENT_PARSE(job_mode, JobMode, job_mode_from_string);
2020
2021 static int bus_set_transient_conditions(
2022 Unit *u,
2023 const char *name,
2024 Condition **list,
2025 bool is_condition,
2026 sd_bus_message *message,
2027 UnitWriteFlags flags,
2028 sd_bus_error *error) {
2029
2030 const char *type_name, *param;
2031 int trigger, negate, r;
2032 bool empty = true;
2033
2034 assert(list);
2035
2036 r = sd_bus_message_enter_container(message, 'a', "(sbbs)");
2037 if (r < 0)
2038 return r;
2039
2040 while ((r = sd_bus_message_read(message, "(sbbs)", &type_name, &trigger, &negate, &param)) > 0) {
2041 ConditionType t;
2042
2043 t = is_condition ? condition_type_from_string(type_name) : assert_type_from_string(type_name);
2044 if (t < 0)
2045 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid condition type: %s", type_name);
2046
2047 if (isempty(param))
2048 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Condition parameter in %s is empty", type_name);
2049
2050 if (condition_takes_path(t) && !path_is_absolute(param))
2051 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path in condition %s is not absolute: %s", type_name, param);
2052
2053 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2054 Condition *c;
2055
2056 c = condition_new(t, param, trigger, negate);
2057 if (!c)
2058 return -ENOMEM;
2059
2060 LIST_PREPEND(conditions, *list, c);
2061
2062 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name,
2063 "%s=%s%s%s", type_name,
2064 trigger ? "|" : "", negate ? "!" : "", param);
2065 }
2066
2067 empty = false;
2068 }
2069 if (r < 0)
2070 return r;
2071
2072 r = sd_bus_message_exit_container(message);
2073 if (r < 0)
2074 return r;
2075
2076 if (!UNIT_WRITE_FLAGS_NOOP(flags) && empty) {
2077 *list = condition_free_list(*list);
2078 unit_write_settingf(u, flags, name, "%sNull=", is_condition ? "Condition" : "Assert");
2079 }
2080
2081 return 1;
2082 }
2083
2084 static int bus_unit_set_transient_property(
2085 Unit *u,
2086 const char *name,
2087 sd_bus_message *message,
2088 UnitWriteFlags flags,
2089 sd_bus_error *error) {
2090
2091 UnitDependency d;
2092 int r;
2093
2094 assert(u);
2095 assert(name);
2096 assert(message);
2097
2098 /* Handles settings when transient units are created. This settings cannot be altered anymore after
2099 * the unit has been created. */
2100
2101 if (streq(name, "SourcePath"))
2102 return bus_set_transient_path(u, name, &u->source_path, message, flags, error);
2103
2104 if (streq(name, "StopWhenUnneeded"))
2105 return bus_set_transient_bool(u, name, &u->stop_when_unneeded, message, flags, error);
2106
2107 if (streq(name, "RefuseManualStart"))
2108 return bus_set_transient_bool(u, name, &u->refuse_manual_start, message, flags, error);
2109
2110 if (streq(name, "RefuseManualStop"))
2111 return bus_set_transient_bool(u, name, &u->refuse_manual_stop, message, flags, error);
2112
2113 if (streq(name, "AllowIsolate"))
2114 return bus_set_transient_bool(u, name, &u->allow_isolate, message, flags, error);
2115
2116 if (streq(name, "DefaultDependencies"))
2117 return bus_set_transient_bool(u, name, &u->default_dependencies, message, flags, error);
2118
2119 if (streq(name, "OnFailureJobMode"))
2120 return bus_set_transient_job_mode(u, name, &u->on_failure_job_mode, message, flags, error);
2121
2122 if (streq(name, "IgnoreOnIsolate"))
2123 return bus_set_transient_bool(u, name, &u->ignore_on_isolate, message, flags, error);
2124
2125 if (streq(name, "JobTimeoutUSec")) {
2126 r = bus_set_transient_usec_fix_0(u, name, &u->job_timeout, message, flags, error);
2127 if (r >= 0 && !UNIT_WRITE_FLAGS_NOOP(flags) && !u->job_running_timeout_set)
2128 u->job_running_timeout = u->job_timeout;
2129 }
2130
2131 if (streq(name, "JobRunningTimeoutUSec")) {
2132 r = bus_set_transient_usec_fix_0(u, name, &u->job_running_timeout, message, flags, error);
2133 if (r >= 0 && !UNIT_WRITE_FLAGS_NOOP(flags))
2134 u->job_running_timeout_set = true;
2135
2136 return r;
2137 }
2138
2139 if (streq(name, "JobTimeoutAction"))
2140 return bus_set_transient_emergency_action(u, name, &u->job_timeout_action, message, flags, error);
2141
2142 if (streq(name, "JobTimeoutRebootArgument"))
2143 return bus_set_transient_string(u, name, &u->job_timeout_reboot_arg, message, flags, error);
2144
2145 if (streq(name, "StartLimitIntervalUSec"))
2146 return bus_set_transient_usec(u, name, &u->start_ratelimit.interval, message, flags, error);
2147
2148 if (streq(name, "StartLimitBurst"))
2149 return bus_set_transient_unsigned(u, name, &u->start_ratelimit.burst, message, flags, error);
2150
2151 if (streq(name, "StartLimitAction"))
2152 return bus_set_transient_emergency_action(u, name, &u->start_limit_action, message, flags, error);
2153
2154 if (streq(name, "FailureAction"))
2155 return bus_set_transient_emergency_action(u, name, &u->failure_action, message, flags, error);
2156
2157 if (streq(name, "SuccessAction"))
2158 return bus_set_transient_emergency_action(u, name, &u->success_action, message, flags, error);
2159
2160 if (streq(name, "FailureActionExitStatus"))
2161 return bus_set_transient_exit_status(u, name, &u->failure_action_exit_status, message, flags, error);
2162
2163 if (streq(name, "SuccessActionExitStatus"))
2164 return bus_set_transient_exit_status(u, name, &u->success_action_exit_status, message, flags, error);
2165
2166 if (streq(name, "RebootArgument"))
2167 return bus_set_transient_string(u, name, &u->reboot_arg, message, flags, error);
2168
2169 if (streq(name, "CollectMode"))
2170 return bus_set_transient_collect_mode(u, name, &u->collect_mode, message, flags, error);
2171
2172 if (streq(name, "Conditions"))
2173 return bus_set_transient_conditions(u, name, &u->conditions, true, message, flags, error);
2174
2175 if (streq(name, "Asserts"))
2176 return bus_set_transient_conditions(u, name, &u->asserts, false, message, flags, error);
2177
2178 if (streq(name, "Documentation")) {
2179 _cleanup_strv_free_ char **l = NULL;
2180 char **p;
2181
2182 r = sd_bus_message_read_strv(message, &l);
2183 if (r < 0)
2184 return r;
2185
2186 STRV_FOREACH(p, l) {
2187 if (!documentation_url_is_valid(*p))
2188 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid URL in %s: %s", name, *p);
2189 }
2190
2191 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2192 if (strv_isempty(l)) {
2193 u->documentation = strv_free(u->documentation);
2194 unit_write_settingf(u, flags, name, "%s=", name);
2195 } else {
2196 strv_extend_strv(&u->documentation, l, false);
2197
2198 STRV_FOREACH(p, l)
2199 unit_write_settingf(u, flags, name, "%s=%s", name, *p);
2200 }
2201 }
2202
2203 return 1;
2204
2205 } else if (streq(name, "Slice")) {
2206 Unit *slice;
2207 const char *s;
2208
2209 if (!UNIT_HAS_CGROUP_CONTEXT(u))
2210 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "The slice property is only available for units with control groups.");
2211 if (u->type == UNIT_SLICE)
2212 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Slice may not be set for slice units.");
2213 if (unit_has_name(u, SPECIAL_INIT_SCOPE))
2214 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot set slice for init.scope");
2215
2216 r = sd_bus_message_read(message, "s", &s);
2217 if (r < 0)
2218 return r;
2219
2220 if (!unit_name_is_valid(s, UNIT_NAME_PLAIN))
2221 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit name '%s'", s);
2222
2223 /* Note that we do not dispatch the load queue here yet, as we don't want our own transient unit to be
2224 * loaded while we are still setting it up. Or in other words, we use manager_load_unit_prepare()
2225 * instead of manager_load_unit() on purpose, here. */
2226 r = manager_load_unit_prepare(u->manager, s, NULL, error, &slice);
2227 if (r < 0)
2228 return r;
2229
2230 if (slice->type != UNIT_SLICE)
2231 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit name '%s' is not a slice", s);
2232
2233 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2234 r = unit_set_slice(u, slice);
2235 if (r < 0)
2236 return r;
2237
2238 unit_write_settingf(u, flags|UNIT_PRIVATE, name, "Slice=%s", s);
2239 }
2240
2241 return 1;
2242
2243 } else if (streq(name, "RequiresMountsFor")) {
2244 _cleanup_strv_free_ char **l = NULL;
2245 char **p;
2246
2247 r = sd_bus_message_read_strv(message, &l);
2248 if (r < 0)
2249 return r;
2250
2251 STRV_FOREACH(p, l) {
2252 path_simplify(*p, true);
2253
2254 if (!path_is_absolute(*p))
2255 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path specified in %s is not absolute: %s", name, *p);
2256
2257 if (!path_is_valid(*p))
2258 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path specified in %s has invalid length: %s", name, *p);
2259
2260 if (!path_is_normalized(*p))
2261 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path specified in %s is not normalized: %s", name, *p);
2262
2263 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2264 r = unit_require_mounts_for(u, *p, UNIT_DEPENDENCY_FILE);
2265 if (r < 0)
2266 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Failed to add required mount \"%s\": %m", *p);
2267
2268 unit_write_settingf(u, flags, name, "%s=%s", name, *p);
2269 }
2270 }
2271
2272 return 1;
2273 }
2274
2275 if (streq(name, "RequiresOverridable"))
2276 d = UNIT_REQUIRES; /* redirect for obsolete unit dependency type */
2277 else if (streq(name, "RequisiteOverridable"))
2278 d = UNIT_REQUISITE; /* same here */
2279 else
2280 d = unit_dependency_from_string(name);
2281
2282 if (d >= 0) {
2283 const char *other;
2284
2285 if (!IN_SET(d,
2286 UNIT_REQUIRES,
2287 UNIT_REQUISITE,
2288 UNIT_WANTS,
2289 UNIT_BINDS_TO,
2290 UNIT_PART_OF,
2291 UNIT_CONFLICTS,
2292 UNIT_BEFORE,
2293 UNIT_AFTER,
2294 UNIT_ON_FAILURE,
2295 UNIT_PROPAGATES_RELOAD_TO,
2296 UNIT_RELOAD_PROPAGATED_FROM,
2297 UNIT_JOINS_NAMESPACE_OF))
2298 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Dependency type %s may not be created transiently.", unit_dependency_to_string(d));
2299
2300 r = sd_bus_message_enter_container(message, 'a', "s");
2301 if (r < 0)
2302 return r;
2303
2304 while ((r = sd_bus_message_read(message, "s", &other)) > 0) {
2305 if (!unit_name_is_valid(other, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE))
2306 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit name %s", other);
2307
2308 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
2309 _cleanup_free_ char *label = NULL;
2310
2311 r = unit_add_dependency_by_name(u, d, other, true, UNIT_DEPENDENCY_FILE);
2312 if (r < 0)
2313 return r;
2314
2315 label = strjoin(name, "-", other);
2316 if (!label)
2317 return -ENOMEM;
2318
2319 unit_write_settingf(u, flags, label, "%s=%s", unit_dependency_to_string(d), other);
2320 }
2321
2322 }
2323 if (r < 0)
2324 return r;
2325
2326 r = sd_bus_message_exit_container(message);
2327 if (r < 0)
2328 return r;
2329
2330 return 1;
2331
2332 } else if (streq(name, "AddRef")) {
2333
2334 int b;
2335
2336 /* Why is this called "AddRef" rather than just "Ref", or "Reference"? There's already a "Ref()" method
2337 * on the Unit interface, and it's probably not a good idea to expose a property and a method on the
2338 * same interface (well, strictly speaking AddRef isn't exposed as full property, we just read it for
2339 * transient units, but still). And "References" and "ReferencedBy" is already used as unit reference
2340 * dependency type, hence let's not confuse things with that.
2341 *
2342 * Note that we don't actually add the reference to the bus track. We do that only after the setup of
2343 * the transient unit is complete, so that setting this property multiple times in the same transient
2344 * unit creation call doesn't count as individual references. */
2345
2346 r = sd_bus_message_read(message, "b", &b);
2347 if (r < 0)
2348 return r;
2349
2350 if (!UNIT_WRITE_FLAGS_NOOP(flags))
2351 u->bus_track_add = b;
2352
2353 return 1;
2354 }
2355
2356 return 0;
2357 }
2358
2359 int bus_unit_set_properties(
2360 Unit *u,
2361 sd_bus_message *message,
2362 UnitWriteFlags flags,
2363 bool commit,
2364 sd_bus_error *error) {
2365
2366 bool for_real = false;
2367 unsigned n = 0;
2368 int r;
2369
2370 assert(u);
2371 assert(message);
2372
2373 /* We iterate through the array twice. First run we just check
2374 * if all passed data is valid, second run actually applies
2375 * it. This is to implement transaction-like behaviour without
2376 * actually providing full transactions. */
2377
2378 r = sd_bus_message_enter_container(message, 'a', "(sv)");
2379 if (r < 0)
2380 return r;
2381
2382 for (;;) {
2383 const char *name;
2384 UnitWriteFlags f;
2385
2386 r = sd_bus_message_enter_container(message, 'r', "sv");
2387 if (r < 0)
2388 return r;
2389 if (r == 0) {
2390 if (for_real || UNIT_WRITE_FLAGS_NOOP(flags))
2391 break;
2392
2393 /* Reached EOF. Let's try again, and this time for realz... */
2394 r = sd_bus_message_rewind(message, false);
2395 if (r < 0)
2396 return r;
2397
2398 for_real = true;
2399 continue;
2400 }
2401
2402 r = sd_bus_message_read(message, "s", &name);
2403 if (r < 0)
2404 return r;
2405
2406 if (!UNIT_VTABLE(u)->bus_set_property)
2407 return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY,
2408 "Objects of this type do not support setting properties.");
2409
2410 r = sd_bus_message_enter_container(message, 'v', NULL);
2411 if (r < 0)
2412 return r;
2413
2414 /* If not for real, then mask out the two target flags */
2415 f = for_real ? flags : (flags & ~(UNIT_RUNTIME|UNIT_PERSISTENT));
2416
2417 r = UNIT_VTABLE(u)->bus_set_property(u, name, message, f, error);
2418 if (r == 0 && u->transient && u->load_state == UNIT_STUB)
2419 r = bus_unit_set_transient_property(u, name, message, f, error);
2420 if (r == 0)
2421 r = bus_unit_set_live_property(u, name, message, f, error);
2422 if (r < 0)
2423 return r;
2424
2425 if (r == 0)
2426 return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY,
2427 "Cannot set property %s, or unknown property.", name);
2428
2429 r = sd_bus_message_exit_container(message);
2430 if (r < 0)
2431 return r;
2432
2433 r = sd_bus_message_exit_container(message);
2434 if (r < 0)
2435 return r;
2436
2437 n += for_real;
2438 }
2439
2440 r = sd_bus_message_exit_container(message);
2441 if (r < 0)
2442 return r;
2443
2444 if (commit && n > 0 && UNIT_VTABLE(u)->bus_commit_properties)
2445 UNIT_VTABLE(u)->bus_commit_properties(u);
2446
2447 return n;
2448 }
2449
2450 int bus_unit_validate_load_state(Unit *u, sd_bus_error *error) {
2451 assert(u);
2452
2453 /* Generates a pretty error if a unit isn't properly loaded. */
2454
2455 switch (u->load_state) {
2456
2457 case UNIT_LOADED:
2458 return 0;
2459
2460 case UNIT_NOT_FOUND:
2461 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not found.", u->id);
2462
2463 case UNIT_BAD_SETTING:
2464 return sd_bus_error_setf(error, BUS_ERROR_BAD_UNIT_SETTING, "Unit %s has a bad unit file setting.", u->id);
2465
2466 case UNIT_ERROR: /* Only show .load_error in UNIT_ERROR state */
2467 return sd_bus_error_set_errnof(error, u->load_error,
2468 "Unit %s failed to load properly, please adjust/correct and reload service manager: %m", u->id);
2469
2470 case UNIT_MASKED:
2471 return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit %s is masked.", u->id);
2472
2473 case UNIT_STUB:
2474 case UNIT_MERGED:
2475 default:
2476 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unexpected load state of unit %s", u->id);
2477 }
2478 }
2479
2480 static int bus_unit_track_handler(sd_bus_track *t, void *userdata) {
2481 Unit *u = userdata;
2482
2483 assert(t);
2484 assert(u);
2485
2486 u->bus_track = sd_bus_track_unref(u->bus_track); /* make sure we aren't called again */
2487
2488 /* If the client that tracks us disappeared, then there's reason to believe that the cgroup is empty now too,
2489 * let's see */
2490 unit_add_to_cgroup_empty_queue(u);
2491
2492 /* Also add the unit to the GC queue, after all if the client left it might be time to GC this unit */
2493 unit_add_to_gc_queue(u);
2494
2495 return 0;
2496 }
2497
2498 static int bus_unit_allocate_bus_track(Unit *u) {
2499 int r;
2500
2501 assert(u);
2502
2503 if (u->bus_track)
2504 return 0;
2505
2506 r = sd_bus_track_new(u->manager->api_bus, &u->bus_track, bus_unit_track_handler, u);
2507 if (r < 0)
2508 return r;
2509
2510 r = sd_bus_track_set_recursive(u->bus_track, true);
2511 if (r < 0) {
2512 u->bus_track = sd_bus_track_unref(u->bus_track);
2513 return r;
2514 }
2515
2516 return 0;
2517 }
2518
2519 int bus_unit_track_add_name(Unit *u, const char *name) {
2520 int r;
2521
2522 assert(u);
2523
2524 r = bus_unit_allocate_bus_track(u);
2525 if (r < 0)
2526 return r;
2527
2528 return sd_bus_track_add_name(u->bus_track, name);
2529 }
2530
2531 int bus_unit_track_add_sender(Unit *u, sd_bus_message *m) {
2532 int r;
2533
2534 assert(u);
2535
2536 r = bus_unit_allocate_bus_track(u);
2537 if (r < 0)
2538 return r;
2539
2540 return sd_bus_track_add_sender(u->bus_track, m);
2541 }
2542
2543 int bus_unit_track_remove_sender(Unit *u, sd_bus_message *m) {
2544 assert(u);
2545
2546 /* If we haven't allocated the bus track object yet, then there's definitely no reference taken yet,
2547 * return an error */
2548 if (!u->bus_track)
2549 return -EUNATCH;
2550
2551 return sd_bus_track_remove_sender(u->bus_track, m);
2552 }