]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/unit-serialize.c
ci: enable arm64 runner for build/unit jobs
[thirdparty/systemd.git] / src / core / unit-serialize.c
CommitLineData
2d3b784d
ZJS
1/* SPDX-License-Identifier: LGPL-2.1-or-later */
2
836e4e7e
DDM
3#include "sd-bus.h"
4
5#include "alloc-util.h"
1e4e5572 6#include "bitfield.h"
836e4e7e
DDM
7#include "cgroup.h"
8#include "condition.h"
2d3b784d 9#include "dbus.h"
836e4e7e 10#include "extract-word.h"
2d3b784d
ZJS
11#include "fileio.h"
12#include "format-util.h"
836e4e7e 13#include "glyph-util.h"
2d3b784d
ZJS
14#include "parse-util.h"
15#include "serialize.h"
836e4e7e
DDM
16#include "set.h"
17#include "string-util.h"
18#include "strv.h"
4ea4abb6 19#include "unit.h"
2d3b784d
ZJS
20#include "unit-serialize.h"
21#include "user-util.h"
22
ff68472a
ZJS
23/* Make sure out values fit in the bitfield. */
24assert_cc(_UNIT_MARKER_MAX <= sizeof(((Unit){}).markers) * 8);
25
26static int serialize_markers(FILE *f, unsigned markers) {
27 assert(f);
28
29 if (markers == 0)
30 return 0;
31
5ce8d7d8
MY
32 bool space = false;
33
ff68472a 34 fputs("markers=", f);
1e4e5572
MY
35 BIT_FOREACH(m, markers)
36 fputs_with_separator(f, unit_marker_to_string(m), /* separator = */ NULL, &space);
ff68472a
ZJS
37 fputc('\n', f);
38 return 0;
39}
40
41static int deserialize_markers(Unit *u, const char *value) {
42 assert(u);
43 assert(value);
44 int r;
45
46 for (const char *p = value;;) {
47 _cleanup_free_ char *word = NULL;
48
49 r = extract_first_word(&p, &word, NULL, 0);
50 if (r <= 0)
51 return r;
52
53 UnitMarker m = unit_marker_from_string(word);
54 if (m < 0) {
55 log_unit_debug_errno(u, m, "Unknown unit marker \"%s\", ignoring.", word);
56 continue;
57 }
58
59 u->markers |= 1u << m;
60 }
61}
62
5699a168 63int unit_serialize_state(Unit *u, FILE *f, FDSet *fds, bool switching_root) {
2d3b784d
ZJS
64 int r;
65
66 assert(u);
67 assert(f);
68 assert(fds);
69
755021d4
ZJS
70 if (switching_root && UNIT_VTABLE(u)->exclude_from_switch_root_serialization) {
71 /* In the new root, paths for mounts and automounts will be different, so it doesn't make
72 * much sense to serialize things. API file systems will be moved to the new root, but we
73 * don't have mount units for those. */
74 log_unit_debug(u, "not serializing before switch-root");
75 return 0;
76 }
77
78 /* Start marker */
79 fputs(u->id, f);
80 fputc('\n', f);
81
1085c0eb
ZJS
82 assert(!!UNIT_VTABLE(u)->serialize == !!UNIT_VTABLE(u)->deserialize_item);
83
84 if (UNIT_VTABLE(u)->serialize) {
2d3b784d
ZJS
85 r = UNIT_VTABLE(u)->serialize(u, f, fds);
86 if (r < 0)
87 return r;
88 }
89
90 (void) serialize_dual_timestamp(f, "state-change-timestamp", &u->state_change_timestamp);
91
92 (void) serialize_dual_timestamp(f, "inactive-exit-timestamp", &u->inactive_exit_timestamp);
93 (void) serialize_dual_timestamp(f, "active-enter-timestamp", &u->active_enter_timestamp);
94 (void) serialize_dual_timestamp(f, "active-exit-timestamp", &u->active_exit_timestamp);
95 (void) serialize_dual_timestamp(f, "inactive-enter-timestamp", &u->inactive_enter_timestamp);
96
97 (void) serialize_dual_timestamp(f, "condition-timestamp", &u->condition_timestamp);
98 (void) serialize_dual_timestamp(f, "assert-timestamp", &u->assert_timestamp);
99
6ef512c0 100 (void) serialize_ratelimit(f, "start-ratelimit", &u->start_ratelimit);
b2bd488e 101 (void) serialize_ratelimit(f, "auto-start-stop-ratelimit", &u->auto_start_stop_ratelimit);
6ef512c0 102
2d3b784d
ZJS
103 if (dual_timestamp_is_set(&u->condition_timestamp))
104 (void) serialize_bool(f, "condition-result", u->condition_result);
105
106 if (dual_timestamp_is_set(&u->assert_timestamp))
107 (void) serialize_bool(f, "assert-result", u->assert_result);
108
109 (void) serialize_bool(f, "transient", u->transient);
110 (void) serialize_bool(f, "in-audit", u->in_audit);
111
40233f70
MY
112 (void) serialize_bool(f, "debug-invocation", u->debug_invocation);
113
2d3b784d
ZJS
114 (void) serialize_bool(f, "exported-invocation-id", u->exported_invocation_id);
115 (void) serialize_bool(f, "exported-log-level-max", u->exported_log_level_max);
116 (void) serialize_bool(f, "exported-log-extra-fields", u->exported_log_extra_fields);
117 (void) serialize_bool(f, "exported-log-rate-limit-interval", u->exported_log_ratelimit_interval);
118 (void) serialize_bool(f, "exported-log-rate-limit-burst", u->exported_log_ratelimit_burst);
119
9cc54544 120 (void) cgroup_runtime_serialize(u, f, fds);
6f50d4f7 121
2d3b784d
ZJS
122 if (uid_is_valid(u->ref_uid))
123 (void) serialize_item_format(f, "ref-uid", UID_FMT, u->ref_uid);
124 if (gid_is_valid(u->ref_gid))
125 (void) serialize_item_format(f, "ref-gid", GID_FMT, u->ref_gid);
126
38a2c2bf 127 (void) serialize_id128(f, "invocation-id", u->invocation_id);
2d3b784d 128
e2f81f8d
MY
129 (void) serialize_item(f, "freezer-state", freezer_state_to_string(u->freezer_state));
130
ff68472a 131 (void) serialize_markers(f, u->markers);
2d3b784d
ZJS
132
133 bus_track_serialize(u->bus_track, f, "ref");
134
755021d4 135 if (!switching_root) {
2d3b784d
ZJS
136 if (u->job) {
137 fputs("job\n", f);
138 job_serialize(u->job, f);
139 }
140
141 if (u->nop_job) {
142 fputs("job\n", f);
143 job_serialize(u->nop_job, f);
144 }
145 }
146
147 /* End marker */
148 fputc('\n', f);
149 return 0;
150}
151
152static int unit_deserialize_job(Unit *u, FILE *f) {
153 _cleanup_(job_freep) Job *j = NULL;
154 int r;
155
156 assert(u);
157 assert(f);
158
159 j = job_new_raw(u);
160 if (!j)
161 return log_oom();
162
163 r = job_deserialize(j, f);
164 if (r < 0)
165 return r;
166
167 r = job_install_deserialized(j);
168 if (r < 0)
169 return r;
170
171 TAKE_PTR(j);
172 return 0;
173}
174
9466ec13
ZJS
175#define MATCH_DESERIALIZE(key, l, v, parse_func, target) \
176 ({ \
177 bool _deserialize_matched = streq(l, key); \
178 if (_deserialize_matched) { \
179 int _deserialize_r = parse_func(v); \
180 if (_deserialize_r < 0) \
181 log_unit_debug_errno(u, _deserialize_r, \
182 "Failed to parse \"%s=%s\", ignoring.", l, v); \
183 else \
184 target = _deserialize_r; \
185 }; \
186 _deserialize_matched; \
187 })
188
189#define MATCH_DESERIALIZE_IMMEDIATE(key, l, v, parse_func, target) \
190 ({ \
191 bool _deserialize_matched = streq(l, key); \
192 if (_deserialize_matched) { \
193 int _deserialize_r = parse_func(v, &target); \
194 if (_deserialize_r < 0) \
195 log_unit_debug_errno(u, _deserialize_r, \
196 "Failed to parse \"%s=%s\", ignoring", l, v); \
197 }; \
198 _deserialize_matched; \
199 })
200
5699a168 201int unit_deserialize_state(Unit *u, FILE *f, FDSet *fds) {
2d3b784d
ZJS
202 int r;
203
204 assert(u);
205 assert(f);
206 assert(fds);
207
208 for (;;) {
0df7d525 209 _cleanup_free_ char *l = NULL;
2d3b784d 210 size_t k;
0df7d525 211 char *v;
2d3b784d 212
0df7d525 213 r = deserialize_read_line(f, &l);
2d3b784d 214 if (r < 0)
0df7d525
LP
215 return r;
216 if (r == 0) /* eof or end marker */
2d3b784d
ZJS
217 break;
218
219 k = strcspn(l, "=");
220
221 if (l[k] == '=') {
222 l[k] = 0;
223 v = l+k+1;
224 } else
225 v = l+k;
226
227 if (streq(l, "job")) {
228 if (v[0] == '\0') {
229 /* New-style serialized job */
230 r = unit_deserialize_job(u, f);
231 if (r < 0)
232 return r;
233 } else /* Legacy for pre-44 */
234 log_unit_warning(u, "Update from too old systemd versions are unsupported, cannot deserialize job: %s", v);
235 continue;
236 } else if (streq(l, "state-change-timestamp")) {
237 (void) deserialize_dual_timestamp(v, &u->state_change_timestamp);
238 continue;
239 } else if (streq(l, "inactive-exit-timestamp")) {
240 (void) deserialize_dual_timestamp(v, &u->inactive_exit_timestamp);
241 continue;
242 } else if (streq(l, "active-enter-timestamp")) {
243 (void) deserialize_dual_timestamp(v, &u->active_enter_timestamp);
244 continue;
245 } else if (streq(l, "active-exit-timestamp")) {
246 (void) deserialize_dual_timestamp(v, &u->active_exit_timestamp);
247 continue;
248 } else if (streq(l, "inactive-enter-timestamp")) {
249 (void) deserialize_dual_timestamp(v, &u->inactive_enter_timestamp);
250 continue;
251 } else if (streq(l, "condition-timestamp")) {
252 (void) deserialize_dual_timestamp(v, &u->condition_timestamp);
253 continue;
254 } else if (streq(l, "assert-timestamp")) {
255 (void) deserialize_dual_timestamp(v, &u->assert_timestamp);
256 continue;
2d3b784d 257
6ef512c0
ZJS
258 } else if (streq(l, "start-ratelimit")) {
259 deserialize_ratelimit(&u->start_ratelimit, l, v);
260 continue;
b2bd488e
ZJS
261 } else if (streq(l, "auto-start-stop-ratelimit")) {
262 deserialize_ratelimit(&u->auto_start_stop_ratelimit, l, v);
263 continue;
6ef512c0 264
9466ec13 265 } else if (MATCH_DESERIALIZE("condition-result", l, v, parse_boolean, u->condition_result))
2d3b784d
ZJS
266 continue;
267
9466ec13 268 else if (MATCH_DESERIALIZE("assert-result", l, v, parse_boolean, u->assert_result))
2d3b784d
ZJS
269 continue;
270
9466ec13 271 else if (MATCH_DESERIALIZE("transient", l, v, parse_boolean, u->transient))
2d3b784d
ZJS
272 continue;
273
9466ec13 274 else if (MATCH_DESERIALIZE("in-audit", l, v, parse_boolean, u->in_audit))
2d3b784d
ZJS
275 continue;
276
40233f70
MY
277 else if (MATCH_DESERIALIZE("debug-invocation", l, v, parse_boolean, u->debug_invocation))
278 continue;
279
9466ec13 280 else if (MATCH_DESERIALIZE("exported-invocation-id", l, v, parse_boolean, u->exported_invocation_id))
2d3b784d
ZJS
281 continue;
282
9466ec13 283 else if (MATCH_DESERIALIZE("exported-log-level-max", l, v, parse_boolean, u->exported_log_level_max))
2d3b784d
ZJS
284 continue;
285
9466ec13 286 else if (MATCH_DESERIALIZE("exported-log-extra-fields", l, v, parse_boolean, u->exported_log_extra_fields))
2d3b784d
ZJS
287 continue;
288
9466ec13 289 else if (MATCH_DESERIALIZE("exported-log-rate-limit-interval", l, v, parse_boolean, u->exported_log_ratelimit_interval))
2d3b784d
ZJS
290 continue;
291
9466ec13 292 else if (MATCH_DESERIALIZE("exported-log-rate-limit-burst", l, v, parse_boolean, u->exported_log_ratelimit_burst))
2d3b784d
ZJS
293 continue;
294
9cc54544 295 else if (streq(l, "ref-uid")) {
2d3b784d
ZJS
296 uid_t uid;
297
298 r = parse_uid(v, &uid);
299 if (r < 0)
9466ec13 300 log_unit_debug(u, "Failed to parse \"%s=%s\", ignoring.", l, v);
2d3b784d
ZJS
301 else
302 unit_ref_uid_gid(u, uid, GID_INVALID);
2d3b784d
ZJS
303 continue;
304
305 } else if (streq(l, "ref-gid")) {
306 gid_t gid;
307
308 r = parse_gid(v, &gid);
309 if (r < 0)
9466ec13 310 log_unit_debug(u, "Failed to parse \"%s=%s\", ignoring.", l, v);
2d3b784d
ZJS
311 else
312 unit_ref_uid_gid(u, UID_INVALID, gid);
2d3b784d
ZJS
313 continue;
314
315 } else if (streq(l, "ref")) {
2d3b784d
ZJS
316 r = strv_extend(&u->deserialized_refs, v);
317 if (r < 0)
318 return log_oom();
2d3b784d 319 continue;
9466ec13 320
2d3b784d
ZJS
321 } else if (streq(l, "invocation-id")) {
322 sd_id128_t id;
323
324 r = sd_id128_from_string(v, &id);
325 if (r < 0)
9466ec13 326 log_unit_debug(u, "Failed to parse \"%s=%s\", ignoring.", l, v);
2d3b784d
ZJS
327 else {
328 r = unit_set_invocation_id(u, id);
329 if (r < 0)
330 log_unit_warning_errno(u, r, "Failed to set invocation ID for unit: %m");
331 }
332
333 continue;
2d3b784d 334
9466ec13 335 } else if (MATCH_DESERIALIZE("freezer-state", l, v, freezer_state_from_string, u->freezer_state))
2d3b784d 336 continue;
2d3b784d 337
ff68472a
ZJS
338 else if (streq(l, "markers")) {
339 r = deserialize_markers(u, v);
340 if (r < 0)
341 log_unit_debug_errno(u, r, "Failed to deserialize \"%s=%s\", ignoring: %m", l, v);
342 continue;
343 }
344
e76506b7 345 r = exec_shared_runtime_deserialize_compat(u, l, v, fds);
fe50aae5
ZJS
346 if (r < 0) {
347 log_unit_warning(u, "Failed to deserialize runtime parameter '%s', ignoring.", l);
348 continue;
349 } else if (r > 0)
2d3b784d 350 /* Returns positive if key was handled by the call */
fe50aae5 351 continue;
2d3b784d 352
9cc54544
LP
353 r = cgroup_runtime_deserialize_one(u, l, v, fds);
354 if (r < 0) {
355 log_unit_warning(u, "Failed to deserialize cgroup runtime parameter '%s, ignoring.", l);
356 continue;
357 } else if (r > 0)
358 continue; /* was handled */
359
1085c0eb 360 if (UNIT_VTABLE(u)->deserialize_item) {
2d3b784d
ZJS
361 r = UNIT_VTABLE(u)->deserialize_item(u, l, v, fds);
362 if (r < 0)
363 log_unit_warning(u, "Failed to deserialize unit parameter '%s', ignoring.", l);
364 }
365 }
366
2d3b784d
ZJS
367 /* Let's make sure that everything that is deserialized also gets any potential new cgroup settings
368 * applied after we are done. For that we invalidate anything already realized, so that we can
369 * realize it again. */
23ac0811
MY
370 CGroupRuntime *crt = unit_get_cgroup_runtime(u);
371 if (crt && crt->cgroup_path) {
372 /* Since v258, CGroupRuntime.cgroup_path is coupled with cgroup realized state, which however
373 * wasn't the case in prior versions with the realized state tracked in a discrete field.
374 * Patch cgroup_realized == 0 back to no cgroup_path here hence. */
375 if (crt->deserialized_cgroup_realized == 0)
376 unit_release_cgroup(u, /* drop_cgroup_runtime = */ false);
377 else {
378 unit_invalidate_cgroup(u, _CGROUP_MASK_ALL);
379 unit_invalidate_cgroup_bpf(u);
380 }
cc815b7f 381 }
2d3b784d
ZJS
382
383 return 0;
384}
385
5699a168 386int unit_deserialize_state_skip(FILE *f) {
2d3b784d 387 int r;
0ff6ff2b 388
2d3b784d
ZJS
389 assert(f);
390
391 /* Skip serialized data for this unit. We don't know what it is. */
392
393 for (;;) {
394 _cleanup_free_ char *line = NULL;
2d3b784d 395
0ff6ff2b 396 r = read_stripped_line(f, LONG_LINE_MAX, &line);
2d3b784d
ZJS
397 if (r < 0)
398 return log_error_errno(r, "Failed to read serialization line: %m");
399 if (r == 0)
400 return 0;
401
2d3b784d 402 /* End marker */
0ff6ff2b 403 if (isempty(line))
2d3b784d
ZJS
404 return 1;
405 }
406}
407
408static void print_unit_dependency_mask(FILE *f, const char *kind, UnitDependencyMask mask, bool *space) {
409 const struct {
410 UnitDependencyMask mask;
411 const char *name;
412 } table[] = {
413 { UNIT_DEPENDENCY_FILE, "file" },
414 { UNIT_DEPENDENCY_IMPLICIT, "implicit" },
415 { UNIT_DEPENDENCY_DEFAULT, "default" },
416 { UNIT_DEPENDENCY_UDEV, "udev" },
417 { UNIT_DEPENDENCY_PATH, "path" },
87c734ee
FB
418 { UNIT_DEPENDENCY_MOUNT_FILE, "mount-file" },
419 { UNIT_DEPENDENCY_MOUNTINFO, "mountinfo" },
2d3b784d 420 { UNIT_DEPENDENCY_PROC_SWAP, "proc-swap" },
899acf5c 421 { UNIT_DEPENDENCY_SLICE_PROPERTY, "slice-property" },
2d3b784d
ZJS
422 };
423
424 assert(f);
425 assert(kind);
426 assert(space);
427
ddb8a639 428 FOREACH_ELEMENT(i, table) {
2d3b784d
ZJS
429 if (mask == 0)
430 break;
431
ddb8a639 432 if (FLAGS_SET(mask, i->mask)) {
2d3b784d
ZJS
433 if (*space)
434 fputc(' ', f);
435 else
436 *space = true;
437
438 fputs(kind, f);
439 fputs("-", f);
ddb8a639 440 fputs(i->name, f);
2d3b784d 441
ddb8a639 442 mask &= ~i->mask;
2d3b784d
ZJS
443 }
444 }
445
446 assert(mask == 0);
447}
448
449void unit_dump(Unit *u, FILE *f, const char *prefix) {
de010b0b 450 char *t;
2d3b784d 451 const char *prefix2;
2d3b784d
ZJS
452 Unit *following;
453 _cleanup_set_free_ Set *following_set = NULL;
454 CGroupMask m;
455 int r;
456
457 assert(u);
458 assert(u->type >= 0);
459
460 prefix = strempty(prefix);
461 prefix2 = strjoina(prefix, "\t");
462
463 fprintf(f,
3a7bb5c9 464 "%s%s Unit %s:\n",
1ae9b0cf 465 prefix, glyph(GLYPH_ARROW_RIGHT), u->id);
2d3b784d
ZJS
466
467 SET_FOREACH(t, u->aliases)
468 fprintf(f, "%s\tAlias: %s\n", prefix, t);
469
470 fprintf(f,
471 "%s\tDescription: %s\n"
472 "%s\tInstance: %s\n"
473 "%s\tUnit Load State: %s\n"
474 "%s\tUnit Active State: %s\n"
475 "%s\tState Change Timestamp: %s\n"
476 "%s\tInactive Exit Timestamp: %s\n"
477 "%s\tActive Enter Timestamp: %s\n"
478 "%s\tActive Exit Timestamp: %s\n"
479 "%s\tInactive Enter Timestamp: %s\n"
480 "%s\tMay GC: %s\n"
481 "%s\tNeed Daemon Reload: %s\n"
482 "%s\tTransient: %s\n"
483 "%s\tPerpetual: %s\n"
39628fed 484 "%s\tGarbage Collection Mode: %s\n",
2d3b784d
ZJS
485 prefix, unit_description(u),
486 prefix, strna(u->instance),
487 prefix, unit_load_state_to_string(u->load_state),
488 prefix, unit_active_state_to_string(unit_active_state(u)),
04f5c018
ZJS
489 prefix, strna(FORMAT_TIMESTAMP(u->state_change_timestamp.realtime)),
490 prefix, strna(FORMAT_TIMESTAMP(u->inactive_exit_timestamp.realtime)),
491 prefix, strna(FORMAT_TIMESTAMP(u->active_enter_timestamp.realtime)),
492 prefix, strna(FORMAT_TIMESTAMP(u->active_exit_timestamp.realtime)),
493 prefix, strna(FORMAT_TIMESTAMP(u->inactive_enter_timestamp.realtime)),
2d3b784d
ZJS
494 prefix, yes_no(unit_may_gc(u)),
495 prefix, yes_no(unit_need_daemon_reload(u)),
496 prefix, yes_no(u->transient),
497 prefix, yes_no(u->perpetual),
39628fed 498 prefix, collect_mode_to_string(u->collect_mode));
2d3b784d 499
ff68472a
ZJS
500 if (u->markers != 0) {
501 fprintf(f, "%s\tMarkers:", prefix);
502
1e4e5572
MY
503 BIT_FOREACH(marker, u->markers)
504 fprintf(f, " %s", unit_marker_to_string(marker));
ff68472a
ZJS
505 fputs("\n", f);
506 }
507
39628fed 508 if (UNIT_HAS_CGROUP_CONTEXT(u)) {
9cc54544
LP
509 CGroupRuntime *crt = unit_get_cgroup_runtime(u);
510
39628fed
LP
511 fprintf(f,
512 "%s\tSlice: %s\n"
23ac0811 513 "%s\tCGroup: %s\n",
39628fed 514 prefix, strna(unit_slice_name(u)),
23ac0811 515 prefix, strna(crt ? crt->cgroup_path : NULL));
39628fed 516
9cc54544 517 if (crt && crt->cgroup_realized_mask != 0) {
39628fed 518 _cleanup_free_ char *s = NULL;
9cc54544 519 (void) cg_mask_to_string(crt->cgroup_realized_mask, &s);
39628fed
LP
520 fprintf(f, "%s\tCGroup realized mask: %s\n", prefix, strnull(s));
521 }
2d3b784d 522
9cc54544 523 if (crt && crt->cgroup_enabled_mask != 0) {
39628fed 524 _cleanup_free_ char *s = NULL;
9cc54544 525 (void) cg_mask_to_string(crt->cgroup_enabled_mask, &s);
39628fed
LP
526 fprintf(f, "%s\tCGroup enabled mask: %s\n", prefix, strnull(s));
527 }
2d3b784d 528
39628fed
LP
529 m = unit_get_own_mask(u);
530 if (m != 0) {
531 _cleanup_free_ char *s = NULL;
532 (void) cg_mask_to_string(m, &s);
533 fprintf(f, "%s\tCGroup own mask: %s\n", prefix, strnull(s));
534 }
2d3b784d 535
39628fed
LP
536 m = unit_get_members_mask(u);
537 if (m != 0) {
538 _cleanup_free_ char *s = NULL;
539 (void) cg_mask_to_string(m, &s);
540 fprintf(f, "%s\tCGroup members mask: %s\n", prefix, strnull(s));
541 }
2d3b784d 542
39628fed
LP
543 m = unit_get_delegate_mask(u);
544 if (m != 0) {
545 _cleanup_free_ char *s = NULL;
546 (void) cg_mask_to_string(m, &s);
547 fprintf(f, "%s\tCGroup delegate mask: %s\n", prefix, strnull(s));
548 }
2d3b784d
ZJS
549 }
550
551 if (!sd_id128_is_null(u->invocation_id))
552 fprintf(f, "%s\tInvocation ID: " SD_ID128_FORMAT_STR "\n",
553 prefix, SD_ID128_FORMAT_VAL(u->invocation_id));
554
555 STRV_FOREACH(j, u->documentation)
556 fprintf(f, "%s\tDocumentation: %s\n", prefix, *j);
557
23e9a7dd
LP
558 if (u->access_selinux_context)
559 fprintf(f, "%s\tAccess SELinux Context: %s\n", prefix, u->access_selinux_context);
560
2d3b784d
ZJS
561 following = unit_following(u);
562 if (following)
563 fprintf(f, "%s\tFollowing: %s\n", prefix, following->id);
564
565 r = unit_following_set(u, &following_set);
566 if (r >= 0) {
567 Unit *other;
568
569 SET_FOREACH(other, following_set)
570 fprintf(f, "%s\tFollowing Set Member: %s\n", prefix, other->id);
571 }
572
573 if (u->fragment_path)
574 fprintf(f, "%s\tFragment Path: %s\n", prefix, u->fragment_path);
575
576 if (u->source_path)
577 fprintf(f, "%s\tSource Path: %s\n", prefix, u->source_path);
578
579 STRV_FOREACH(j, u->dropin_paths)
580 fprintf(f, "%s\tDropIn Path: %s\n", prefix, *j);
581
582 if (u->failure_action != EMERGENCY_ACTION_NONE)
583 fprintf(f, "%s\tFailure Action: %s\n", prefix, emergency_action_to_string(u->failure_action));
584 if (u->failure_action_exit_status >= 0)
585 fprintf(f, "%s\tFailure Action Exit Status: %i\n", prefix, u->failure_action_exit_status);
586 if (u->success_action != EMERGENCY_ACTION_NONE)
587 fprintf(f, "%s\tSuccess Action: %s\n", prefix, emergency_action_to_string(u->success_action));
588 if (u->success_action_exit_status >= 0)
589 fprintf(f, "%s\tSuccess Action Exit Status: %i\n", prefix, u->success_action_exit_status);
590
591 if (u->job_timeout != USEC_INFINITY)
5291f26d 592 fprintf(f, "%s\tJob Timeout: %s\n", prefix, FORMAT_TIMESPAN(u->job_timeout, 0));
2d3b784d
ZJS
593
594 if (u->job_timeout_action != EMERGENCY_ACTION_NONE)
595 fprintf(f, "%s\tJob Timeout Action: %s\n", prefix, emergency_action_to_string(u->job_timeout_action));
596
597 if (u->job_timeout_reboot_arg)
598 fprintf(f, "%s\tJob Timeout Reboot Argument: %s\n", prefix, u->job_timeout_reboot_arg);
599
600 condition_dump_list(u->conditions, f, prefix, condition_type_to_string);
601 condition_dump_list(u->asserts, f, prefix, assert_type_to_string);
602
603 if (dual_timestamp_is_set(&u->condition_timestamp))
604 fprintf(f,
605 "%s\tCondition Timestamp: %s\n"
606 "%s\tCondition Result: %s\n",
04f5c018 607 prefix, strna(FORMAT_TIMESTAMP(u->condition_timestamp.realtime)),
2d3b784d
ZJS
608 prefix, yes_no(u->condition_result));
609
610 if (dual_timestamp_is_set(&u->assert_timestamp))
611 fprintf(f,
612 "%s\tAssert Timestamp: %s\n"
613 "%s\tAssert Result: %s\n",
04f5c018 614 prefix, strna(FORMAT_TIMESTAMP(u->assert_timestamp.realtime)),
2d3b784d
ZJS
615 prefix, yes_no(u->assert_result));
616
617 for (UnitDependency d = 0; d < _UNIT_DEPENDENCY_MAX; d++) {
618 UnitDependencyInfo di;
619 Unit *other;
620
15ed3c3a 621 HASHMAP_FOREACH_KEY(di.data, other, unit_get_dependencies(u, d)) {
2d3b784d
ZJS
622 bool space = false;
623
624 fprintf(f, "%s\t%s: %s (", prefix, unit_dependency_to_string(d), other->id);
625
626 print_unit_dependency_mask(f, "origin", di.origin_mask, &space);
627 print_unit_dependency_mask(f, "destination", di.destination_mask, &space);
628
629 fputs(")\n", f);
630 }
631 }
632
9e615fa3
LB
633 for (UnitMountDependencyType type = 0; type < _UNIT_MOUNT_DEPENDENCY_TYPE_MAX; type++)
634 if (!hashmap_isempty(u->mounts_for[type])) {
635 UnitDependencyInfo di;
636 const char *path;
2d3b784d 637
9e615fa3
LB
638 HASHMAP_FOREACH_KEY(di.data, path, u->mounts_for[type]) {
639 bool space = false;
2d3b784d 640
9e615fa3
LB
641 fprintf(f,
642 "%s\t%s: %s (",
643 prefix,
644 unit_mount_dependency_type_to_string(type),
645 path);
2d3b784d 646
9e615fa3
LB
647 print_unit_dependency_mask(f, "origin", di.origin_mask, &space);
648 print_unit_dependency_mask(f, "destination", di.destination_mask, &space);
2d3b784d 649
9e615fa3
LB
650 fputs(")\n", f);
651 }
2d3b784d 652 }
2d3b784d
ZJS
653
654 if (u->load_state == UNIT_LOADED) {
655
656 fprintf(f,
657 "%s\tStopWhenUnneeded: %s\n"
658 "%s\tRefuseManualStart: %s\n"
659 "%s\tRefuseManualStop: %s\n"
660 "%s\tDefaultDependencies: %s\n"
559214cb 661 "%s\tSurviveFinalKillSignal: %s\n"
294446dc 662 "%s\tOnSuccessJobMode: %s\n"
2d3b784d
ZJS
663 "%s\tOnFailureJobMode: %s\n"
664 "%s\tIgnoreOnIsolate: %s\n",
665 prefix, yes_no(u->stop_when_unneeded),
666 prefix, yes_no(u->refuse_manual_start),
667 prefix, yes_no(u->refuse_manual_stop),
668 prefix, yes_no(u->default_dependencies),
559214cb 669 prefix, yes_no(u->survive_final_kill_signal),
294446dc 670 prefix, job_mode_to_string(u->on_success_job_mode),
2d3b784d
ZJS
671 prefix, job_mode_to_string(u->on_failure_job_mode),
672 prefix, yes_no(u->ignore_on_isolate));
673
674 if (UNIT_VTABLE(u)->dump)
675 UNIT_VTABLE(u)->dump(u, f, prefix2);
676
677 } else if (u->load_state == UNIT_MERGED)
678 fprintf(f,
679 "%s\tMerged into: %s\n",
680 prefix, u->merged_into->id);
38553034 681 else if (u->load_state == UNIT_ERROR) {
836e4e7e 682 errno = ABS(u->load_error);
38553034
ZJS
683 fprintf(f, "%s\tLoad Error Code: %m\n", prefix);
684 }
2d3b784d
ZJS
685
686 for (const char *n = sd_bus_track_first(u->bus_track); n; n = sd_bus_track_next(u->bus_track))
687 fprintf(f, "%s\tBus Ref: %s\n", prefix, n);
688
689 if (u->job)
690 job_dump(u->job, f, prefix2);
691
692 if (u->nop_job)
693 job_dump(u->nop_job, f, prefix2);
694}