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