Bug Summary

File:build-scan/../src/core/unit.c
Warning:line 4689, column 41
Potential leak of memory pointed to by 'q'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name unit.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fdenormal-fp-math=preserve-sign,preserve-sign -ffp-contract=fast -fno-rounding-math -ffast-math -ffinite-math-only -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -include config.h -I src/core/libcore.a.p -I src/core -I ../src/core -I src/basic -I ../src/basic -I src/shared -I ../src/shared -I src/systemd -I ../src/systemd -I src/journal -I ../src/journal -I src/journal-remote -I ../src/journal-remote -I src/nspawn -I ../src/nspawn -I src/resolve -I ../src/resolve -I src/timesync -I ../src/timesync -I ../src/time-wait-sync -I src/login -I ../src/login -I src/udev -I ../src/udev -I src/libudev -I ../src/libudev -I ../src/libsystemd/sd-bus -I ../src/libsystemd/sd-device -I ../src/libsystemd/sd-hwdb -I ../src/libsystemd/sd-id128 -I ../src/libsystemd/sd-netlink -I ../src/libsystemd/sd-network -I src/libsystemd-network -I ../src/libsystemd-network -I . -I .. -I /usr/include/libmount -I /usr/include/blkid -D _FILE_OFFSET_BITS=64 -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wwrite-strings -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-result -Wno-format-signedness -Wno-error=nonnull -std=gnu99 -fconst-strings -fdebug-compilation-dir /home/mrc0mmand/repos/@redhat-plumbers/systemd-rhel8/build-scan -ferror-limit 19 -fvisibility hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-07-16-221226-1465241-1 -x c ../src/core/unit.c
1/* SPDX-License-Identifier: LGPL-2.1+ */
2
3#include <errno(*__errno_location ()).h>
4#include <stdlib.h>
5#include <string.h>
6#include <sys/prctl.h>
7#include <sys/stat.h>
8#include <unistd.h>
9
10#include "sd-id128.h"
11#include "sd-messages.h"
12
13#include "alloc-util.h"
14#include "all-units.h"
15#include "bus-common-errors.h"
16#include "bus-util.h"
17#include "cgroup-util.h"
18#include "dbus-unit.h"
19#include "dbus.h"
20#include "dropin.h"
21#include "escape.h"
22#include "execute.h"
23#include "fd-util.h"
24#include "fileio-label.h"
25#include "format-util.h"
26#include "fs-util.h"
27#include "id128-util.h"
28#include "io-util.h"
29#include "load-dropin.h"
30#include "load-fragment.h"
31#include "log.h"
32#include "macro.h"
33#include "missing.h"
34#include "mkdir.h"
35#include "parse-util.h"
36#include "path-util.h"
37#include "process-util.h"
38#include "set.h"
39#include "signal-util.h"
40#include "sparse-endian.h"
41#include "special.h"
42#include "specifier.h"
43#include "stat-util.h"
44#include "stdio-util.h"
45#include "string-table.h"
46#include "string-util.h"
47#include "strv.h"
48#include "umask-util.h"
49#include "unit-name.h"
50#include "unit.h"
51#include "user-util.h"
52#include "virt.h"
53
54const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = {
55 [UNIT_SERVICE] = &service_vtable,
56 [UNIT_SOCKET] = &socket_vtable,
57 [UNIT_TARGET] = &target_vtable,
58 [UNIT_DEVICE] = &device_vtable,
59 [UNIT_MOUNT] = &mount_vtable,
60 [UNIT_AUTOMOUNT] = &automount_vtable,
61 [UNIT_SWAP] = &swap_vtable,
62 [UNIT_TIMER] = &timer_vtable,
63 [UNIT_PATH] = &path_vtable,
64 [UNIT_SLICE] = &slice_vtable,
65 [UNIT_SCOPE] = &scope_vtable,
66};
67
68static void maybe_warn_about_dependency(Unit *u, const char *other, UnitDependency dependency);
69
70Unit *unit_new(Manager *m, size_t size) {
71 Unit *u;
72
73 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/core/unit.c", 73, __PRETTY_FUNCTION__
); } while (0)
;
74 assert(size >= sizeof(Unit))do { if ((__builtin_expect(!!(!(size >= sizeof(Unit))),0))
) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("size >= sizeof(Unit)"
), "../src/core/unit.c", 74, __PRETTY_FUNCTION__); } while (0
)
;
75
76 u = malloc0(size)(calloc(1, (size)));
77 if (!u)
78 return NULL((void*)0);
79
80 u->names = set_new(&string_hash_ops)internal_set_new(&string_hash_ops );
81 if (!u->names)
82 return mfree(u);
83
84 u->manager = m;
85 u->type = _UNIT_TYPE_INVALID;
86 u->default_dependencies = true1;
87 u->unit_file_state = _UNIT_FILE_STATE_INVALID;
88 u->unit_file_preset = -1;
89 u->on_failure_job_mode = JOB_REPLACE;
90 u->cgroup_inotify_wd = -1;
91 u->job_timeout = USEC_INFINITY((usec_t) -1);
92 u->job_running_timeout = USEC_INFINITY((usec_t) -1);
93 u->ref_uid = UID_INVALID((uid_t) -1);
94 u->ref_gid = GID_INVALID((gid_t) -1);
95 u->cpu_usage_last = NSEC_INFINITY((nsec_t) -1);
96 u->cgroup_bpf_state = UNIT_CGROUP_BPF_INVALIDATED;
97
98 u->ip_accounting_ingress_map_fd = -1;
99 u->ip_accounting_egress_map_fd = -1;
100 u->ipv4_allow_map_fd = -1;
101 u->ipv6_allow_map_fd = -1;
102 u->ipv4_deny_map_fd = -1;
103 u->ipv6_deny_map_fd = -1;
104
105 u->last_section_private = -1;
106
107 RATELIMIT_INIT(u->start_limit, m->default_start_limit_interval, m->default_start_limit_burst)do { RateLimit *_r = &(u->start_limit); _r->interval
= (m->default_start_limit_interval); _r->burst = (m->
default_start_limit_burst); _r->num = 0; _r->begin = 0;
} while (0)
;
108 RATELIMIT_INIT(u->auto_stop_ratelimit, 10 * USEC_PER_SEC, 16)do { RateLimit *_r = &(u->auto_stop_ratelimit); _r->
interval = (10 * ((usec_t) 1000000ULL)); _r->burst = (16);
_r->num = 0; _r->begin = 0; } while (0)
;
109
110 return u;
111}
112
113int unit_new_for_name(Manager *m, size_t size, const char *name, Unit **ret) {
114 _cleanup_(unit_freep)__attribute__((cleanup(unit_freep))) Unit *u = NULL((void*)0);
115 int r;
116
117 u = unit_new(m, size);
118 if (!u)
119 return -ENOMEM12;
120
121 r = unit_add_name(u, name);
122 if (r < 0)
123 return r;
124
125 *ret = TAKE_PTR(u)({ typeof(u) _ptr_ = (u); (u) = ((void*)0); _ptr_; });
126
127 return r;
128}
129
130bool_Bool unit_has_name(Unit *u, const char *name) {
131 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 131, __PRETTY_FUNCTION__
); } while (0)
;
132 assert(name)do { if ((__builtin_expect(!!(!(name)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("name"), "../src/core/unit.c", 132, __PRETTY_FUNCTION__
); } while (0)
;
133
134 return set_contains(u->names, (char*) name);
135}
136
137static void unit_init(Unit *u) {
138 CGroupContext *cc;
139 ExecContext *ec;
140 KillContext *kc;
141
142 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 142, __PRETTY_FUNCTION__
); } while (0)
;
143 assert(u->manager)do { if ((__builtin_expect(!!(!(u->manager)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u->manager"), "../src/core/unit.c", 143
, __PRETTY_FUNCTION__); } while (0)
;
144 assert(u->type >= 0)do { if ((__builtin_expect(!!(!(u->type >= 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u->type >= 0"), "../src/core/unit.c"
, 144, __PRETTY_FUNCTION__); } while (0)
;
145
146 cc = unit_get_cgroup_context(u);
147 if (cc) {
148 cgroup_context_init(cc);
149
150 /* Copy in the manager defaults into the cgroup
151 * context, _before_ the rest of the settings have
152 * been initialized */
153
154 cc->cpu_accounting = u->manager->default_cpu_accounting;
155 cc->io_accounting = u->manager->default_io_accounting;
156 cc->ip_accounting = u->manager->default_ip_accounting;
157 cc->blockio_accounting = u->manager->default_blockio_accounting;
158 cc->memory_accounting = u->manager->default_memory_accounting;
159 cc->tasks_accounting = u->manager->default_tasks_accounting;
160 cc->ip_accounting = u->manager->default_ip_accounting;
161
162 if (u->type != UNIT_SLICE)
163 cc->tasks_max = u->manager->default_tasks_max;
164 }
165
166 ec = unit_get_exec_context(u);
167 if (ec) {
168 exec_context_init(ec);
169
170 ec->keyring_mode = MANAGER_IS_SYSTEM(u->manager)((u->manager)->unit_file_scope == UNIT_FILE_SYSTEM) ?
171 EXEC_KEYRING_SHARED : EXEC_KEYRING_INHERIT;
172 }
173
174 kc = unit_get_kill_context(u);
175 if (kc)
176 kill_context_init(kc);
177
178 if (UNIT_VTABLE(u)unit_vtable[(u)->type]->init)
179 UNIT_VTABLE(u)unit_vtable[(u)->type]->init(u);
180}
181
182int unit_add_name(Unit *u, const char *text) {
183 _cleanup_free___attribute__((cleanup(freep))) char *s = NULL((void*)0), *i = NULL((void*)0);
184 UnitType t;
185 int r;
186
187 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 187, __PRETTY_FUNCTION__
); } while (0)
;
188 assert(text)do { if ((__builtin_expect(!!(!(text)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("text"), "../src/core/unit.c", 188, __PRETTY_FUNCTION__
); } while (0)
;
189
190 if (unit_name_is_valid(text, UNIT_NAME_TEMPLATE)) {
191
192 if (!u->instance)
193 return -EINVAL22;
194
195 r = unit_name_replace_instance(text, u->instance, &s);
196 if (r < 0)
197 return r;
198 } else {
199 s = strdup(text);
200 if (!s)
201 return -ENOMEM12;
202 }
203
204 if (set_contains(u->names, s))
205 return 0;
206 if (hashmap_contains(u->manager->units, s))
207 return -EEXIST17;
208
209 if (!unit_name_is_valid(s, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE))
210 return -EINVAL22;
211
212 t = unit_name_to_type(s);
213 if (t < 0)
214 return -EINVAL22;
215
216 if (u->type != _UNIT_TYPE_INVALID && t != u->type)
217 return -EINVAL22;
218
219 r = unit_name_to_instance(s, &i);
220 if (r < 0)
221 return r;
222
223 if (i && !unit_type_may_template(t))
224 return -EINVAL22;
225
226 /* Ensure that this unit is either instanced or not instanced,
227 * but not both. Note that we do allow names with different
228 * instance names however! */
229 if (u->type != _UNIT_TYPE_INVALID && !u->instance != !i)
230 return -EINVAL22;
231
232 if (!unit_type_may_alias(t) && !set_isempty(u->names))
233 return -EEXIST17;
234
235 if (hashmap_size(u->manager->units) >= MANAGER_MAX_NAMES131072)
236 return -E2BIG7;
237
238 r = set_put(u->names, s);
239 if (r < 0)
240 return r;
241 assert(r > 0)do { if ((__builtin_expect(!!(!(r > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("r > 0"), "../src/core/unit.c", 241, __PRETTY_FUNCTION__
); } while (0)
;
242
243 r = hashmap_put(u->manager->units, s, u);
244 if (r < 0) {
245 (void) set_remove(u->names, s);
246 return r;
247 }
248
249 if (u->type == _UNIT_TYPE_INVALID) {
250 u->type = t;
251 u->id = s;
252 u->instance = TAKE_PTR(i)({ typeof(i) _ptr_ = (i); (i) = ((void*)0); _ptr_; });
253
254 LIST_PREPEND(units_by_type, u->manager->units_by_type[t], u)do { typeof(*(u->manager->units_by_type[t])) **_head = &
(u->manager->units_by_type[t]), *_item = (u); do { if (
(__builtin_expect(!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("_item"), "../src/core/unit.c", 254, __PRETTY_FUNCTION__);
} while (0); if ((_item->units_by_type_next = *_head)) _item
->units_by_type_next->units_by_type_prev = _item; _item
->units_by_type_prev = ((void*)0); *_head = _item; } while
(0)
;
255
256 unit_init(u);
257 }
258
259 s = NULL((void*)0);
260
261 unit_add_to_dbus_queue(u);
262 return 0;
263}
264
265int unit_choose_id(Unit *u, const char *name) {
266 _cleanup_free___attribute__((cleanup(freep))) char *t = NULL((void*)0);
267 char *s, *i;
268 int r;
269
270 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 270, __PRETTY_FUNCTION__
); } while (0)
;
271 assert(name)do { if ((__builtin_expect(!!(!(name)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("name"), "../src/core/unit.c", 271, __PRETTY_FUNCTION__
); } while (0)
;
272
273 if (unit_name_is_valid(name, UNIT_NAME_TEMPLATE)) {
274
275 if (!u->instance)
276 return -EINVAL22;
277
278 r = unit_name_replace_instance(name, u->instance, &t);
279 if (r < 0)
280 return r;
281
282 name = t;
283 }
284
285 /* Selects one of the names of this unit as the id */
286 s = set_get(u->names, (char*) name);
287 if (!s)
288 return -ENOENT2;
289
290 /* Determine the new instance from the new id */
291 r = unit_name_to_instance(s, &i);
292 if (r < 0)
293 return r;
294
295 u->id = s;
296
297 free(u->instance);
298 u->instance = i;
299
300 unit_add_to_dbus_queue(u);
301
302 return 0;
303}
304
305int unit_set_description(Unit *u, const char *description) {
306 int r;
307
308 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 308, __PRETTY_FUNCTION__
); } while (0)
;
309
310 r = free_and_strdup(&u->description, empty_to_null(description));
311 if (r < 0)
312 return r;
313 if (r > 0)
314 unit_add_to_dbus_queue(u);
315
316 return 0;
317}
318
319bool_Bool unit_may_gc(Unit *u) {
320 UnitActiveState state;
321 int r;
322
323 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 323, __PRETTY_FUNCTION__
); } while (0)
;
324
325 /* Checks whether the unit is ready to be unloaded for garbage collection.
326 * Returns true when the unit may be collected, and false if there's some
327 * reason to keep it loaded.
328 *
329 * References from other units are *not* checked here. Instead, this is done
330 * in unit_gc_sweep(), but using markers to properly collect dependency loops.
331 */
332
333 if (u->job)
334 return false0;
335
336 if (u->nop_job)
337 return false0;
338
339 state = unit_active_state(u);
340
341 /* If the unit is inactive and failed and no job is queued for it, then release its runtime resources */
342 if (UNIT_IS_INACTIVE_OR_FAILED(state) &&
343 UNIT_VTABLE(u)unit_vtable[(u)->type]->release_resources)
344 UNIT_VTABLE(u)unit_vtable[(u)->type]->release_resources(u);
345
346 if (u->perpetual)
347 return false0;
348
349 if (sd_bus_track_count(u->bus_track) > 0)
350 return false0;
351
352 /* But we keep the unit object around for longer when it is referenced or configured to not be gc'ed */
353 switch (u->collect_mode) {
354
355 case COLLECT_INACTIVE:
356 if (state != UNIT_INACTIVE)
357 return false0;
358
359 break;
360
361 case COLLECT_INACTIVE_OR_FAILED:
362 if (!IN_SET(state, UNIT_INACTIVE, UNIT_FAILED)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){UNIT_INACTIVE, UNIT_FAILED})/sizeof(int)
]; switch(state) { case UNIT_INACTIVE: case UNIT_FAILED: _found
= 1; break; default: break; } _found; })
)
363 return false0;
364
365 break;
366
367 default:
368 assert_not_reached("Unknown garbage collection mode")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, (
"Unknown garbage collection mode"), "../src/core/unit.c", 368
, __PRETTY_FUNCTION__); } while (0)
;
369 }
370
371 if (u->cgroup_path) {
372 /* If the unit has a cgroup, then check whether there's anything in it. If so, we should stay
373 * around. Units with active processes should never be collected. */
374
375 r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER"_systemd", u->cgroup_path);
376 if (r < 0)
377 log_unit_debug_errno(u, r, "Failed to determine whether cgroup %s is empty: %m", u->cgroup_path)({ const Unit *_u = (u); _u ? log_object_internal(7, r, "../src/core/unit.c"
, 377, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to determine whether cgroup %s is empty: %m", u->
cgroup_path) : log_internal_realm(((LOG_REALM_SYSTEMD) <<
10 | ((7))), r, "../src/core/unit.c", 377, __func__, "Failed to determine whether cgroup %s is empty: %m"
, u->cgroup_path); })
;
378 if (r <= 0)
379 return false0;
380 }
381
382 if (UNIT_VTABLE(u)unit_vtable[(u)->type]->may_gc && !UNIT_VTABLE(u)unit_vtable[(u)->type]->may_gc(u))
383 return false0;
384
385 return true1;
386}
387
388void unit_add_to_load_queue(Unit *u) {
389 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 389, __PRETTY_FUNCTION__
); } while (0)
;
390 assert(u->type != _UNIT_TYPE_INVALID)do { if ((__builtin_expect(!!(!(u->type != _UNIT_TYPE_INVALID
)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("u->type != _UNIT_TYPE_INVALID"
), "../src/core/unit.c", 390, __PRETTY_FUNCTION__); } while (
0)
;
391
392 if (u->load_state != UNIT_STUB || u->in_load_queue)
393 return;
394
395 LIST_PREPEND(load_queue, u->manager->load_queue, u)do { typeof(*(u->manager->load_queue)) **_head = &(
u->manager->load_queue), *_item = (u); do { if ((__builtin_expect
(!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD,
("_item"), "../src/core/unit.c", 395, __PRETTY_FUNCTION__); }
while (0); if ((_item->load_queue_next = *_head)) _item->
load_queue_next->load_queue_prev = _item; _item->load_queue_prev
= ((void*)0); *_head = _item; } while (0)
;
396 u->in_load_queue = true1;
397}
398
399void unit_add_to_cleanup_queue(Unit *u) {
400 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 400, __PRETTY_FUNCTION__
); } while (0)
;
401
402 if (u->in_cleanup_queue)
403 return;
404
405 LIST_PREPEND(cleanup_queue, u->manager->cleanup_queue, u)do { typeof(*(u->manager->cleanup_queue)) **_head = &
(u->manager->cleanup_queue), *_item = (u); do { if ((__builtin_expect
(!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD,
("_item"), "../src/core/unit.c", 405, __PRETTY_FUNCTION__); }
while (0); if ((_item->cleanup_queue_next = *_head)) _item
->cleanup_queue_next->cleanup_queue_prev = _item; _item
->cleanup_queue_prev = ((void*)0); *_head = _item; } while
(0)
;
406 u->in_cleanup_queue = true1;
407}
408
409void unit_add_to_gc_queue(Unit *u) {
410 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 410, __PRETTY_FUNCTION__
); } while (0)
;
411
412 if (u->in_gc_queue || u->in_cleanup_queue)
413 return;
414
415 if (!unit_may_gc(u))
416 return;
417
418 LIST_PREPEND(gc_queue, u->manager->gc_unit_queue, u)do { typeof(*(u->manager->gc_unit_queue)) **_head = &
(u->manager->gc_unit_queue), *_item = (u); do { if ((__builtin_expect
(!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD,
("_item"), "../src/core/unit.c", 418, __PRETTY_FUNCTION__); }
while (0); if ((_item->gc_queue_next = *_head)) _item->
gc_queue_next->gc_queue_prev = _item; _item->gc_queue_prev
= ((void*)0); *_head = _item; } while (0)
;
419 u->in_gc_queue = true1;
420}
421
422void unit_add_to_dbus_queue(Unit *u) {
423 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 423, __PRETTY_FUNCTION__
); } while (0)
;
424 assert(u->type != _UNIT_TYPE_INVALID)do { if ((__builtin_expect(!!(!(u->type != _UNIT_TYPE_INVALID
)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("u->type != _UNIT_TYPE_INVALID"
), "../src/core/unit.c", 424, __PRETTY_FUNCTION__); } while (
0)
;
425
426 if (u->load_state == UNIT_STUB || u->in_dbus_queue)
427 return;
428
429 /* Shortcut things if nobody cares */
430 if (sd_bus_track_count(u->manager->subscribed) <= 0 &&
431 sd_bus_track_count(u->bus_track) <= 0 &&
432 set_isempty(u->manager->private_buses)) {
433 u->sent_dbus_new_signal = true1;
434 return;
435 }
436
437 LIST_PREPEND(dbus_queue, u->manager->dbus_unit_queue, u)do { typeof(*(u->manager->dbus_unit_queue)) **_head = &
(u->manager->dbus_unit_queue), *_item = (u); do { if ((
__builtin_expect(!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("_item"), "../src/core/unit.c", 437, __PRETTY_FUNCTION__);
} while (0); if ((_item->dbus_queue_next = *_head)) _item
->dbus_queue_next->dbus_queue_prev = _item; _item->dbus_queue_prev
= ((void*)0); *_head = _item; } while (0)
;
438 u->in_dbus_queue = true1;
439}
440
441void unit_add_to_stop_when_unneeded_queue(Unit *u) {
442 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 442, __PRETTY_FUNCTION__
); } while (0)
;
443
444 if (u->in_stop_when_unneeded_queue)
445 return;
446
447 if (!u->stop_when_unneeded)
448 return;
449
450 if (!UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u)))
451 return;
452
453 LIST_PREPEND(stop_when_unneeded_queue, u->manager->stop_when_unneeded_queue, u)do { typeof(*(u->manager->stop_when_unneeded_queue)) **
_head = &(u->manager->stop_when_unneeded_queue), *_item
= (u); do { if ((__builtin_expect(!!(!(_item)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("_item"), "../src/core/unit.c", 453, __PRETTY_FUNCTION__
); } while (0); if ((_item->stop_when_unneeded_queue_next =
*_head)) _item->stop_when_unneeded_queue_next->stop_when_unneeded_queue_prev
= _item; _item->stop_when_unneeded_queue_prev = ((void*)0
); *_head = _item; } while (0)
;
454 u->in_stop_when_unneeded_queue = true1;
455}
456
457static void bidi_set_free(Unit *u, Hashmap *h) {
458 Unit *other;
459 Iterator i;
460 void *v;
461
462 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 462, __PRETTY_FUNCTION__
); } while (0)
;
463
464 /* Frees the hashmap and makes sure we are dropped from the inverse pointers */
465
466 HASHMAP_FOREACH_KEY(v, other, h, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); hashmap_iterate((h), &(i), (void
**)&(v), (const void**) &(other)); )
{
467 UnitDependency d;
468
469 for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++)
470 hashmap_remove(other->dependencies[d], u);
471
472 unit_add_to_gc_queue(other);
473 }
474
475 hashmap_free(h);
476}
477
478static void unit_remove_transient(Unit *u) {
479 char **i;
480
481 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 481, __PRETTY_FUNCTION__
); } while (0)
;
482
483 if (!u->transient)
484 return;
485
486 if (u->fragment_path)
487 (void) unlink(u->fragment_path);
488
489 STRV_FOREACH(i, u->dropin_paths)for ((i) = (u->dropin_paths); (i) && *(i); (i)++) {
490 _cleanup_free___attribute__((cleanup(freep))) char *p = NULL((void*)0), *pp = NULL((void*)0);
491
492 p = dirname_malloc(*i); /* Get the drop-in directory from the drop-in file */
493 if (!p)
494 continue;
495
496 pp = dirname_malloc(p); /* Get the config directory from the drop-in directory */
497 if (!pp)
498 continue;
499
500 /* Only drop transient drop-ins */
501 if (!path_equal(u->manager->lookup_paths.transient, pp))
502 continue;
503
504 (void) unlink(*i);
505 (void) rmdir(p);
506 }
507}
508
509static void unit_free_requires_mounts_for(Unit *u) {
510 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 510, __PRETTY_FUNCTION__
); } while (0)
;
511
512 for (;;) {
513 _cleanup_free___attribute__((cleanup(freep))) char *path;
514
515 path = hashmap_steal_first_key(u->requires_mounts_for);
516 if (!path)
517 break;
518 else {
519 char s[strlen(path) + 1];
520
521 PATH_FOREACH_PREFIX_MORE(s, path)for (char *_slash = ({ path_simplify(strcpy(s, path), 0); if (
(strcmp((s),("/")) == 0)) s[0] = 0; strrchr(s, 0); }); _slash
&& ((*_slash = 0), 1); _slash = strrchr((s), '/'))
{
522 char *y;
523 Set *x;
524
525 x = hashmap_get2(u->manager->units_requiring_mounts_for, s, (void**) &y);
526 if (!x)
527 continue;
528
529 (void) set_remove(x, u);
530
531 if (set_isempty(x)) {
532 (void) hashmap_remove(u->manager->units_requiring_mounts_for, y);
533 free(y);
534 set_free(x);
535 }
536 }
537 }
538 }
539
540 u->requires_mounts_for = hashmap_free(u->requires_mounts_for);
541}
542
543static void unit_done(Unit *u) {
544 ExecContext *ec;
545 CGroupContext *cc;
546
547 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 547, __PRETTY_FUNCTION__
); } while (0)
;
548
549 if (u->type < 0)
550 return;
551
552 if (UNIT_VTABLE(u)unit_vtable[(u)->type]->done)
553 UNIT_VTABLE(u)unit_vtable[(u)->type]->done(u);
554
555 ec = unit_get_exec_context(u);
556 if (ec)
557 exec_context_done(ec);
558
559 cc = unit_get_cgroup_context(u);
560 if (cc)
561 cgroup_context_done(cc);
562}
563
564void unit_free(Unit *u) {
565 UnitDependency d;
566 Iterator i;
567 char *t;
568
569 if (!u)
570 return;
571
572 u->transient_file = safe_fclose(u->transient_file);
573
574 if (!MANAGER_IS_RELOADING(u->manager)((u->manager)->n_reloading > 0))
575 unit_remove_transient(u);
576
577 bus_unit_send_removed_signal(u);
578
579 unit_done(u);
580
581 unit_dequeue_rewatch_pids(u);
582
583 sd_bus_slot_unref(u->match_bus_slot);
584 sd_bus_track_unref(u->bus_track);
585 u->deserialized_refs = strv_free(u->deserialized_refs);
586 u->pending_freezer_message = sd_bus_message_unref(u->pending_freezer_message);
587
588 unit_free_requires_mounts_for(u);
589
590 SET_FOREACH(t, u->names, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); set_iterate((u->names), &(i)
, (void**)&(t)); )
591 hashmap_remove_value(u->manager->units, t, u);
592
593 if (!sd_id128_is_null(u->invocation_id))
594 hashmap_remove_value(u->manager->units_by_invocation_id, &u->invocation_id, u);
595
596 if (u->job) {
597 Job *j = u->job;
598 job_uninstall(j);
599 job_free(j);
600 }
601
602 if (u->nop_job) {
603 Job *j = u->nop_job;
604 job_uninstall(j);
605 job_free(j);
606 }
607
608 for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++)
609 bidi_set_free(u, u->dependencies[d]);
610
611 if (u->on_console)
612 manager_unref_console(u->manager);
613
614 unit_release_cgroup(u);
615
616 if (!MANAGER_IS_RELOADING(u->manager)((u->manager)->n_reloading > 0))
617 unit_unlink_state_files(u);
618
619 unit_unref_uid_gid(u, false0);
620
621 (void) manager_update_failed_units(u->manager, u, false0);
622 set_remove(u->manager->startup_units, u);
623
624 unit_unwatch_all_pids(u);
625
626 unit_ref_unset(&u->slice);
627 while (u->refs_by_target)
628 unit_ref_unset(u->refs_by_target);
629
630 if (u->type != _UNIT_TYPE_INVALID)
631 LIST_REMOVE(units_by_type, u->manager->units_by_type[u->type], u)do { typeof(*(u->manager->units_by_type[u->type])) *
*_head = &(u->manager->units_by_type[u->type]), *
_item = (u); do { if ((__builtin_expect(!!(!(_item)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("_item"), "../src/core/unit.c", 631, __PRETTY_FUNCTION__
); } while (0); if (_item->units_by_type_next) _item->units_by_type_next
->units_by_type_prev = _item->units_by_type_prev; if (_item
->units_by_type_prev) _item->units_by_type_prev->units_by_type_next
= _item->units_by_type_next; else { do { if ((__builtin_expect
(!!(!(*_head == _item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("*_head == _item"), "../src/core/unit.c", 631, __PRETTY_FUNCTION__
); } while (0); *_head = _item->units_by_type_next; } _item
->units_by_type_next = _item->units_by_type_prev = ((void
*)0); } while (0)
;
632
633 if (u->in_load_queue)
634 LIST_REMOVE(load_queue, u->manager->load_queue, u)do { typeof(*(u->manager->load_queue)) **_head = &(
u->manager->load_queue), *_item = (u); do { if ((__builtin_expect
(!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD,
("_item"), "../src/core/unit.c", 634, __PRETTY_FUNCTION__); }
while (0); if (_item->load_queue_next) _item->load_queue_next
->load_queue_prev = _item->load_queue_prev; if (_item->
load_queue_prev) _item->load_queue_prev->load_queue_next
= _item->load_queue_next; else { do { if ((__builtin_expect
(!!(!(*_head == _item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("*_head == _item"), "../src/core/unit.c", 634, __PRETTY_FUNCTION__
); } while (0); *_head = _item->load_queue_next; } _item->
load_queue_next = _item->load_queue_prev = ((void*)0); } while
(0)
;
635
636 if (u->in_dbus_queue)
637 LIST_REMOVE(dbus_queue, u->manager->dbus_unit_queue, u)do { typeof(*(u->manager->dbus_unit_queue)) **_head = &
(u->manager->dbus_unit_queue), *_item = (u); do { if ((
__builtin_expect(!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("_item"), "../src/core/unit.c", 637, __PRETTY_FUNCTION__);
} while (0); if (_item->dbus_queue_next) _item->dbus_queue_next
->dbus_queue_prev = _item->dbus_queue_prev; if (_item->
dbus_queue_prev) _item->dbus_queue_prev->dbus_queue_next
= _item->dbus_queue_next; else { do { if ((__builtin_expect
(!!(!(*_head == _item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("*_head == _item"), "../src/core/unit.c", 637, __PRETTY_FUNCTION__
); } while (0); *_head = _item->dbus_queue_next; } _item->
dbus_queue_next = _item->dbus_queue_prev = ((void*)0); } while
(0)
;
638
639 if (u->in_gc_queue)
640 LIST_REMOVE(gc_queue, u->manager->gc_unit_queue, u)do { typeof(*(u->manager->gc_unit_queue)) **_head = &
(u->manager->gc_unit_queue), *_item = (u); do { if ((__builtin_expect
(!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD,
("_item"), "../src/core/unit.c", 640, __PRETTY_FUNCTION__); }
while (0); if (_item->gc_queue_next) _item->gc_queue_next
->gc_queue_prev = _item->gc_queue_prev; if (_item->gc_queue_prev
) _item->gc_queue_prev->gc_queue_next = _item->gc_queue_next
; else { do { if ((__builtin_expect(!!(!(*_head == _item)),0)
)) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("*_head == _item"
), "../src/core/unit.c", 640, __PRETTY_FUNCTION__); } while (
0); *_head = _item->gc_queue_next; } _item->gc_queue_next
= _item->gc_queue_prev = ((void*)0); } while (0)
;
641
642 if (u->in_cgroup_realize_queue)
643 LIST_REMOVE(cgroup_realize_queue, u->manager->cgroup_realize_queue, u)do { typeof(*(u->manager->cgroup_realize_queue)) **_head
= &(u->manager->cgroup_realize_queue), *_item = (u
); do { if ((__builtin_expect(!!(!(_item)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("_item"), "../src/core/unit.c", 643, __PRETTY_FUNCTION__
); } while (0); if (_item->cgroup_realize_queue_next) _item
->cgroup_realize_queue_next->cgroup_realize_queue_prev =
_item->cgroup_realize_queue_prev; if (_item->cgroup_realize_queue_prev
) _item->cgroup_realize_queue_prev->cgroup_realize_queue_next
= _item->cgroup_realize_queue_next; else { do { if ((__builtin_expect
(!!(!(*_head == _item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("*_head == _item"), "../src/core/unit.c", 643, __PRETTY_FUNCTION__
); } while (0); *_head = _item->cgroup_realize_queue_next;
} _item->cgroup_realize_queue_next = _item->cgroup_realize_queue_prev
= ((void*)0); } while (0)
;
644
645 if (u->in_cgroup_empty_queue)
646 LIST_REMOVE(cgroup_empty_queue, u->manager->cgroup_empty_queue, u)do { typeof(*(u->manager->cgroup_empty_queue)) **_head =
&(u->manager->cgroup_empty_queue), *_item = (u); do
{ if ((__builtin_expect(!!(!(_item)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("_item"), "../src/core/unit.c", 646, __PRETTY_FUNCTION__
); } while (0); if (_item->cgroup_empty_queue_next) _item->
cgroup_empty_queue_next->cgroup_empty_queue_prev = _item->
cgroup_empty_queue_prev; if (_item->cgroup_empty_queue_prev
) _item->cgroup_empty_queue_prev->cgroup_empty_queue_next
= _item->cgroup_empty_queue_next; else { do { if ((__builtin_expect
(!!(!(*_head == _item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("*_head == _item"), "../src/core/unit.c", 646, __PRETTY_FUNCTION__
); } while (0); *_head = _item->cgroup_empty_queue_next; }
_item->cgroup_empty_queue_next = _item->cgroup_empty_queue_prev
= ((void*)0); } while (0)
;
647
648 if (u->in_cleanup_queue)
649 LIST_REMOVE(cleanup_queue, u->manager->cleanup_queue, u)do { typeof(*(u->manager->cleanup_queue)) **_head = &
(u->manager->cleanup_queue), *_item = (u); do { if ((__builtin_expect
(!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD,
("_item"), "../src/core/unit.c", 649, __PRETTY_FUNCTION__); }
while (0); if (_item->cleanup_queue_next) _item->cleanup_queue_next
->cleanup_queue_prev = _item->cleanup_queue_prev; if (_item
->cleanup_queue_prev) _item->cleanup_queue_prev->cleanup_queue_next
= _item->cleanup_queue_next; else { do { if ((__builtin_expect
(!!(!(*_head == _item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("*_head == _item"), "../src/core/unit.c", 649, __PRETTY_FUNCTION__
); } while (0); *_head = _item->cleanup_queue_next; } _item
->cleanup_queue_next = _item->cleanup_queue_prev = ((void
*)0); } while (0)
;
650
651 if (u->in_target_deps_queue)
652 LIST_REMOVE(target_deps_queue, u->manager->target_deps_queue, u)do { typeof(*(u->manager->target_deps_queue)) **_head =
&(u->manager->target_deps_queue), *_item = (u); do
{ if ((__builtin_expect(!!(!(_item)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("_item"), "../src/core/unit.c", 652, __PRETTY_FUNCTION__
); } while (0); if (_item->target_deps_queue_next) _item->
target_deps_queue_next->target_deps_queue_prev = _item->
target_deps_queue_prev; if (_item->target_deps_queue_prev)
_item->target_deps_queue_prev->target_deps_queue_next =
_item->target_deps_queue_next; else { do { if ((__builtin_expect
(!!(!(*_head == _item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("*_head == _item"), "../src/core/unit.c", 652, __PRETTY_FUNCTION__
); } while (0); *_head = _item->target_deps_queue_next; } _item
->target_deps_queue_next = _item->target_deps_queue_prev
= ((void*)0); } while (0)
;
653
654 if (u->in_stop_when_unneeded_queue)
655 LIST_REMOVE(stop_when_unneeded_queue, u->manager->stop_when_unneeded_queue, u)do { typeof(*(u->manager->stop_when_unneeded_queue)) **
_head = &(u->manager->stop_when_unneeded_queue), *_item
= (u); do { if ((__builtin_expect(!!(!(_item)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("_item"), "../src/core/unit.c", 655, __PRETTY_FUNCTION__
); } while (0); if (_item->stop_when_unneeded_queue_next) _item
->stop_when_unneeded_queue_next->stop_when_unneeded_queue_prev
= _item->stop_when_unneeded_queue_prev; if (_item->stop_when_unneeded_queue_prev
) _item->stop_when_unneeded_queue_prev->stop_when_unneeded_queue_next
= _item->stop_when_unneeded_queue_next; else { do { if ((
__builtin_expect(!!(!(*_head == _item)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("*_head == _item"), "../src/core/unit.c"
, 655, __PRETTY_FUNCTION__); } while (0); *_head = _item->
stop_when_unneeded_queue_next; } _item->stop_when_unneeded_queue_next
= _item->stop_when_unneeded_queue_prev = ((void*)0); } while
(0)
;
656
657 safe_close(u->ip_accounting_ingress_map_fd);
658 safe_close(u->ip_accounting_egress_map_fd);
659
660 safe_close(u->ipv4_allow_map_fd);
661 safe_close(u->ipv6_allow_map_fd);
662 safe_close(u->ipv4_deny_map_fd);
663 safe_close(u->ipv6_deny_map_fd);
664
665 bpf_program_unref(u->ip_bpf_ingress);
666 bpf_program_unref(u->ip_bpf_ingress_installed);
667 bpf_program_unref(u->ip_bpf_egress);
668 bpf_program_unref(u->ip_bpf_egress_installed);
669
670 condition_free_list(u->conditions);
671 condition_free_list(u->asserts);
672
673 free(u->description);
674 strv_free(u->documentation);
675 free(u->fragment_path);
676 free(u->source_path);
677 strv_free(u->dropin_paths);
678 free(u->instance);
679
680 free(u->job_timeout_reboot_arg);
681
682 set_free_free(u->names);
683
684 free(u->reboot_arg);
685
686 free(u);
687}
688
689FreezerState unit_freezer_state(Unit *u) {
690 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 690, __PRETTY_FUNCTION__
); } while (0)
;
691
692 return u->freezer_state;
693}
694
695int unit_freezer_state_kernel(Unit *u, FreezerState *ret) {
696 char *values[1] = {};
697 int r;
698
699 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 699, __PRETTY_FUNCTION__
); } while (0)
;
700
701 r = cg_get_keyed_attribute(SYSTEMD_CGROUP_CONTROLLER"_systemd", u->cgroup_path, "cgroup.events",
702 STRV_MAKE("frozen")((char**) ((const char*[]) { "frozen", ((void*)0) })), values);
703 if (r < 0)
704 return r;
705
706 r = _FREEZER_STATE_INVALID;
707
708 if (values[0]) {
709 if (streq(values[0], "0")(strcmp((values[0]),("0")) == 0))
710 r = FREEZER_RUNNING;
711 else if (streq(values[0], "1")(strcmp((values[0]),("1")) == 0))
712 r = FREEZER_FROZEN;
713 }
714
715 free(values[0]);
716 *ret = r;
717
718 return 0;
719}
720
721UnitActiveState unit_active_state(Unit *u) {
722 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 722, __PRETTY_FUNCTION__
); } while (0)
;
723
724 if (u->load_state == UNIT_MERGED)
725 return unit_active_state(unit_follow_merge(u));
726
727 /* After a reload it might happen that a unit is not correctly
728 * loaded but still has a process around. That's why we won't
729 * shortcut failed loading to UNIT_INACTIVE_FAILED. */
730
731 return UNIT_VTABLE(u)unit_vtable[(u)->type]->active_state(u);
732}
733
734const char* unit_sub_state_to_string(Unit *u) {
735 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 735, __PRETTY_FUNCTION__
); } while (0)
;
736
737 return UNIT_VTABLE(u)unit_vtable[(u)->type]->sub_state_to_string(u);
738}
739
740static int set_complete_move(Set **s, Set **other) {
741 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/core/unit.c", 741, __PRETTY_FUNCTION__
); } while (0)
;
742 assert(other)do { if ((__builtin_expect(!!(!(other)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("other"), "../src/core/unit.c", 742, __PRETTY_FUNCTION__
); } while (0)
;
743
744 if (!other)
745 return 0;
746
747 if (*s)
748 return set_move(*s, *other);
749 else
750 *s = TAKE_PTR(*other)({ typeof(*other) _ptr_ = (*other); (*other) = ((void*)0); _ptr_
; })
;
751
752 return 0;
753}
754
755static int hashmap_complete_move(Hashmap **s, Hashmap **other) {
756 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/core/unit.c", 756, __PRETTY_FUNCTION__
); } while (0)
;
757 assert(other)do { if ((__builtin_expect(!!(!(other)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("other"), "../src/core/unit.c", 757, __PRETTY_FUNCTION__
); } while (0)
;
758
759 if (!*other)
760 return 0;
761
762 if (*s)
763 return hashmap_move(*s, *other);
764 else
765 *s = TAKE_PTR(*other)({ typeof(*other) _ptr_ = (*other); (*other) = ((void*)0); _ptr_
; })
;
766
767 return 0;
768}
769
770static int merge_names(Unit *u, Unit *other) {
771 char *t;
772 Iterator i;
773 int r;
774
775 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 775, __PRETTY_FUNCTION__
); } while (0)
;
776 assert(other)do { if ((__builtin_expect(!!(!(other)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("other"), "../src/core/unit.c", 776, __PRETTY_FUNCTION__
); } while (0)
;
777
778 r = set_complete_move(&u->names, &other->names);
779 if (r < 0)
780 return r;
781
782 set_free_free(other->names);
783 other->names = NULL((void*)0);
784 other->id = NULL((void*)0);
785
786 SET_FOREACH(t, u->names, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); set_iterate((u->names), &(i)
, (void**)&(t)); )
787 assert_se(hashmap_replace(u->manager->units, t, u) == 0)do { if ((__builtin_expect(!!(!(hashmap_replace(u->manager
->units, t, u) == 0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("hashmap_replace(u->manager->units, t, u) == 0"), "../src/core/unit.c"
, 787, __PRETTY_FUNCTION__); } while (0)
;
788
789 return 0;
790}
791
792static int reserve_dependencies(Unit *u, Unit *other, UnitDependency d) {
793 unsigned n_reserve;
794
795 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 795, __PRETTY_FUNCTION__
); } while (0)
;
796 assert(other)do { if ((__builtin_expect(!!(!(other)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("other"), "../src/core/unit.c", 796, __PRETTY_FUNCTION__
); } while (0)
;
797 assert(d < _UNIT_DEPENDENCY_MAX)do { if ((__builtin_expect(!!(!(d < _UNIT_DEPENDENCY_MAX))
,0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("d < _UNIT_DEPENDENCY_MAX"
), "../src/core/unit.c", 797, __PRETTY_FUNCTION__); } while (
0)
;
798
799 /*
800 * If u does not have this dependency set allocated, there is no need
801 * to reserve anything. In that case other's set will be transferred
802 * as a whole to u by complete_move().
803 */
804 if (!u->dependencies[d])
805 return 0;
806
807 /* merge_dependencies() will skip a u-on-u dependency */
808 n_reserve = hashmap_size(other->dependencies[d]) - !!hashmap_get(other->dependencies[d], u);
809
810 return hashmap_reserve(u->dependencies[d], n_reserve);
811}
812
813static void merge_dependencies(Unit *u, Unit *other, const char *other_id, UnitDependency d) {
814 Iterator i;
815 Unit *back;
816 void *v;
817 int r;
818
819 /* Merges all dependencies of type 'd' of the unit 'other' into the deps of the unit 'u' */
820
821 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 821, __PRETTY_FUNCTION__
); } while (0)
;
822 assert(other)do { if ((__builtin_expect(!!(!(other)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("other"), "../src/core/unit.c", 822, __PRETTY_FUNCTION__
); } while (0)
;
823 assert(d < _UNIT_DEPENDENCY_MAX)do { if ((__builtin_expect(!!(!(d < _UNIT_DEPENDENCY_MAX))
,0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("d < _UNIT_DEPENDENCY_MAX"
), "../src/core/unit.c", 823, __PRETTY_FUNCTION__); } while (
0)
;
824
825 /* Fix backwards pointers. Let's iterate through all dependendent units of the other unit. */
826 HASHMAP_FOREACH_KEY(v, back, other->dependencies[d], i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); hashmap_iterate((other->dependencies
[d]), &(i), (void**)&(v), (const void**) &(back))
; )
{
827 UnitDependency k;
828
829 /* Let's now iterate through the dependencies of that dependencies of the other units, looking for
830 * pointers back, and let's fix them up, to instead point to 'u'. */
831
832 for (k = 0; k < _UNIT_DEPENDENCY_MAX; k++) {
833 if (back == u) {
834 /* Do not add dependencies between u and itself. */
835 if (hashmap_remove(back->dependencies[k], other))
836 maybe_warn_about_dependency(u, other_id, k);
837 } else {
838 UnitDependencyInfo di_u, di_other, di_merged;
839
840 /* Let's drop this dependency between "back" and "other", and let's create it between
841 * "back" and "u" instead. Let's merge the bit masks of the dependency we are moving,
842 * and any such dependency which might already exist */
843
844 di_other.data = hashmap_get(back->dependencies[k], other);
845 if (!di_other.data)
846 continue; /* dependency isn't set, let's try the next one */
847
848 di_u.data = hashmap_get(back->dependencies[k], u);
849
850 di_merged = (UnitDependencyInfo) {
851 .origin_mask = di_u.origin_mask | di_other.origin_mask,
852 .destination_mask = di_u.destination_mask | di_other.destination_mask,
853 };
854
855 r = hashmap_remove_and_replace(back->dependencies[k], other, u, di_merged.data);
856 if (r < 0)
857 log_warning_errno(r, "Failed to remove/replace: back=%s other=%s u=%s: %m", back->id, other_id, u->id)({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/core/unit.c", 857, __func__, "Failed to remove/replace: back=%s other=%s u=%s: %m"
, back->id, other_id, u->id) : -abs(_e); })
;
858 assert(r >= 0)do { if ((__builtin_expect(!!(!(r >= 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("r >= 0"), "../src/core/unit.c", 858,
__PRETTY_FUNCTION__); } while (0)
;
859
860 /* assert_se(hashmap_remove_and_replace(back->dependencies[k], other, u, di_merged.data) >= 0); */
861 }
862 }
863
864 }
865
866 /* Also do not move dependencies on u to itself */
867 back = hashmap_remove(other->dependencies[d], u);
868 if (back)
869 maybe_warn_about_dependency(u, other_id, d);
870
871 /* The move cannot fail. The caller must have performed a reservation. */
872 assert_se(hashmap_complete_move(&u->dependencies[d], &other->dependencies[d]) == 0)do { if ((__builtin_expect(!!(!(hashmap_complete_move(&u->
dependencies[d], &other->dependencies[d]) == 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("hashmap_complete_move(&u->dependencies[d], &other->dependencies[d]) == 0"
), "../src/core/unit.c", 872, __PRETTY_FUNCTION__); } while (
0)
;
873
874 other->dependencies[d] = hashmap_free(other->dependencies[d]);
875}
876
877int unit_merge(Unit *u, Unit *other) {
878 UnitDependency d;
879 const char *other_id = NULL((void*)0);
880 int r;
881
882 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 882, __PRETTY_FUNCTION__
); } while (0)
;
883 assert(other)do { if ((__builtin_expect(!!(!(other)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("other"), "../src/core/unit.c", 883, __PRETTY_FUNCTION__
); } while (0)
;
884 assert(u->manager == other->manager)do { if ((__builtin_expect(!!(!(u->manager == other->manager
)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("u->manager == other->manager"
), "../src/core/unit.c", 884, __PRETTY_FUNCTION__); } while (
0)
;
885 assert(u->type != _UNIT_TYPE_INVALID)do { if ((__builtin_expect(!!(!(u->type != _UNIT_TYPE_INVALID
)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("u->type != _UNIT_TYPE_INVALID"
), "../src/core/unit.c", 885, __PRETTY_FUNCTION__); } while (
0)
;
886
887 other = unit_follow_merge(other);
888
889 if (other == u)
890 return 0;
891
892 if (u->type != other->type)
893 return -EINVAL22;
894
895 if (!u->instance != !other->instance)
896 return -EINVAL22;
897
898 if (!unit_type_may_alias(u->type)) /* Merging only applies to unit names that support aliases */
899 return -EEXIST17;
900
901 if (!IN_SET(other->load_state, UNIT_STUB, UNIT_NOT_FOUND)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){UNIT_STUB, UNIT_NOT_FOUND})/sizeof(int)]
; switch(other->load_state) { case UNIT_STUB: case UNIT_NOT_FOUND
: _found = 1; break; default: break; } _found; })
)
902 return -EEXIST17;
903
904 if (other->job)
905 return -EEXIST17;
906
907 if (other->nop_job)
908 return -EEXIST17;
909
910 if (!UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other)))
911 return -EEXIST17;
912
913 if (other->id)
914 other_id = strdupa(other->id)(__extension__ ({ const char *__old = (other->id); size_t __len
= strlen (__old) + 1; char *__new = (char *) __builtin_alloca
(__len); (char *) memcpy (__new, __old, __len); }))
;
915
916 /* Make reservations to ensure merge_dependencies() won't fail */
917 for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) {
918 r = reserve_dependencies(u, other, d);
919 /*
920 * We don't rollback reservations if we fail. We don't have
921 * a way to undo reservations. A reservation is not a leak.
922 */
923 if (r < 0)
924 return r;
925 }
926
927 /* Merge names */
928 r = merge_names(u, other);
929 if (r < 0)
930 return r;
931
932 /* Redirect all references */
933 while (other->refs_by_target)
934 unit_ref_set(other->refs_by_target, other->refs_by_target->source, u);
935
936 /* Merge dependencies */
937 for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++)
938 merge_dependencies(u, other, other_id, d);
939
940 other->load_state = UNIT_MERGED;
941 other->merged_into = u;
942
943 /* If there is still some data attached to the other node, we
944 * don't need it anymore, and can free it. */
945 if (other->load_state != UNIT_STUB)
946 if (UNIT_VTABLE(other)unit_vtable[(other)->type]->done)
947 UNIT_VTABLE(other)unit_vtable[(other)->type]->done(other);
948
949 unit_add_to_dbus_queue(u);
950 unit_add_to_cleanup_queue(other);
951
952 return 0;
953}
954
955int unit_merge_by_name(Unit *u, const char *name) {
956 _cleanup_free___attribute__((cleanup(freep))) char *s = NULL((void*)0);
957 Unit *other;
958 int r;
959
960 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 960, __PRETTY_FUNCTION__
); } while (0)
;
961 assert(name)do { if ((__builtin_expect(!!(!(name)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("name"), "../src/core/unit.c", 961, __PRETTY_FUNCTION__
); } while (0)
;
962
963 if (unit_name_is_valid(name, UNIT_NAME_TEMPLATE)) {
964 if (!u->instance)
965 return -EINVAL22;
966
967 r = unit_name_replace_instance(name, u->instance, &s);
968 if (r < 0)
969 return r;
970
971 name = s;
972 }
973
974 other = manager_get_unit(u->manager, name);
975 if (other)
976 return unit_merge(u, other);
977
978 return unit_add_name(u, name);
979}
980
981Unit* unit_follow_merge(Unit *u) {
982 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 982, __PRETTY_FUNCTION__
); } while (0)
;
983
984 while (u->load_state == UNIT_MERGED)
985 assert_se(u = u->merged_into)do { if ((__builtin_expect(!!(!(u = u->merged_into)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u = u->merged_into"), "../src/core/unit.c"
, 985, __PRETTY_FUNCTION__); } while (0)
;
986
987 return u;
988}
989
990int unit_add_exec_dependencies(Unit *u, ExecContext *c) {
991 ExecDirectoryType dt;
992 char **dp;
993 int r;
994
995 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 995, __PRETTY_FUNCTION__
); } while (0)
;
1
Assuming 'u' is non-null
2
Taking false branch
3
Loop condition is false. Exiting loop
996 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/core/unit.c", 996, __PRETTY_FUNCTION__
); } while (0)
;
4
Assuming 'c' is non-null
5
Taking false branch
6
Loop condition is false. Exiting loop
997
998 if (c->working_directory) {
7
Assuming field 'working_directory' is non-null
8
Taking true branch
999 r = unit_require_mounts_for(u, c->working_directory, UNIT_DEPENDENCY_FILE);
9
Calling 'unit_require_mounts_for'
1000 if (r < 0)
1001 return r;
1002 }
1003
1004 if (c->root_directory) {
1005 r = unit_require_mounts_for(u, c->root_directory, UNIT_DEPENDENCY_FILE);
1006 if (r < 0)
1007 return r;
1008 }
1009
1010 if (c->root_image) {
1011 r = unit_require_mounts_for(u, c->root_image, UNIT_DEPENDENCY_FILE);
1012 if (r < 0)
1013 return r;
1014 }
1015
1016 for (dt = 0; dt < _EXEC_DIRECTORY_TYPE_MAX; dt++) {
1017 if (!u->manager->prefix[dt])
1018 continue;
1019
1020 STRV_FOREACH(dp, c->directories[dt].paths)for ((dp) = (c->directories[dt].paths); (dp) && *(
dp); (dp)++)
{
1021 _cleanup_free___attribute__((cleanup(freep))) char *p;
1022
1023 p = strjoin(u->manager->prefix[dt], "/", *dp)strjoin_real((u->manager->prefix[dt]), "/", *dp, ((void
*)0))
;
1024 if (!p)
1025 return -ENOMEM12;
1026
1027 r = unit_require_mounts_for(u, p, UNIT_DEPENDENCY_FILE);
1028 if (r < 0)
1029 return r;
1030 }
1031 }
1032
1033 if (!MANAGER_IS_SYSTEM(u->manager)((u->manager)->unit_file_scope == UNIT_FILE_SYSTEM))
1034 return 0;
1035
1036 if (c->private_tmp) {
1037 r = unit_add_dependency_by_name(u, UNIT_AFTER, "tmp.mount", NULL((void*)0), true1, UNIT_DEPENDENCY_FILE);
1038 if (r < 0)
1039 return r;
1040
1041 r = unit_require_mounts_for(u, "/var/tmp", UNIT_DEPENDENCY_FILE);
1042 if (r < 0)
1043 return r;
1044
1045 r = unit_add_dependency_by_name(u, UNIT_AFTER, SPECIAL_TMPFILES_SETUP_SERVICE"systemd-tmpfiles-setup.service", NULL((void*)0), true1, UNIT_DEPENDENCY_FILE);
1046 if (r < 0)
1047 return r;
1048 }
1049
1050 if (!IN_SET(c->std_output,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){EXEC_OUTPUT_JOURNAL, EXEC_OUTPUT_JOURNAL_AND_CONSOLE
, EXEC_OUTPUT_KMSG, EXEC_OUTPUT_KMSG_AND_CONSOLE, EXEC_OUTPUT_SYSLOG
, EXEC_OUTPUT_SYSLOG_AND_CONSOLE})/sizeof(int)]; switch(c->
std_output) { case EXEC_OUTPUT_JOURNAL: case EXEC_OUTPUT_JOURNAL_AND_CONSOLE
: case EXEC_OUTPUT_KMSG: case EXEC_OUTPUT_KMSG_AND_CONSOLE: case
EXEC_OUTPUT_SYSLOG: case EXEC_OUTPUT_SYSLOG_AND_CONSOLE: _found
= 1; break; default: break; } _found; })
1051 EXEC_OUTPUT_JOURNAL, EXEC_OUTPUT_JOURNAL_AND_CONSOLE,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){EXEC_OUTPUT_JOURNAL, EXEC_OUTPUT_JOURNAL_AND_CONSOLE
, EXEC_OUTPUT_KMSG, EXEC_OUTPUT_KMSG_AND_CONSOLE, EXEC_OUTPUT_SYSLOG
, EXEC_OUTPUT_SYSLOG_AND_CONSOLE})/sizeof(int)]; switch(c->
std_output) { case EXEC_OUTPUT_JOURNAL: case EXEC_OUTPUT_JOURNAL_AND_CONSOLE
: case EXEC_OUTPUT_KMSG: case EXEC_OUTPUT_KMSG_AND_CONSOLE: case
EXEC_OUTPUT_SYSLOG: case EXEC_OUTPUT_SYSLOG_AND_CONSOLE: _found
= 1; break; default: break; } _found; })
1052 EXEC_OUTPUT_KMSG, EXEC_OUTPUT_KMSG_AND_CONSOLE,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){EXEC_OUTPUT_JOURNAL, EXEC_OUTPUT_JOURNAL_AND_CONSOLE
, EXEC_OUTPUT_KMSG, EXEC_OUTPUT_KMSG_AND_CONSOLE, EXEC_OUTPUT_SYSLOG
, EXEC_OUTPUT_SYSLOG_AND_CONSOLE})/sizeof(int)]; switch(c->
std_output) { case EXEC_OUTPUT_JOURNAL: case EXEC_OUTPUT_JOURNAL_AND_CONSOLE
: case EXEC_OUTPUT_KMSG: case EXEC_OUTPUT_KMSG_AND_CONSOLE: case
EXEC_OUTPUT_SYSLOG: case EXEC_OUTPUT_SYSLOG_AND_CONSOLE: _found
= 1; break; default: break; } _found; })
1053 EXEC_OUTPUT_SYSLOG, EXEC_OUTPUT_SYSLOG_AND_CONSOLE)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){EXEC_OUTPUT_JOURNAL, EXEC_OUTPUT_JOURNAL_AND_CONSOLE
, EXEC_OUTPUT_KMSG, EXEC_OUTPUT_KMSG_AND_CONSOLE, EXEC_OUTPUT_SYSLOG
, EXEC_OUTPUT_SYSLOG_AND_CONSOLE})/sizeof(int)]; switch(c->
std_output) { case EXEC_OUTPUT_JOURNAL: case EXEC_OUTPUT_JOURNAL_AND_CONSOLE
: case EXEC_OUTPUT_KMSG: case EXEC_OUTPUT_KMSG_AND_CONSOLE: case
EXEC_OUTPUT_SYSLOG: case EXEC_OUTPUT_SYSLOG_AND_CONSOLE: _found
= 1; break; default: break; } _found; })
&&
1054 !IN_SET(c->std_error,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){EXEC_OUTPUT_JOURNAL, EXEC_OUTPUT_JOURNAL_AND_CONSOLE
, EXEC_OUTPUT_KMSG, EXEC_OUTPUT_KMSG_AND_CONSOLE, EXEC_OUTPUT_SYSLOG
, EXEC_OUTPUT_SYSLOG_AND_CONSOLE})/sizeof(int)]; switch(c->
std_error) { case EXEC_OUTPUT_JOURNAL: case EXEC_OUTPUT_JOURNAL_AND_CONSOLE
: case EXEC_OUTPUT_KMSG: case EXEC_OUTPUT_KMSG_AND_CONSOLE: case
EXEC_OUTPUT_SYSLOG: case EXEC_OUTPUT_SYSLOG_AND_CONSOLE: _found
= 1; break; default: break; } _found; })
1055 EXEC_OUTPUT_JOURNAL, EXEC_OUTPUT_JOURNAL_AND_CONSOLE,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){EXEC_OUTPUT_JOURNAL, EXEC_OUTPUT_JOURNAL_AND_CONSOLE
, EXEC_OUTPUT_KMSG, EXEC_OUTPUT_KMSG_AND_CONSOLE, EXEC_OUTPUT_SYSLOG
, EXEC_OUTPUT_SYSLOG_AND_CONSOLE})/sizeof(int)]; switch(c->
std_error) { case EXEC_OUTPUT_JOURNAL: case EXEC_OUTPUT_JOURNAL_AND_CONSOLE
: case EXEC_OUTPUT_KMSG: case EXEC_OUTPUT_KMSG_AND_CONSOLE: case
EXEC_OUTPUT_SYSLOG: case EXEC_OUTPUT_SYSLOG_AND_CONSOLE: _found
= 1; break; default: break; } _found; })
1056 EXEC_OUTPUT_KMSG, EXEC_OUTPUT_KMSG_AND_CONSOLE,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){EXEC_OUTPUT_JOURNAL, EXEC_OUTPUT_JOURNAL_AND_CONSOLE
, EXEC_OUTPUT_KMSG, EXEC_OUTPUT_KMSG_AND_CONSOLE, EXEC_OUTPUT_SYSLOG
, EXEC_OUTPUT_SYSLOG_AND_CONSOLE})/sizeof(int)]; switch(c->
std_error) { case EXEC_OUTPUT_JOURNAL: case EXEC_OUTPUT_JOURNAL_AND_CONSOLE
: case EXEC_OUTPUT_KMSG: case EXEC_OUTPUT_KMSG_AND_CONSOLE: case
EXEC_OUTPUT_SYSLOG: case EXEC_OUTPUT_SYSLOG_AND_CONSOLE: _found
= 1; break; default: break; } _found; })
1057 EXEC_OUTPUT_SYSLOG, EXEC_OUTPUT_SYSLOG_AND_CONSOLE)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){EXEC_OUTPUT_JOURNAL, EXEC_OUTPUT_JOURNAL_AND_CONSOLE
, EXEC_OUTPUT_KMSG, EXEC_OUTPUT_KMSG_AND_CONSOLE, EXEC_OUTPUT_SYSLOG
, EXEC_OUTPUT_SYSLOG_AND_CONSOLE})/sizeof(int)]; switch(c->
std_error) { case EXEC_OUTPUT_JOURNAL: case EXEC_OUTPUT_JOURNAL_AND_CONSOLE
: case EXEC_OUTPUT_KMSG: case EXEC_OUTPUT_KMSG_AND_CONSOLE: case
EXEC_OUTPUT_SYSLOG: case EXEC_OUTPUT_SYSLOG_AND_CONSOLE: _found
= 1; break; default: break; } _found; })
)
1058 return 0;
1059
1060 /* If syslog or kernel logging is requested, make sure our own
1061 * logging daemon is run first. */
1062
1063 r = unit_add_dependency_by_name(u, UNIT_AFTER, SPECIAL_JOURNALD_SOCKET"systemd-journald.socket", NULL((void*)0), true1, UNIT_DEPENDENCY_FILE);
1064 if (r < 0)
1065 return r;
1066
1067 return 0;
1068}
1069
1070const char *unit_description(Unit *u) {
1071 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 1071, __PRETTY_FUNCTION__
); } while (0)
;
1072
1073 if (u->description)
1074 return u->description;
1075
1076 return strna(u->id);
1077}
1078
1079static void print_unit_dependency_mask(FILE *f, const char *kind, UnitDependencyMask mask, bool_Bool *space) {
1080 const struct {
1081 UnitDependencyMask mask;
1082 const char *name;
1083 } table[] = {
1084 { UNIT_DEPENDENCY_FILE, "file" },
1085 { UNIT_DEPENDENCY_IMPLICIT, "implicit" },
1086 { UNIT_DEPENDENCY_DEFAULT, "default" },
1087 { UNIT_DEPENDENCY_UDEV, "udev" },
1088 { UNIT_DEPENDENCY_PATH, "path" },
1089 { UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT, "mountinfo-implicit" },
1090 { UNIT_DEPENDENCY_MOUNTINFO_DEFAULT, "mountinfo-default" },
1091 { UNIT_DEPENDENCY_PROC_SWAP, "proc-swap" },
1092 };
1093 size_t i;
1094
1095 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/core/unit.c", 1095, __PRETTY_FUNCTION__
); } while (0)
;
1096 assert(kind)do { if ((__builtin_expect(!!(!(kind)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("kind"), "../src/core/unit.c", 1096, __PRETTY_FUNCTION__
); } while (0)
;
1097 assert(space)do { if ((__builtin_expect(!!(!(space)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("space"), "../src/core/unit.c", 1097, __PRETTY_FUNCTION__
); } while (0)
;
1098
1099 for (i = 0; i < ELEMENTSOF(table)__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(table), typeof(&*(table))), sizeof(table)/sizeof(
(table)[0]), ((void)0)))
; i++) {
1100
1101 if (mask == 0)
1102 break;
1103
1104 if (FLAGS_SET(mask, table[i].mask)(((mask) & (table[i].mask)) == (table[i].mask))) {
1105 if (*space)
1106 fputc(' ', f);
1107 else
1108 *space = true1;
1109
1110 fputs(kind, f);
1111 fputs("-", f);
1112 fputs(table[i].name, f);
1113
1114 mask &= ~table[i].mask;
1115 }
1116 }
1117
1118 assert(mask == 0)do { if ((__builtin_expect(!!(!(mask == 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("mask == 0"), "../src/core/unit.c", 1118
, __PRETTY_FUNCTION__); } while (0)
;
1119}
1120
1121void unit_dump(Unit *u, FILE *f, const char *prefix) {
1122 char *t, **j;
1123 UnitDependency d;
1124 Iterator i;
1125 const char *prefix2;
1126 char
1127 timestamp0[FORMAT_TIMESTAMP_MAX(3+1+10+1+8+1+6+1+6+1)],
1128 timestamp1[FORMAT_TIMESTAMP_MAX(3+1+10+1+8+1+6+1+6+1)],
1129 timestamp2[FORMAT_TIMESTAMP_MAX(3+1+10+1+8+1+6+1+6+1)],
1130 timestamp3[FORMAT_TIMESTAMP_MAX(3+1+10+1+8+1+6+1+6+1)],
1131 timestamp4[FORMAT_TIMESTAMP_MAX(3+1+10+1+8+1+6+1+6+1)],
1132 timespan[FORMAT_TIMESPAN_MAX64];
1133 Unit *following;
1134 _cleanup_set_free___attribute__((cleanup(set_freep))) Set *following_set = NULL((void*)0);
1135 const char *n;
1136 CGroupMask m;
1137 int r;
1138
1139 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 1139, __PRETTY_FUNCTION__
); } while (0)
;
1140 assert(u->type >= 0)do { if ((__builtin_expect(!!(!(u->type >= 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u->type >= 0"), "../src/core/unit.c"
, 1140, __PRETTY_FUNCTION__); } while (0)
;
1141
1142 prefix = strempty(prefix);
1143 prefix2 = strjoina(prefix, "\t")({ const char *_appendees_[] = { prefix, "\t" }; char *_d_, *
_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__
(__builtin_choose_expr( !__builtin_types_compatible_p(typeof
(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
1144
1145 fprintf(f,
1146 "%s-> Unit %s:\n"
1147 "%s\tDescription: %s\n"
1148 "%s\tInstance: %s\n"
1149 "%s\tUnit Load State: %s\n"
1150 "%s\tUnit Active State: %s\n"
1151 "%s\tState Change Timestamp: %s\n"
1152 "%s\tInactive Exit Timestamp: %s\n"
1153 "%s\tActive Enter Timestamp: %s\n"
1154 "%s\tActive Exit Timestamp: %s\n"
1155 "%s\tInactive Enter Timestamp: %s\n"
1156 "%s\tMay GC: %s\n"
1157 "%s\tNeed Daemon Reload: %s\n"
1158 "%s\tTransient: %s\n"
1159 "%s\tPerpetual: %s\n"
1160 "%s\tGarbage Collection Mode: %s\n"
1161 "%s\tSlice: %s\n"
1162 "%s\tCGroup: %s\n"
1163 "%s\tCGroup realized: %s\n",
1164 prefix, u->id,
1165 prefix, unit_description(u),
1166 prefix, strna(u->instance),
1167 prefix, unit_load_state_to_string(u->load_state),
1168 prefix, unit_active_state_to_string(unit_active_state(u)),
1169 prefix, strna(format_timestamp(timestamp0, sizeof(timestamp0), u->state_change_timestamp.realtime)),
1170 prefix, strna(format_timestamp(timestamp1, sizeof(timestamp1), u->inactive_exit_timestamp.realtime)),
1171 prefix, strna(format_timestamp(timestamp2, sizeof(timestamp2), u->active_enter_timestamp.realtime)),
1172 prefix, strna(format_timestamp(timestamp3, sizeof(timestamp3), u->active_exit_timestamp.realtime)),
1173 prefix, strna(format_timestamp(timestamp4, sizeof(timestamp4), u->inactive_enter_timestamp.realtime)),
1174 prefix, yes_no(unit_may_gc(u)),
1175 prefix, yes_no(unit_need_daemon_reload(u)),
1176 prefix, yes_no(u->transient),
1177 prefix, yes_no(u->perpetual),
1178 prefix, collect_mode_to_string(u->collect_mode),
1179 prefix, strna(unit_slice_name(u)),
1180 prefix, strna(u->cgroup_path),
1181 prefix, yes_no(u->cgroup_realized));
1182
1183 if (u->cgroup_realized_mask != 0) {
1184 _cleanup_free___attribute__((cleanup(freep))) char *s = NULL((void*)0);
1185 (void) cg_mask_to_string(u->cgroup_realized_mask, &s);
1186 fprintf(f, "%s\tCGroup realized mask: %s\n", prefix, strnull(s));
1187 }
1188 if (u->cgroup_enabled_mask != 0) {
1189 _cleanup_free___attribute__((cleanup(freep))) char *s = NULL((void*)0);
1190 (void) cg_mask_to_string(u->cgroup_enabled_mask, &s);
1191 fprintf(f, "%s\tCGroup enabled mask: %s\n", prefix, strnull(s));
1192 }
1193 m = unit_get_own_mask(u);
1194 if (m != 0) {
1195 _cleanup_free___attribute__((cleanup(freep))) char *s = NULL((void*)0);
1196 (void) cg_mask_to_string(m, &s);
1197 fprintf(f, "%s\tCGroup own mask: %s\n", prefix, strnull(s));
1198 }
1199 m = unit_get_members_mask(u);
1200 if (m != 0) {
1201 _cleanup_free___attribute__((cleanup(freep))) char *s = NULL((void*)0);
1202 (void) cg_mask_to_string(m, &s);
1203 fprintf(f, "%s\tCGroup members mask: %s\n", prefix, strnull(s));
1204 }
1205
1206 SET_FOREACH(t, u->names, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); set_iterate((u->names), &(i)
, (void**)&(t)); )
1207 fprintf(f, "%s\tName: %s\n", prefix, t);
1208
1209 if (!sd_id128_is_null(u->invocation_id))
1210 fprintf(f, "%s\tInvocation ID: " SD_ID128_FORMAT_STR"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" "\n",
1211 prefix, SD_ID128_FORMAT_VAL(u->invocation_id)(u->invocation_id).bytes[0], (u->invocation_id).bytes[1
], (u->invocation_id).bytes[2], (u->invocation_id).bytes
[3], (u->invocation_id).bytes[4], (u->invocation_id).bytes
[5], (u->invocation_id).bytes[6], (u->invocation_id).bytes
[7], (u->invocation_id).bytes[8], (u->invocation_id).bytes
[9], (u->invocation_id).bytes[10], (u->invocation_id).bytes
[11], (u->invocation_id).bytes[12], (u->invocation_id).
bytes[13], (u->invocation_id).bytes[14], (u->invocation_id
).bytes[15]
);
1212
1213 STRV_FOREACH(j, u->documentation)for ((j) = (u->documentation); (j) && *(j); (j)++)
1214 fprintf(f, "%s\tDocumentation: %s\n", prefix, *j);
1215
1216 following = unit_following(u);
1217 if (following)
1218 fprintf(f, "%s\tFollowing: %s\n", prefix, following->id);
1219
1220 r = unit_following_set(u, &following_set);
1221 if (r >= 0) {
1222 Unit *other;
1223
1224 SET_FOREACH(other, following_set, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); set_iterate((following_set), &(
i), (void**)&(other)); )
1225 fprintf(f, "%s\tFollowing Set Member: %s\n", prefix, other->id);
1226 }
1227
1228 if (u->fragment_path)
1229 fprintf(f, "%s\tFragment Path: %s\n", prefix, u->fragment_path);
1230
1231 if (u->source_path)
1232 fprintf(f, "%s\tSource Path: %s\n", prefix, u->source_path);
1233
1234 STRV_FOREACH(j, u->dropin_paths)for ((j) = (u->dropin_paths); (j) && *(j); (j)++)
1235 fprintf(f, "%s\tDropIn Path: %s\n", prefix, *j);
1236
1237 if (u->failure_action != EMERGENCY_ACTION_NONE)
1238 fprintf(f, "%s\tFailure Action: %s\n", prefix, emergency_action_to_string(u->failure_action));
1239 if (u->success_action != EMERGENCY_ACTION_NONE)
1240 fprintf(f, "%s\tSuccess Action: %s\n", prefix, emergency_action_to_string(u->success_action));
1241
1242 if (u->job_timeout != USEC_INFINITY((usec_t) -1))
1243 fprintf(f, "%s\tJob Timeout: %s\n", prefix, format_timespan(timespan, sizeof(timespan), u->job_timeout, 0));
1244
1245 if (u->job_timeout_action != EMERGENCY_ACTION_NONE)
1246 fprintf(f, "%s\tJob Timeout Action: %s\n", prefix, emergency_action_to_string(u->job_timeout_action));
1247
1248 if (u->job_timeout_reboot_arg)
1249 fprintf(f, "%s\tJob Timeout Reboot Argument: %s\n", prefix, u->job_timeout_reboot_arg);
1250
1251 condition_dump_list(u->conditions, f, prefix, condition_type_to_string);
1252 condition_dump_list(u->asserts, f, prefix, assert_type_to_string);
1253
1254 if (dual_timestamp_is_set(&u->condition_timestamp))
1255 fprintf(f,
1256 "%s\tCondition Timestamp: %s\n"
1257 "%s\tCondition Result: %s\n",
1258 prefix, strna(format_timestamp(timestamp1, sizeof(timestamp1), u->condition_timestamp.realtime)),
1259 prefix, yes_no(u->condition_result));
1260
1261 if (dual_timestamp_is_set(&u->assert_timestamp))
1262 fprintf(f,
1263 "%s\tAssert Timestamp: %s\n"
1264 "%s\tAssert Result: %s\n",
1265 prefix, strna(format_timestamp(timestamp1, sizeof(timestamp1), u->assert_timestamp.realtime)),
1266 prefix, yes_no(u->assert_result));
1267
1268 for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) {
1269 UnitDependencyInfo di;
1270 Unit *other;
1271
1272 HASHMAP_FOREACH_KEY(di.data, other, u->dependencies[d], i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); hashmap_iterate((u->dependencies
[d]), &(i), (void**)&(di.data), (const void**) &(
other)); )
{
1273 bool_Bool space = false0;
1274
1275 fprintf(f, "%s\t%s: %s (", prefix, unit_dependency_to_string(d), other->id);
1276
1277 print_unit_dependency_mask(f, "origin", di.origin_mask, &space);
1278 print_unit_dependency_mask(f, "destination", di.destination_mask, &space);
1279
1280 fputs(")\n", f);
1281 }
1282 }
1283
1284 if (!hashmap_isempty(u->requires_mounts_for)) {
1285 UnitDependencyInfo di;
1286 const char *path;
1287
1288 HASHMAP_FOREACH_KEY(di.data, path, u->requires_mounts_for, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); hashmap_iterate((u->requires_mounts_for
), &(i), (void**)&(di.data), (const void**) &(path
)); )
{
1289 bool_Bool space = false0;
1290
1291 fprintf(f, "%s\tRequiresMountsFor: %s (", prefix, path);
1292
1293 print_unit_dependency_mask(f, "origin", di.origin_mask, &space);
1294 print_unit_dependency_mask(f, "destination", di.destination_mask, &space);
1295
1296 fputs(")\n", f);
1297 }
1298 }
1299
1300 if (u->load_state == UNIT_LOADED) {
1301
1302 fprintf(f,
1303 "%s\tStopWhenUnneeded: %s\n"
1304 "%s\tRefuseManualStart: %s\n"
1305 "%s\tRefuseManualStop: %s\n"
1306 "%s\tDefaultDependencies: %s\n"
1307 "%s\tOnFailureJobMode: %s\n"
1308 "%s\tIgnoreOnIsolate: %s\n",
1309 prefix, yes_no(u->stop_when_unneeded),
1310 prefix, yes_no(u->refuse_manual_start),
1311 prefix, yes_no(u->refuse_manual_stop),
1312 prefix, yes_no(u->default_dependencies),
1313 prefix, job_mode_to_string(u->on_failure_job_mode),
1314 prefix, yes_no(u->ignore_on_isolate));
1315
1316 if (UNIT_VTABLE(u)unit_vtable[(u)->type]->dump)
1317 UNIT_VTABLE(u)unit_vtable[(u)->type]->dump(u, f, prefix2);
1318
1319 } else if (u->load_state == UNIT_MERGED)
1320 fprintf(f,
1321 "%s\tMerged into: %s\n",
1322 prefix, u->merged_into->id);
1323 else if (u->load_state == UNIT_ERROR)
1324 fprintf(f, "%s\tLoad Error Code: %s\n", prefix, strerror(-u->load_error));
1325
1326 for (n = sd_bus_track_first(u->bus_track); n; n = sd_bus_track_next(u->bus_track))
1327 fprintf(f, "%s\tBus Ref: %s\n", prefix, n);
1328
1329 if (u->job)
1330 job_dump(u->job, f, prefix2);
1331
1332 if (u->nop_job)
1333 job_dump(u->nop_job, f, prefix2);
1334}
1335
1336/* Common implementation for multiple backends */
1337int unit_load_fragment_and_dropin(Unit *u) {
1338 int r;
1339
1340 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 1340, __PRETTY_FUNCTION__
); } while (0)
;
1341
1342 /* Load a .{service,socket,...} file */
1343 r = unit_load_fragment(u);
1344 if (r < 0)
1345 return r;
1346
1347 if (u->load_state == UNIT_STUB)
1348 return -ENOENT2;
1349
1350 /* Load drop-in directory data. If u is an alias, we might be reloading the
1351 * target unit needlessly. But we cannot be sure which drops-ins have already
1352 * been loaded and which not, at least without doing complicated book-keeping,
1353 * so let's always reread all drop-ins. */
1354 return unit_load_dropin(unit_follow_merge(u));
1355}
1356
1357/* Common implementation for multiple backends */
1358int unit_load_fragment_and_dropin_optional(Unit *u) {
1359 int r;
1360
1361 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 1361, __PRETTY_FUNCTION__
); } while (0)
;
1362
1363 /* Same as unit_load_fragment_and_dropin(), but whether
1364 * something can be loaded or not doesn't matter. */
1365
1366 /* Load a .service/.socket/.slice/… file */
1367 r = unit_load_fragment(u);
1368 if (r < 0)
1369 return r;
1370
1371 if (u->load_state == UNIT_STUB)
1372 u->load_state = UNIT_LOADED;
1373
1374 /* Load drop-in directory data */
1375 return unit_load_dropin(unit_follow_merge(u));
1376}
1377
1378void unit_add_to_target_deps_queue(Unit *u) {
1379 Manager *m = u->manager;
1380
1381 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 1381, __PRETTY_FUNCTION__
); } while (0)
;
1382
1383 if (u->in_target_deps_queue)
1384 return;
1385
1386 LIST_PREPEND(target_deps_queue, m->target_deps_queue, u)do { typeof(*(m->target_deps_queue)) **_head = &(m->
target_deps_queue), *_item = (u); do { if ((__builtin_expect(
!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, (
"_item"), "../src/core/unit.c", 1386, __PRETTY_FUNCTION__); }
while (0); if ((_item->target_deps_queue_next = *_head)) _item
->target_deps_queue_next->target_deps_queue_prev = _item
; _item->target_deps_queue_prev = ((void*)0); *_head = _item
; } while (0)
;
1387 u->in_target_deps_queue = true1;
1388}
1389
1390int unit_add_default_target_dependency(Unit *u, Unit *target) {
1391 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 1391, __PRETTY_FUNCTION__
); } while (0)
;
1392 assert(target)do { if ((__builtin_expect(!!(!(target)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("target"), "../src/core/unit.c", 1392, __PRETTY_FUNCTION__
); } while (0)
;
1393
1394 if (target->type != UNIT_TARGET)
1395 return 0;
1396
1397 /* Only add the dependency if both units are loaded, so that
1398 * that loop check below is reliable */
1399 if (u->load_state != UNIT_LOADED ||
1400 target->load_state != UNIT_LOADED)
1401 return 0;
1402
1403 /* If either side wants no automatic dependencies, then let's
1404 * skip this */
1405 if (!u->default_dependencies ||
1406 !target->default_dependencies)
1407 return 0;
1408
1409 /* Don't create loops */
1410 if (hashmap_get(target->dependencies[UNIT_BEFORE], u))
1411 return 0;
1412
1413 return unit_add_dependency(target, UNIT_AFTER, u, true1, UNIT_DEPENDENCY_DEFAULT);
1414}
1415
1416static int unit_add_slice_dependencies(Unit *u) {
1417 UnitDependencyMask mask;
1418 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 1418, __PRETTY_FUNCTION__
); } while (0)
;
1419
1420 if (!UNIT_HAS_CGROUP_CONTEXT(u)(unit_vtable[(u)->type]->cgroup_context_offset > 0))
1421 return 0;
1422
1423 /* Slice units are implicitly ordered against their parent slices (as this relationship is encoded in the
1424 name), while all other units are ordered based on configuration (as in their case Slice= configures the
1425 relationship). */
1426 mask = u->type == UNIT_SLICE ? UNIT_DEPENDENCY_IMPLICIT : UNIT_DEPENDENCY_FILE;
1427
1428 if (UNIT_ISSET(u->slice)(!!(u->slice).target))
1429 return unit_add_two_dependencies(u, UNIT_AFTER, UNIT_REQUIRES, UNIT_DEREF(u->slice)((u->slice).target), true1, mask);
1430
1431 if (unit_has_name(u, SPECIAL_ROOT_SLICE"-.slice"))
1432 return 0;
1433
1434 return unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_REQUIRES, SPECIAL_ROOT_SLICE"-.slice", NULL((void*)0), true1, mask);
1435}
1436
1437static int unit_add_mount_dependencies(Unit *u) {
1438 UnitDependencyInfo di;
1439 const char *path;
1440 Iterator i;
1441 int r;
1442
1443 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 1443, __PRETTY_FUNCTION__
); } while (0)
;
1444
1445 HASHMAP_FOREACH_KEY(di.data, path, u->requires_mounts_for, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); hashmap_iterate((u->requires_mounts_for
), &(i), (void**)&(di.data), (const void**) &(path
)); )
{
1446 char prefix[strlen(path) + 1];
1447
1448 PATH_FOREACH_PREFIX_MORE(prefix, path)for (char *_slash = ({ path_simplify(strcpy(prefix, path), 0)
; if ((strcmp((prefix),("/")) == 0)) prefix[0] = 0; strrchr(prefix
, 0); }); _slash && ((*_slash = 0), 1); _slash = strrchr
((prefix), '/'))
{
1449 _cleanup_free___attribute__((cleanup(freep))) char *p = NULL((void*)0);
1450 Unit *m;
1451
1452 r = unit_name_from_path(prefix, ".mount", &p);
1453 if (r < 0)
1454 return r;
1455
1456 m = manager_get_unit(u->manager, p);
1457 if (!m) {
1458 /* Make sure to load the mount unit if
1459 * it exists. If so the dependencies
1460 * on this unit will be added later
1461 * during the loading of the mount
1462 * unit. */
1463 (void) manager_load_unit_prepare(u->manager, p, NULL((void*)0), NULL((void*)0), &m);
1464 continue;
1465 }
1466 if (m == u)
1467 continue;
1468
1469 if (m->load_state != UNIT_LOADED)
1470 continue;
1471
1472 r = unit_add_dependency(u, UNIT_AFTER, m, true1, di.origin_mask);
1473 if (r < 0)
1474 return r;
1475
1476 if (m->fragment_path && !streq(m->id, "tmp.mount")(strcmp((m->id),("tmp.mount")) == 0)) {
1477 r = unit_add_dependency(u, UNIT_REQUIRES, m, true1, di.origin_mask);
1478 if (r < 0)
1479 return r;
1480 }
1481 }
1482 }
1483
1484 return 0;
1485}
1486
1487static int unit_add_startup_units(Unit *u) {
1488 CGroupContext *c;
1489 int r;
1490
1491 c = unit_get_cgroup_context(u);
1492 if (!c)
1493 return 0;
1494
1495 if (c->startup_cpu_shares == CGROUP_CPU_SHARES_INVALID((uint64_t) -1) &&
1496 c->startup_io_weight == CGROUP_WEIGHT_INVALID((uint64_t) -1) &&
1497 c->startup_blockio_weight == CGROUP_BLKIO_WEIGHT_INVALID((uint64_t) -1))
1498 return 0;
1499
1500 r = set_ensure_allocated(&u->manager->startup_units, NULL)internal_set_ensure_allocated(&u->manager->startup_units
, ((void*)0) )
;
1501 if (r < 0)
1502 return r;
1503
1504 return set_put(u->manager->startup_units, u);
1505}
1506
1507int unit_load(Unit *u) {
1508 int r;
1509
1510 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 1510, __PRETTY_FUNCTION__
); } while (0)
;
1511
1512 if (u->in_load_queue) {
1513 LIST_REMOVE(load_queue, u->manager->load_queue, u)do { typeof(*(u->manager->load_queue)) **_head = &(
u->manager->load_queue), *_item = (u); do { if ((__builtin_expect
(!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD,
("_item"), "../src/core/unit.c", 1513, __PRETTY_FUNCTION__);
} while (0); if (_item->load_queue_next) _item->load_queue_next
->load_queue_prev = _item->load_queue_prev; if (_item->
load_queue_prev) _item->load_queue_prev->load_queue_next
= _item->load_queue_next; else { do { if ((__builtin_expect
(!!(!(*_head == _item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("*_head == _item"), "../src/core/unit.c", 1513, __PRETTY_FUNCTION__
); } while (0); *_head = _item->load_queue_next; } _item->
load_queue_next = _item->load_queue_prev = ((void*)0); } while
(0)
;
1514 u->in_load_queue = false0;
1515 }
1516
1517 if (u->type == _UNIT_TYPE_INVALID)
1518 return -EINVAL22;
1519
1520 if (u->load_state != UNIT_STUB)
1521 return 0;
1522
1523 if (u->transient_file) {
1524 r = fflush_and_check(u->transient_file);
1525 if (r < 0)
1526 goto fail;
1527
1528 u->transient_file = safe_fclose(u->transient_file);
1529 u->fragment_mtime = now(CLOCK_REALTIME0);
1530 }
1531
1532 if (UNIT_VTABLE(u)unit_vtable[(u)->type]->load) {
1533 r = UNIT_VTABLE(u)unit_vtable[(u)->type]->load(u);
1534 if (r < 0)
1535 goto fail;
1536 }
1537
1538 if (u->load_state == UNIT_STUB) {
1539 r = -ENOENT2;
1540 goto fail;
1541 }
1542
1543 if (u->load_state == UNIT_LOADED) {
1544 unit_add_to_target_deps_queue(u);
1545
1546 r = unit_add_slice_dependencies(u);
1547 if (r < 0)
1548 goto fail;
1549
1550 r = unit_add_mount_dependencies(u);
1551 if (r < 0)
1552 goto fail;
1553
1554 r = unit_add_startup_units(u);
1555 if (r < 0)
1556 goto fail;
1557
1558 if (u->on_failure_job_mode == JOB_ISOLATE && hashmap_size(u->dependencies[UNIT_ON_FAILURE]) > 1) {
1559 log_unit_error(u, "More than one OnFailure= dependencies specified but OnFailureJobMode=isolate set. Refusing.")({ const Unit *_u = (u); _u ? log_object_internal(3, 0, "../src/core/unit.c"
, 1559, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "More than one OnFailure= dependencies specified but OnFailureJobMode=isolate set. Refusing."
) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3
))), 0, "../src/core/unit.c", 1559, __func__, "More than one OnFailure= dependencies specified but OnFailureJobMode=isolate set. Refusing."
); })
;
1560 r = -ENOEXEC8;
1561 goto fail;
1562 }
1563
1564 if (u->job_running_timeout != USEC_INFINITY((usec_t) -1) && u->job_running_timeout > u->job_timeout)
1565 log_unit_warning(u, "JobRunningTimeoutSec= is greater than JobTimeoutSec=, it has no effect.")({ const Unit *_u = (u); _u ? log_object_internal(4, 0, "../src/core/unit.c"
, 1565, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "JobRunningTimeoutSec= is greater than JobTimeoutSec=, it has no effect."
) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4
))), 0, "../src/core/unit.c", 1565, __func__, "JobRunningTimeoutSec= is greater than JobTimeoutSec=, it has no effect."
); })
;
1566
1567 unit_update_cgroup_members_masks(u);
1568 }
1569
1570 assert((u->load_state != UNIT_MERGED) == !u->merged_into)do { if ((__builtin_expect(!!(!((u->load_state != UNIT_MERGED
) == !u->merged_into)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("(u->load_state != UNIT_MERGED) == !u->merged_into")
, "../src/core/unit.c", 1570, __PRETTY_FUNCTION__); } while (
0)
;
1571
1572 unit_add_to_dbus_queue(unit_follow_merge(u));
1573 unit_add_to_gc_queue(u);
1574
1575 return 0;
1576
1577fail:
1578 /* We convert ENOEXEC errors to the UNIT_BAD_SETTING load state here. Configuration parsing code should hence
1579 * return ENOEXEC to ensure units are placed in this state after loading */
1580
1581 u->load_state = u->load_state == UNIT_STUB ? UNIT_NOT_FOUND :
1582 r == -ENOEXEC8 ? UNIT_BAD_SETTING :
1583 UNIT_ERROR;
1584 u->load_error = r;
1585
1586 unit_add_to_dbus_queue(u);
1587 unit_add_to_gc_queue(u);
1588
1589 return log_unit_debug_errno(u, r, "Failed to load configuration: %m")({ const Unit *_u = (u); _u ? log_object_internal(7, r, "../src/core/unit.c"
, 1589, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to load configuration: %m") : log_internal_realm(((
LOG_REALM_SYSTEMD) << 10 | ((7))), r, "../src/core/unit.c"
, 1589, __func__, "Failed to load configuration: %m"); })
;
1590}
1591
1592static bool_Bool unit_condition_test_list(Unit *u, Condition *first, const char *(*to_string)(ConditionType t)) {
1593 Condition *c;
1594 int triggered = -1;
1595
1596 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 1596, __PRETTY_FUNCTION__
); } while (0)
;
1597 assert(to_string)do { if ((__builtin_expect(!!(!(to_string)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("to_string"), "../src/core/unit.c", 1597
, __PRETTY_FUNCTION__); } while (0)
;
1598
1599 /* If the condition list is empty, then it is true */
1600 if (!first)
1601 return true1;
1602
1603 /* Otherwise, if all of the non-trigger conditions apply and
1604 * if any of the trigger conditions apply (unless there are
1605 * none) we return true */
1606 LIST_FOREACH(conditions, c, first)for ((c) = (first); (c); (c) = (c)->conditions_next) {
1607 int r;
1608
1609 r = condition_test(c);
1610 if (r < 0)
1611 log_unit_warning(u,({ const Unit *_u = (u); _u ? log_object_internal(4, 0, "../src/core/unit.c"
, 1616, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Couldn't determine result for %s=%s%s%s, assuming failed: %m"
, to_string(c->type), c->trigger ? "|" : "", c->negate
? "!" : "", c->parameter) : log_internal_realm(((LOG_REALM_SYSTEMD
) << 10 | ((4))), 0, "../src/core/unit.c", 1616, __func__
, "Couldn't determine result for %s=%s%s%s, assuming failed: %m"
, to_string(c->type), c->trigger ? "|" : "", c->negate
? "!" : "", c->parameter); })
1612 "Couldn't determine result for %s=%s%s%s, assuming failed: %m",({ const Unit *_u = (u); _u ? log_object_internal(4, 0, "../src/core/unit.c"
, 1616, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Couldn't determine result for %s=%s%s%s, assuming failed: %m"
, to_string(c->type), c->trigger ? "|" : "", c->negate
? "!" : "", c->parameter) : log_internal_realm(((LOG_REALM_SYSTEMD
) << 10 | ((4))), 0, "../src/core/unit.c", 1616, __func__
, "Couldn't determine result for %s=%s%s%s, assuming failed: %m"
, to_string(c->type), c->trigger ? "|" : "", c->negate
? "!" : "", c->parameter); })
1613 to_string(c->type),({ const Unit *_u = (u); _u ? log_object_internal(4, 0, "../src/core/unit.c"
, 1616, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Couldn't determine result for %s=%s%s%s, assuming failed: %m"
, to_string(c->type), c->trigger ? "|" : "", c->negate
? "!" : "", c->parameter) : log_internal_realm(((LOG_REALM_SYSTEMD
) << 10 | ((4))), 0, "../src/core/unit.c", 1616, __func__
, "Couldn't determine result for %s=%s%s%s, assuming failed: %m"
, to_string(c->type), c->trigger ? "|" : "", c->negate
? "!" : "", c->parameter); })
1614 c->trigger ? "|" : "",({ const Unit *_u = (u); _u ? log_object_internal(4, 0, "../src/core/unit.c"
, 1616, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Couldn't determine result for %s=%s%s%s, assuming failed: %m"
, to_string(c->type), c->trigger ? "|" : "", c->negate
? "!" : "", c->parameter) : log_internal_realm(((LOG_REALM_SYSTEMD
) << 10 | ((4))), 0, "../src/core/unit.c", 1616, __func__
, "Couldn't determine result for %s=%s%s%s, assuming failed: %m"
, to_string(c->type), c->trigger ? "|" : "", c->negate
? "!" : "", c->parameter); })
1615 c->negate ? "!" : "",({ const Unit *_u = (u); _u ? log_object_internal(4, 0, "../src/core/unit.c"
, 1616, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Couldn't determine result for %s=%s%s%s, assuming failed: %m"
, to_string(c->type), c->trigger ? "|" : "", c->negate
? "!" : "", c->parameter) : log_internal_realm(((LOG_REALM_SYSTEMD
) << 10 | ((4))), 0, "../src/core/unit.c", 1616, __func__
, "Couldn't determine result for %s=%s%s%s, assuming failed: %m"
, to_string(c->type), c->trigger ? "|" : "", c->negate
? "!" : "", c->parameter); })
1616 c->parameter)({ const Unit *_u = (u); _u ? log_object_internal(4, 0, "../src/core/unit.c"
, 1616, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Couldn't determine result for %s=%s%s%s, assuming failed: %m"
, to_string(c->type), c->trigger ? "|" : "", c->negate
? "!" : "", c->parameter) : log_internal_realm(((LOG_REALM_SYSTEMD
) << 10 | ((4))), 0, "../src/core/unit.c", 1616, __func__
, "Couldn't determine result for %s=%s%s%s, assuming failed: %m"
, to_string(c->type), c->trigger ? "|" : "", c->negate
? "!" : "", c->parameter); })
;
1617 else
1618 log_unit_debug(u,({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/unit.c"
, 1624, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "%s=%s%s%s %s.", to_string(c->type), c->trigger ? "|"
: "", c->negate ? "!" : "", c->parameter, condition_result_to_string
(c->result)) : log_internal_realm(((LOG_REALM_SYSTEMD) <<
10 | ((7))), 0, "../src/core/unit.c", 1624, __func__, "%s=%s%s%s %s."
, to_string(c->type), c->trigger ? "|" : "", c->negate
? "!" : "", c->parameter, condition_result_to_string(c->
result)); })
1619 "%s=%s%s%s %s.",({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/unit.c"
, 1624, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "%s=%s%s%s %s.", to_string(c->type), c->trigger ? "|"
: "", c->negate ? "!" : "", c->parameter, condition_result_to_string
(c->result)) : log_internal_realm(((LOG_REALM_SYSTEMD) <<
10 | ((7))), 0, "../src/core/unit.c", 1624, __func__, "%s=%s%s%s %s."
, to_string(c->type), c->trigger ? "|" : "", c->negate
? "!" : "", c->parameter, condition_result_to_string(c->
result)); })
1620 to_string(c->type),({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/unit.c"
, 1624, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "%s=%s%s%s %s.", to_string(c->type), c->trigger ? "|"
: "", c->negate ? "!" : "", c->parameter, condition_result_to_string
(c->result)) : log_internal_realm(((LOG_REALM_SYSTEMD) <<
10 | ((7))), 0, "../src/core/unit.c", 1624, __func__, "%s=%s%s%s %s."
, to_string(c->type), c->trigger ? "|" : "", c->negate
? "!" : "", c->parameter, condition_result_to_string(c->
result)); })
1621 c->trigger ? "|" : "",({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/unit.c"
, 1624, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "%s=%s%s%s %s.", to_string(c->type), c->trigger ? "|"
: "", c->negate ? "!" : "", c->parameter, condition_result_to_string
(c->result)) : log_internal_realm(((LOG_REALM_SYSTEMD) <<
10 | ((7))), 0, "../src/core/unit.c", 1624, __func__, "%s=%s%s%s %s."
, to_string(c->type), c->trigger ? "|" : "", c->negate
? "!" : "", c->parameter, condition_result_to_string(c->
result)); })
1622 c->negate ? "!" : "",({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/unit.c"
, 1624, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "%s=%s%s%s %s.", to_string(c->type), c->trigger ? "|"
: "", c->negate ? "!" : "", c->parameter, condition_result_to_string
(c->result)) : log_internal_realm(((LOG_REALM_SYSTEMD) <<
10 | ((7))), 0, "../src/core/unit.c", 1624, __func__, "%s=%s%s%s %s."
, to_string(c->type), c->trigger ? "|" : "", c->negate
? "!" : "", c->parameter, condition_result_to_string(c->
result)); })
1623 c->parameter,({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/unit.c"
, 1624, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "%s=%s%s%s %s.", to_string(c->type), c->trigger ? "|"
: "", c->negate ? "!" : "", c->parameter, condition_result_to_string
(c->result)) : log_internal_realm(((LOG_REALM_SYSTEMD) <<
10 | ((7))), 0, "../src/core/unit.c", 1624, __func__, "%s=%s%s%s %s."
, to_string(c->type), c->trigger ? "|" : "", c->negate
? "!" : "", c->parameter, condition_result_to_string(c->
result)); })
1624 condition_result_to_string(c->result))({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/unit.c"
, 1624, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "%s=%s%s%s %s.", to_string(c->type), c->trigger ? "|"
: "", c->negate ? "!" : "", c->parameter, condition_result_to_string
(c->result)) : log_internal_realm(((LOG_REALM_SYSTEMD) <<
10 | ((7))), 0, "../src/core/unit.c", 1624, __func__, "%s=%s%s%s %s."
, to_string(c->type), c->trigger ? "|" : "", c->negate
? "!" : "", c->parameter, condition_result_to_string(c->
result)); })
;
1625
1626 if (!c->trigger && r <= 0)
1627 return false0;
1628
1629 if (c->trigger && triggered <= 0)
1630 triggered = r > 0;
1631 }
1632
1633 return triggered != 0;
1634}
1635
1636static bool_Bool unit_condition_test(Unit *u) {
1637 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 1637, __PRETTY_FUNCTION__
); } while (0)
;
1638
1639 dual_timestamp_get(&u->condition_timestamp);
1640 u->condition_result = unit_condition_test_list(u, u->conditions, condition_type_to_string);
1641
1642 return u->condition_result;
1643}
1644
1645static bool_Bool unit_assert_test(Unit *u) {
1646 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 1646, __PRETTY_FUNCTION__
); } while (0)
;
1647
1648 dual_timestamp_get(&u->assert_timestamp);
1649 u->assert_result = unit_condition_test_list(u, u->asserts, assert_type_to_string);
1650
1651 return u->assert_result;
1652}
1653
1654void unit_status_printf(Unit *u, const char *status, const char *unit_status_msg_format) {
1655 DISABLE_WARNING_FORMAT_NONLITERALGCC diagnostic push ; GCC diagnostic ignored "-Wformat-nonliteral"
;
1656 manager_status_printf(u->manager, STATUS_TYPE_NORMAL, status, unit_status_msg_format, unit_description(u));
1657 REENABLE_WARNINGGCC diagnostic pop ;
1658}
1659
1660
1661int unit_start_limit_test(Unit *u) {
1662 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 1662, __PRETTY_FUNCTION__
); } while (0)
;
1663
1664 if (ratelimit_below(&u->start_limit)) {
1665 u->start_limit_hit = false0;
1666 return 0;
1667 }
1668
1669 log_unit_warning(u, "Start request repeated too quickly.")({ const Unit *_u = (u); _u ? log_object_internal(4, 0, "../src/core/unit.c"
, 1669, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Start request repeated too quickly.") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((4))), 0, "../src/core/unit.c"
, 1669, __func__, "Start request repeated too quickly."); })
;
1670 u->start_limit_hit = true1;
1671
1672 return emergency_action(u->manager, u->start_limit_action, u->reboot_arg, "unit failed");
1673}
1674
1675bool_Bool unit_shall_confirm_spawn(Unit *u) {
1676 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 1676, __PRETTY_FUNCTION__
); } while (0)
;
1677
1678 if (manager_is_confirm_spawn_disabled(u->manager))
1679 return false0;
1680
1681 /* For some reasons units remaining in the same process group
1682 * as PID 1 fail to acquire the console even if it's not used
1683 * by any process. So skip the confirmation question for them. */
1684 return !unit_get_exec_context(u)->same_pgrp;
1685}
1686
1687static bool_Bool unit_verify_deps(Unit *u) {
1688 Unit *other;
1689 Iterator j;
1690 void *v;
1691
1692 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 1692, __PRETTY_FUNCTION__
); } while (0)
;
1693
1694 /* Checks whether all BindsTo= dependencies of this unit are fulfilled — if they are also combined with
1695 * After=. We do not check Requires= or Requisite= here as they only should have an effect on the job
1696 * processing, but do not have any effect afterwards. We don't check BindsTo= dependencies that are not used in
1697 * conjunction with After= as for them any such check would make things entirely racy. */
1698
1699 HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_BINDS_TO], j)for ((j) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); hashmap_iterate((u->dependencies
[UNIT_BINDS_TO]), &(j), (void**)&(v), (const void**) &
(other)); )
{
1700
1701 if (!hashmap_contains(u->dependencies[UNIT_AFTER], other))
1702 continue;
1703
1704 if (!UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(other))) {
1705 log_unit_notice(u, "Bound to unit %s, but unit isn't active.", other->id)({ const Unit *_u = (u); _u ? log_object_internal(5, 0, "../src/core/unit.c"
, 1705, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Bound to unit %s, but unit isn't active.", other->id) :
log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((5)))
, 0, "../src/core/unit.c", 1705, __func__, "Bound to unit %s, but unit isn't active."
, other->id); })
;
1706 return false0;
1707 }
1708 }
1709
1710 return true1;
1711}
1712
1713/* Errors:
1714 * -EBADR: This unit type does not support starting.
1715 * -EALREADY: Unit is already started.
1716 * -EAGAIN: An operation is already in progress. Retry later.
1717 * -ECANCELED: Too many requests for now.
1718 * -EPROTO: Assert failed
1719 * -EINVAL: Unit not loaded
1720 * -EOPNOTSUPP: Unit type not supported
1721 * -ENOLINK: The necessary dependencies are not fulfilled.
1722 * -ESTALE: This unit has been started before and can't be started a second time
1723 */
1724int unit_start(Unit *u) {
1725 UnitActiveState state;
1726 Unit *following;
1727
1728 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 1728, __PRETTY_FUNCTION__
); } while (0)
;
1729
1730 /* If this is already started, then this will succeed. Note
1731 * that this will even succeed if this unit is not startable
1732 * by the user. This is relied on to detect when we need to
1733 * wait for units and when waiting is finished. */
1734 state = unit_active_state(u);
1735 if (UNIT_IS_ACTIVE_OR_RELOADING(state))
1736 return -EALREADY114;
1737
1738 /* Units that aren't loaded cannot be started */
1739 if (u->load_state != UNIT_LOADED)
1740 return -EINVAL22;
1741
1742 /* Refuse starting scope units more than once */
1743 if (UNIT_VTABLE(u)unit_vtable[(u)->type]->once_only && dual_timestamp_is_set(&u->inactive_enter_timestamp))
1744 return -ESTALE116;
1745
1746 /* If the conditions failed, don't do anything at all. If we
1747 * already are activating this call might still be useful to
1748 * speed up activation in case there is some hold-off time,
1749 * but we don't want to recheck the condition in that case. */
1750 if (state != UNIT_ACTIVATING &&
1751 !unit_condition_test(u)) {
1752 log_unit_debug(u, "Starting requested but condition failed. Not starting unit.")({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/unit.c"
, 1752, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Starting requested but condition failed. Not starting unit."
) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7
))), 0, "../src/core/unit.c", 1752, __func__, "Starting requested but condition failed. Not starting unit."
); })
;
1753 return -EALREADY114;
1754 }
1755
1756 /* If the asserts failed, fail the entire job */
1757 if (state != UNIT_ACTIVATING &&
1758 !unit_assert_test(u)) {
1759 log_unit_notice(u, "Starting requested but asserts failed.")({ const Unit *_u = (u); _u ? log_object_internal(5, 0, "../src/core/unit.c"
, 1759, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Starting requested but asserts failed.") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((5))), 0, "../src/core/unit.c"
, 1759, __func__, "Starting requested but asserts failed."); }
)
;
1760 return -EPROTO71;
1761 }
1762
1763 /* Units of types that aren't supported cannot be
1764 * started. Note that we do this test only after the condition
1765 * checks, so that we rather return condition check errors
1766 * (which are usually not considered a true failure) than "not
1767 * supported" errors (which are considered a failure).
1768 */
1769 if (!unit_supported(u))
1770 return -EOPNOTSUPP95;
1771
1772 /* Let's make sure that the deps really are in order before we start this. Normally the job engine should have
1773 * taken care of this already, but let's check this here again. After all, our dependencies might not be in
1774 * effect anymore, due to a reload or due to a failed condition. */
1775 if (!unit_verify_deps(u))
1776 return -ENOLINK67;
1777
1778 /* Forward to the main object, if we aren't it. */
1779 following = unit_following(u);
1780 if (following) {
1781 log_unit_debug(u, "Redirecting start request from %s to %s.", u->id, following->id)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/unit.c"
, 1781, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Redirecting start request from %s to %s.", u->id, following
->id) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10
| ((7))), 0, "../src/core/unit.c", 1781, __func__, "Redirecting start request from %s to %s."
, u->id, following->id); })
;
1782 return unit_start(following);
1783 }
1784
1785 /* If it is stopped, but we cannot start it, then fail */
1786 if (!UNIT_VTABLE(u)unit_vtable[(u)->type]->start)
1787 return -EBADR53;
1788
1789 /* We don't suppress calls to ->start() here when we are
1790 * already starting, to allow this request to be used as a
1791 * "hurry up" call, for example when the unit is in some "auto
1792 * restart" state where it waits for a holdoff timer to elapse
1793 * before it will start again. */
1794
1795 unit_add_to_dbus_queue(u);
1796 unit_cgroup_freezer_action(u, FREEZER_THAW);
1797
1798 return UNIT_VTABLE(u)unit_vtable[(u)->type]->start(u);
1799}
1800
1801bool_Bool unit_can_start(Unit *u) {
1802 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 1802, __PRETTY_FUNCTION__
); } while (0)
;
1803
1804 if (u->load_state != UNIT_LOADED)
1805 return false0;
1806
1807 if (!unit_supported(u))
1808 return false0;
1809
1810 /* Scope units may be started only once */
1811 if (UNIT_VTABLE(u)unit_vtable[(u)->type]->once_only && dual_timestamp_is_set(&u->inactive_exit_timestamp))
1812 return false0;
1813
1814 return !!UNIT_VTABLE(u)unit_vtable[(u)->type]->start;
1815}
1816
1817bool_Bool unit_can_isolate(Unit *u) {
1818 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 1818, __PRETTY_FUNCTION__
); } while (0)
;
1819
1820 return unit_can_start(u) &&
1821 u->allow_isolate;
1822}
1823
1824/* Errors:
1825 * -EBADR: This unit type does not support stopping.
1826 * -EALREADY: Unit is already stopped.
1827 * -EAGAIN: An operation is already in progress. Retry later.
1828 */
1829int unit_stop(Unit *u) {
1830 UnitActiveState state;
1831 Unit *following;
1832
1833 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 1833, __PRETTY_FUNCTION__
); } while (0)
;
1834
1835 state = unit_active_state(u);
1836 if (UNIT_IS_INACTIVE_OR_FAILED(state))
1837 return -EALREADY114;
1838
1839 following = unit_following(u);
1840 if (following) {
1841 log_unit_debug(u, "Redirecting stop request from %s to %s.", u->id, following->id)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/unit.c"
, 1841, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Redirecting stop request from %s to %s.", u->id, following
->id) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10
| ((7))), 0, "../src/core/unit.c", 1841, __func__, "Redirecting stop request from %s to %s."
, u->id, following->id); })
;
1842 return unit_stop(following);
1843 }
1844
1845 if (!UNIT_VTABLE(u)unit_vtable[(u)->type]->stop)
1846 return -EBADR53;
1847
1848 unit_add_to_dbus_queue(u);
1849 unit_cgroup_freezer_action(u, FREEZER_THAW);
1850
1851 return UNIT_VTABLE(u)unit_vtable[(u)->type]->stop(u);
1852}
1853
1854bool_Bool unit_can_stop(Unit *u) {
1855 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 1855, __PRETTY_FUNCTION__
); } while (0)
;
1856
1857 if (!unit_supported(u))
1858 return false0;
1859
1860 if (u->perpetual)
1861 return false0;
1862
1863 return !!UNIT_VTABLE(u)unit_vtable[(u)->type]->stop;
1864}
1865
1866/* Errors:
1867 * -EBADR: This unit type does not support reloading.
1868 * -ENOEXEC: Unit is not started.
1869 * -EAGAIN: An operation is already in progress. Retry later.
1870 */
1871int unit_reload(Unit *u) {
1872 UnitActiveState state;
1873 Unit *following;
1874
1875 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 1875, __PRETTY_FUNCTION__
); } while (0)
;
1876
1877 if (u->load_state != UNIT_LOADED)
1878 return -EINVAL22;
1879
1880 if (!unit_can_reload(u))
1881 return -EBADR53;
1882
1883 state = unit_active_state(u);
1884 if (state == UNIT_RELOADING)
1885 return -EALREADY114;
1886
1887 if (state != UNIT_ACTIVE) {
1888 log_unit_warning(u, "Unit cannot be reloaded because it is inactive.")({ const Unit *_u = (u); _u ? log_object_internal(4, 0, "../src/core/unit.c"
, 1888, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Unit cannot be reloaded because it is inactive.") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((4))), 0, "../src/core/unit.c"
, 1888, __func__, "Unit cannot be reloaded because it is inactive."
); })
;
1889 return -ENOEXEC8;
1890 }
1891
1892 following = unit_following(u);
1893 if (following) {
1894 log_unit_debug(u, "Redirecting reload request from %s to %s.", u->id, following->id)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/unit.c"
, 1894, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Redirecting reload request from %s to %s.", u->id, following
->id) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10
| ((7))), 0, "../src/core/unit.c", 1894, __func__, "Redirecting reload request from %s to %s."
, u->id, following->id); })
;
1895 return unit_reload(following);
1896 }
1897
1898 unit_add_to_dbus_queue(u);
1899
1900 if (!UNIT_VTABLE(u)unit_vtable[(u)->type]->reload) {
1901 /* Unit doesn't have a reload function, but we need to propagate the reload anyway */
1902 unit_notify(u, unit_active_state(u), unit_active_state(u), 0);
1903 return 0;
1904 }
1905
1906 unit_cgroup_freezer_action(u, FREEZER_THAW);
1907
1908 return UNIT_VTABLE(u)unit_vtable[(u)->type]->reload(u);
1909}
1910
1911bool_Bool unit_can_reload(Unit *u) {
1912 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 1912, __PRETTY_FUNCTION__
); } while (0)
;
1913
1914 if (UNIT_VTABLE(u)unit_vtable[(u)->type]->can_reload)
1915 return UNIT_VTABLE(u)unit_vtable[(u)->type]->can_reload(u);
1916
1917 if (!hashmap_isempty(u->dependencies[UNIT_PROPAGATES_RELOAD_TO]))
1918 return true1;
1919
1920 return UNIT_VTABLE(u)unit_vtable[(u)->type]->reload;
1921}
1922
1923bool_Bool unit_is_unneeded(Unit *u) {
1924 static const UnitDependency deps[] = {
1925 UNIT_REQUIRED_BY,
1926 UNIT_REQUISITE_OF,
1927 UNIT_WANTED_BY,
1928 UNIT_BOUND_BY,
1929 };
1930 size_t j;
1931
1932 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 1932, __PRETTY_FUNCTION__
); } while (0)
;
1933
1934 if (!u->stop_when_unneeded)
1935 return false0;
1936
1937 /* Don't clean up while the unit is transitioning or is even inactive. */
1938 if (!UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u)))
1939 return false0;
1940 if (u->job)
1941 return false0;
1942
1943 for (j = 0; j < ELEMENTSOF(deps)__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(deps), typeof(&*(deps))), sizeof(deps)/sizeof((deps
)[0]), ((void)0)))
; j++) {
1944 Unit *other;
1945 Iterator i;
1946 void *v;
1947
1948 /* If a dependending unit has a job queued, or is active (or in transitioning), or is marked for
1949 * restart, then don't clean this one up. */
1950
1951 HASHMAP_FOREACH_KEY(v, other, u->dependencies[deps[j]], i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); hashmap_iterate((u->dependencies
[deps[j]]), &(i), (void**)&(v), (const void**) &(
other)); )
{
1952 if (u->job)
1953 return false0;
1954
1955 if (!UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other)))
1956 return false0;
1957
1958 if (unit_will_restart(other))
1959 return false0;
1960 }
1961 }
1962
1963 return true1;
1964}
1965
1966static void check_unneeded_dependencies(Unit *u) {
1967
1968 static const UnitDependency deps[] = {
1969 UNIT_REQUIRES,
1970 UNIT_REQUISITE,
1971 UNIT_WANTS,
1972 UNIT_BINDS_TO,
1973 };
1974 size_t j;
1975
1976 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 1976, __PRETTY_FUNCTION__
); } while (0)
;
1977
1978 /* Add all units this unit depends on to the queue that processes StopWhenUnneeded= behaviour. */
1979
1980 for (j = 0; j < ELEMENTSOF(deps)__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(deps), typeof(&*(deps))), sizeof(deps)/sizeof((deps
)[0]), ((void)0)))
; j++) {
1981 Unit *other;
1982 Iterator i;
1983 void *v;
1984
1985 HASHMAP_FOREACH_KEY(v, other, u->dependencies[deps[j]], i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); hashmap_iterate((u->dependencies
[deps[j]]), &(i), (void**)&(v), (const void**) &(
other)); )
1986 unit_add_to_stop_when_unneeded_queue(other);
1987 }
1988}
1989
1990static void unit_check_binds_to(Unit *u) {
1991 _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0});
1992 bool_Bool stop = false0;
1993 Unit *other;
1994 Iterator i;
1995 void *v;
1996 int r;
1997
1998 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 1998, __PRETTY_FUNCTION__
); } while (0)
;
1999
2000 if (u->job)
2001 return;
2002
2003 if (unit_active_state(u) != UNIT_ACTIVE)
2004 return;
2005
2006 HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_BINDS_TO], i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); hashmap_iterate((u->dependencies
[UNIT_BINDS_TO]), &(i), (void**)&(v), (const void**) &
(other)); )
{
2007 if (other->job)
2008 continue;
2009
2010 if (!other->coldplugged)
2011 /* We might yet create a job for the other unit… */
2012 continue;
2013
2014 if (!UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other)))
2015 continue;
2016
2017 stop = true1;
2018 break;
2019 }
2020
2021 if (!stop)
2022 return;
2023
2024 /* If stopping a unit fails continuously we might enter a stop
2025 * loop here, hence stop acting on the service being
2026 * unnecessary after a while. */
2027 if (!ratelimit_below(&u->auto_stop_ratelimit)) {
2028 log_unit_warning(u, "Unit is bound to inactive unit %s, but not stopping since we tried this too often recently.", other->id)({ const Unit *_u = (u); _u ? log_object_internal(4, 0, "../src/core/unit.c"
, 2028, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Unit is bound to inactive unit %s, but not stopping since we tried this too often recently."
, other->id) : log_internal_realm(((LOG_REALM_SYSTEMD) <<
10 | ((4))), 0, "../src/core/unit.c", 2028, __func__, "Unit is bound to inactive unit %s, but not stopping since we tried this too often recently."
, other->id); })
;
2029 return;
2030 }
2031
2032 assert(other)do { if ((__builtin_expect(!!(!(other)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("other"), "../src/core/unit.c", 2032, __PRETTY_FUNCTION__
); } while (0)
;
2033 log_unit_info(u, "Unit is bound to inactive unit %s. Stopping, too.", other->id)({ const Unit *_u = (u); _u ? log_object_internal(6, 0, "../src/core/unit.c"
, 2033, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Unit is bound to inactive unit %s. Stopping, too.", other->
id) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | (
(6))), 0, "../src/core/unit.c", 2033, __func__, "Unit is bound to inactive unit %s. Stopping, too."
, other->id); })
;
2034
2035 /* A unit we need to run is gone. Sniff. Let's stop this. */
2036 r = manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, NULL((void*)0), &error, NULL((void*)0));
2037 if (r < 0)
2038 log_unit_warning_errno(u, r, "Failed to enqueue stop job, ignoring: %s", bus_error_message(&error, r))({ const Unit *_u = (u); _u ? log_object_internal(4, r, "../src/core/unit.c"
, 2038, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to enqueue stop job, ignoring: %s", bus_error_message
(&error, r)) : log_internal_realm(((LOG_REALM_SYSTEMD) <<
10 | ((4))), r, "../src/core/unit.c", 2038, __func__, "Failed to enqueue stop job, ignoring: %s"
, bus_error_message(&error, r)); })
;
2039}
2040
2041static void retroactively_start_dependencies(Unit *u) {
2042 Iterator i;
2043 Unit *other;
2044 void *v;
2045
2046 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 2046, __PRETTY_FUNCTION__
); } while (0)
;
2047 assert(UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u)))do { if ((__builtin_expect(!!(!(UNIT_IS_ACTIVE_OR_ACTIVATING(
unit_active_state(u)))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u))"), "../src/core/unit.c"
, 2047, __PRETTY_FUNCTION__); } while (0)
;
2048
2049 HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_REQUIRES], i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); hashmap_iterate((u->dependencies
[UNIT_REQUIRES]), &(i), (void**)&(v), (const void**) &
(other)); )
2050 if (!hashmap_get(u->dependencies[UNIT_AFTER], other) &&
2051 !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
2052 manager_add_job(u->manager, JOB_START, other, JOB_REPLACE, NULL((void*)0), NULL((void*)0), NULL((void*)0));
2053
2054 HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_BINDS_TO], i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); hashmap_iterate((u->dependencies
[UNIT_BINDS_TO]), &(i), (void**)&(v), (const void**) &
(other)); )
2055 if (!hashmap_get(u->dependencies[UNIT_AFTER], other) &&
2056 !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
2057 manager_add_job(u->manager, JOB_START, other, JOB_REPLACE, NULL((void*)0), NULL((void*)0), NULL((void*)0));
2058
2059 HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_WANTS], i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); hashmap_iterate((u->dependencies
[UNIT_WANTS]), &(i), (void**)&(v), (const void**) &
(other)); )
2060 if (!hashmap_get(u->dependencies[UNIT_AFTER], other) &&
2061 !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
2062 manager_add_job(u->manager, JOB_START, other, JOB_FAIL, NULL((void*)0), NULL((void*)0), NULL((void*)0));
2063
2064 HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_CONFLICTS], i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); hashmap_iterate((u->dependencies
[UNIT_CONFLICTS]), &(i), (void**)&(v), (const void**)
&(other)); )
2065 if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
2066 manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, NULL((void*)0), NULL((void*)0), NULL((void*)0));
2067
2068 HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_CONFLICTED_BY], i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); hashmap_iterate((u->dependencies
[UNIT_CONFLICTED_BY]), &(i), (void**)&(v), (const void
**) &(other)); )
2069 if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
2070 manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, NULL((void*)0), NULL((void*)0), NULL((void*)0));
2071}
2072
2073static void retroactively_stop_dependencies(Unit *u) {
2074 Unit *other;
2075 Iterator i;
2076 void *v;
2077
2078 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 2078, __PRETTY_FUNCTION__
); } while (0)
;
2079 assert(UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(u)))do { if ((__builtin_expect(!!(!(UNIT_IS_INACTIVE_OR_DEACTIVATING
(unit_active_state(u)))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(u))"),
"../src/core/unit.c", 2079, __PRETTY_FUNCTION__); } while (0
)
;
2080
2081 /* Pull down units which are bound to us recursively if enabled */
2082 HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_BOUND_BY], i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); hashmap_iterate((u->dependencies
[UNIT_BOUND_BY]), &(i), (void**)&(v), (const void**) &
(other)); )
2083 if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
2084 manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, NULL((void*)0), NULL((void*)0), NULL((void*)0));
2085}
2086
2087void unit_start_on_failure(Unit *u) {
2088 Unit *other;
2089 Iterator i;
2090 void *v;
2091 int r;
2092
2093 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 2093, __PRETTY_FUNCTION__
); } while (0)
;
2094
2095 if (hashmap_size(u->dependencies[UNIT_ON_FAILURE]) <= 0)
2096 return;
2097
2098 log_unit_info(u, "Triggering OnFailure= dependencies.")({ const Unit *_u = (u); _u ? log_object_internal(6, 0, "../src/core/unit.c"
, 2098, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Triggering OnFailure= dependencies.") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((6))), 0, "../src/core/unit.c"
, 2098, __func__, "Triggering OnFailure= dependencies."); })
;
2099
2100 HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_ON_FAILURE], i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); hashmap_iterate((u->dependencies
[UNIT_ON_FAILURE]), &(i), (void**)&(v), (const void**
) &(other)); )
{
2101 _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0});
2102
2103 r = manager_add_job(u->manager, JOB_START, other, u->on_failure_job_mode, NULL((void*)0), &error, NULL((void*)0));
2104 if (r < 0)
2105 log_unit_warning_errno(u, r, "Failed to enqueue OnFailure= job, ignoring: %s", bus_error_message(&error, r))({ const Unit *_u = (u); _u ? log_object_internal(4, r, "../src/core/unit.c"
, 2105, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to enqueue OnFailure= job, ignoring: %s", bus_error_message
(&error, r)) : log_internal_realm(((LOG_REALM_SYSTEMD) <<
10 | ((4))), r, "../src/core/unit.c", 2105, __func__, "Failed to enqueue OnFailure= job, ignoring: %s"
, bus_error_message(&error, r)); })
;
2106 }
2107}
2108
2109void unit_trigger_notify(Unit *u) {
2110 Unit *other;
2111 Iterator i;
2112 void *v;
2113
2114 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 2114, __PRETTY_FUNCTION__
); } while (0)
;
2115
2116 HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_TRIGGERED_BY], i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); hashmap_iterate((u->dependencies
[UNIT_TRIGGERED_BY]), &(i), (void**)&(v), (const void
**) &(other)); )
2117 if (UNIT_VTABLE(other)unit_vtable[(other)->type]->trigger_notify)
2118 UNIT_VTABLE(other)unit_vtable[(other)->type]->trigger_notify(other, u);
2119}
2120
2121static int unit_log_resources(Unit *u) {
2122
2123 struct iovec iovec[1 + _CGROUP_IP_ACCOUNTING_METRIC_MAX + 4];
2124 size_t n_message_parts = 0, n_iovec = 0;
2125 char* message_parts[3 + 1], *t;
2126 nsec_t nsec = NSEC_INFINITY((nsec_t) -1);
2127 CGroupIPAccountingMetric m;
2128 size_t i;
2129 int r;
2130 const char* const ip_fields[_CGROUP_IP_ACCOUNTING_METRIC_MAX] = {
2131 [CGROUP_IP_INGRESS_BYTES] = "IP_METRIC_INGRESS_BYTES",
2132 [CGROUP_IP_INGRESS_PACKETS] = "IP_METRIC_INGRESS_PACKETS",
2133 [CGROUP_IP_EGRESS_BYTES] = "IP_METRIC_EGRESS_BYTES",
2134 [CGROUP_IP_EGRESS_PACKETS] = "IP_METRIC_EGRESS_PACKETS",
2135 };
2136
2137 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 2137, __PRETTY_FUNCTION__
); } while (0)
;
2138
2139 /* Invoked whenever a unit enters failed or dead state. Logs information about consumed resources if resource
2140 * accounting was enabled for a unit. It does this in two ways: a friendly human readable string with reduced
2141 * information and the complete data in structured fields. */
2142
2143 (void) unit_get_cpu_usage(u, &nsec);
2144 if (nsec != NSEC_INFINITY((nsec_t) -1)) {
2145 char buf[FORMAT_TIMESPAN_MAX64] = "";
2146
2147 /* Format the CPU time for inclusion in the structured log message */
2148 if (asprintf(&t, "CPU_USAGE_NSEC=%" PRIu64"l" "u", nsec) < 0) {
2149 r = log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/core/unit.c", 2149
, __func__)
;
2150 goto finish;
2151 }
2152 iovec[n_iovec++] = IOVEC_MAKE_STRING(t)(struct iovec) { .iov_base = ((char*) t), .iov_len = (strlen(
t)) }
;
2153
2154 /* Format the CPU time for inclusion in the human language message string */
2155 format_timespan(buf, sizeof(buf), nsec / NSEC_PER_USEC((nsec_t) 1000ULL), USEC_PER_MSEC((usec_t) 1000ULL));
2156 t = strjoin(n_message_parts > 0 ? "consumed " : "Consumed ", buf, " CPU time")strjoin_real((n_message_parts > 0 ? "consumed " : "Consumed "
), buf, " CPU time", ((void*)0))
;
2157 if (!t) {
2158 r = log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/core/unit.c", 2158
, __func__)
;
2159 goto finish;
2160 }
2161
2162 message_parts[n_message_parts++] = t;
2163 }
2164
2165 for (m = 0; m < _CGROUP_IP_ACCOUNTING_METRIC_MAX; m++) {
2166 char buf[FORMAT_BYTES_MAX8] = "";
2167 uint64_t value = UINT64_MAX(18446744073709551615UL);
2168
2169 assert(ip_fields[m])do { if ((__builtin_expect(!!(!(ip_fields[m])),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ip_fields[m]"), "../src/core/unit.c", 2169
, __PRETTY_FUNCTION__); } while (0)
;
2170
2171 (void) unit_get_ip_accounting(u, m, &value);
2172 if (value == UINT64_MAX(18446744073709551615UL))
2173 continue;
2174
2175 /* Format IP accounting data for inclusion in the structured log message */
2176 if (asprintf(&t, "%s=%" PRIu64"l" "u", ip_fields[m], value) < 0) {
2177 r = log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/core/unit.c", 2177
, __func__)
;
2178 goto finish;
2179 }
2180 iovec[n_iovec++] = IOVEC_MAKE_STRING(t)(struct iovec) { .iov_base = ((char*) t), .iov_len = (strlen(
t)) }
;
2181
2182 /* Format the IP accounting data for inclusion in the human language message string, but only for the
2183 * bytes counters (and not for the packets counters) */
2184 if (m == CGROUP_IP_INGRESS_BYTES)
2185 t = strjoin(n_message_parts > 0 ? "received " : "Received ",strjoin_real((n_message_parts > 0 ? "received " : "Received "
), format_bytes(buf, sizeof(buf), value), " IP traffic", ((void
*)0))
2186 format_bytes(buf, sizeof(buf), value),strjoin_real((n_message_parts > 0 ? "received " : "Received "
), format_bytes(buf, sizeof(buf), value), " IP traffic", ((void
*)0))
2187 " IP traffic")strjoin_real((n_message_parts > 0 ? "received " : "Received "
), format_bytes(buf, sizeof(buf), value), " IP traffic", ((void
*)0))
;
2188 else if (m == CGROUP_IP_EGRESS_BYTES)
2189 t = strjoin(n_message_parts > 0 ? "sent " : "Sent ",strjoin_real((n_message_parts > 0 ? "sent " : "Sent "), format_bytes
(buf, sizeof(buf), value), " IP traffic", ((void*)0))
2190 format_bytes(buf, sizeof(buf), value),strjoin_real((n_message_parts > 0 ? "sent " : "Sent "), format_bytes
(buf, sizeof(buf), value), " IP traffic", ((void*)0))
2191 " IP traffic")strjoin_real((n_message_parts > 0 ? "sent " : "Sent "), format_bytes
(buf, sizeof(buf), value), " IP traffic", ((void*)0))
;
2192 else
2193 continue;
2194 if (!t) {
2195 r = log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/core/unit.c", 2195
, __func__)
;
2196 goto finish;
2197 }
2198
2199 message_parts[n_message_parts++] = t;
2200 }
2201
2202 /* Is there any accounting data available at all? */
2203 if (n_iovec == 0) {
2204 r = 0;
2205 goto finish;
2206 }
2207
2208 if (n_message_parts == 0)
2209 t = strjoina("MESSAGE=", u->id, ": Completed")({ const char *_appendees_[] = { "MESSAGE=", u->id, ": Completed"
}; char *_d_, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ =
0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
2210 else {
2211 _cleanup_free___attribute__((cleanup(freep))) char *joined;
2212
2213 message_parts[n_message_parts] = NULL((void*)0);
2214
2215 joined = strv_join(message_parts, ", ");
2216 if (!joined) {
2217 r = log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/core/unit.c", 2217
, __func__)
;
2218 goto finish;
2219 }
2220
2221 t = strjoina("MESSAGE=", u->id, ": ", joined)({ const char *_appendees_[] = { "MESSAGE=", u->id, ": ", joined
}; char *_d_, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ =
0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
2222 }
2223
2224 /* The following four fields we allocate on the stack or are static strings, we hence don't want to free them,
2225 * and hence don't increase n_iovec for them */
2226 iovec[n_iovec] = IOVEC_MAKE_STRING(t)(struct iovec) { .iov_base = ((char*) t), .iov_len = (strlen(
t)) }
;
2227 iovec[n_iovec + 1] = IOVEC_MAKE_STRING("MESSAGE_ID=" SD_MESSAGE_UNIT_RESOURCES_STR)(struct iovec) { .iov_base = ((char*) "MESSAGE_ID=" "ae" "8f"
"7b" "86" "6b" "03" "47" "b9" "af" "31" "fe" "1c" "80" "b1" "27"
"c0"), .iov_len = (strlen("MESSAGE_ID=" "ae" "8f" "7b" "86" "6b"
"03" "47" "b9" "af" "31" "fe" "1c" "80" "b1" "27" "c0")) }
;
2228
2229 t = strjoina(u->manager->unit_log_field, u->id)({ const char *_appendees_[] = { u->manager->unit_log_field
, u->id }; char *_d_, *_p_; size_t _len_ = 0; size_t _i_; for
(_i_ = 0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
2230 iovec[n_iovec + 2] = IOVEC_MAKE_STRING(t)(struct iovec) { .iov_base = ((char*) t), .iov_len = (strlen(
t)) }
;
2231
2232 t = strjoina(u->manager->invocation_log_field, u->invocation_id_string)({ const char *_appendees_[] = { u->manager->invocation_log_field
, u->invocation_id_string }; char *_d_, *_p_; size_t _len_
= 0; size_t _i_; for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _len_ += strlen
(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca (_len_ + 1);
for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr(
!__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
2233 iovec[n_iovec + 3] = IOVEC_MAKE_STRING(t)(struct iovec) { .iov_base = ((char*) t), .iov_len = (strlen(
t)) }
;
2234
2235 log_struct_iovec(LOG_INFO, iovec, n_iovec + 4)log_struct_iovec_internal(((LOG_REALM_SYSTEMD) << 10 | (
6)), 0, "../src/core/unit.c", 2235, __func__, iovec, n_iovec +
4)
;
2236 r = 0;
2237
2238finish:
2239 for (i = 0; i < n_message_parts; i++)
2240 free(message_parts[i]);
2241
2242 for (i = 0; i < n_iovec; i++)
2243 free(iovec[i].iov_base);
2244
2245 return r;
2246
2247}
2248
2249static void unit_update_on_console(Unit *u) {
2250 bool_Bool b;
2251
2252 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 2252, __PRETTY_FUNCTION__
); } while (0)
;
2253
2254 b = unit_needs_console(u);
2255 if (u->on_console == b)
2256 return;
2257
2258 u->on_console = b;
2259 if (b)
2260 manager_ref_console(u->manager);
2261 else
2262 manager_unref_console(u->manager);
2263}
2264
2265static bool_Bool unit_process_job(Job *j, UnitActiveState ns, UnitNotifyFlags flags) {
2266 bool_Bool unexpected = false0;
2267 JobResult result;
2268
2269 assert(j)do { if ((__builtin_expect(!!(!(j)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("j"), "../src/core/unit.c", 2269, __PRETTY_FUNCTION__
); } while (0)
;
2270
2271 if (j->state == JOB_WAITING)
2272
2273 /* So we reached a different state for this job. Let's see if we can run it now if it failed previously
2274 * due to EAGAIN. */
2275 job_add_to_run_queue(j);
2276
2277 /* Let's check whether the unit's new state constitutes a finished job, or maybe contradicts a running job and
2278 * hence needs to invalidate jobs. */
2279
2280 switch (j->type) {
2281
2282 case JOB_START:
2283 case JOB_VERIFY_ACTIVE:
2284
2285 if (UNIT_IS_ACTIVE_OR_RELOADING(ns))
2286 job_finish_and_invalidate(j, JOB_DONE, true1, false0);
2287 else if (j->state == JOB_RUNNING && ns != UNIT_ACTIVATING) {
2288 unexpected = true1;
2289
2290 if (UNIT_IS_INACTIVE_OR_FAILED(ns)) {
2291 if (ns == UNIT_FAILED)
2292 result = JOB_FAILED;
2293 else if (FLAGS_SET(flags, UNIT_NOTIFY_SKIP_CONDITION)(((flags) & (UNIT_NOTIFY_SKIP_CONDITION)) == (UNIT_NOTIFY_SKIP_CONDITION
))
)
2294 result = JOB_SKIPPED;
2295 else
2296 result = JOB_DONE;
2297
2298 job_finish_and_invalidate(j, result, true1, false0);
2299 }
2300 }
2301
2302 break;
2303
2304 case JOB_RELOAD:
2305 case JOB_RELOAD_OR_START:
2306 case JOB_TRY_RELOAD:
2307
2308 if (j->state == JOB_RUNNING) {
2309 if (ns == UNIT_ACTIVE)
2310 job_finish_and_invalidate(j, (flags & UNIT_NOTIFY_RELOAD_FAILURE) ? JOB_FAILED : JOB_DONE, true1, false0);
2311 else if (!IN_SET(ns, UNIT_ACTIVATING, UNIT_RELOADING)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){UNIT_ACTIVATING, UNIT_RELOADING})/sizeof
(int)]; switch(ns) { case UNIT_ACTIVATING: case UNIT_RELOADING
: _found = 1; break; default: break; } _found; })
) {
2312 unexpected = true1;
2313
2314 if (UNIT_IS_INACTIVE_OR_FAILED(ns))
2315 job_finish_and_invalidate(j, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE, true1, false0);
2316 }
2317 }
2318
2319 break;
2320
2321 case JOB_STOP:
2322 case JOB_RESTART:
2323 case JOB_TRY_RESTART:
2324
2325 if (UNIT_IS_INACTIVE_OR_FAILED(ns))
2326 job_finish_and_invalidate(j, JOB_DONE, true1, false0);
2327 else if (j->state == JOB_RUNNING && ns != UNIT_DEACTIVATING) {
2328 unexpected = true1;
2329 job_finish_and_invalidate(j, JOB_FAILED, true1, false0);
2330 }
2331
2332 break;
2333
2334 default:
2335 assert_not_reached("Job type unknown")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, (
"Job type unknown"), "../src/core/unit.c", 2335, __PRETTY_FUNCTION__
); } while (0)
;
2336 }
2337
2338 return unexpected;
2339}
2340
2341void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, UnitNotifyFlags flags) {
2342 bool_Bool unexpected;
2343 Manager *m;
2344
2345 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 2345, __PRETTY_FUNCTION__
); } while (0)
;
2346 assert(os < _UNIT_ACTIVE_STATE_MAX)do { if ((__builtin_expect(!!(!(os < _UNIT_ACTIVE_STATE_MAX
)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("os < _UNIT_ACTIVE_STATE_MAX"
), "../src/core/unit.c", 2346, __PRETTY_FUNCTION__); } while (
0)
;
2347 assert(ns < _UNIT_ACTIVE_STATE_MAX)do { if ((__builtin_expect(!!(!(ns < _UNIT_ACTIVE_STATE_MAX
)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("ns < _UNIT_ACTIVE_STATE_MAX"
), "../src/core/unit.c", 2347, __PRETTY_FUNCTION__); } while (
0)
;
2348
2349 /* Note that this is called for all low-level state changes, even if they might map to the same high-level
2350 * UnitActiveState! That means that ns == os is an expected behavior here. For example: if a mount point is
2351 * remounted this function will be called too! */
2352
2353 m = u->manager;
2354
2355 /* Update timestamps for state changes */
2356 if (!MANAGER_IS_RELOADING(m)((m)->n_reloading > 0)) {
2357 dual_timestamp_get(&u->state_change_timestamp);
2358
2359 if (UNIT_IS_INACTIVE_OR_FAILED(os) && !UNIT_IS_INACTIVE_OR_FAILED(ns))
2360 u->inactive_exit_timestamp = u->state_change_timestamp;
2361 else if (!UNIT_IS_INACTIVE_OR_FAILED(os) && UNIT_IS_INACTIVE_OR_FAILED(ns))
2362 u->inactive_enter_timestamp = u->state_change_timestamp;
2363
2364 if (!UNIT_IS_ACTIVE_OR_RELOADING(os) && UNIT_IS_ACTIVE_OR_RELOADING(ns))
2365 u->active_enter_timestamp = u->state_change_timestamp;
2366 else if (UNIT_IS_ACTIVE_OR_RELOADING(os) && !UNIT_IS_ACTIVE_OR_RELOADING(ns))
2367 u->active_exit_timestamp = u->state_change_timestamp;
2368 }
2369
2370 /* Keep track of failed units */
2371 (void) manager_update_failed_units(u->manager, u, ns == UNIT_FAILED);
2372
2373 /* Make sure the cgroup and state files are always removed when we become inactive */
2374 if (UNIT_IS_INACTIVE_OR_FAILED(ns)) {
2375 unit_prune_cgroup(u);
2376 unit_unlink_state_files(u);
2377 }
2378
2379 unit_update_on_console(u);
2380
2381 /* Let's propagate state changes to the job */
2382 if (u->job)
2383 unexpected = unit_process_job(u->job, ns, flags);
2384 else
2385 unexpected = true1;
2386
2387 if (!MANAGER_IS_RELOADING(m)((m)->n_reloading > 0)) {
2388
2389 /* If this state change happened without being
2390 * requested by a job, then let's retroactively start
2391 * or stop dependencies. We skip that step when
2392 * deserializing, since we don't want to create any
2393 * additional jobs just because something is already
2394 * activated. */
2395
2396 if (unexpected) {
2397 if (UNIT_IS_INACTIVE_OR_FAILED(os) && UNIT_IS_ACTIVE_OR_ACTIVATING(ns))
2398 retroactively_start_dependencies(u);
2399 else if (UNIT_IS_ACTIVE_OR_ACTIVATING(os) && UNIT_IS_INACTIVE_OR_DEACTIVATING(ns))
2400 retroactively_stop_dependencies(u);
2401 }
2402
2403 /* stop unneeded units regardless if going down was expected or not */
2404 if (UNIT_IS_INACTIVE_OR_FAILED(ns))
2405 check_unneeded_dependencies(u);
2406
2407 if (ns != os && ns == UNIT_FAILED) {
2408 log_unit_debug(u, "Unit entered failed state.")({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/unit.c"
, 2408, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Unit entered failed state.") : log_internal_realm(((LOG_REALM_SYSTEMD
) << 10 | ((7))), 0, "../src/core/unit.c", 2408, __func__
, "Unit entered failed state."); })
;
2409
2410 if (!(flags & UNIT_NOTIFY_WILL_AUTO_RESTART))
2411 unit_start_on_failure(u);
2412 }
2413 }
2414
2415 if (UNIT_IS_ACTIVE_OR_RELOADING(ns)) {
2416
2417 if (u->type == UNIT_SERVICE &&
2418 !UNIT_IS_ACTIVE_OR_RELOADING(os) &&
2419 !MANAGER_IS_RELOADING(m)((m)->n_reloading > 0)) {
2420 /* Write audit record if we have just finished starting up */
2421 manager_send_unit_audit(m, u, AUDIT_SERVICE_START1130, true1);
2422 u->in_audit = true1;
2423 }
2424
2425 if (!UNIT_IS_ACTIVE_OR_RELOADING(os))
2426 manager_send_unit_plymouth(m, u);
2427
2428 } else {
2429
2430 if (UNIT_IS_INACTIVE_OR_FAILED(ns) &&
2431 !UNIT_IS_INACTIVE_OR_FAILED(os)
2432 && !MANAGER_IS_RELOADING(m)((m)->n_reloading > 0)) {
2433
2434 /* This unit just stopped/failed. */
2435 if (u->type == UNIT_SERVICE) {
2436
2437 /* Hmm, if there was no start record written
2438 * write it now, so that we always have a nice
2439 * pair */
2440 if (!u->in_audit) {
2441 manager_send_unit_audit(m, u, AUDIT_SERVICE_START1130, ns == UNIT_INACTIVE);
2442
2443 if (ns == UNIT_INACTIVE)
2444 manager_send_unit_audit(m, u, AUDIT_SERVICE_STOP1131, true1);
2445 } else
2446 /* Write audit record if we have just finished shutting down */
2447 manager_send_unit_audit(m, u, AUDIT_SERVICE_STOP1131, ns == UNIT_INACTIVE);
2448
2449 u->in_audit = false0;
2450 }
2451
2452 /* Write a log message about consumed resources */
2453 unit_log_resources(u);
2454 }
2455 }
2456
2457 manager_recheck_journal(m);
2458 manager_recheck_dbus(m);
2459
2460 unit_trigger_notify(u);
2461
2462 if (!MANAGER_IS_RELOADING(u->manager)((u->manager)->n_reloading > 0)) {
2463 /* Maybe we finished startup and are now ready for being stopped because unneeded? */
2464 unit_add_to_stop_when_unneeded_queue(u);
2465
2466 /* Maybe we finished startup, but something we needed has vanished? Let's die then. (This happens when
2467 * something BindsTo= to a Type=oneshot unit, as these units go directly from starting to inactive,
2468 * without ever entering started.) */
2469 unit_check_binds_to(u);
2470
2471 if (os != UNIT_FAILED && ns == UNIT_FAILED)
2472 (void) emergency_action(u->manager, u->failure_action, u->reboot_arg, "unit failed");
2473 else if (!UNIT_IS_INACTIVE_OR_FAILED(os) && ns == UNIT_INACTIVE)
2474 (void) emergency_action(u->manager, u->success_action, u->reboot_arg, "unit succeeded");
2475 }
2476
2477 unit_add_to_dbus_queue(u);
2478 unit_add_to_gc_queue(u);
2479}
2480
2481int unit_watch_pid(Unit *u, pid_t pid, bool_Bool exclusive) {
2482 int r;
2483
2484 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 2484, __PRETTY_FUNCTION__
); } while (0)
;
2485 assert(pid_is_valid(pid))do { if ((__builtin_expect(!!(!(pid_is_valid(pid))),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("pid_is_valid(pid)"), "../src/core/unit.c"
, 2485, __PRETTY_FUNCTION__); } while (0)
;
2486
2487 /* Watch a specific PID */
2488
2489 /* Caller might be sure that this PID belongs to this unit only. Let's take this
2490 * opportunity to remove any stalled references to this PID as they can be created
2491 * easily (when watching a process which is not our direct child). */
2492 if (exclusive)
2493 manager_unwatch_pid(u->manager, pid);
2494
2495 r = set_ensure_allocated(&u->pids, NULL)internal_set_ensure_allocated(&u->pids, ((void*)0) );
2496 if (r < 0)
2497 return r;
2498
2499 r = hashmap_ensure_allocated(&u->manager->watch_pids, NULL)internal_hashmap_ensure_allocated(&u->manager->watch_pids
, ((void*)0) )
;
2500 if (r < 0)
2501 return r;
2502
2503 /* First try, let's add the unit keyed by "pid". */
2504 r = hashmap_put(u->manager->watch_pids, PID_TO_PTR(pid), u);
2505 if (r == -EEXIST17) {
2506 Unit **array;
2507 bool_Bool found = false0;
2508 size_t n = 0;
2509
2510 /* OK, the "pid" key is already assigned to a different unit. Let's see if the "-pid" key (which points
2511 * to an array of Units rather than just a Unit), lists us already. */
2512
2513 array = hashmap_get(u->manager->watch_pids, PID_TO_PTR(-pid));
2514 if (array)
2515 for (; array[n]; n++)
2516 if (array[n] == u)
2517 found = true1;
2518
2519 if (found) /* Found it already? if so, do nothing */
2520 r = 0;
2521 else {
2522 Unit **new_array;
2523
2524 /* Allocate a new array */
2525 new_array = new(Unit*, n + 2)((Unit**) malloc_multiply(sizeof(Unit*), (n + 2)));
2526 if (!new_array)
2527 return -ENOMEM12;
2528
2529 memcpy_safe(new_array, array, sizeof(Unit*) * n);
2530 new_array[n] = u;
2531 new_array[n+1] = NULL((void*)0);
2532
2533 /* Add or replace the old array */
2534 r = hashmap_replace(u->manager->watch_pids, PID_TO_PTR(-pid), new_array);
2535 if (r < 0) {
2536 free(new_array);
2537 return r;
2538 }
2539
2540 free(array);
2541 }
2542 } else if (r < 0)
2543 return r;
2544
2545 r = set_put(u->pids, PID_TO_PTR(pid));
2546 if (r < 0)
2547 return r;
2548
2549 return 0;
2550}
2551
2552void unit_unwatch_pid(Unit *u, pid_t pid) {
2553 Unit **array;
2554
2555 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 2555, __PRETTY_FUNCTION__
); } while (0)
;
2556 assert(pid_is_valid(pid))do { if ((__builtin_expect(!!(!(pid_is_valid(pid))),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("pid_is_valid(pid)"), "../src/core/unit.c"
, 2556, __PRETTY_FUNCTION__); } while (0)
;
2557
2558 /* First let's drop the unit in case it's keyed as "pid". */
2559 (void) hashmap_remove_value(u->manager->watch_pids, PID_TO_PTR(pid), u);
2560
2561 /* Then, let's also drop the unit, in case it's in the array keyed by -pid */
2562 array = hashmap_get(u->manager->watch_pids, PID_TO_PTR(-pid));
2563 if (array) {
2564 size_t n, m = 0;
2565
2566 /* Let's iterate through the array, dropping our own entry */
2567 for (n = 0; array[n]; n++)
2568 if (array[n] != u)
2569 array[m++] = array[n];
2570 array[m] = NULL((void*)0);
2571
2572 if (m == 0) {
2573 /* The array is now empty, remove the entire entry */
2574 assert(hashmap_remove(u->manager->watch_pids, PID_TO_PTR(-pid)) == array)do { if ((__builtin_expect(!!(!(hashmap_remove(u->manager->
watch_pids, PID_TO_PTR(-pid)) == array)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("hashmap_remove(u->manager->watch_pids, PID_TO_PTR(-pid)) == array"
), "../src/core/unit.c", 2574, __PRETTY_FUNCTION__); } while (
0)
;
2575 free(array);
2576 }
2577 }
2578
2579 (void) set_remove(u->pids, PID_TO_PTR(pid));
2580}
2581
2582void unit_unwatch_all_pids(Unit *u) {
2583 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 2583, __PRETTY_FUNCTION__
); } while (0)
;
2584
2585 while (!set_isempty(u->pids))
2586 unit_unwatch_pid(u, PTR_TO_PID(set_first(u->pids)));
2587
2588 u->pids = set_free(u->pids);
2589}
2590
2591static void unit_tidy_watch_pids(Unit *u) {
2592 pid_t except1, except2;
2593 Iterator i;
2594 void *e;
2595
2596 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 2596, __PRETTY_FUNCTION__
); } while (0)
;
2597
2598 /* Cleans dead PIDs from our list */
2599
2600 except1 = unit_main_pid(u);
2601 except2 = unit_control_pid(u);
2602
2603 SET_FOREACH(e, u->pids, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); set_iterate((u->pids), &(i),
(void**)&(e)); )
{
2604 pid_t pid = PTR_TO_PID(e);
2605
2606 if (pid == except1 || pid == except2)
2607 continue;
2608
2609 if (!pid_is_unwaited(pid))
2610 unit_unwatch_pid(u, pid);
2611 }
2612}
2613
2614static int on_rewatch_pids_event(sd_event_source *s, void *userdata) {
2615 Unit *u = userdata;
2616
2617 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/core/unit.c", 2617, __PRETTY_FUNCTION__
); } while (0)
;
2618 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 2618, __PRETTY_FUNCTION__
); } while (0)
;
2619
2620 unit_tidy_watch_pids(u);
2621 unit_watch_all_pids(u);
2622
2623 /* If the PID set is empty now, then let's finish this off. */
2624 unit_synthesize_cgroup_empty_event(u);
2625
2626 return 0;
2627}
2628
2629int unit_enqueue_rewatch_pids(Unit *u) {
2630 int r;
2631
2632 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 2632, __PRETTY_FUNCTION__
); } while (0)
;
2633
2634 if (!u->cgroup_path)
2635 return -ENOENT2;
2636
2637 r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER"_systemd");
2638 if (r < 0)
2639 return r;
2640 if (r > 0) /* On unified we can use proper notifications */
2641 return 0;
2642
2643 /* Enqueues a low-priority job that will clean up dead PIDs from our list of PIDs to watch and subscribe to new
2644 * PIDs that might have appeared. We do this in a delayed job because the work might be quite slow, as it
2645 * involves issuing kill(pid, 0) on all processes we watch. */
2646
2647 if (!u->rewatch_pids_event_source) {
2648 _cleanup_(sd_event_source_unrefp)__attribute__((cleanup(sd_event_source_unrefp))) sd_event_source *s = NULL((void*)0);
2649
2650 r = sd_event_add_defer(u->manager->event, &s, on_rewatch_pids_event, u);
2651 if (r < 0)
2652 return log_error_errno(r, "Failed to allocate event source for tidying watched PIDs: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/core/unit.c", 2652, __func__, "Failed to allocate event source for tidying watched PIDs: %m"
) : -abs(_e); })
;
2653
2654 r = sd_event_source_set_priority(s, SD_EVENT_PRIORITY_IDLE);
2655 if (r < 0)
2656 return log_error_errno(r, "Failed to adjust priority of event source for tidying watched PIDs: m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/core/unit.c", 2656, __func__, "Failed to adjust priority of event source for tidying watched PIDs: m"
) : -abs(_e); })
;
2657
2658 (void) sd_event_source_set_description(s, "tidy-watch-pids");
2659
2660 u->rewatch_pids_event_source = TAKE_PTR(s)({ typeof(s) _ptr_ = (s); (s) = ((void*)0); _ptr_; });
2661 }
2662
2663 r = sd_event_source_set_enabled(u->rewatch_pids_event_source, SD_EVENT_ONESHOT);
2664 if (r < 0)
2665 return log_error_errno(r, "Failed to enable event source for tidying watched PIDs: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/core/unit.c", 2665, __func__, "Failed to enable event source for tidying watched PIDs: %m"
) : -abs(_e); })
;
2666
2667 return 0;
2668}
2669
2670void unit_dequeue_rewatch_pids(Unit *u) {
2671 int r;
2672 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 2672, __PRETTY_FUNCTION__
); } while (0)
;
2673
2674 if (!u->rewatch_pids_event_source)
2675 return;
2676
2677 r = sd_event_source_set_enabled(u->rewatch_pids_event_source, SD_EVENT_OFF);
2678 if (r < 0)
2679 log_warning_errno(r, "Failed to disable event source for tidying watched PIDs, ignoring: %m")({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/core/unit.c", 2679, __func__, "Failed to disable event source for tidying watched PIDs, ignoring: %m"
) : -abs(_e); })
;
2680
2681 u->rewatch_pids_event_source = sd_event_source_unref(u->rewatch_pids_event_source);
2682}
2683
2684bool_Bool unit_job_is_applicable(Unit *u, JobType j) {
2685 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 2685, __PRETTY_FUNCTION__
); } while (0)
;
2686 assert(j >= 0 && j < _JOB_TYPE_MAX)do { if ((__builtin_expect(!!(!(j >= 0 && j < _JOB_TYPE_MAX
)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("j >= 0 && j < _JOB_TYPE_MAX"
), "../src/core/unit.c", 2686, __PRETTY_FUNCTION__); } while (
0)
;
2687
2688 switch (j) {
2689
2690 case JOB_VERIFY_ACTIVE:
2691 case JOB_START:
2692 case JOB_NOP:
2693 /* Note that we don't check unit_can_start() here. That's because .device units and suchlike are not
2694 * startable by us but may appear due to external events, and it thus makes sense to permit enqueing
2695 * jobs for it. */
2696 return true1;
2697
2698 case JOB_STOP:
2699 /* Similar as above. However, perpetual units can never be stopped (neither explicitly nor due to
2700 * external events), hence it makes no sense to permit enqueing such a request either. */
2701 return !u->perpetual;
2702
2703 case JOB_RESTART:
2704 case JOB_TRY_RESTART:
2705 return unit_can_stop(u) && unit_can_start(u);
2706
2707 case JOB_RELOAD:
2708 case JOB_TRY_RELOAD:
2709 return unit_can_reload(u);
2710
2711 case JOB_RELOAD_OR_START:
2712 return unit_can_reload(u) && unit_can_start(u);
2713
2714 default:
2715 assert_not_reached("Invalid job type")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, (
"Invalid job type"), "../src/core/unit.c", 2715, __PRETTY_FUNCTION__
); } while (0)
;
2716 }
2717}
2718
2719static void maybe_warn_about_dependency(Unit *u, const char *other, UnitDependency dependency) {
2720 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 2720, __PRETTY_FUNCTION__
); } while (0)
;
2721
2722 /* Only warn about some unit types */
2723 if (!IN_SET(dependency, UNIT_CONFLICTS, UNIT_CONFLICTED_BY, UNIT_BEFORE, UNIT_AFTER, UNIT_ON_FAILURE, UNIT_TRIGGERS, UNIT_TRIGGERED_BY)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){UNIT_CONFLICTS, UNIT_CONFLICTED_BY, UNIT_BEFORE
, UNIT_AFTER, UNIT_ON_FAILURE, UNIT_TRIGGERS, UNIT_TRIGGERED_BY
})/sizeof(int)]; switch(dependency) { case UNIT_CONFLICTS: case
UNIT_CONFLICTED_BY: case UNIT_BEFORE: case UNIT_AFTER: case UNIT_ON_FAILURE
: case UNIT_TRIGGERS: case UNIT_TRIGGERED_BY: _found = 1; break
; default: break; } _found; })
)
2724 return;
2725
2726 if (streq_ptr(u->id, other))
2727 log_unit_warning(u, "Dependency %s=%s dropped", unit_dependency_to_string(dependency), u->id)({ const Unit *_u = (u); _u ? log_object_internal(4, 0, "../src/core/unit.c"
, 2727, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Dependency %s=%s dropped", unit_dependency_to_string(dependency
), u->id) : log_internal_realm(((LOG_REALM_SYSTEMD) <<
10 | ((4))), 0, "../src/core/unit.c", 2727, __func__, "Dependency %s=%s dropped"
, unit_dependency_to_string(dependency), u->id); })
;
2728 else
2729 log_unit_warning(u, "Dependency %s=%s dropped, merged into %s", unit_dependency_to_string(dependency), strna(other), u->id)({ const Unit *_u = (u); _u ? log_object_internal(4, 0, "../src/core/unit.c"
, 2729, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Dependency %s=%s dropped, merged into %s", unit_dependency_to_string
(dependency), strna(other), u->id) : log_internal_realm(((
LOG_REALM_SYSTEMD) << 10 | ((4))), 0, "../src/core/unit.c"
, 2729, __func__, "Dependency %s=%s dropped, merged into %s",
unit_dependency_to_string(dependency), strna(other), u->id
); })
;
2730}
2731
2732static int unit_add_dependency_hashmap(
2733 Hashmap **h,
2734 Unit *other,
2735 UnitDependencyMask origin_mask,
2736 UnitDependencyMask destination_mask) {
2737
2738 UnitDependencyInfo info;
2739 int r;
2740
2741 assert(h)do { if ((__builtin_expect(!!(!(h)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("h"), "../src/core/unit.c", 2741, __PRETTY_FUNCTION__
); } while (0)
;
2742 assert(other)do { if ((__builtin_expect(!!(!(other)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("other"), "../src/core/unit.c", 2742, __PRETTY_FUNCTION__
); } while (0)
;
2743 assert(origin_mask < _UNIT_DEPENDENCY_MASK_FULL)do { if ((__builtin_expect(!!(!(origin_mask < _UNIT_DEPENDENCY_MASK_FULL
)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("origin_mask < _UNIT_DEPENDENCY_MASK_FULL"
), "../src/core/unit.c", 2743, __PRETTY_FUNCTION__); } while (
0)
;
2744 assert(destination_mask < _UNIT_DEPENDENCY_MASK_FULL)do { if ((__builtin_expect(!!(!(destination_mask < _UNIT_DEPENDENCY_MASK_FULL
)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("destination_mask < _UNIT_DEPENDENCY_MASK_FULL"
), "../src/core/unit.c", 2744, __PRETTY_FUNCTION__); } while (
0)
;
2745 assert(origin_mask > 0 || destination_mask > 0)do { if ((__builtin_expect(!!(!(origin_mask > 0 || destination_mask
> 0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("origin_mask > 0 || destination_mask > 0"
), "../src/core/unit.c", 2745, __PRETTY_FUNCTION__); } while (
0)
;
2746
2747 r = hashmap_ensure_allocated(h, NULL)internal_hashmap_ensure_allocated(h, ((void*)0) );
2748 if (r < 0)
2749 return r;
2750
2751 assert_cc(sizeof(void*) == sizeof(info))GCC diagnostic push ; GCC diagnostic ignored "-Wdeclaration-after-statement"
; struct _assert_struct_40 { char x[(sizeof(void*) == sizeof
(info)) ? 0 : -1]; }; GCC diagnostic pop
;
2752
2753 info.data = hashmap_get(*h, other);
2754 if (info.data) {
2755 /* Entry already exists. Add in our mask. */
2756
2757 if (FLAGS_SET(origin_mask, info.origin_mask)(((origin_mask) & (info.origin_mask)) == (info.origin_mask
))
&&
2758 FLAGS_SET(destination_mask, info.destination_mask)(((destination_mask) & (info.destination_mask)) == (info.
destination_mask))
)
2759 return 0; /* NOP */
2760
2761 info.origin_mask |= origin_mask;
2762 info.destination_mask |= destination_mask;
2763
2764 r = hashmap_update(*h, other, info.data);
2765 } else {
2766 info = (UnitDependencyInfo) {
2767 .origin_mask = origin_mask,
2768 .destination_mask = destination_mask,
2769 };
2770
2771 r = hashmap_put(*h, other, info.data);
2772 }
2773 if (r < 0)
2774 return r;
2775
2776 return 1;
2777}
2778
2779int unit_add_dependency(
2780 Unit *u,
2781 UnitDependency d,
2782 Unit *other,
2783 bool_Bool add_reference,
2784 UnitDependencyMask mask) {
2785
2786 static const UnitDependency inverse_table[_UNIT_DEPENDENCY_MAX] = {
2787 [UNIT_REQUIRES] = UNIT_REQUIRED_BY,
2788 [UNIT_WANTS] = UNIT_WANTED_BY,
2789 [UNIT_REQUISITE] = UNIT_REQUISITE_OF,
2790 [UNIT_BINDS_TO] = UNIT_BOUND_BY,
2791 [UNIT_PART_OF] = UNIT_CONSISTS_OF,
2792 [UNIT_REQUIRED_BY] = UNIT_REQUIRES,
2793 [UNIT_REQUISITE_OF] = UNIT_REQUISITE,
2794 [UNIT_WANTED_BY] = UNIT_WANTS,
2795 [UNIT_BOUND_BY] = UNIT_BINDS_TO,
2796 [UNIT_CONSISTS_OF] = UNIT_PART_OF,
2797 [UNIT_CONFLICTS] = UNIT_CONFLICTED_BY,
2798 [UNIT_CONFLICTED_BY] = UNIT_CONFLICTS,
2799 [UNIT_BEFORE] = UNIT_AFTER,
2800 [UNIT_AFTER] = UNIT_BEFORE,
2801 [UNIT_ON_FAILURE] = _UNIT_DEPENDENCY_INVALID,
2802 [UNIT_REFERENCES] = UNIT_REFERENCED_BY,
2803 [UNIT_REFERENCED_BY] = UNIT_REFERENCES,
2804 [UNIT_TRIGGERS] = UNIT_TRIGGERED_BY,
2805 [UNIT_TRIGGERED_BY] = UNIT_TRIGGERS,
2806 [UNIT_PROPAGATES_RELOAD_TO] = UNIT_RELOAD_PROPAGATED_FROM,
2807 [UNIT_RELOAD_PROPAGATED_FROM] = UNIT_PROPAGATES_RELOAD_TO,
2808 [UNIT_JOINS_NAMESPACE_OF] = UNIT_JOINS_NAMESPACE_OF,
2809 };
2810 Unit *original_u = u, *original_other = other;
2811 int r;
2812
2813 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 2813, __PRETTY_FUNCTION__
); } while (0)
;
2814 assert(d >= 0 && d < _UNIT_DEPENDENCY_MAX)do { if ((__builtin_expect(!!(!(d >= 0 && d < _UNIT_DEPENDENCY_MAX
)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("d >= 0 && d < _UNIT_DEPENDENCY_MAX"
), "../src/core/unit.c", 2814, __PRETTY_FUNCTION__); } while (
0)
;
2815 assert(other)do { if ((__builtin_expect(!!(!(other)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("other"), "../src/core/unit.c", 2815, __PRETTY_FUNCTION__
); } while (0)
;
2816
2817 u = unit_follow_merge(u);
2818 other = unit_follow_merge(other);
2819
2820 /* We won't allow dependencies on ourselves. We will not
2821 * consider them an error however. */
2822 if (u == other) {
2823 maybe_warn_about_dependency(original_u, original_other->id, d);
2824 return 0;
2825 }
2826
2827 if ((d == UNIT_BEFORE && other->type == UNIT_DEVICE) ||
2828 (d == UNIT_AFTER && u->type == UNIT_DEVICE)) {
2829 log_unit_warning(u, "Dependency Before=%s ignored (.device units cannot be delayed)", other->id)({ const Unit *_u = (u); _u ? log_object_internal(4, 0, "../src/core/unit.c"
, 2829, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Dependency Before=%s ignored (.device units cannot be delayed)"
, other->id) : log_internal_realm(((LOG_REALM_SYSTEMD) <<
10 | ((4))), 0, "../src/core/unit.c", 2829, __func__, "Dependency Before=%s ignored (.device units cannot be delayed)"
, other->id); })
;
2830 return 0;
2831 }
2832
2833 r = unit_add_dependency_hashmap(u->dependencies + d, other, mask, 0);
2834 if (r < 0)
2835 return r;
2836
2837 if (inverse_table[d] != _UNIT_DEPENDENCY_INVALID && inverse_table[d] != d) {
2838 r = unit_add_dependency_hashmap(other->dependencies + inverse_table[d], u, 0, mask);
2839 if (r < 0)
2840 return r;
2841 }
2842
2843 if (add_reference) {
2844 r = unit_add_dependency_hashmap(u->dependencies + UNIT_REFERENCES, other, mask, 0);
2845 if (r < 0)
2846 return r;
2847
2848 r = unit_add_dependency_hashmap(other->dependencies + UNIT_REFERENCED_BY, u, 0, mask);
2849 if (r < 0)
2850 return r;
2851 }
2852
2853 unit_add_to_dbus_queue(u);
2854 return 0;
2855}
2856
2857int unit_add_two_dependencies(Unit *u, UnitDependency d, UnitDependency e, Unit *other, bool_Bool add_reference, UnitDependencyMask mask) {
2858 int r;
2859
2860 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 2860, __PRETTY_FUNCTION__
); } while (0)
;
2861
2862 r = unit_add_dependency(u, d, other, add_reference, mask);
2863 if (r < 0)
2864 return r;
2865
2866 return unit_add_dependency(u, e, other, add_reference, mask);
2867}
2868
2869static int resolve_template(Unit *u, const char *name, const char*path, char **buf, const char **ret) {
2870 int r;
2871
2872 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 2872, __PRETTY_FUNCTION__
); } while (0)
;
2873 assert(name || path)do { if ((__builtin_expect(!!(!(name || path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("name || path"), "../src/core/unit.c", 2873
, __PRETTY_FUNCTION__); } while (0)
;
2874 assert(buf)do { if ((__builtin_expect(!!(!(buf)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("buf"), "../src/core/unit.c", 2874, __PRETTY_FUNCTION__
); } while (0)
;
2875 assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret"), "../src/core/unit.c", 2875, __PRETTY_FUNCTION__
); } while (0)
;
2876
2877 if (!name)
2878 name = basename(path);
2879
2880 if (!unit_name_is_valid(name, UNIT_NAME_TEMPLATE)) {
2881 *buf = NULL((void*)0);
2882 *ret = name;
2883 return 0;
2884 }
2885
2886 if (u->instance)
2887 r = unit_name_replace_instance(name, u->instance, buf);
2888 else {
2889 _cleanup_free___attribute__((cleanup(freep))) char *i = NULL((void*)0);
2890
2891 r = unit_name_to_prefix(u->id, &i);
2892 if (r < 0)
2893 return r;
2894
2895 r = unit_name_replace_instance(name, i, buf);
2896 }
2897 if (r < 0)
2898 return r;
2899
2900 *ret = *buf;
2901 return 0;
2902}
2903
2904int unit_add_dependency_by_name(Unit *u, UnitDependency d, const char *name, const char *path, bool_Bool add_reference, UnitDependencyMask mask) {
2905 _cleanup_free___attribute__((cleanup(freep))) char *buf = NULL((void*)0);
2906 Unit *other;
2907 int r;
2908
2909 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 2909, __PRETTY_FUNCTION__
); } while (0)
;
2910 assert(name || path)do { if ((__builtin_expect(!!(!(name || path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("name || path"), "../src/core/unit.c", 2910
, __PRETTY_FUNCTION__); } while (0)
;
2911
2912 r = resolve_template(u, name, path, &buf, &name);
2913 if (r < 0)
2914 return r;
2915
2916 r = manager_load_unit(u->manager, name, path, NULL((void*)0), &other);
2917 if (r < 0)
2918 return r;
2919
2920 return unit_add_dependency(u, d, other, add_reference, mask);
2921}
2922
2923int unit_add_two_dependencies_by_name(Unit *u, UnitDependency d, UnitDependency e, const char *name, const char *path, bool_Bool add_reference, UnitDependencyMask mask) {
2924 _cleanup_free___attribute__((cleanup(freep))) char *buf = NULL((void*)0);
2925 Unit *other;
2926 int r;
2927
2928 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 2928, __PRETTY_FUNCTION__
); } while (0)
;
2929 assert(name || path)do { if ((__builtin_expect(!!(!(name || path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("name || path"), "../src/core/unit.c", 2929
, __PRETTY_FUNCTION__); } while (0)
;
2930
2931 r = resolve_template(u, name, path, &buf, &name);
2932 if (r < 0)
2933 return r;
2934
2935 r = manager_load_unit(u->manager, name, path, NULL((void*)0), &other);
2936 if (r < 0)
2937 return r;
2938
2939 return unit_add_two_dependencies(u, d, e, other, add_reference, mask);
2940}
2941
2942int set_unit_path(const char *p) {
2943 /* This is mostly for debug purposes */
2944 if (setenv("SYSTEMD_UNIT_PATH", p, 1) < 0)
2945 return -errno(*__errno_location ());
2946
2947 return 0;
2948}
2949
2950char *unit_dbus_path(Unit *u) {
2951 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 2951, __PRETTY_FUNCTION__
); } while (0)
;
2952
2953 if (!u->id)
2954 return NULL((void*)0);
2955
2956 return unit_dbus_path_from_name(u->id);
2957}
2958
2959char *unit_dbus_path_invocation_id(Unit *u) {
2960 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 2960, __PRETTY_FUNCTION__
); } while (0)
;
2961
2962 if (sd_id128_is_null(u->invocation_id))
2963 return NULL((void*)0);
2964
2965 return unit_dbus_path_from_name(u->invocation_id_string);
2966}
2967
2968int unit_set_slice(Unit *u, Unit *slice) {
2969 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 2969, __PRETTY_FUNCTION__
); } while (0)
;
2970 assert(slice)do { if ((__builtin_expect(!!(!(slice)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("slice"), "../src/core/unit.c", 2970, __PRETTY_FUNCTION__
); } while (0)
;
2971
2972 /* Sets the unit slice if it has not been set before. Is extra
2973 * careful, to only allow this for units that actually have a
2974 * cgroup context. Also, we don't allow to set this for slices
2975 * (since the parent slice is derived from the name). Make
2976 * sure the unit we set is actually a slice. */
2977
2978 if (!UNIT_HAS_CGROUP_CONTEXT(u)(unit_vtable[(u)->type]->cgroup_context_offset > 0))
2979 return -EOPNOTSUPP95;
2980
2981 if (u->type == UNIT_SLICE)
2982 return -EINVAL22;
2983
2984 if (unit_active_state(u) != UNIT_INACTIVE)
2985 return -EBUSY16;
2986
2987 if (slice->type != UNIT_SLICE)
2988 return -EINVAL22;
2989
2990 if (unit_has_name(u, SPECIAL_INIT_SCOPE"init.scope") &&
2991 !unit_has_name(slice, SPECIAL_ROOT_SLICE"-.slice"))
2992 return -EPERM1;
2993
2994 if (UNIT_DEREF(u->slice)((u->slice).target) == slice)
2995 return 0;
2996
2997 /* Disallow slice changes if @u is already bound to cgroups */
2998 if (UNIT_ISSET(u->slice)(!!(u->slice).target) && u->cgroup_realized)
2999 return -EBUSY16;
3000
3001 unit_ref_set(&u->slice, u, slice);
3002 return 1;
3003}
3004
3005int unit_set_default_slice(Unit *u) {
3006 _cleanup_free___attribute__((cleanup(freep))) char *b = NULL((void*)0);
3007 const char *slice_name;
3008 Unit *slice;
3009 int r;
3010
3011 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 3011, __PRETTY_FUNCTION__
); } while (0)
;
3012
3013 if (UNIT_ISSET(u->slice)(!!(u->slice).target))
3014 return 0;
3015
3016 if (u->instance) {
3017 _cleanup_free___attribute__((cleanup(freep))) char *prefix = NULL((void*)0), *escaped = NULL((void*)0);
3018
3019 /* Implicitly place all instantiated units in their
3020 * own per-template slice */
3021
3022 r = unit_name_to_prefix(u->id, &prefix);
3023 if (r < 0)
3024 return r;
3025
3026 /* The prefix is already escaped, but it might include
3027 * "-" which has a special meaning for slice units,
3028 * hence escape it here extra. */
3029 escaped = unit_name_escape(prefix);
3030 if (!escaped)
3031 return -ENOMEM12;
3032
3033 if (MANAGER_IS_SYSTEM(u->manager)((u->manager)->unit_file_scope == UNIT_FILE_SYSTEM))
3034 b = strjoin("system-", escaped, ".slice")strjoin_real(("system-"), escaped, ".slice", ((void*)0));
3035 else
3036 b = strappend(escaped, ".slice");
3037 if (!b)
3038 return -ENOMEM12;
3039
3040 slice_name = b;
3041 } else
3042 slice_name =
3043 MANAGER_IS_SYSTEM(u->manager)((u->manager)->unit_file_scope == UNIT_FILE_SYSTEM) && !unit_has_name(u, SPECIAL_INIT_SCOPE"init.scope")
3044 ? SPECIAL_SYSTEM_SLICE"system.slice"
3045 : SPECIAL_ROOT_SLICE"-.slice";
3046
3047 r = manager_load_unit(u->manager, slice_name, NULL((void*)0), NULL((void*)0), &slice);
3048 if (r < 0)
3049 return r;
3050
3051 return unit_set_slice(u, slice);
3052}
3053
3054const char *unit_slice_name(Unit *u) {
3055 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 3055, __PRETTY_FUNCTION__
); } while (0)
;
3056
3057 if (!UNIT_ISSET(u->slice)(!!(u->slice).target))
3058 return NULL((void*)0);
3059
3060 return UNIT_DEREF(u->slice)((u->slice).target)->id;
3061}
3062
3063int unit_load_related_unit(Unit *u, const char *type, Unit **_found) {
3064 _cleanup_free___attribute__((cleanup(freep))) char *t = NULL((void*)0);
3065 int r;
3066
3067 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 3067, __PRETTY_FUNCTION__
); } while (0)
;
3068 assert(type)do { if ((__builtin_expect(!!(!(type)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("type"), "../src/core/unit.c", 3068, __PRETTY_FUNCTION__
); } while (0)
;
3069 assert(_found)do { if ((__builtin_expect(!!(!(_found)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("_found"), "../src/core/unit.c", 3069, __PRETTY_FUNCTION__
); } while (0)
;
3070
3071 r = unit_name_change_suffix(u->id, type, &t);
3072 if (r < 0)
3073 return r;
3074 if (unit_has_name(u, t))
3075 return -EINVAL22;
3076
3077 r = manager_load_unit(u->manager, t, NULL((void*)0), NULL((void*)0), _found);
3078 assert(r < 0 || *_found != u)do { if ((__builtin_expect(!!(!(r < 0 || *_found != u)),0)
)) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("r < 0 || *_found != u"
), "../src/core/unit.c", 3078, __PRETTY_FUNCTION__); } while (
0)
;
3079 return r;
3080}
3081
3082static int signal_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
3083 const char *name, *old_owner, *new_owner;
3084 Unit *u = userdata;
3085 int r;
3086
3087 assert(message)do { if ((__builtin_expect(!!(!(message)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("message"), "../src/core/unit.c", 3087, __PRETTY_FUNCTION__
); } while (0)
;
3088 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 3088, __PRETTY_FUNCTION__
); } while (0)
;
3089
3090 r = sd_bus_message_read(message, "sss", &name, &old_owner, &new_owner);
3091 if (r < 0) {
3092 bus_log_parse_error(r);
3093 return 0;
3094 }
3095
3096 old_owner = empty_to_null(old_owner);
3097 new_owner = empty_to_null(new_owner);
3098
3099 if (UNIT_VTABLE(u)unit_vtable[(u)->type]->bus_name_owner_change)
3100 UNIT_VTABLE(u)unit_vtable[(u)->type]->bus_name_owner_change(u, name, old_owner, new_owner);
3101
3102 return 0;
3103}
3104
3105int unit_install_bus_match(Unit *u, sd_bus *bus, const char *name) {
3106 const char *match;
3107
3108 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 3108, __PRETTY_FUNCTION__
); } while (0)
;
3109 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/core/unit.c", 3109, __PRETTY_FUNCTION__
); } while (0)
;
3110 assert(name)do { if ((__builtin_expect(!!(!(name)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("name"), "../src/core/unit.c", 3110, __PRETTY_FUNCTION__
); } while (0)
;
3111
3112 if (u->match_bus_slot)
3113 return -EBUSY16;
3114
3115 match = strjoina("type='signal',"({ const char *_appendees_[] = { "type='signal'," "sender='org.freedesktop.DBus',"
"path='/org/freedesktop/DBus'," "interface='org.freedesktop.DBus',"
"member='NameOwnerChanged'," "arg0='", name, "'" }; char *_d_
, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__
(__builtin_choose_expr( !__builtin_types_compatible_p(typeof
(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
3116 "sender='org.freedesktop.DBus',"({ const char *_appendees_[] = { "type='signal'," "sender='org.freedesktop.DBus',"
"path='/org/freedesktop/DBus'," "interface='org.freedesktop.DBus',"
"member='NameOwnerChanged'," "arg0='", name, "'" }; char *_d_
, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__
(__builtin_choose_expr( !__builtin_types_compatible_p(typeof
(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
3117 "path='/org/freedesktop/DBus',"({ const char *_appendees_[] = { "type='signal'," "sender='org.freedesktop.DBus',"
"path='/org/freedesktop/DBus'," "interface='org.freedesktop.DBus',"
"member='NameOwnerChanged'," "arg0='", name, "'" }; char *_d_
, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__
(__builtin_choose_expr( !__builtin_types_compatible_p(typeof
(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
3118 "interface='org.freedesktop.DBus',"({ const char *_appendees_[] = { "type='signal'," "sender='org.freedesktop.DBus',"
"path='/org/freedesktop/DBus'," "interface='org.freedesktop.DBus',"
"member='NameOwnerChanged'," "arg0='", name, "'" }; char *_d_
, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__
(__builtin_choose_expr( !__builtin_types_compatible_p(typeof
(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
3119 "member='NameOwnerChanged',"({ const char *_appendees_[] = { "type='signal'," "sender='org.freedesktop.DBus',"
"path='/org/freedesktop/DBus'," "interface='org.freedesktop.DBus',"
"member='NameOwnerChanged'," "arg0='", name, "'" }; char *_d_
, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__
(__builtin_choose_expr( !__builtin_types_compatible_p(typeof
(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
3120 "arg0='", name, "'")({ const char *_appendees_[] = { "type='signal'," "sender='org.freedesktop.DBus',"
"path='/org/freedesktop/DBus'," "interface='org.freedesktop.DBus',"
"member='NameOwnerChanged'," "arg0='", name, "'" }; char *_d_
, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__
(__builtin_choose_expr( !__builtin_types_compatible_p(typeof
(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
3121
3122 return sd_bus_add_match_async(bus, &u->match_bus_slot, match, signal_name_owner_changed, NULL((void*)0), u);
3123}
3124
3125int unit_watch_bus_name(Unit *u, const char *name) {
3126 int r;
3127
3128 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 3128, __PRETTY_FUNCTION__
); } while (0)
;
3129 assert(name)do { if ((__builtin_expect(!!(!(name)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("name"), "../src/core/unit.c", 3129, __PRETTY_FUNCTION__
); } while (0)
;
3130
3131 /* Watch a specific name on the bus. We only support one unit
3132 * watching each name for now. */
3133
3134 if (u->manager->api_bus) {
3135 /* If the bus is already available, install the match directly.
3136 * Otherwise, just put the name in the list. bus_setup_api() will take care later. */
3137 r = unit_install_bus_match(u, u->manager->api_bus, name);
3138 if (r < 0)
3139 return log_warning_errno(r, "Failed to subscribe to NameOwnerChanged signal for '%s': %m", name)({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/core/unit.c", 3139, __func__, "Failed to subscribe to NameOwnerChanged signal for '%s': %m"
, name) : -abs(_e); })
;
3140 }
3141
3142 r = hashmap_put(u->manager->watch_bus, name, u);
3143 if (r < 0) {
3144 u->match_bus_slot = sd_bus_slot_unref(u->match_bus_slot);
3145 return log_warning_errno(r, "Failed to put bus name to hashmap: %m")({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/core/unit.c", 3145, __func__, "Failed to put bus name to hashmap: %m"
) : -abs(_e); })
;
3146 }
3147
3148 return 0;
3149}
3150
3151void unit_unwatch_bus_name(Unit *u, const char *name) {
3152 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 3152, __PRETTY_FUNCTION__
); } while (0)
;
3153 assert(name)do { if ((__builtin_expect(!!(!(name)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("name"), "../src/core/unit.c", 3153, __PRETTY_FUNCTION__
); } while (0)
;
3154
3155 (void) hashmap_remove_value(u->manager->watch_bus, name, u);
3156 u->match_bus_slot = sd_bus_slot_unref(u->match_bus_slot);
3157}
3158
3159bool_Bool unit_can_serialize(Unit *u) {
3160 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 3160, __PRETTY_FUNCTION__
); } while (0)
;
3161
3162 return UNIT_VTABLE(u)unit_vtable[(u)->type]->serialize && UNIT_VTABLE(u)unit_vtable[(u)->type]->deserialize_item;
3163}
3164
3165static int unit_serialize_cgroup_mask(FILE *f, const char *key, CGroupMask mask) {
3166 _cleanup_free___attribute__((cleanup(freep))) char *s = NULL((void*)0);
3167 int r = 0;
3168
3169 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/core/unit.c", 3169, __PRETTY_FUNCTION__
); } while (0)
;
3170 assert(key)do { if ((__builtin_expect(!!(!(key)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("key"), "../src/core/unit.c", 3170, __PRETTY_FUNCTION__
); } while (0)
;
3171
3172 if (mask != 0) {
3173 r = cg_mask_to_string(mask, &s);
3174 if (r >= 0) {
3175 fputs(key, f);
3176 fputc('=', f);
3177 fputs(s, f);
3178 fputc('\n', f);
3179 }
3180 }
3181 return r;
3182}
3183
3184static const char *ip_accounting_metric_field[_CGROUP_IP_ACCOUNTING_METRIC_MAX] = {
3185 [CGROUP_IP_INGRESS_BYTES] = "ip-accounting-ingress-bytes",
3186 [CGROUP_IP_INGRESS_PACKETS] = "ip-accounting-ingress-packets",
3187 [CGROUP_IP_EGRESS_BYTES] = "ip-accounting-egress-bytes",
3188 [CGROUP_IP_EGRESS_PACKETS] = "ip-accounting-egress-packets",
3189};
3190
3191int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool_Bool serialize_jobs) {
3192 CGroupIPAccountingMetric m;
3193 int r;
3194
3195 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 3195, __PRETTY_FUNCTION__
); } while (0)
;
3196 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/core/unit.c", 3196, __PRETTY_FUNCTION__
); } while (0)
;
3197 assert(fds)do { if ((__builtin_expect(!!(!(fds)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("fds"), "../src/core/unit.c", 3197, __PRETTY_FUNCTION__
); } while (0)
;
3198
3199 if (unit_can_serialize(u)) {
3200 r = UNIT_VTABLE(u)unit_vtable[(u)->type]->serialize(u, f, fds);
3201 if (r < 0)
3202 return r;
3203 }
3204
3205 dual_timestamp_serialize(f, "state-change-timestamp", &u->state_change_timestamp);
3206
3207 dual_timestamp_serialize(f, "inactive-exit-timestamp", &u->inactive_exit_timestamp);
3208 dual_timestamp_serialize(f, "active-enter-timestamp", &u->active_enter_timestamp);
3209 dual_timestamp_serialize(f, "active-exit-timestamp", &u->active_exit_timestamp);
3210 dual_timestamp_serialize(f, "inactive-enter-timestamp", &u->inactive_enter_timestamp);
3211
3212 dual_timestamp_serialize(f, "condition-timestamp", &u->condition_timestamp);
3213 dual_timestamp_serialize(f, "assert-timestamp", &u->assert_timestamp);
3214
3215 if (dual_timestamp_is_set(&u->condition_timestamp))
3216 unit_serialize_item(u, f, "condition-result", yes_no(u->condition_result));
3217
3218 if (dual_timestamp_is_set(&u->assert_timestamp))
3219 unit_serialize_item(u, f, "assert-result", yes_no(u->assert_result));
3220
3221 unit_serialize_item(u, f, "transient", yes_no(u->transient));
3222
3223 unit_serialize_item(u, f, "exported-invocation-id", yes_no(u->exported_invocation_id));
3224 unit_serialize_item(u, f, "exported-log-level-max", yes_no(u->exported_log_level_max));
3225 unit_serialize_item(u, f, "exported-log-extra-fields", yes_no(u->exported_log_extra_fields));
3226 unit_serialize_item(u, f, "exported-log-rate-limit-interval", yes_no(u->exported_log_rate_limit_interval));
3227 unit_serialize_item(u, f, "exported-log-rate-limit-burst", yes_no(u->exported_log_rate_limit_burst));
3228
3229 unit_serialize_item_format(u, f, "cpu-usage-base", "%" PRIu64"l" "u", u->cpu_usage_base);
3230 if (u->cpu_usage_last != NSEC_INFINITY((nsec_t) -1))
3231 unit_serialize_item_format(u, f, "cpu-usage-last", "%" PRIu64"l" "u", u->cpu_usage_last);
3232
3233 if (u->cgroup_path)
3234 unit_serialize_item(u, f, "cgroup", u->cgroup_path);
3235 unit_serialize_item(u, f, "cgroup-realized", yes_no(u->cgroup_realized));
3236 (void) unit_serialize_cgroup_mask(f, "cgroup-realized-mask", u->cgroup_realized_mask);
3237 (void) unit_serialize_cgroup_mask(f, "cgroup-enabled-mask", u->cgroup_enabled_mask);
3238 unit_serialize_item_format(u, f, "cgroup-bpf-realized", "%i", u->cgroup_bpf_state);
3239
3240 if (uid_is_valid(u->ref_uid))
3241 unit_serialize_item_format(u, f, "ref-uid", UID_FMT"%" "u", u->ref_uid);
3242 if (gid_is_valid(u->ref_gid))
3243 unit_serialize_item_format(u, f, "ref-gid", GID_FMT"%" "u", u->ref_gid);
3244
3245 if (!sd_id128_is_null(u->invocation_id))
3246 unit_serialize_item_format(u, f, "invocation-id", SD_ID128_FORMAT_STR"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", SD_ID128_FORMAT_VAL(u->invocation_id)(u->invocation_id).bytes[0], (u->invocation_id).bytes[1
], (u->invocation_id).bytes[2], (u->invocation_id).bytes
[3], (u->invocation_id).bytes[4], (u->invocation_id).bytes
[5], (u->invocation_id).bytes[6], (u->invocation_id).bytes
[7], (u->invocation_id).bytes[8], (u->invocation_id).bytes
[9], (u->invocation_id).bytes[10], (u->invocation_id).bytes
[11], (u->invocation_id).bytes[12], (u->invocation_id).
bytes[13], (u->invocation_id).bytes[14], (u->invocation_id
).bytes[15]
);
3247
3248 (void) unit_serialize_item_format(u, f, "freezer-state", "%s", freezer_state_to_string(unit_freezer_state(u)));
3249
3250 bus_track_serialize(u->bus_track, f, "ref");
3251
3252 for (m = 0; m < _CGROUP_IP_ACCOUNTING_METRIC_MAX; m++) {
3253 uint64_t v;
3254
3255 r = unit_get_ip_accounting(u, m, &v);
3256 if (r >= 0)
3257 unit_serialize_item_format(u, f, ip_accounting_metric_field[m], "%" PRIu64"l" "u", v);
3258 }
3259
3260 if (serialize_jobs) {
3261 if (u->job) {
3262 fprintf(f, "job\n");
3263 job_serialize(u->job, f);
3264 }
3265
3266 if (u->nop_job) {
3267 fprintf(f, "job\n");
3268 job_serialize(u->nop_job, f);
3269 }
3270 }
3271
3272 /* End marker */
3273 fputc('\n', f);
3274 return 0;
3275}
3276
3277int unit_serialize_item(Unit *u, FILE *f, const char *key, const char *value) {
3278 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 3278, __PRETTY_FUNCTION__
); } while (0)
;
3279 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/core/unit.c", 3279, __PRETTY_FUNCTION__
); } while (0)
;
3280 assert(key)do { if ((__builtin_expect(!!(!(key)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("key"), "../src/core/unit.c", 3280, __PRETTY_FUNCTION__
); } while (0)
;
3281
3282 if (!value)
3283 return 0;
3284
3285 fputs(key, f);
3286 fputc('=', f);
3287 fputs(value, f);
3288 fputc('\n', f);
3289
3290 return 1;
3291}
3292
3293int unit_serialize_item_escaped(Unit *u, FILE *f, const char *key, const char *value) {
3294 _cleanup_free___attribute__((cleanup(freep))) char *c = NULL((void*)0);
3295
3296 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 3296, __PRETTY_FUNCTION__
); } while (0)
;
3297 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/core/unit.c", 3297, __PRETTY_FUNCTION__
); } while (0)
;
3298 assert(key)do { if ((__builtin_expect(!!(!(key)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("key"), "../src/core/unit.c", 3298, __PRETTY_FUNCTION__
); } while (0)
;
3299
3300 if (!value)
3301 return 0;
3302
3303 c = cescape(value);
3304 if (!c)
3305 return -ENOMEM12;
3306
3307 fputs(key, f);
3308 fputc('=', f);
3309 fputs(c, f);
3310 fputc('\n', f);
3311
3312 return 1;
3313}
3314
3315int unit_serialize_item_fd(Unit *u, FILE *f, FDSet *fds, const char *key, int fd) {
3316 int copy;
3317
3318 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 3318, __PRETTY_FUNCTION__
); } while (0)
;
3319 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/core/unit.c", 3319, __PRETTY_FUNCTION__
); } while (0)
;
3320 assert(key)do { if ((__builtin_expect(!!(!(key)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("key"), "../src/core/unit.c", 3320, __PRETTY_FUNCTION__
); } while (0)
;
3321
3322 if (fd < 0)
3323 return 0;
3324
3325 copy = fdset_put_dup(fds, fd);
3326 if (copy < 0)
3327 return copy;
3328
3329 fprintf(f, "%s=%i\n", key, copy);
3330 return 1;
3331}
3332
3333void unit_serialize_item_format(Unit *u, FILE *f, const char *key, const char *format, ...) {
3334 va_list ap;
3335
3336 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 3336, __PRETTY_FUNCTION__
); } while (0)
;
3337 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/core/unit.c", 3337, __PRETTY_FUNCTION__
); } while (0)
;
3338 assert(key)do { if ((__builtin_expect(!!(!(key)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("key"), "../src/core/unit.c", 3338, __PRETTY_FUNCTION__
); } while (0)
;
3339 assert(format)do { if ((__builtin_expect(!!(!(format)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("format"), "../src/core/unit.c", 3339, __PRETTY_FUNCTION__
); } while (0)
;
3340
3341 fputs(key, f);
3342 fputc('=', f);
3343
3344 va_start(ap, format)__builtin_va_start(ap, format);
3345 vfprintf(f, format, ap);
3346 va_end(ap)__builtin_va_end(ap);
3347
3348 fputc('\n', f);
3349}
3350
3351int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
3352 int r;
3353
3354 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 3354, __PRETTY_FUNCTION__
); } while (0)
;
3355 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/core/unit.c", 3355, __PRETTY_FUNCTION__
); } while (0)
;
3356 assert(fds)do { if ((__builtin_expect(!!(!(fds)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("fds"), "../src/core/unit.c", 3356, __PRETTY_FUNCTION__
); } while (0)
;
3357
3358 for (;;) {
3359 _cleanup_free___attribute__((cleanup(freep))) char *line = NULL((void*)0);
3360 CGroupIPAccountingMetric m;
3361 char *l, *v;
3362 size_t k;
3363
3364 r = read_line(f, LONG_LINE_MAX(1U*1024U*1024U), &line);
3365 if (r < 0)
3366 return log_error_errno(r, "Failed to read serialization line: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/core/unit.c", 3366, __func__, "Failed to read serialization line: %m"
) : -abs(_e); })
;
3367 if (r == 0) /* eof */
3368 break;
3369
3370 l = strstrip(line);
3371 if (isempty(l)) /* End marker */
3372 break;
3373
3374 k = strcspn(l, "=");
3375
3376 if (l[k] == '=') {
3377 l[k] = 0;
3378 v = l+k+1;
3379 } else
3380 v = l+k;
3381
3382 if (streq(l, "job")(strcmp((l),("job")) == 0)) {
3383 if (v[0] == '\0') {
3384 /* new-style serialized job */
3385 Job *j;
3386
3387 j = job_new_raw(u);
3388 if (!j)
3389 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/core/unit.c", 3389
, __func__)
;
3390
3391 r = job_deserialize(j, f);
3392 if (r < 0) {
3393 job_free(j);
3394 return r;
3395 }
3396
3397 r = hashmap_put(u->manager->jobs, UINT32_TO_PTR(j->id)((void *) ((uintptr_t) (j->id))), j);
3398 if (r < 0) {
3399 job_free(j);
3400 return r;
3401 }
3402
3403 r = job_install_deserialized(j);
3404 if (r < 0) {
3405 hashmap_remove(u->manager->jobs, UINT32_TO_PTR(j->id)((void *) ((uintptr_t) (j->id))));
3406 job_free(j);
3407 return r;
3408 }
3409 } else /* legacy for pre-44 */
3410 log_unit_warning(u, "Update from too old systemd versions are unsupported, cannot deserialize job: %s", v)({ const Unit *_u = (u); _u ? log_object_internal(4, 0, "../src/core/unit.c"
, 3410, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Update from too old systemd versions are unsupported, cannot deserialize job: %s"
, v) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | (
(4))), 0, "../src/core/unit.c", 3410, __func__, "Update from too old systemd versions are unsupported, cannot deserialize job: %s"
, v); })
;
3411 continue;
3412 } else if (streq(l, "state-change-timestamp")(strcmp((l),("state-change-timestamp")) == 0)) {
3413 dual_timestamp_deserialize(v, &u->state_change_timestamp);
3414 continue;
3415 } else if (streq(l, "inactive-exit-timestamp")(strcmp((l),("inactive-exit-timestamp")) == 0)) {
3416 dual_timestamp_deserialize(v, &u->inactive_exit_timestamp);
3417 continue;
3418 } else if (streq(l, "active-enter-timestamp")(strcmp((l),("active-enter-timestamp")) == 0)) {
3419 dual_timestamp_deserialize(v, &u->active_enter_timestamp);
3420 continue;
3421 } else if (streq(l, "active-exit-timestamp")(strcmp((l),("active-exit-timestamp")) == 0)) {
3422 dual_timestamp_deserialize(v, &u->active_exit_timestamp);
3423 continue;
3424 } else if (streq(l, "inactive-enter-timestamp")(strcmp((l),("inactive-enter-timestamp")) == 0)) {
3425 dual_timestamp_deserialize(v, &u->inactive_enter_timestamp);
3426 continue;
3427 } else if (streq(l, "condition-timestamp")(strcmp((l),("condition-timestamp")) == 0)) {
3428 dual_timestamp_deserialize(v, &u->condition_timestamp);
3429 continue;
3430 } else if (streq(l, "assert-timestamp")(strcmp((l),("assert-timestamp")) == 0)) {
3431 dual_timestamp_deserialize(v, &u->assert_timestamp);
3432 continue;
3433 } else if (streq(l, "condition-result")(strcmp((l),("condition-result")) == 0)) {
3434
3435 r = parse_boolean(v);
3436 if (r < 0)
3437 log_unit_debug(u, "Failed to parse condition result value %s, ignoring.", v)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/unit.c"
, 3437, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to parse condition result value %s, ignoring.", v) :
log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7)))
, 0, "../src/core/unit.c", 3437, __func__, "Failed to parse condition result value %s, ignoring."
, v); })
;
3438 else
3439 u->condition_result = r;
3440
3441 continue;
3442
3443 } else if (streq(l, "assert-result")(strcmp((l),("assert-result")) == 0)) {
3444
3445 r = parse_boolean(v);
3446 if (r < 0)
3447 log_unit_debug(u, "Failed to parse assert result value %s, ignoring.", v)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/unit.c"
, 3447, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to parse assert result value %s, ignoring.", v) : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/unit.c"
, 3447, __func__, "Failed to parse assert result value %s, ignoring."
, v); })
;
3448 else
3449 u->assert_result = r;
3450
3451 continue;
3452
3453 } else if (streq(l, "transient")(strcmp((l),("transient")) == 0)) {
3454
3455 r = parse_boolean(v);
3456 if (r < 0)
3457 log_unit_debug(u, "Failed to parse transient bool %s, ignoring.", v)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/unit.c"
, 3457, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to parse transient bool %s, ignoring.", v) : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/unit.c"
, 3457, __func__, "Failed to parse transient bool %s, ignoring."
, v); })
;
3458 else
3459 u->transient = r;
3460
3461 continue;
3462
3463 } else if (streq(l, "exported-invocation-id")(strcmp((l),("exported-invocation-id")) == 0)) {
3464
3465 r = parse_boolean(v);
3466 if (r < 0)
3467 log_unit_debug(u, "Failed to parse exported invocation ID bool %s, ignoring.", v)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/unit.c"
, 3467, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to parse exported invocation ID bool %s, ignoring."
, v) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | (
(7))), 0, "../src/core/unit.c", 3467, __func__, "Failed to parse exported invocation ID bool %s, ignoring."
, v); })
;
3468 else
3469 u->exported_invocation_id = r;
3470
3471 continue;
3472
3473 } else if (streq(l, "exported-log-level-max")(strcmp((l),("exported-log-level-max")) == 0)) {
3474
3475 r = parse_boolean(v);
3476 if (r < 0)
3477 log_unit_debug(u, "Failed to parse exported log level max bool %s, ignoring.", v)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/unit.c"
, 3477, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to parse exported log level max bool %s, ignoring."
, v) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | (
(7))), 0, "../src/core/unit.c", 3477, __func__, "Failed to parse exported log level max bool %s, ignoring."
, v); })
;
3478 else
3479 u->exported_log_level_max = r;
3480
3481 continue;
3482
3483 } else if (streq(l, "exported-log-extra-fields")(strcmp((l),("exported-log-extra-fields")) == 0)) {
3484
3485 r = parse_boolean(v);
3486 if (r < 0)
3487 log_unit_debug(u, "Failed to parse exported log extra fields bool %s, ignoring.", v)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/unit.c"
, 3487, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to parse exported log extra fields bool %s, ignoring."
, v) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | (
(7))), 0, "../src/core/unit.c", 3487, __func__, "Failed to parse exported log extra fields bool %s, ignoring."
, v); })
;
3488 else
3489 u->exported_log_extra_fields = r;
3490
3491 continue;
3492
3493 } else if (streq(l, "exported-log-rate-limit-interval")(strcmp((l),("exported-log-rate-limit-interval")) == 0)) {
3494
3495 r = parse_boolean(v);
3496 if (r < 0)
3497 log_unit_debug(u, "Failed to parse exported log rate limit interval %s, ignoring.", v)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/unit.c"
, 3497, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to parse exported log rate limit interval %s, ignoring."
, v) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | (
(7))), 0, "../src/core/unit.c", 3497, __func__, "Failed to parse exported log rate limit interval %s, ignoring."
, v); })
;
3498 else
3499 u->exported_log_rate_limit_interval = r;
3500
3501 continue;
3502
3503 } else if (streq(l, "exported-log-rate-limit-burst")(strcmp((l),("exported-log-rate-limit-burst")) == 0)) {
3504
3505 r = parse_boolean(v);
3506 if (r < 0)
3507 log_unit_debug(u, "Failed to parse exported log rate limit burst %s, ignoring.", v)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/unit.c"
, 3507, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to parse exported log rate limit burst %s, ignoring."
, v) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | (
(7))), 0, "../src/core/unit.c", 3507, __func__, "Failed to parse exported log rate limit burst %s, ignoring."
, v); })
;
3508 else
3509 u->exported_log_rate_limit_burst = r;
3510
3511 continue;
3512
3513 } else if (STR_IN_SET(l, "cpu-usage-base", "cpuacct-usage-base")(!!strv_find((((char**) ((const char*[]) { "cpu-usage-base", "cpuacct-usage-base"
, ((void*)0) }))), (l)))
) {
3514
3515 r = safe_atou64(v, &u->cpu_usage_base);
3516 if (r < 0)
3517 log_unit_debug(u, "Failed to parse CPU usage base %s, ignoring.", v)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/unit.c"
, 3517, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to parse CPU usage base %s, ignoring.", v) : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/unit.c"
, 3517, __func__, "Failed to parse CPU usage base %s, ignoring."
, v); })
;
3518
3519 continue;
3520
3521 } else if (streq(l, "cpu-usage-last")(strcmp((l),("cpu-usage-last")) == 0)) {
3522
3523 r = safe_atou64(v, &u->cpu_usage_last);
3524 if (r < 0)
3525 log_unit_debug(u, "Failed to read CPU usage last %s, ignoring.", v)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/unit.c"
, 3525, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to read CPU usage last %s, ignoring.", v) : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/unit.c"
, 3525, __func__, "Failed to read CPU usage last %s, ignoring."
, v); })
;
3526
3527 continue;
3528
3529 } else if (streq(l, "cgroup")(strcmp((l),("cgroup")) == 0)) {
3530
3531 r = unit_set_cgroup_path(u, v);
3532 if (r < 0)
3533 log_unit_debug_errno(u, r, "Failed to set cgroup path %s, ignoring: %m", v)({ const Unit *_u = (u); _u ? log_object_internal(7, r, "../src/core/unit.c"
, 3533, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to set cgroup path %s, ignoring: %m", v) : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((7))), r, "../src/core/unit.c"
, 3533, __func__, "Failed to set cgroup path %s, ignoring: %m"
, v); })
;
3534
3535 (void) unit_watch_cgroup(u);
3536
3537 continue;
3538 } else if (streq(l, "cgroup-realized")(strcmp((l),("cgroup-realized")) == 0)) {
3539 int b;
3540
3541 b = parse_boolean(v);
3542 if (b < 0)
3543 log_unit_debug(u, "Failed to parse cgroup-realized bool %s, ignoring.", v)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/unit.c"
, 3543, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to parse cgroup-realized bool %s, ignoring.", v) : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/unit.c"
, 3543, __func__, "Failed to parse cgroup-realized bool %s, ignoring."
, v); })
;
3544 else
3545 u->cgroup_realized = b;
3546
3547 continue;
3548
3549 } else if (streq(l, "cgroup-realized-mask")(strcmp((l),("cgroup-realized-mask")) == 0)) {
3550
3551 r = cg_mask_from_string(v, &u->cgroup_realized_mask);
3552 if (r < 0)
3553 log_unit_debug(u, "Failed to parse cgroup-realized-mask %s, ignoring.", v)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/unit.c"
, 3553, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to parse cgroup-realized-mask %s, ignoring.", v) : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/unit.c"
, 3553, __func__, "Failed to parse cgroup-realized-mask %s, ignoring."
, v); })
;
3554 continue;
3555
3556 } else if (streq(l, "cgroup-enabled-mask")(strcmp((l),("cgroup-enabled-mask")) == 0)) {
3557
3558 r = cg_mask_from_string(v, &u->cgroup_enabled_mask);
3559 if (r < 0)
3560 log_unit_debug(u, "Failed to parse cgroup-enabled-mask %s, ignoring.", v)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/unit.c"
, 3560, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to parse cgroup-enabled-mask %s, ignoring.", v) : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/unit.c"
, 3560, __func__, "Failed to parse cgroup-enabled-mask %s, ignoring."
, v); })
;
3561 continue;
3562
3563 } else if (streq(l, "cgroup-bpf-realized")(strcmp((l),("cgroup-bpf-realized")) == 0)) {
3564 int i;
3565
3566 r = safe_atoi(v, &i);
3567 if (r < 0)
3568 log_unit_debug(u, "Failed to parse cgroup BPF state %s, ignoring.", v)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/unit.c"
, 3568, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to parse cgroup BPF state %s, ignoring.", v) : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/unit.c"
, 3568, __func__, "Failed to parse cgroup BPF state %s, ignoring."
, v); })
;
3569 else
3570 u->cgroup_bpf_state =
3571 i < 0 ? UNIT_CGROUP_BPF_INVALIDATED :
3572 i > 0 ? UNIT_CGROUP_BPF_ON :
3573 UNIT_CGROUP_BPF_OFF;
3574
3575 continue;
3576
3577 } else if (streq(l, "ref-uid")(strcmp((l),("ref-uid")) == 0)) {
3578 uid_t uid;
3579
3580 r = parse_uid(v, &uid);
3581 if (r < 0)
3582 log_unit_debug(u, "Failed to parse referenced UID %s, ignoring.", v)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/unit.c"
, 3582, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to parse referenced UID %s, ignoring.", v) : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/unit.c"
, 3582, __func__, "Failed to parse referenced UID %s, ignoring."
, v); })
;
3583 else
3584 unit_ref_uid_gid(u, uid, GID_INVALID((gid_t) -1));
3585
3586 continue;
3587
3588 } else if (streq(l, "ref-gid")(strcmp((l),("ref-gid")) == 0)) {
3589 gid_t gid;
3590
3591 r = parse_gid(v, &gid);
3592 if (r < 0)
3593 log_unit_debug(u, "Failed to parse referenced GID %s, ignoring.", v)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/unit.c"
, 3593, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to parse referenced GID %s, ignoring.", v) : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/unit.c"
, 3593, __func__, "Failed to parse referenced GID %s, ignoring."
, v); })
;
3594 else
3595 unit_ref_uid_gid(u, UID_INVALID((uid_t) -1), gid);
3596
3597 } else if (streq(l, "ref")(strcmp((l),("ref")) == 0)) {
3598
3599 r = strv_extend(&u->deserialized_refs, v);
3600 if (r < 0)
3601 log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/core/unit.c", 3601
, __func__)
;
3602
3603 continue;
3604 } else if (streq(l, "invocation-id")(strcmp((l),("invocation-id")) == 0)) {
3605 sd_id128_t id;
3606
3607 r = sd_id128_from_string(v, &id);
3608 if (r < 0)
3609 log_unit_debug(u, "Failed to parse invocation id %s, ignoring.", v)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/unit.c"
, 3609, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to parse invocation id %s, ignoring.", v) : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/unit.c"
, 3609, __func__, "Failed to parse invocation id %s, ignoring."
, v); })
;
3610 else {
3611 r = unit_set_invocation_id(u, id);
3612 if (r < 0)
3613 log_unit_warning_errno(u, r, "Failed to set invocation ID for unit: %m")({ const Unit *_u = (u); _u ? log_object_internal(4, r, "../src/core/unit.c"
, 3613, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to set invocation ID for unit: %m") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((4))), r, "../src/core/unit.c"
, 3613, __func__, "Failed to set invocation ID for unit: %m")
; })
;
3614 }
3615
3616 continue;
3617 } else if (streq(l, "freezer-state")(strcmp((l),("freezer-state")) == 0)) {
3618 FreezerState s;
3619
3620 s = freezer_state_from_string(v);
3621 if (s < 0)
3622 log_unit_debug(u, "Failed to deserialize freezer-state '%s', ignoring.", v)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/unit.c"
, 3622, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to deserialize freezer-state '%s', ignoring.", v) :
log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7)))
, 0, "../src/core/unit.c", 3622, __func__, "Failed to deserialize freezer-state '%s', ignoring."
, v); })
;
3623 else
3624 u->freezer_state = s;
3625
3626 continue;
3627 }
3628
3629 /* Check if this is an IP accounting metric serialization field */
3630 for (m = 0; m < _CGROUP_IP_ACCOUNTING_METRIC_MAX; m++)
3631 if (streq(l, ip_accounting_metric_field[m])(strcmp((l),(ip_accounting_metric_field[m])) == 0))
3632 break;
3633 if (m < _CGROUP_IP_ACCOUNTING_METRIC_MAX) {
3634 uint64_t c;
3635
3636 r = safe_atou64(v, &c);
3637 if (r < 0)
3638 log_unit_debug(u, "Failed to parse IP accounting value %s, ignoring.", v)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/unit.c"
, 3638, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to parse IP accounting value %s, ignoring.", v) : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/unit.c"
, 3638, __func__, "Failed to parse IP accounting value %s, ignoring."
, v); })
;
3639 else
3640 u->ip_accounting_extra[m] = c;
3641 continue;
3642 }
3643
3644 if (unit_can_serialize(u)) {
3645 r = exec_runtime_deserialize_compat(u, l, v, fds);
3646 if (r < 0) {
3647 log_unit_warning(u, "Failed to deserialize runtime parameter '%s', ignoring.", l)({ const Unit *_u = (u); _u ? log_object_internal(4, 0, "../src/core/unit.c"
, 3647, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to deserialize runtime parameter '%s', ignoring.", l
) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4
))), 0, "../src/core/unit.c", 3647, __func__, "Failed to deserialize runtime parameter '%s', ignoring."
, l); })
;
3648 continue;
3649 }
3650
3651 /* Returns positive if key was handled by the call */
3652 if (r > 0)
3653 continue;
3654
3655 r = UNIT_VTABLE(u)unit_vtable[(u)->type]->deserialize_item(u, l, v, fds);
3656 if (r < 0)
3657 log_unit_warning(u, "Failed to deserialize unit parameter '%s', ignoring.", l)({ const Unit *_u = (u); _u ? log_object_internal(4, 0, "../src/core/unit.c"
, 3657, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to deserialize unit parameter '%s', ignoring.", l) :
log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4)))
, 0, "../src/core/unit.c", 3657, __func__, "Failed to deserialize unit parameter '%s', ignoring."
, l); })
;
3658 }
3659 }
3660
3661 /* Versions before 228 did not carry a state change timestamp. In this case, take the current time. This is
3662 * useful, so that timeouts based on this timestamp don't trigger too early, and is in-line with the logic from
3663 * before 228 where the base for timeouts was not persistent across reboots. */
3664
3665 if (!dual_timestamp_is_set(&u->state_change_timestamp))
3666 dual_timestamp_get(&u->state_change_timestamp);
3667
3668 /* Let's make sure that everything that is deserialized also gets any potential new cgroup settings applied
3669 * after we are done. For that we invalidate anything already realized, so that we can realize it again. */
3670 unit_invalidate_cgroup(u, _CGROUP_MASK_ALL);
3671 unit_invalidate_cgroup_bpf(u);
3672
3673 return 0;
3674}
3675
3676int unit_deserialize_skip(FILE *f) {
3677 int r;
3678 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/core/unit.c", 3678, __PRETTY_FUNCTION__
); } while (0)
;
3679
3680 /* Skip serialized data for this unit. We don't know what it is. */
3681
3682 for (;;) {
3683 _cleanup_free___attribute__((cleanup(freep))) char *line = NULL((void*)0);
3684 char *l;
3685
3686 r = read_line(f, LONG_LINE_MAX(1U*1024U*1024U), &line);
3687 if (r < 0)
3688 return log_error_errno(r, "Failed to read serialization line: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/core/unit.c", 3688, __func__, "Failed to read serialization line: %m"
) : -abs(_e); })
;
3689 if (r == 0)
3690 return 0;
3691
3692 l = strstrip(line);
3693
3694 /* End marker */
3695 if (isempty(l))
3696 return 1;
3697 }
3698}
3699
3700int unit_add_node_dependency(Unit *u, const char *what, bool_Bool wants, UnitDependency dep, UnitDependencyMask mask) {
3701 Unit *device;
3702 _cleanup_free___attribute__((cleanup(freep))) char *e = NULL((void*)0);
3703 int r;
3704
3705 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 3705, __PRETTY_FUNCTION__
); } while (0)
;
3706
3707 /* Adds in links to the device node that this unit is based on */
3708 if (isempty(what))
3709 return 0;
3710
3711 if (!is_device_path(what))
3712 return 0;
3713
3714 /* When device units aren't supported (such as in a
3715 * container), don't create dependencies on them. */
3716 if (!unit_type_supported(UNIT_DEVICE))
3717 return 0;
3718
3719 r = unit_name_from_path(what, ".device", &e);
3720 if (r < 0)
3721 return r;
3722
3723 r = manager_load_unit(u->manager, e, NULL((void*)0), NULL((void*)0), &device);
3724 if (r < 0)
3725 return r;
3726
3727 if (dep == UNIT_REQUIRES && device_shall_be_bound_by(device, u))
3728 dep = UNIT_BINDS_TO;
3729
3730 r = unit_add_two_dependencies(u, UNIT_AFTER,
3731 MANAGER_IS_SYSTEM(u->manager)((u->manager)->unit_file_scope == UNIT_FILE_SYSTEM) ? dep : UNIT_WANTS,
3732 device, true1, mask);
3733 if (r < 0)
3734 return r;
3735
3736 if (wants) {
3737 r = unit_add_dependency(device, UNIT_WANTS, u, false0, mask);
3738 if (r < 0)
3739 return r;
3740 }
3741
3742 return 0;
3743}
3744
3745int unit_coldplug(Unit *u) {
3746 int r = 0, q;
3747 char **i;
3748 Job *uj;
3749
3750 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 3750, __PRETTY_FUNCTION__
); } while (0)
;
3751
3752 /* Make sure we don't enter a loop, when coldplugging recursively. */
3753 if (u->coldplugged)
3754 return 0;
3755
3756 u->coldplugged = true1;
3757
3758 STRV_FOREACH(i, u->deserialized_refs)for ((i) = (u->deserialized_refs); (i) && *(i); (i
)++)
{
3759 q = bus_unit_track_add_name(u, *i);
3760 if (q < 0 && r >= 0)
3761 r = q;
3762 }
3763 u->deserialized_refs = strv_free(u->deserialized_refs);
3764
3765 if (UNIT_VTABLE(u)unit_vtable[(u)->type]->coldplug) {
3766 q = UNIT_VTABLE(u)unit_vtable[(u)->type]->coldplug(u);
3767 if (q < 0 && r >= 0)
3768 r = q;
3769 }
3770
3771 uj = u->job ?: u->nop_job;
3772 if (uj) {
3773 q = job_coldplug(uj);
3774 if (q < 0 && r >= 0)
3775 r = q;
3776 }
3777
3778 return r;
3779}
3780
3781void unit_catchup(Unit *u) {
3782 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 3782, __PRETTY_FUNCTION__
); } while (0)
;
3783
3784 if (UNIT_VTABLE(u)unit_vtable[(u)->type]->catchup)
3785 UNIT_VTABLE(u)unit_vtable[(u)->type]->catchup(u);
3786}
3787
3788static bool_Bool fragment_mtime_newer(const char *path, usec_t mtime, bool_Bool path_masked) {
3789 struct stat st;
3790
3791 if (!path)
3792 return false0;
3793
3794 /* If the source is some virtual kernel file system, then we assume we watch it anyway, and hence pretend we
3795 * are never out-of-date. */
3796 if (PATH_STARTSWITH_SET(path, "/proc", "/sys")({ char **s; _Bool _found = 0; for ((s) = (((char**) ((const char
*[]) { "/proc", "/sys", ((void*)0) }))); (s) && *(s);
(s)++) if (path_startswith(path, *s)) { _found = 1; break; }
_found; })
)
3797 return false0;
3798
3799 if (stat(path, &st) < 0)
3800 /* What, cannot access this anymore? */
3801 return true1;
3802
3803 if (path_masked)
3804 /* For masked files check if they are still so */
3805 return !null_or_empty(&st);
3806 else
3807 /* For non-empty files check the mtime */
3808 return timespec_load(&st.st_mtim) > mtime;
3809
3810 return false0;
3811}
3812
3813bool_Bool unit_need_daemon_reload(Unit *u) {
3814 _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **t = NULL((void*)0);
3815 char **path;
3816
3817 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 3817, __PRETTY_FUNCTION__
); } while (0)
;
3818
3819 /* For unit files, we allow masking… */
3820 if (fragment_mtime_newer(u->fragment_path, u->fragment_mtime,
3821 u->load_state == UNIT_MASKED))
3822 return true1;
3823
3824 /* Source paths should not be masked… */
3825 if (fragment_mtime_newer(u->source_path, u->source_mtime, false0))
3826 return true1;
3827
3828 if (u->load_state == UNIT_LOADED)
3829 (void) unit_find_dropin_paths(u, &t);
3830 if (!strv_equal(u->dropin_paths, t))
3831 return true1;
3832
3833 /* … any drop-ins that are masked are simply omitted from the list. */
3834 STRV_FOREACH(path, u->dropin_paths)for ((path) = (u->dropin_paths); (path) && *(path)
; (path)++)
3835 if (fragment_mtime_newer(*path, u->dropin_mtime, false0))
3836 return true1;
3837
3838 return false0;
3839}
3840
3841void unit_reset_failed(Unit *u) {
3842 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 3842, __PRETTY_FUNCTION__
); } while (0)
;
3843
3844 if (UNIT_VTABLE(u)unit_vtable[(u)->type]->reset_failed)
3845 UNIT_VTABLE(u)unit_vtable[(u)->type]->reset_failed(u);
3846
3847 RATELIMIT_RESET(u->start_limit)do { RateLimit *_r = &(u->start_limit); _r->num = 0
; _r->begin = 0; } while (0)
;
3848 u->start_limit_hit = false0;
3849}
3850
3851Unit *unit_following(Unit *u) {
3852 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 3852, __PRETTY_FUNCTION__
); } while (0)
;
3853
3854 if (UNIT_VTABLE(u)unit_vtable[(u)->type]->following)
3855 return UNIT_VTABLE(u)unit_vtable[(u)->type]->following(u);
3856
3857 return NULL((void*)0);
3858}
3859
3860bool_Bool unit_stop_pending(Unit *u) {
3861 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 3861, __PRETTY_FUNCTION__
); } while (0)
;
3862
3863 /* This call does check the current state of the unit. It's
3864 * hence useful to be called from state change calls of the
3865 * unit itself, where the state isn't updated yet. This is
3866 * different from unit_inactive_or_pending() which checks both
3867 * the current state and for a queued job. */
3868
3869 return u->job && u->job->type == JOB_STOP;
3870}
3871
3872bool_Bool unit_inactive_or_pending(Unit *u) {
3873 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 3873, __PRETTY_FUNCTION__
); } while (0)
;
3874
3875 /* Returns true if the unit is inactive or going down */
3876
3877 if (UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(u)))
3878 return true1;
3879
3880 if (unit_stop_pending(u))
3881 return true1;
3882
3883 return false0;
3884}
3885
3886bool_Bool unit_active_or_pending(Unit *u) {
3887 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 3887, __PRETTY_FUNCTION__
); } while (0)
;
3888
3889 /* Returns true if the unit is active or going up */
3890
3891 if (UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u)))
3892 return true1;
3893
3894 if (u->job &&
3895 IN_SET(u->job->type, JOB_START, JOB_RELOAD_OR_START, JOB_RESTART)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){JOB_START, JOB_RELOAD_OR_START, JOB_RESTART
})/sizeof(int)]; switch(u->job->type) { case JOB_START:
case JOB_RELOAD_OR_START: case JOB_RESTART: _found = 1; break
; default: break; } _found; })
)
3896 return true1;
3897
3898 return false0;
3899}
3900
3901bool_Bool unit_will_restart(Unit *u) {
3902 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 3902, __PRETTY_FUNCTION__
); } while (0)
;
3903
3904 if (!UNIT_VTABLE(u)unit_vtable[(u)->type]->will_restart)
3905 return false0;
3906
3907 return UNIT_VTABLE(u)unit_vtable[(u)->type]->will_restart(u);
3908}
3909
3910int unit_kill(Unit *u, KillWho w, int signo, sd_bus_error *error) {
3911 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 3911, __PRETTY_FUNCTION__
); } while (0)
;
3912 assert(w >= 0 && w < _KILL_WHO_MAX)do { if ((__builtin_expect(!!(!(w >= 0 && w < _KILL_WHO_MAX
)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("w >= 0 && w < _KILL_WHO_MAX"
), "../src/core/unit.c", 3912, __PRETTY_FUNCTION__); } while (
0)
;
3913 assert(SIGNAL_VALID(signo))do { if ((__builtin_expect(!!(!(SIGNAL_VALID(signo))),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("SIGNAL_VALID(signo)"), "../src/core/unit.c"
, 3913, __PRETTY_FUNCTION__); } while (0)
;
3914
3915 if (!UNIT_VTABLE(u)unit_vtable[(u)->type]->kill)
3916 return -EOPNOTSUPP95;
3917
3918 return UNIT_VTABLE(u)unit_vtable[(u)->type]->kill(u, w, signo, error);
3919}
3920
3921static Set *unit_pid_set(pid_t main_pid, pid_t control_pid) {
3922 _cleanup_set_free___attribute__((cleanup(set_freep))) Set *pid_set = NULL((void*)0);
3923 int r;
3924
3925 pid_set = set_new(NULL)internal_set_new(((void*)0) );
3926 if (!pid_set)
3927 return NULL((void*)0);
3928
3929 /* Exclude the main/control pids from being killed via the cgroup */
3930 if (main_pid > 0) {
3931 r = set_put(pid_set, PID_TO_PTR(main_pid));
3932 if (r < 0)
3933 return NULL((void*)0);
3934 }
3935
3936 if (control_pid > 0) {
3937 r = set_put(pid_set, PID_TO_PTR(control_pid));
3938 if (r < 0)
3939 return NULL((void*)0);
3940 }
3941
3942 return TAKE_PTR(pid_set)({ typeof(pid_set) _ptr_ = (pid_set); (pid_set) = ((void*)0);
_ptr_; })
;
3943}
3944
3945int unit_kill_common(
3946 Unit *u,
3947 KillWho who,
3948 int signo,
3949 pid_t main_pid,
3950 pid_t control_pid,
3951 sd_bus_error *error) {
3952
3953 int r = 0;
3954 bool_Bool killed = false0;
3955
3956 if (IN_SET(who, KILL_MAIN, KILL_MAIN_FAIL)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){KILL_MAIN, KILL_MAIN_FAIL})/sizeof(int)]
; switch(who) { case KILL_MAIN: case KILL_MAIN_FAIL: _found =
1; break; default: break; } _found; })
) {
3957 if (main_pid < 0)
3958 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PROCESS"org.freedesktop.systemd1.NoSuchProcess", "%s units have no main processes", unit_type_to_string(u->type));
3959 else if (main_pid == 0)
3960 return sd_bus_error_set_const(error, BUS_ERROR_NO_SUCH_PROCESS"org.freedesktop.systemd1.NoSuchProcess", "No main process to kill");
3961 }
3962
3963 if (IN_SET(who, KILL_CONTROL, KILL_CONTROL_FAIL)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){KILL_CONTROL, KILL_CONTROL_FAIL})/sizeof
(int)]; switch(who) { case KILL_CONTROL: case KILL_CONTROL_FAIL
: _found = 1; break; default: break; } _found; })
) {
3964 if (control_pid < 0)
3965 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PROCESS"org.freedesktop.systemd1.NoSuchProcess", "%s units have no control processes", unit_type_to_string(u->type));
3966 else if (control_pid == 0)
3967 return sd_bus_error_set_const(error, BUS_ERROR_NO_SUCH_PROCESS"org.freedesktop.systemd1.NoSuchProcess", "No control process to kill");
3968 }
3969
3970 if (IN_SET(who, KILL_CONTROL, KILL_CONTROL_FAIL, KILL_ALL, KILL_ALL_FAIL)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){KILL_CONTROL, KILL_CONTROL_FAIL, KILL_ALL
, KILL_ALL_FAIL})/sizeof(int)]; switch(who) { case KILL_CONTROL
: case KILL_CONTROL_FAIL: case KILL_ALL: case KILL_ALL_FAIL: _found
= 1; break; default: break; } _found; })
)
3971 if (control_pid > 0) {
3972 if (kill(control_pid, signo) < 0)
3973 r = -errno(*__errno_location ());
3974 else
3975 killed = true1;
3976 }
3977
3978 if (IN_SET(who, KILL_MAIN, KILL_MAIN_FAIL, KILL_ALL, KILL_ALL_FAIL)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){KILL_MAIN, KILL_MAIN_FAIL, KILL_ALL, KILL_ALL_FAIL
})/sizeof(int)]; switch(who) { case KILL_MAIN: case KILL_MAIN_FAIL
: case KILL_ALL: case KILL_ALL_FAIL: _found = 1; break; default
: break; } _found; })
)
3979 if (main_pid > 0) {
3980 if (kill(main_pid, signo) < 0)
3981 r = -errno(*__errno_location ());
3982 else
3983 killed = true1;
3984 }
3985
3986 if (IN_SET(who, KILL_ALL, KILL_ALL_FAIL)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){KILL_ALL, KILL_ALL_FAIL})/sizeof(int)]; switch
(who) { case KILL_ALL: case KILL_ALL_FAIL: _found = 1; break;
default: break; } _found; })
&& u->cgroup_path) {
3987 _cleanup_set_free___attribute__((cleanup(set_freep))) Set *pid_set = NULL((void*)0);
3988 int q;
3989
3990 /* Exclude the main/control pids from being killed via the cgroup */
3991 pid_set = unit_pid_set(main_pid, control_pid);
3992 if (!pid_set)
3993 return -ENOMEM12;
3994
3995 q = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER"_systemd", u->cgroup_path, signo, 0, pid_set, NULL((void*)0), NULL((void*)0));
3996 if (q < 0 && !IN_SET(q, -EAGAIN, -ESRCH, -ENOENT)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){-11, -3, -2})/sizeof(int)]; switch(q) { case
-11: case -3: case -2: _found = 1; break; default: break; } _found
; })
)
3997 r = q;
3998 else
3999 killed = true1;
4000 }
4001
4002 if (r == 0 && !killed && IN_SET(who, KILL_ALL_FAIL, KILL_CONTROL_FAIL)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){KILL_ALL_FAIL, KILL_CONTROL_FAIL})/sizeof
(int)]; switch(who) { case KILL_ALL_FAIL: case KILL_CONTROL_FAIL
: _found = 1; break; default: break; } _found; })
)
4003 return -ESRCH3;
4004
4005 return r;
4006}
4007
4008int unit_following_set(Unit *u, Set **s) {
4009 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 4009, __PRETTY_FUNCTION__
); } while (0)
;
4010 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/core/unit.c", 4010, __PRETTY_FUNCTION__
); } while (0)
;
4011
4012 if (UNIT_VTABLE(u)unit_vtable[(u)->type]->following_set)
4013 return UNIT_VTABLE(u)unit_vtable[(u)->type]->following_set(u, s);
4014
4015 *s = NULL((void*)0);
4016 return 0;
4017}
4018
4019UnitFileState unit_get_unit_file_state(Unit *u) {
4020 int r;
4021
4022 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 4022, __PRETTY_FUNCTION__
); } while (0)
;
4023
4024 if (u->unit_file_state < 0 && u->fragment_path) {
4025 r = unit_file_get_state(
4026 u->manager->unit_file_scope,
4027 NULL((void*)0),
4028 u->id,
4029 &u->unit_file_state);
4030 if (r < 0)
4031 u->unit_file_state = UNIT_FILE_BAD;
4032 }
4033
4034 return u->unit_file_state;
4035}
4036
4037int unit_get_unit_file_preset(Unit *u) {
4038 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 4038, __PRETTY_FUNCTION__
); } while (0)
;
4039
4040 if (u->unit_file_preset < 0 && u->fragment_path)
4041 u->unit_file_preset = unit_file_query_preset(
4042 u->manager->unit_file_scope,
4043 NULL((void*)0),
4044 basename(u->fragment_path));
4045
4046 return u->unit_file_preset;
4047}
4048
4049Unit* unit_ref_set(UnitRef *ref, Unit *source, Unit *target) {
4050 assert(ref)do { if ((__builtin_expect(!!(!(ref)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ref"), "../src/core/unit.c", 4050, __PRETTY_FUNCTION__
); } while (0)
;
4051 assert(source)do { if ((__builtin_expect(!!(!(source)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("source"), "../src/core/unit.c", 4051, __PRETTY_FUNCTION__
); } while (0)
;
4052 assert(target)do { if ((__builtin_expect(!!(!(target)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("target"), "../src/core/unit.c", 4052, __PRETTY_FUNCTION__
); } while (0)
;
4053
4054 if (ref->target)
4055 unit_ref_unset(ref);
4056
4057 ref->source = source;
4058 ref->target = target;
4059 LIST_PREPEND(refs_by_target, target->refs_by_target, ref)do { typeof(*(target->refs_by_target)) **_head = &(target
->refs_by_target), *_item = (ref); do { if ((__builtin_expect
(!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD,
("_item"), "../src/core/unit.c", 4059, __PRETTY_FUNCTION__);
} while (0); if ((_item->refs_by_target_next = *_head)) _item
->refs_by_target_next->refs_by_target_prev = _item; _item
->refs_by_target_prev = ((void*)0); *_head = _item; } while
(0)
;
4060 return target;
4061}
4062
4063void unit_ref_unset(UnitRef *ref) {
4064 assert(ref)do { if ((__builtin_expect(!!(!(ref)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ref"), "../src/core/unit.c", 4064, __PRETTY_FUNCTION__
); } while (0)
;
4065
4066 if (!ref->target)
4067 return;
4068
4069 /* We are about to drop a reference to the unit, make sure the garbage collection has a look at it as it might
4070 * be unreferenced now. */
4071 unit_add_to_gc_queue(ref->target);
4072
4073 LIST_REMOVE(refs_by_target, ref->target->refs_by_target, ref)do { typeof(*(ref->target->refs_by_target)) **_head = &
(ref->target->refs_by_target), *_item = (ref); do { if (
(__builtin_expect(!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("_item"), "../src/core/unit.c", 4073, __PRETTY_FUNCTION__)
; } while (0); if (_item->refs_by_target_next) _item->refs_by_target_next
->refs_by_target_prev = _item->refs_by_target_prev; if (
_item->refs_by_target_prev) _item->refs_by_target_prev->
refs_by_target_next = _item->refs_by_target_next; else { do
{ if ((__builtin_expect(!!(!(*_head == _item)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("*_head == _item"), "../src/core/unit.c"
, 4073, __PRETTY_FUNCTION__); } while (0); *_head = _item->
refs_by_target_next; } _item->refs_by_target_next = _item->
refs_by_target_prev = ((void*)0); } while (0)
;
4074 ref->source = ref->target = NULL((void*)0);
4075}
4076
4077static int user_from_unit_name(Unit *u, char **ret) {
4078
4079 static const uint8_t hash_key[] = {
4080 0x58, 0x1a, 0xaf, 0xe6, 0x28, 0x58, 0x4e, 0x96,
4081 0xb4, 0x4e, 0xf5, 0x3b, 0x8c, 0x92, 0x07, 0xec
4082 };
4083
4084 _cleanup_free___attribute__((cleanup(freep))) char *n = NULL((void*)0);
4085 int r;
4086
4087 r = unit_name_to_prefix(u->id, &n);
4088 if (r < 0)
4089 return r;
4090
4091 if (valid_user_group_name(n, 0)) {
4092 *ret = TAKE_PTR(n)({ typeof(n) _ptr_ = (n); (n) = ((void*)0); _ptr_; });
4093 return 0;
4094 }
4095
4096 /* If we can't use the unit name as a user name, then let's hash it and use that */
4097 if (asprintf(ret, "_du%016" PRIx64"l" "x", siphash24(n, strlen(n), hash_key)) < 0)
4098 return -ENOMEM12;
4099
4100 return 0;
4101}
4102
4103int unit_patch_contexts(Unit *u) {
4104 CGroupContext *cc;
4105 ExecContext *ec;
4106 unsigned i;
4107 int r;
4108
4109 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 4109, __PRETTY_FUNCTION__
); } while (0)
;
4110
4111 /* Patch in the manager defaults into the exec and cgroup
4112 * contexts, _after_ the rest of the settings have been
4113 * initialized */
4114
4115 ec = unit_get_exec_context(u);
4116 if (ec) {
4117 /* This only copies in the ones that need memory */
4118 for (i = 0; i < _RLIMIT_MAX(__RLIMIT_RTTIME+1 > __RLIMIT_NLIMITS ? __RLIMIT_RTTIME+1 :
__RLIMIT_NLIMITS)
; i++)
4119 if (u->manager->rlimit[i] && !ec->rlimit[i]) {
4120 ec->rlimit[i] = newdup(struct rlimit, u->manager->rlimit[i], 1)((struct rlimit*) memdup_multiply(u->manager->rlimit[i]
, sizeof(struct rlimit), (1)))
;
4121 if (!ec->rlimit[i])
4122 return -ENOMEM12;
4123 }
4124
4125 if (MANAGER_IS_USER(u->manager)((u->manager)->unit_file_scope != UNIT_FILE_SYSTEM) &&
4126 !ec->working_directory) {
4127
4128 r = get_home_dir(&ec->working_directory);
4129 if (r < 0)
4130 return r;
4131
4132 /* Allow user services to run, even if the
4133 * home directory is missing */
4134 ec->working_directory_missing_ok = true1;
4135 }
4136
4137 if (ec->private_devices)
4138 ec->capability_bounding_set &= ~((UINT64_C(1)1UL << CAP_MKNOD27) | (UINT64_C(1)1UL << CAP_SYS_RAWIO17));
4139
4140 if (ec->protect_kernel_modules)
4141 ec->capability_bounding_set &= ~(UINT64_C(1)1UL << CAP_SYS_MODULE16);
4142
4143 if (ec->dynamic_user) {
4144 if (!ec->user) {
4145 r = user_from_unit_name(u, &ec->user);
4146 if (r < 0)
4147 return r;
4148 }
4149
4150 if (!ec->group) {
4151 ec->group = strdup(ec->user);
4152 if (!ec->group)
4153 return -ENOMEM12;
4154 }
4155
4156 /* If the dynamic user option is on, let's make sure that the unit can't leave its
4157 * UID/GID around in the file system or on IPC objects. Hence enforce a strict
4158 * sandbox. */
4159
4160 ec->private_tmp = true1;
4161 ec->remove_ipc = true1;
4162 ec->protect_system = PROTECT_SYSTEM_STRICT;
4163 if (ec->protect_home == PROTECT_HOME_NO)
4164 ec->protect_home = PROTECT_HOME_READ_ONLY;
4165
4166 /* Make sure this service can neither benefit from SUID/SGID binaries nor create
4167 * them. */
4168 ec->no_new_privileges = true1;
4169 ec->restrict_suid_sgid = true1;
4170 }
4171 }
4172
4173 cc = unit_get_cgroup_context(u);
4174 if (cc) {
4175
4176 if (ec &&
4177 ec->private_devices &&
4178 cc->device_policy == CGROUP_AUTO)
4179 cc->device_policy = CGROUP_CLOSED;
4180 }
4181
4182 return 0;
4183}
4184
4185ExecContext *unit_get_exec_context(Unit *u) {
4186 size_t offset;
4187 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 4187, __PRETTY_FUNCTION__
); } while (0)
;
4188
4189 if (u->type < 0)
4190 return NULL((void*)0);
4191
4192 offset = UNIT_VTABLE(u)unit_vtable[(u)->type]->exec_context_offset;
4193 if (offset <= 0)
4194 return NULL((void*)0);
4195
4196 return (ExecContext*) ((uint8_t*) u + offset);
4197}
4198
4199KillContext *unit_get_kill_context(Unit *u) {
4200 size_t offset;
4201 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 4201, __PRETTY_FUNCTION__
); } while (0)
;
4202
4203 if (u->type < 0)
4204 return NULL((void*)0);
4205
4206 offset = UNIT_VTABLE(u)unit_vtable[(u)->type]->kill_context_offset;
4207 if (offset <= 0)
4208 return NULL((void*)0);
4209
4210 return (KillContext*) ((uint8_t*) u + offset);
4211}
4212
4213CGroupContext *unit_get_cgroup_context(Unit *u) {
4214 size_t offset;
4215
4216 if (u->type < 0)
4217 return NULL((void*)0);
4218
4219 offset = UNIT_VTABLE(u)unit_vtable[(u)->type]->cgroup_context_offset;
4220 if (offset <= 0)
4221 return NULL((void*)0);
4222
4223 return (CGroupContext*) ((uint8_t*) u + offset);
4224}
4225
4226ExecRuntime *unit_get_exec_runtime(Unit *u) {
4227 size_t offset;
4228
4229 if (u->type < 0)
4230 return NULL((void*)0);
4231
4232 offset = UNIT_VTABLE(u)unit_vtable[(u)->type]->exec_runtime_offset;
4233 if (offset <= 0)
4234 return NULL((void*)0);
4235
4236 return *(ExecRuntime**) ((uint8_t*) u + offset);
4237}
4238
4239static const char* unit_drop_in_dir(Unit *u, UnitWriteFlags flags) {
4240 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 4240, __PRETTY_FUNCTION__
); } while (0)
;
4241
4242 if (UNIT_WRITE_FLAGS_NOOP(flags)(((flags) & (UNIT_RUNTIME|UNIT_PERSISTENT)) == 0))
4243 return NULL((void*)0);
4244
4245 if (u->transient) /* Redirect drop-ins for transient units always into the transient directory. */
4246 return u->manager->lookup_paths.transient;
4247
4248 if (flags & UNIT_PERSISTENT)
4249 return u->manager->lookup_paths.persistent_control;
4250
4251 if (flags & UNIT_RUNTIME)
4252 return u->manager->lookup_paths.runtime_control;
4253
4254 return NULL((void*)0);
4255}
4256
4257char* unit_escape_setting(const char *s, UnitWriteFlags flags, char **buf) {
4258 char *ret = NULL((void*)0);
4259
4260 if (!s)
4261 return NULL((void*)0);
4262
4263 /* Escapes the input string as requested. Returns the escaped string. If 'buf' is specified then the allocated
4264 * return buffer pointer is also written to *buf, except if no escaping was necessary, in which case *buf is
4265 * set to NULL, and the input pointer is returned as-is. This means the return value always contains a properly
4266 * escaped version, but *buf when passed only contains a pointer if an allocation was necessary. If *buf is
4267 * not specified, then the return value always needs to be freed. Callers can use this to optimize memory
4268 * allocations. */
4269
4270 if (flags & UNIT_ESCAPE_SPECIFIERS) {
4271 ret = specifier_escape(s);
4272 if (!ret)
4273 return NULL((void*)0);
4274
4275 s = ret;
4276 }
4277
4278 if (flags & UNIT_ESCAPE_C) {
4279 char *a;
4280
4281 a = cescape(s);
4282 free(ret);
4283 if (!a)
4284 return NULL((void*)0);
4285
4286 ret = a;
4287 }
4288
4289 if (buf) {
4290 *buf = ret;
4291 return ret ?: (char*) s;
4292 }
4293
4294 return ret ?: strdup(s);
4295}
4296
4297char* unit_concat_strv(char **l, UnitWriteFlags flags) {
4298 _cleanup_free___attribute__((cleanup(freep))) char *result = NULL((void*)0);
4299 size_t n = 0, allocated = 0;
4300 char **i;
4301
4302 /* Takes a list of strings, escapes them, and concatenates them. This may be used to format command lines in a
4303 * way suitable for ExecStart= stanzas */
4304
4305 STRV_FOREACH(i, l)for ((i) = (l); (i) && *(i); (i)++) {
4306 _cleanup_free___attribute__((cleanup(freep))) char *buf = NULL((void*)0);
4307 const char *p;
4308 size_t a;
4309 char *q;
4310
4311 p = unit_escape_setting(*i, flags, &buf);
4312 if (!p)
4313 return NULL((void*)0);
4314
4315 a = (n > 0) + 1 + strlen(p) + 1; /* separating space + " + entry + " */
4316 if (!GREEDY_REALLOC(result, allocated, n + a + 1)greedy_realloc((void**) &(result), &(allocated), (n +
a + 1), sizeof((result)[0]))
)
4317 return NULL((void*)0);
4318
4319 q = result + n;
4320 if (n > 0)
4321 *(q++) = ' ';
4322
4323 *(q++) = '"';
4324 q = stpcpy(q, p);
4325 *(q++) = '"';
4326
4327 n += a;
4328 }
4329
4330 if (!GREEDY_REALLOC(result, allocated, n + 1)greedy_realloc((void**) &(result), &(allocated), (n +
1), sizeof((result)[0]))
)
4331 return NULL((void*)0);
4332
4333 result[n] = 0;
4334
4335 return TAKE_PTR(result)({ typeof(result) _ptr_ = (result); (result) = ((void*)0); _ptr_
; })
;
4336}
4337
4338int unit_write_setting(Unit *u, UnitWriteFlags flags, const char *name, const char *data) {
4339 _cleanup_free___attribute__((cleanup(freep))) char *p = NULL((void*)0), *q = NULL((void*)0), *escaped = NULL((void*)0);
4340 const char *dir, *wrapped;
4341 int r;
4342
4343 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 4343, __PRETTY_FUNCTION__
); } while (0)
;
4344 assert(name)do { if ((__builtin_expect(!!(!(name)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("name"), "../src/core/unit.c", 4344, __PRETTY_FUNCTION__
); } while (0)
;
4345 assert(data)do { if ((__builtin_expect(!!(!(data)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("data"), "../src/core/unit.c", 4345, __PRETTY_FUNCTION__
); } while (0)
;
4346
4347 if (UNIT_WRITE_FLAGS_NOOP(flags)(((flags) & (UNIT_RUNTIME|UNIT_PERSISTENT)) == 0))
4348 return 0;
4349
4350 data = unit_escape_setting(data, flags, &escaped);
4351 if (!data)
4352 return -ENOMEM12;
4353
4354 /* Prefix the section header. If we are writing this out as transient file, then let's suppress this if the
4355 * previous section header is the same */
4356
4357 if (flags & UNIT_PRIVATE) {
4358 if (!UNIT_VTABLE(u)unit_vtable[(u)->type]->private_section)
4359 return -EINVAL22;
4360
4361 if (!u->transient_file || u->last_section_private < 0)
4362 data = strjoina("[", UNIT_VTABLE(u)->private_section, "]\n", data)({ const char *_appendees_[] = { "[", unit_vtable[(u)->type
]->private_section, "]\n", data }; char *_d_, *_p_; size_t
_len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__ (
__builtin_choose_expr( !__builtin_types_compatible_p(typeof(_appendees_
), typeof(&*(_appendees_))), sizeof(_appendees_)/sizeof((
_appendees_)[0]), ((void)0))) && _appendees_[_i_]; _i_
++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
4363 else if (u->last_section_private == 0)
4364 data = strjoina("\n[", UNIT_VTABLE(u)->private_section, "]\n", data)({ const char *_appendees_[] = { "\n[", unit_vtable[(u)->type
]->private_section, "]\n", data }; char *_d_, *_p_; size_t
_len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__ (
__builtin_choose_expr( !__builtin_types_compatible_p(typeof(_appendees_
), typeof(&*(_appendees_))), sizeof(_appendees_)/sizeof((
_appendees_)[0]), ((void)0))) && _appendees_[_i_]; _i_
++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
4365 } else {
4366 if (!u->transient_file || u->last_section_private < 0)
4367 data = strjoina("[Unit]\n", data)({ const char *_appendees_[] = { "[Unit]\n", data }; char *_d_
, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__
(__builtin_choose_expr( !__builtin_types_compatible_p(typeof
(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
4368 else if (u->last_section_private > 0)
4369 data = strjoina("\n[Unit]\n", data)({ const char *_appendees_[] = { "\n[Unit]\n", data }; char *
_d_, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ <
__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
4370 }
4371
4372 if (u->transient_file) {
4373 /* When this is a transient unit file in creation, then let's not create a new drop-in but instead
4374 * write to the transient unit file. */
4375 fputs(data, u->transient_file);
4376
4377 if (!endswith(data, "\n"))
4378 fputc('\n', u->transient_file);
4379
4380 /* Remember which section we wrote this entry to */
4381 u->last_section_private = !!(flags & UNIT_PRIVATE);
4382 return 0;
4383 }
4384
4385 dir = unit_drop_in_dir(u, flags);
4386 if (!dir)
4387 return -EINVAL22;
4388
4389 wrapped = strjoina("# This is a drop-in unit file extension, created via \"systemctl set-property\"\n"({ const char *_appendees_[] = { "# This is a drop-in unit file extension, created via \"systemctl set-property\"\n"
"# or an equivalent operation. Do not edit.\n", data, "\n" }
; char *_d_, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0
; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
4390 "# or an equivalent operation. Do not edit.\n",({ const char *_appendees_[] = { "# This is a drop-in unit file extension, created via \"systemctl set-property\"\n"
"# or an equivalent operation. Do not edit.\n", data, "\n" }
; char *_d_, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0
; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
4391 data,({ const char *_appendees_[] = { "# This is a drop-in unit file extension, created via \"systemctl set-property\"\n"
"# or an equivalent operation. Do not edit.\n", data, "\n" }
; char *_d_, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0
; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
4392 "\n")({ const char *_appendees_[] = { "# This is a drop-in unit file extension, created via \"systemctl set-property\"\n"
"# or an equivalent operation. Do not edit.\n", data, "\n" }
; char *_d_, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0
; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
4393
4394 r = drop_in_file(dir, u->id, 50, name, &p, &q);
4395 if (r < 0)
4396 return r;
4397
4398 (void) mkdir_p_label(p, 0755);
4399 r = write_string_file_atomic_label(q, wrapped);
4400 if (r < 0)
4401 return r;
4402
4403 r = strv_push(&u->dropin_paths, q);
4404 if (r < 0)
4405 return r;
4406 q = NULL((void*)0);
4407
4408 strv_uniq(u->dropin_paths);
4409
4410 u->dropin_mtime = now(CLOCK_REALTIME0);
4411
4412 return 0;
4413}
4414
4415int unit_write_settingf(Unit *u, UnitWriteFlags flags, const char *name, const char *format, ...) {
4416 _cleanup_free___attribute__((cleanup(freep))) char *p = NULL((void*)0);
4417 va_list ap;
4418 int r;
4419
4420 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 4420, __PRETTY_FUNCTION__
); } while (0)
;
4421 assert(name)do { if ((__builtin_expect(!!(!(name)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("name"), "../src/core/unit.c", 4421, __PRETTY_FUNCTION__
); } while (0)
;
4422 assert(format)do { if ((__builtin_expect(!!(!(format)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("format"), "../src/core/unit.c", 4422, __PRETTY_FUNCTION__
); } while (0)
;
4423
4424 if (UNIT_WRITE_FLAGS_NOOP(flags)(((flags) & (UNIT_RUNTIME|UNIT_PERSISTENT)) == 0))
4425 return 0;
4426
4427 va_start(ap, format)__builtin_va_start(ap, format);
4428 r = vasprintf(&p, format, ap);
4429 va_end(ap)__builtin_va_end(ap);
4430
4431 if (r < 0)
4432 return -ENOMEM12;
4433
4434 return unit_write_setting(u, flags, name, p);
4435}
4436
4437int unit_make_transient(Unit *u) {
4438 _cleanup_free___attribute__((cleanup(freep))) char *path = NULL((void*)0);
4439 FILE *f;
4440
4441 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 4441, __PRETTY_FUNCTION__
); } while (0)
;
4442
4443 if (!UNIT_VTABLE(u)unit_vtable[(u)->type]->can_transient)
4444 return -EOPNOTSUPP95;
4445
4446 (void) mkdir_p_label(u->manager->lookup_paths.transient, 0755);
4447
4448 path = strjoin(u->manager->lookup_paths.transient, "/", u->id)strjoin_real((u->manager->lookup_paths.transient), "/",
u->id, ((void*)0))
;
4449 if (!path)
4450 return -ENOMEM12;
4451
4452 /* Let's open the file we'll write the transient settings into. This file is kept open as long as we are
4453 * creating the transient, and is closed in unit_load(), as soon as we start loading the file. */
4454
4455 RUN_WITH_UMASK(0022)for (__attribute__((cleanup(_reset_umask_))) struct _umask_struct_
_saved_umask_ = { umask(0022), 0 }; !_saved_umask_.quit ; _saved_umask_
.quit = 1)
{
4456 f = fopen(path, "we");
4457 if (!f)
4458 return -errno(*__errno_location ());
4459 }
4460
4461 safe_fclose(u->transient_file);
4462 u->transient_file = f;
4463
4464 free_and_replace(u->fragment_path, path)({ free(u->fragment_path); (u->fragment_path) = (path);
(path) = ((void*)0); 0; })
;
4465
4466 u->source_path = mfree(u->source_path);
4467 u->dropin_paths = strv_free(u->dropin_paths);
4468 u->fragment_mtime = u->source_mtime = u->dropin_mtime = 0;
4469
4470 u->load_state = UNIT_STUB;
4471 u->load_error = 0;
4472 u->transient = true1;
4473
4474 unit_add_to_dbus_queue(u);
4475 unit_add_to_gc_queue(u);
4476
4477 fputs("# This is a transient unit file, created programmatically via the systemd API. Do not edit.\n",
4478 u->transient_file);
4479
4480 return 0;
4481}
4482
4483static void log_kill(pid_t pid, int sig, void *userdata) {
4484 _cleanup_free___attribute__((cleanup(freep))) char *comm = NULL((void*)0);
4485
4486 (void) get_process_comm(pid, &comm);
4487
4488 /* Don't log about processes marked with brackets, under the assumption that these are temporary processes
4489 only, like for example systemd's own PAM stub process. */
4490 if (comm && comm[0] == '(')
4491 return;
4492
4493 log_unit_notice(userdata,({ const Unit *_u = (userdata); _u ? log_object_internal(5, 0
, "../src/core/unit.c", 4497, __func__, _u->manager->unit_log_field
, _u->id, _u->manager->invocation_log_field, _u->
invocation_id_string, "Killing process " "%" "i" " (%s) with signal SIG%s."
, pid, strna(comm), signal_to_string(sig)) : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((5))), 0, "../src/core/unit.c"
, 4497, __func__, "Killing process " "%" "i" " (%s) with signal SIG%s."
, pid, strna(comm), signal_to_string(sig)); })
4494 "Killing process " PID_FMT " (%s) with signal SIG%s.",({ const Unit *_u = (userdata); _u ? log_object_internal(5, 0
, "../src/core/unit.c", 4497, __func__, _u->manager->unit_log_field
, _u->id, _u->manager->invocation_log_field, _u->
invocation_id_string, "Killing process " "%" "i" " (%s) with signal SIG%s."
, pid, strna(comm), signal_to_string(sig)) : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((5))), 0, "../src/core/unit.c"
, 4497, __func__, "Killing process " "%" "i" " (%s) with signal SIG%s."
, pid, strna(comm), signal_to_string(sig)); })
4495 pid,({ const Unit *_u = (userdata); _u ? log_object_internal(5, 0
, "../src/core/unit.c", 4497, __func__, _u->manager->unit_log_field
, _u->id, _u->manager->invocation_log_field, _u->
invocation_id_string, "Killing process " "%" "i" " (%s) with signal SIG%s."
, pid, strna(comm), signal_to_string(sig)) : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((5))), 0, "../src/core/unit.c"
, 4497, __func__, "Killing process " "%" "i" " (%s) with signal SIG%s."
, pid, strna(comm), signal_to_string(sig)); })
4496 strna(comm),({ const Unit *_u = (userdata); _u ? log_object_internal(5, 0
, "../src/core/unit.c", 4497, __func__, _u->manager->unit_log_field
, _u->id, _u->manager->invocation_log_field, _u->
invocation_id_string, "Killing process " "%" "i" " (%s) with signal SIG%s."
, pid, strna(comm), signal_to_string(sig)) : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((5))), 0, "../src/core/unit.c"
, 4497, __func__, "Killing process " "%" "i" " (%s) with signal SIG%s."
, pid, strna(comm), signal_to_string(sig)); })
4497 signal_to_string(sig))({ const Unit *_u = (userdata); _u ? log_object_internal(5, 0
, "../src/core/unit.c", 4497, __func__, _u->manager->unit_log_field
, _u->id, _u->manager->invocation_log_field, _u->
invocation_id_string, "Killing process " "%" "i" " (%s) with signal SIG%s."
, pid, strna(comm), signal_to_string(sig)) : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((5))), 0, "../src/core/unit.c"
, 4497, __func__, "Killing process " "%" "i" " (%s) with signal SIG%s."
, pid, strna(comm), signal_to_string(sig)); })
;
4498}
4499
4500static int operation_to_signal(KillContext *c, KillOperation k) {
4501 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/core/unit.c", 4501, __PRETTY_FUNCTION__
); } while (0)
;
4502
4503 switch (k) {
4504
4505 case KILL_TERMINATE:
4506 case KILL_TERMINATE_AND_LOG:
4507 return c->kill_signal;
4508
4509 case KILL_KILL:
4510 return SIGKILL9;
4511
4512 case KILL_ABORT:
4513 return SIGABRT6;
4514
4515 default:
4516 assert_not_reached("KillOperation unknown")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, (
"KillOperation unknown"), "../src/core/unit.c", 4516, __PRETTY_FUNCTION__
); } while (0)
;
4517 }
4518}
4519
4520int unit_kill_context(
4521 Unit *u,
4522 KillContext *c,
4523 KillOperation k,
4524 pid_t main_pid,
4525 pid_t control_pid,
4526 bool_Bool main_pid_alien) {
4527
4528 bool_Bool wait_for_exit = false0, send_sighup;
4529 cg_kill_log_func_t log_func = NULL((void*)0);
4530 int sig, r;
4531
4532 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 4532, __PRETTY_FUNCTION__
); } while (0)
;
4533 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/core/unit.c", 4533, __PRETTY_FUNCTION__
); } while (0)
;
4534
4535 /* Kill the processes belonging to this unit, in preparation for shutting the unit down.
4536 * Returns > 0 if we killed something worth waiting for, 0 otherwise. */
4537
4538 if (c->kill_mode == KILL_NONE)
4539 return 0;
4540
4541 sig = operation_to_signal(c, k);
4542
4543 send_sighup =
4544 c->send_sighup &&
4545 IN_SET(k, KILL_TERMINATE, KILL_TERMINATE_AND_LOG)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){KILL_TERMINATE, KILL_TERMINATE_AND_LOG})
/sizeof(int)]; switch(k) { case KILL_TERMINATE: case KILL_TERMINATE_AND_LOG
: _found = 1; break; default: break; } _found; })
&&
4546 sig != SIGHUP1;
4547
4548 if (k != KILL_TERMINATE || IN_SET(sig, SIGKILL, SIGABRT)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){9, 6})/sizeof(int)]; switch(sig) { case 9
: case 6: _found = 1; break; default: break; } _found; })
)
4549 log_func = log_kill;
4550
4551 if (main_pid > 0) {
4552 if (log_func)
4553 log_func(main_pid, sig, u);
4554
4555 r = kill_and_sigcont(main_pid, sig);
4556 if (r < 0 && r != -ESRCH3) {
4557 _cleanup_free___attribute__((cleanup(freep))) char *comm = NULL((void*)0);
4558 (void) get_process_comm(main_pid, &comm);
4559
4560 log_unit_warning_errno(u, r, "Failed to kill main process " PID_FMT " (%s), ignoring: %m", main_pid, strna(comm))({ const Unit *_u = (u); _u ? log_object_internal(4, r, "../src/core/unit.c"
, 4560, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to kill main process " "%" "i" " (%s), ignoring: %m"
, main_pid, strna(comm)) : log_internal_realm(((LOG_REALM_SYSTEMD
) << 10 | ((4))), r, "../src/core/unit.c", 4560, __func__
, "Failed to kill main process " "%" "i" " (%s), ignoring: %m"
, main_pid, strna(comm)); })
;
4561 } else {
4562 if (!main_pid_alien)
4563 wait_for_exit = true1;
4564
4565 if (r != -ESRCH3 && send_sighup)
4566 (void) kill(main_pid, SIGHUP1);
4567 }
4568 }
4569
4570 if (control_pid > 0) {
4571 if (log_func)
4572 log_func(control_pid, sig, u);
4573
4574 r = kill_and_sigcont(control_pid, sig);
4575 if (r < 0 && r != -ESRCH3) {
4576 _cleanup_free___attribute__((cleanup(freep))) char *comm = NULL((void*)0);
4577 (void) get_process_comm(control_pid, &comm);
4578
4579 log_unit_warning_errno(u, r, "Failed to kill control process " PID_FMT " (%s), ignoring: %m", control_pid, strna(comm))({ const Unit *_u = (u); _u ? log_object_internal(4, r, "../src/core/unit.c"
, 4579, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to kill control process " "%" "i" " (%s), ignoring: %m"
, control_pid, strna(comm)) : log_internal_realm(((LOG_REALM_SYSTEMD
) << 10 | ((4))), r, "../src/core/unit.c", 4579, __func__
, "Failed to kill control process " "%" "i" " (%s), ignoring: %m"
, control_pid, strna(comm)); })
;
4580 } else {
4581 wait_for_exit = true1;
4582
4583 if (r != -ESRCH3 && send_sighup)
4584 (void) kill(control_pid, SIGHUP1);
4585 }
4586 }
4587
4588 if (u->cgroup_path &&
4589 (c->kill_mode == KILL_CONTROL_GROUP || (c->kill_mode == KILL_MIXED && k == KILL_KILL))) {
4590 _cleanup_set_free___attribute__((cleanup(set_freep))) Set *pid_set = NULL((void*)0);
4591
4592 /* Exclude the main/control pids from being killed via the cgroup */
4593 pid_set = unit_pid_set(main_pid, control_pid);
4594 if (!pid_set)
4595 return -ENOMEM12;
4596
4597 r = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER"_systemd", u->cgroup_path,
4598 sig,
4599 CGROUP_SIGCONT|CGROUP_IGNORE_SELF,
4600 pid_set,
4601 log_func, u);
4602 if (r < 0) {
4603 if (!IN_SET(r, -EAGAIN, -ESRCH, -ENOENT)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){-11, -3, -2})/sizeof(int)]; switch(r) { case
-11: case -3: case -2: _found = 1; break; default: break; } _found
; })
)
4604 log_unit_warning_errno(u, r, "Failed to kill control group %s, ignoring: %m", u->cgroup_path)({ const Unit *_u = (u); _u ? log_object_internal(4, r, "../src/core/unit.c"
, 4604, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to kill control group %s, ignoring: %m", u->cgroup_path
) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4
))), r, "../src/core/unit.c", 4604, __func__, "Failed to kill control group %s, ignoring: %m"
, u->cgroup_path); })
;
4605
4606 } else if (r > 0) {
4607
4608 wait_for_exit = true1;
4609
4610 if (send_sighup) {
4611 set_free(pid_set);
4612
4613 pid_set = unit_pid_set(main_pid, control_pid);
4614 if (!pid_set)
4615 return -ENOMEM12;
4616
4617 cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER"_systemd", u->cgroup_path,
4618 SIGHUP1,
4619 CGROUP_IGNORE_SELF,
4620 pid_set,
4621 NULL((void*)0), NULL((void*)0));
4622 }
4623 }
4624 }
4625
4626 return wait_for_exit;
4627}
4628
4629int unit_require_mounts_for(Unit *u, const char *path, UnitDependencyMask mask) {
4630 _cleanup_free___attribute__((cleanup(freep))) char *p = NULL((void*)0);
4631 char *prefix;
4632 UnitDependencyInfo di;
4633 int r;
4634
4635 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 4635, __PRETTY_FUNCTION__
); } while (0)
;
10
Taking false branch
11
Loop condition is false. Exiting loop
4636 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/core/unit.c", 4636, __PRETTY_FUNCTION__
); } while (0)
;
12
Taking false branch
13
Loop condition is false. Exiting loop
4637
4638 /* Registers a unit for requiring a certain path and all its prefixes. We keep a hashtable of these paths in
4639 * the unit (from the path to the UnitDependencyInfo structure indicating how to the dependency came to
4640 * be). However, we build a prefix table for all possible prefixes so that new appearing mount units can easily
4641 * determine which units to make themselves a dependency of. */
4642
4643 if (!path_is_absolute(path))
14
Assuming the condition is false
15
Taking false branch
4644 return -EINVAL22;
4645
4646 r = hashmap_ensure_allocated(&u->requires_mounts_for, &path_hash_ops)internal_hashmap_ensure_allocated(&u->requires_mounts_for
, &path_hash_ops )
;
4647 if (r < 0)
16
Assuming 'r' is >= 0
17
Taking false branch
4648 return r;
4649
4650 p = strdup(path);
4651 if (!p)
18
Assuming 'p' is non-null
19
Taking false branch
4652 return -ENOMEM12;
4653
4654 path = path_simplify(p, false0);
4655
4656 if (!path_is_normalized(path))
20
Assuming the condition is false
21
Taking false branch
4657 return -EPERM1;
4658
4659 if (hashmap_contains(u->requires_mounts_for, path))
22
Assuming the condition is false
23
Taking false branch
4660 return 0;
4661
4662 di = (UnitDependencyInfo) {
4663 .origin_mask = mask
4664 };
4665
4666 r = hashmap_put(u->requires_mounts_for, path, di.data);
4667 if (r < 0)
24
Assuming 'r' is >= 0
25
Taking false branch
4668 return r;
4669 p = NULL((void*)0);
4670
4671 prefix = alloca(strlen(path) + 1)__builtin_alloca (strlen(path) + 1);
4672 PATH_FOREACH_PREFIX_MORE(prefix, path)for (char *_slash = ({ path_simplify(strcpy(prefix, path), 0)
; if ((strcmp((prefix),("/")) == 0)) prefix[0] = 0; strrchr(prefix
, 0); }); _slash && ((*_slash = 0), 1); _slash = strrchr
((prefix), '/'))
{
26
Assuming the condition is false
27
Taking false branch
28
Assuming '_slash' is non-null
29
Loop condition is true. Entering loop body
4673 Set *x;
4674
4675 x = hashmap_get(u->manager->units_requiring_mounts_for, prefix);
4676 if (!x) {
30
Assuming 'x' is null
31
Taking true branch
4677 _cleanup_free___attribute__((cleanup(freep))) char *q = NULL((void*)0);
4678
4679 r = hashmap_ensure_allocated(&u->manager->units_requiring_mounts_for, &path_hash_ops)internal_hashmap_ensure_allocated(&u->manager->units_requiring_mounts_for
, &path_hash_ops )
;
4680 if (r < 0)
32
Assuming 'r' is >= 0
33
Taking false branch
4681 return r;
4682
4683 q = strdup(prefix);
34
Memory is allocated
4684 if (!q)
35
Assuming 'q' is non-null
36
Taking false branch
4685 return -ENOMEM12;
4686
4687 x = set_new(NULL)internal_set_new(((void*)0) );
4688 if (!x)
37
Assuming 'x' is null
38
Taking true branch
4689 return -ENOMEM12;
39
Potential leak of memory pointed to by 'q'
4690
4691 r = hashmap_put(u->manager->units_requiring_mounts_for, q, x);
4692 if (r < 0) {
4693 set_free(x);
4694 return r;
4695 }
4696 q = NULL((void*)0);
4697 }
4698
4699 r = set_put(x, u);
4700 if (r < 0)
4701 return r;
4702 }
4703
4704 return 0;
4705}
4706
4707int unit_setup_exec_runtime(Unit *u) {
4708 ExecRuntime **rt;
4709 size_t offset;
4710 Unit *other;
4711 Iterator i;
4712 void *v;
4713 int r;
4714
4715 offset = UNIT_VTABLE(u)unit_vtable[(u)->type]->exec_runtime_offset;
4716 assert(offset > 0)do { if ((__builtin_expect(!!(!(offset > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("offset > 0"), "../src/core/unit.c", 4716
, __PRETTY_FUNCTION__); } while (0)
;
4717
4718 /* Check if there already is an ExecRuntime for this unit? */
4719 rt = (ExecRuntime**) ((uint8_t*) u + offset);
4720 if (*rt)
4721 return 0;
4722
4723 /* Try to get it from somebody else */
4724 HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_JOINS_NAMESPACE_OF], i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); hashmap_iterate((u->dependencies
[UNIT_JOINS_NAMESPACE_OF]), &(i), (void**)&(v), (const
void**) &(other)); )
{
4725 r = exec_runtime_acquire(u->manager, NULL((void*)0), other->id, false0, rt);
4726 if (r == 1)
4727 return 1;
4728 }
4729
4730 return exec_runtime_acquire(u->manager, unit_get_exec_context(u), u->id, true1, rt);
4731}
4732
4733int unit_setup_dynamic_creds(Unit *u) {
4734 ExecContext *ec;
4735 DynamicCreds *dcreds;
4736 size_t offset;
4737
4738 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 4738, __PRETTY_FUNCTION__
); } while (0)
;
4739
4740 offset = UNIT_VTABLE(u)unit_vtable[(u)->type]->dynamic_creds_offset;
4741 assert(offset > 0)do { if ((__builtin_expect(!!(!(offset > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("offset > 0"), "../src/core/unit.c", 4741
, __PRETTY_FUNCTION__); } while (0)
;
4742 dcreds = (DynamicCreds*) ((uint8_t*) u + offset);
4743
4744 ec = unit_get_exec_context(u);
4745 assert(ec)do { if ((__builtin_expect(!!(!(ec)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ec"), "../src/core/unit.c", 4745, __PRETTY_FUNCTION__
); } while (0)
;
4746
4747 if (!ec->dynamic_user)
4748 return 0;
4749
4750 return dynamic_creds_acquire(dcreds, u->manager, ec->user, ec->group);
4751}
4752
4753bool_Bool unit_type_supported(UnitType t) {
4754 if (_unlikely_(t < 0)(__builtin_expect(!!(t < 0),0)))
4755 return false0;
4756 if (_unlikely_(t >= _UNIT_TYPE_MAX)(__builtin_expect(!!(t >= _UNIT_TYPE_MAX),0)))
4757 return false0;
4758
4759 if (!unit_vtable[t]->supported)
4760 return true1;
4761
4762 return unit_vtable[t]->supported();
4763}
4764
4765void unit_warn_if_dir_nonempty(Unit *u, const char* where) {
4766 int r;
4767
4768 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 4768, __PRETTY_FUNCTION__
); } while (0)
;
4769 assert(where)do { if ((__builtin_expect(!!(!(where)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("where"), "../src/core/unit.c", 4769, __PRETTY_FUNCTION__
); } while (0)
;
4770
4771 r = dir_is_empty(where);
4772 if (r > 0 || r == -ENOTDIR20)
4773 return;
4774 if (r < 0) {
4775 log_unit_warning_errno(u, r, "Failed to check directory %s: %m", where)({ const Unit *_u = (u); _u ? log_object_internal(4, r, "../src/core/unit.c"
, 4775, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to check directory %s: %m", where) : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((4))), r, "../src/core/unit.c"
, 4775, __func__, "Failed to check directory %s: %m", where);
})
;
4776 return;
4777 }
4778
4779 log_struct(LOG_NOTICE,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (5)), 0
, "../src/core/unit.c", 4784, __func__, "MESSAGE_ID=" "1d" "ee"
"03" "69" "c7" "fc" "47" "36" "b7" "09" "9b" "38" "ec" "b4" "6e"
"e7", (u)->manager->unit_log_format_string, (u)->id
, (u)->manager->invocation_log_format_string, (u)->invocation_id_string
, "MESSAGE=%s: " "Directory %s to mount over is not empty, mounting anyway."
, (u)->id, where, "WHERE=%s", where, ((void*)0))
4780 "MESSAGE_ID=" SD_MESSAGE_OVERMOUNTING_STR,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (5)), 0
, "../src/core/unit.c", 4784, __func__, "MESSAGE_ID=" "1d" "ee"
"03" "69" "c7" "fc" "47" "36" "b7" "09" "9b" "38" "ec" "b4" "6e"
"e7", (u)->manager->unit_log_format_string, (u)->id
, (u)->manager->invocation_log_format_string, (u)->invocation_id_string
, "MESSAGE=%s: " "Directory %s to mount over is not empty, mounting anyway."
, (u)->id, where, "WHERE=%s", where, ((void*)0))
4781 LOG_UNIT_ID(u),log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (5)), 0
, "../src/core/unit.c", 4784, __func__, "MESSAGE_ID=" "1d" "ee"
"03" "69" "c7" "fc" "47" "36" "b7" "09" "9b" "38" "ec" "b4" "6e"
"e7", (u)->manager->unit_log_format_string, (u)->id
, (u)->manager->invocation_log_format_string, (u)->invocation_id_string
, "MESSAGE=%s: " "Directory %s to mount over is not empty, mounting anyway."
, (u)->id, where, "WHERE=%s", where, ((void*)0))
4782 LOG_UNIT_INVOCATION_ID(u),log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (5)), 0
, "../src/core/unit.c", 4784, __func__, "MESSAGE_ID=" "1d" "ee"
"03" "69" "c7" "fc" "47" "36" "b7" "09" "9b" "38" "ec" "b4" "6e"
"e7", (u)->manager->unit_log_format_string, (u)->id
, (u)->manager->invocation_log_format_string, (u)->invocation_id_string
, "MESSAGE=%s: " "Directory %s to mount over is not empty, mounting anyway."
, (u)->id, where, "WHERE=%s", where, ((void*)0))
4783 LOG_UNIT_MESSAGE(u, "Directory %s to mount over is not empty, mounting anyway.", where),log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (5)), 0
, "../src/core/unit.c", 4784, __func__, "MESSAGE_ID=" "1d" "ee"
"03" "69" "c7" "fc" "47" "36" "b7" "09" "9b" "38" "ec" "b4" "6e"
"e7", (u)->manager->unit_log_format_string, (u)->id
, (u)->manager->invocation_log_format_string, (u)->invocation_id_string
, "MESSAGE=%s: " "Directory %s to mount over is not empty, mounting anyway."
, (u)->id, where, "WHERE=%s", where, ((void*)0))
4784 "WHERE=%s", where)log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (5)), 0
, "../src/core/unit.c", 4784, __func__, "MESSAGE_ID=" "1d" "ee"
"03" "69" "c7" "fc" "47" "36" "b7" "09" "9b" "38" "ec" "b4" "6e"
"e7", (u)->manager->unit_log_format_string, (u)->id
, (u)->manager->invocation_log_format_string, (u)->invocation_id_string
, "MESSAGE=%s: " "Directory %s to mount over is not empty, mounting anyway."
, (u)->id, where, "WHERE=%s", where, ((void*)0))
;
4785}
4786
4787int unit_fail_if_noncanonical(Unit *u, const char* where) {
4788 _cleanup_free___attribute__((cleanup(freep))) char *canonical_where;
4789 int r;
4790
4791 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 4791, __PRETTY_FUNCTION__
); } while (0)
;
4792 assert(where)do { if ((__builtin_expect(!!(!(where)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("where"), "../src/core/unit.c", 4792, __PRETTY_FUNCTION__
); } while (0)
;
4793
4794 r = chase_symlinks(where, NULL((void*)0), CHASE_NONEXISTENT, &canonical_where);
4795 if (r < 0) {
4796 log_unit_debug_errno(u, r, "Failed to check %s for symlinks, ignoring: %m", where)({ const Unit *_u = (u); _u ? log_object_internal(7, r, "../src/core/unit.c"
, 4796, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to check %s for symlinks, ignoring: %m", where) : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((7))), r, "../src/core/unit.c"
, 4796, __func__, "Failed to check %s for symlinks, ignoring: %m"
, where); })
;
4797 return 0;
4798 }
4799
4800 /* We will happily ignore a trailing slash (or any redundant slashes) */
4801 if (path_equal(where, canonical_where))
4802 return 0;
4803
4804 /* No need to mention "." or "..", they would already have been rejected by unit_name_from_path() */
4805 log_struct(LOG_ERR,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (3)), 0
, "../src/core/unit.c", 4810, __func__, "MESSAGE_ID=" "1d" "ee"
"03" "69" "c7" "fc" "47" "36" "b7" "09" "9b" "38" "ec" "b4" "6e"
"e7", (u)->manager->unit_log_format_string, (u)->id
, (u)->manager->invocation_log_format_string, (u)->invocation_id_string
, "MESSAGE=%s: " "Mount path %s is not canonical (contains a symlink)."
, (u)->id, where, "WHERE=%s", where, ((void*)0))
4806 "MESSAGE_ID=" SD_MESSAGE_OVERMOUNTING_STR,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (3)), 0
, "../src/core/unit.c", 4810, __func__, "MESSAGE_ID=" "1d" "ee"
"03" "69" "c7" "fc" "47" "36" "b7" "09" "9b" "38" "ec" "b4" "6e"
"e7", (u)->manager->unit_log_format_string, (u)->id
, (u)->manager->invocation_log_format_string, (u)->invocation_id_string
, "MESSAGE=%s: " "Mount path %s is not canonical (contains a symlink)."
, (u)->id, where, "WHERE=%s", where, ((void*)0))
4807 LOG_UNIT_ID(u),log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (3)), 0
, "../src/core/unit.c", 4810, __func__, "MESSAGE_ID=" "1d" "ee"
"03" "69" "c7" "fc" "47" "36" "b7" "09" "9b" "38" "ec" "b4" "6e"
"e7", (u)->manager->unit_log_format_string, (u)->id
, (u)->manager->invocation_log_format_string, (u)->invocation_id_string
, "MESSAGE=%s: " "Mount path %s is not canonical (contains a symlink)."
, (u)->id, where, "WHERE=%s", where, ((void*)0))
4808 LOG_UNIT_INVOCATION_ID(u),log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (3)), 0
, "../src/core/unit.c", 4810, __func__, "MESSAGE_ID=" "1d" "ee"
"03" "69" "c7" "fc" "47" "36" "b7" "09" "9b" "38" "ec" "b4" "6e"
"e7", (u)->manager->unit_log_format_string, (u)->id
, (u)->manager->invocation_log_format_string, (u)->invocation_id_string
, "MESSAGE=%s: " "Mount path %s is not canonical (contains a symlink)."
, (u)->id, where, "WHERE=%s", where, ((void*)0))
4809 LOG_UNIT_MESSAGE(u, "Mount path %s is not canonical (contains a symlink).", where),log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (3)), 0
, "../src/core/unit.c", 4810, __func__, "MESSAGE_ID=" "1d" "ee"
"03" "69" "c7" "fc" "47" "36" "b7" "09" "9b" "38" "ec" "b4" "6e"
"e7", (u)->manager->unit_log_format_string, (u)->id
, (u)->manager->invocation_log_format_string, (u)->invocation_id_string
, "MESSAGE=%s: " "Mount path %s is not canonical (contains a symlink)."
, (u)->id, where, "WHERE=%s", where, ((void*)0))
4810 "WHERE=%s", where)log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (3)), 0
, "../src/core/unit.c", 4810, __func__, "MESSAGE_ID=" "1d" "ee"
"03" "69" "c7" "fc" "47" "36" "b7" "09" "9b" "38" "ec" "b4" "6e"
"e7", (u)->manager->unit_log_format_string, (u)->id
, (u)->manager->invocation_log_format_string, (u)->invocation_id_string
, "MESSAGE=%s: " "Mount path %s is not canonical (contains a symlink)."
, (u)->id, where, "WHERE=%s", where, ((void*)0))
;
4811
4812 return -ELOOP40;
4813}
4814
4815bool_Bool unit_is_pristine(Unit *u) {
4816 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 4816, __PRETTY_FUNCTION__
); } while (0)
;
4817
4818 /* Check if the unit already exists or is already around,
4819 * in a number of different ways. Note that to cater for unit
4820 * types such as slice, we are generally fine with units that
4821 * are marked UNIT_LOADED even though nothing was actually
4822 * loaded, as those unit types don't require a file on disk. */
4823
4824 return !(!IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_LOADED)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){UNIT_NOT_FOUND, UNIT_LOADED})/sizeof(int
)]; switch(u->load_state) { case UNIT_NOT_FOUND: case UNIT_LOADED
: _found = 1; break; default: break; } _found; })
||
4825 u->fragment_path ||
4826 u->source_path ||
4827 !strv_isempty(u->dropin_paths) ||
4828 u->job ||
4829 u->merged_into);
4830}
4831
4832pid_t unit_control_pid(Unit *u) {
4833 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 4833, __PRETTY_FUNCTION__
); } while (0)
;
4834
4835 if (UNIT_VTABLE(u)unit_vtable[(u)->type]->control_pid)
4836 return UNIT_VTABLE(u)unit_vtable[(u)->type]->control_pid(u);
4837
4838 return 0;
4839}
4840
4841pid_t unit_main_pid(Unit *u) {
4842 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 4842, __PRETTY_FUNCTION__
); } while (0)
;
4843
4844 if (UNIT_VTABLE(u)unit_vtable[(u)->type]->main_pid)
4845 return UNIT_VTABLE(u)unit_vtable[(u)->type]->main_pid(u);
4846
4847 return 0;
4848}
4849
4850static void unit_unref_uid_internal(
4851 Unit *u,
4852 uid_t *ref_uid,
4853 bool_Bool destroy_now,
4854 void (*_manager_unref_uid)(Manager *m, uid_t uid, bool_Bool destroy_now)) {
4855
4856 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 4856, __PRETTY_FUNCTION__
); } while (0)
;
4857 assert(ref_uid)do { if ((__builtin_expect(!!(!(ref_uid)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ref_uid"), "../src/core/unit.c", 4857, __PRETTY_FUNCTION__
); } while (0)
;
4858 assert(_manager_unref_uid)do { if ((__builtin_expect(!!(!(_manager_unref_uid)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("_manager_unref_uid"), "../src/core/unit.c"
, 4858, __PRETTY_FUNCTION__); } while (0)
;
4859
4860 /* Generic implementation of both unit_unref_uid() and unit_unref_gid(), under the assumption that uid_t and
4861 * gid_t are actually the same time, with the same validity rules.
4862 *
4863 * Drops a reference to UID/GID from a unit. */
4864
4865 assert_cc(sizeof(uid_t) == sizeof(gid_t))GCC diagnostic push ; GCC diagnostic ignored "-Wdeclaration-after-statement"
; struct _assert_struct_41 { char x[(sizeof(uid_t) == sizeof
(gid_t)) ? 0 : -1]; }; GCC diagnostic pop
;
4866 assert_cc(UID_INVALID == (uid_t) GID_INVALID)GCC diagnostic push ; GCC diagnostic ignored "-Wdeclaration-after-statement"
; struct _assert_struct_42 { char x[(((uid_t) -1) == (uid_t)
((gid_t) -1)) ? 0 : -1]; }; GCC diagnostic pop
;
4867
4868 if (!uid_is_valid(*ref_uid))
4869 return;
4870
4871 _manager_unref_uid(u->manager, *ref_uid, destroy_now);
4872 *ref_uid = UID_INVALID((uid_t) -1);
4873}
4874
4875void unit_unref_uid(Unit *u, bool_Bool destroy_now) {
4876 unit_unref_uid_internal(u, &u->ref_uid, destroy_now, manager_unref_uid);
4877}
4878
4879void unit_unref_gid(Unit *u, bool_Bool destroy_now) {
4880 unit_unref_uid_internal(u, (uid_t*) &u->ref_gid, destroy_now, manager_unref_gid);
4881}
4882
4883static int unit_ref_uid_internal(
4884 Unit *u,
4885 uid_t *ref_uid,
4886 uid_t uid,
4887 bool_Bool clean_ipc,
4888 int (*_manager_ref_uid)(Manager *m, uid_t uid, bool_Bool clean_ipc)) {
4889
4890 int r;
4891
4892 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 4892, __PRETTY_FUNCTION__
); } while (0)
;
4893 assert(ref_uid)do { if ((__builtin_expect(!!(!(ref_uid)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ref_uid"), "../src/core/unit.c", 4893, __PRETTY_FUNCTION__
); } while (0)
;
4894 assert(uid_is_valid(uid))do { if ((__builtin_expect(!!(!(uid_is_valid(uid))),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("uid_is_valid(uid)"), "../src/core/unit.c"
, 4894, __PRETTY_FUNCTION__); } while (0)
;
4895 assert(_manager_ref_uid)do { if ((__builtin_expect(!!(!(_manager_ref_uid)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("_manager_ref_uid"), "../src/core/unit.c"
, 4895, __PRETTY_FUNCTION__); } while (0)
;
4896
4897 /* Generic implementation of both unit_ref_uid() and unit_ref_guid(), under the assumption that uid_t and gid_t
4898 * are actually the same type, and have the same validity rules.
4899 *
4900 * Adds a reference on a specific UID/GID to this unit. Each unit referencing the same UID/GID maintains a
4901 * reference so that we can destroy the UID/GID's IPC resources as soon as this is requested and the counter
4902 * drops to zero. */
4903
4904 assert_cc(sizeof(uid_t) == sizeof(gid_t))GCC diagnostic push ; GCC diagnostic ignored "-Wdeclaration-after-statement"
; struct _assert_struct_43 { char x[(sizeof(uid_t) == sizeof
(gid_t)) ? 0 : -1]; }; GCC diagnostic pop
;
4905 assert_cc(UID_INVALID == (uid_t) GID_INVALID)GCC diagnostic push ; GCC diagnostic ignored "-Wdeclaration-after-statement"
; struct _assert_struct_44 { char x[(((uid_t) -1) == (uid_t)
((gid_t) -1)) ? 0 : -1]; }; GCC diagnostic pop
;
4906
4907 if (*ref_uid == uid)
4908 return 0;
4909
4910 if (uid_is_valid(*ref_uid)) /* Already set? */
4911 return -EBUSY16;
4912
4913 r = _manager_ref_uid(u->manager, uid, clean_ipc);
4914 if (r < 0)
4915 return r;
4916
4917 *ref_uid = uid;
4918 return 1;
4919}
4920
4921int unit_ref_uid(Unit *u, uid_t uid, bool_Bool clean_ipc) {
4922 return unit_ref_uid_internal(u, &u->ref_uid, uid, clean_ipc, manager_ref_uid);
4923}
4924
4925int unit_ref_gid(Unit *u, gid_t gid, bool_Bool clean_ipc) {
4926 return unit_ref_uid_internal(u, (uid_t*) &u->ref_gid, (uid_t) gid, clean_ipc, manager_ref_gid);
4927}
4928
4929static int unit_ref_uid_gid_internal(Unit *u, uid_t uid, gid_t gid, bool_Bool clean_ipc) {
4930 int r = 0, q = 0;
4931
4932 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 4932, __PRETTY_FUNCTION__
); } while (0)
;
4933
4934 /* Reference both a UID and a GID in one go. Either references both, or neither. */
4935
4936 if (uid_is_valid(uid)) {
4937 r = unit_ref_uid(u, uid, clean_ipc);
4938 if (r < 0)
4939 return r;
4940 }
4941
4942 if (gid_is_valid(gid)) {
4943 q = unit_ref_gid(u, gid, clean_ipc);
4944 if (q < 0) {
4945 if (r > 0)
4946 unit_unref_uid(u, false0);
4947
4948 return q;
4949 }
4950 }
4951
4952 return r > 0 || q > 0;
4953}
4954
4955int unit_ref_uid_gid(Unit *u, uid_t uid, gid_t gid) {
4956 ExecContext *c;
4957 int r;
4958
4959 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 4959, __PRETTY_FUNCTION__
); } while (0)
;
4960
4961 c = unit_get_exec_context(u);
4962
4963 r = unit_ref_uid_gid_internal(u, uid, gid, c ? c->remove_ipc : false0);
4964 if (r < 0)
4965 return log_unit_warning_errno(u, r, "Couldn't add UID/GID reference to unit, proceeding without: %m")({ const Unit *_u = (u); _u ? log_object_internal(4, r, "../src/core/unit.c"
, 4965, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Couldn't add UID/GID reference to unit, proceeding without: %m"
) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4
))), r, "../src/core/unit.c", 4965, __func__, "Couldn't add UID/GID reference to unit, proceeding without: %m"
); })
;
4966
4967 return r;
4968}
4969
4970void unit_unref_uid_gid(Unit *u, bool_Bool destroy_now) {
4971 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 4971, __PRETTY_FUNCTION__
); } while (0)
;
4972
4973 unit_unref_uid(u, destroy_now);
4974 unit_unref_gid(u, destroy_now);
4975}
4976
4977void unit_notify_user_lookup(Unit *u, uid_t uid, gid_t gid) {
4978 int r;
4979
4980 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 4980, __PRETTY_FUNCTION__
); } while (0)
;
4981
4982 /* This is invoked whenever one of the forked off processes let's us know the UID/GID its user name/group names
4983 * resolved to. We keep track of which UID/GID is currently assigned in order to be able to destroy its IPC
4984 * objects when no service references the UID/GID anymore. */
4985
4986 r = unit_ref_uid_gid(u, uid, gid);
4987 if (r > 0)
4988 bus_unit_send_change_signal(u);
4989}
4990
4991int unit_set_invocation_id(Unit *u, sd_id128_t id) {
4992 int r;
4993
4994 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 4994, __PRETTY_FUNCTION__
); } while (0)
;
4995
4996 /* Set the invocation ID for this unit. If we cannot, this will not roll back, but reset the whole thing. */
4997
4998 if (sd_id128_equal(u->invocation_id, id))
4999 return 0;
5000
5001 if (!sd_id128_is_null(u->invocation_id))
5002 (void) hashmap_remove_value(u->manager->units_by_invocation_id, &u->invocation_id, u);
5003
5004 if (sd_id128_is_null(id)) {
5005 r = 0;
5006 goto reset;
5007 }
5008
5009 r = hashmap_ensure_allocated(&u->manager->units_by_invocation_id, &id128_hash_ops)internal_hashmap_ensure_allocated(&u->manager->units_by_invocation_id
, &id128_hash_ops )
;
5010 if (r < 0)
5011 goto reset;
5012
5013 u->invocation_id = id;
5014 sd_id128_to_string(id, u->invocation_id_string);
5015
5016 r = hashmap_put(u->manager->units_by_invocation_id, &u->invocation_id, u);
5017 if (r < 0)
5018 goto reset;
5019
5020 return 0;
5021
5022reset:
5023 u->invocation_id = SD_ID128_NULL((const sd_id128_t) { .qwords = { 0, 0 }});
5024 u->invocation_id_string[0] = 0;
5025 return r;
5026}
5027
5028int unit_acquire_invocation_id(Unit *u) {
5029 sd_id128_t id;
5030 int r;
5031
5032 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 5032, __PRETTY_FUNCTION__
); } while (0)
;
5033
5034 r = sd_id128_randomize(&id);
5035 if (r < 0)
5036 return log_unit_error_errno(u, r, "Failed to generate invocation ID for unit: %m")({ const Unit *_u = (u); _u ? log_object_internal(3, r, "../src/core/unit.c"
, 5036, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to generate invocation ID for unit: %m") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((3))), r, "../src/core/unit.c"
, 5036, __func__, "Failed to generate invocation ID for unit: %m"
); })
;
5037
5038 r = unit_set_invocation_id(u, id);
5039 if (r < 0)
5040 return log_unit_error_errno(u, r, "Failed to set invocation ID for unit: %m")({ const Unit *_u = (u); _u ? log_object_internal(3, r, "../src/core/unit.c"
, 5040, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to set invocation ID for unit: %m") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((3))), r, "../src/core/unit.c"
, 5040, __func__, "Failed to set invocation ID for unit: %m")
; })
;
5041
5042 return 0;
5043}
5044
5045void unit_set_exec_params(Unit *u, ExecParameters *p) {
5046 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 5046, __PRETTY_FUNCTION__
); } while (0)
;
5047 assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("p"), "../src/core/unit.c", 5047, __PRETTY_FUNCTION__
); } while (0)
;
5048
5049 /* Copy parameters from manager */
5050 p->environment = u->manager->environment;
5051 p->confirm_spawn = manager_get_confirm_spawn(u->manager);
5052 p->cgroup_supported = u->manager->cgroup_supported;
5053 p->prefix = u->manager->prefix;
5054 SET_FLAG(p->flags, EXEC_PASS_LOG_UNIT|EXEC_CHOWN_DIRECTORIES, MANAGER_IS_SYSTEM(u->manager))(p->flags) = (((u->manager)->unit_file_scope == UNIT_FILE_SYSTEM
)) ? ((p->flags) | (EXEC_PASS_LOG_UNIT|EXEC_CHOWN_DIRECTORIES
)) : ((p->flags) & ~(EXEC_PASS_LOG_UNIT|EXEC_CHOWN_DIRECTORIES
))
;
5055
5056 /* Copy paramaters from unit */
5057 p->cgroup_path = u->cgroup_path;
5058 SET_FLAG(p->flags, EXEC_CGROUP_DELEGATE, unit_cgroup_delegate(u))(p->flags) = (unit_cgroup_delegate(u)) ? ((p->flags) | (
EXEC_CGROUP_DELEGATE)) : ((p->flags) & ~(EXEC_CGROUP_DELEGATE
))
;
5059}
5060
5061int unit_fork_helper_process(Unit *u, const char *name, pid_t *ret) {
5062 int r;
5063
5064 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 5064, __PRETTY_FUNCTION__
); } while (0)
;
5065 assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret"), "../src/core/unit.c", 5065, __PRETTY_FUNCTION__
); } while (0)
;
5066
5067 /* Forks off a helper process and makes sure it is a member of the unit's cgroup. Returns == 0 in the child,
5068 * and > 0 in the parent. The pid parameter is always filled in with the child's PID. */
5069
5070 (void) unit_realize_cgroup(u);
5071
5072 r = safe_fork(name, FORK_REOPEN_LOG, ret);
5073 if (r != 0)
5074 return r;
5075
5076 (void) default_signals(SIGNALS_CRASH_HANDLER11,4,8,7,3,6, SIGNALS_IGNORE13, -1);
5077 (void) ignore_signals(SIGPIPE13, -1);
5078
5079 (void) prctl(PR_SET_PDEATHSIG1, SIGTERM15);
5080
5081 if (u->cgroup_path) {
5082 r = cg_attach_everywhere(u->manager->cgroup_supported, u->cgroup_path, 0, NULL((void*)0), NULL((void*)0));
5083 if (r < 0) {
5084 log_unit_error_errno(u, r, "Failed to join unit cgroup %s: %m", u->cgroup_path)({ const Unit *_u = (u); _u ? log_object_internal(3, r, "../src/core/unit.c"
, 5084, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to join unit cgroup %s: %m", u->cgroup_path) : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((3))), r, "../src/core/unit.c"
, 5084, __func__, "Failed to join unit cgroup %s: %m", u->
cgroup_path); })
;
5085 _exit(EXIT_CGROUP);
5086 }
5087 }
5088
5089 return 0;
5090}
5091
5092static void unit_update_dependency_mask(Unit *u, UnitDependency d, Unit *other, UnitDependencyInfo di) {
5093 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 5093, __PRETTY_FUNCTION__
); } while (0)
;
5094 assert(d >= 0)do { if ((__builtin_expect(!!(!(d >= 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("d >= 0"), "../src/core/unit.c", 5094
, __PRETTY_FUNCTION__); } while (0)
;
5095 assert(d < _UNIT_DEPENDENCY_MAX)do { if ((__builtin_expect(!!(!(d < _UNIT_DEPENDENCY_MAX))
,0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("d < _UNIT_DEPENDENCY_MAX"
), "../src/core/unit.c", 5095, __PRETTY_FUNCTION__); } while (
0)
;
5096 assert(other)do { if ((__builtin_expect(!!(!(other)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("other"), "../src/core/unit.c", 5096, __PRETTY_FUNCTION__
); } while (0)
;
5097
5098 if (di.origin_mask == 0 && di.destination_mask == 0) {
5099 /* No bit set anymore, let's drop the whole entry */
5100 assert_se(hashmap_remove(u->dependencies[d], other))do { if ((__builtin_expect(!!(!(hashmap_remove(u->dependencies
[d], other))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD,
("hashmap_remove(u->dependencies[d], other)"), "../src/core/unit.c"
, 5100, __PRETTY_FUNCTION__); } while (0)
;
5101 log_unit_debug(u, "%s lost dependency %s=%s", u->id, unit_dependency_to_string(d), other->id)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/unit.c"
, 5101, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "%s lost dependency %s=%s", u->id, unit_dependency_to_string
(d), other->id) : log_internal_realm(((LOG_REALM_SYSTEMD) <<
10 | ((7))), 0, "../src/core/unit.c", 5101, __func__, "%s lost dependency %s=%s"
, u->id, unit_dependency_to_string(d), other->id); })
;
5102 } else
5103 /* Mask was reduced, let's update the entry */
5104 assert_se(hashmap_update(u->dependencies[d], other, di.data) == 0)do { if ((__builtin_expect(!!(!(hashmap_update(u->dependencies
[d], other, di.data) == 0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("hashmap_update(u->dependencies[d], other, di.data) == 0"
), "../src/core/unit.c", 5104, __PRETTY_FUNCTION__); } while (
0)
;
5105}
5106
5107void unit_remove_dependencies(Unit *u, UnitDependencyMask mask) {
5108 UnitDependency d;
5109
5110 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 5110, __PRETTY_FUNCTION__
); } while (0)
;
5111
5112 /* Removes all dependencies u has on other units marked for ownership by 'mask'. */
5113
5114 if (mask == 0)
5115 return;
5116
5117 for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) {
5118 bool_Bool done;
5119
5120 do {
5121 UnitDependencyInfo di;
5122 Unit *other;
5123 Iterator i;
5124
5125 done = true1;
5126
5127 HASHMAP_FOREACH_KEY(di.data, other, u->dependencies[d], i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); hashmap_iterate((u->dependencies
[d]), &(i), (void**)&(di.data), (const void**) &(
other)); )
{
5128 UnitDependency q;
5129
5130 if ((di.origin_mask & ~mask) == di.origin_mask)
5131 continue;
5132 di.origin_mask &= ~mask;
5133 unit_update_dependency_mask(u, d, other, di);
5134
5135 /* We updated the dependency from our unit to the other unit now. But most dependencies
5136 * imply a reverse dependency. Hence, let's delete that one too. For that we go through
5137 * all dependency types on the other unit and delete all those which point to us and
5138 * have the right mask set. */
5139
5140 for (q = 0; q < _UNIT_DEPENDENCY_MAX; q++) {
5141 UnitDependencyInfo dj;
5142
5143 dj.data = hashmap_get(other->dependencies[q], u);
5144 if ((dj.destination_mask & ~mask) == dj.destination_mask)
5145 continue;
5146 dj.destination_mask &= ~mask;
5147
5148 unit_update_dependency_mask(other, q, u, dj);
5149 }
5150
5151 unit_add_to_gc_queue(other);
5152
5153 done = false0;
5154 break;
5155 }
5156
5157 } while (!done);
5158 }
5159}
5160
5161static int unit_export_invocation_id(Unit *u) {
5162 const char *p;
5163 int r;
5164
5165 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 5165, __PRETTY_FUNCTION__
); } while (0)
;
5166
5167 if (u->exported_invocation_id)
5168 return 0;
5169
5170 if (sd_id128_is_null(u->invocation_id))
5171 return 0;
5172
5173 p = strjoina("/run/systemd/units/invocation:", u->id)({ const char *_appendees_[] = { "/run/systemd/units/invocation:"
, u->id }; char *_d_, *_p_; size_t _len_ = 0; size_t _i_; for
(_i_ = 0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
5174 r = symlink_atomic(u->invocation_id_string, p);
5175 if (r < 0)
5176 return log_unit_debug_errno(u, r, "Failed to create invocation ID symlink %s: %m", p)({ const Unit *_u = (u); _u ? log_object_internal(7, r, "../src/core/unit.c"
, 5176, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to create invocation ID symlink %s: %m", p) : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((7))), r, "../src/core/unit.c"
, 5176, __func__, "Failed to create invocation ID symlink %s: %m"
, p); })
;
5177
5178 u->exported_invocation_id = true1;
5179 return 0;
5180}
5181
5182static int unit_export_log_level_max(Unit *u, const ExecContext *c) {
5183 const char *p;
5184 char buf[2];
5185 int r;
5186
5187 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 5187, __PRETTY_FUNCTION__
); } while (0)
;
5188 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/core/unit.c", 5188, __PRETTY_FUNCTION__
); } while (0)
;
5189
5190 if (u->exported_log_level_max)
5191 return 0;
5192
5193 if (c->log_level_max < 0)
5194 return 0;
5195
5196 assert(c->log_level_max <= 7)do { if ((__builtin_expect(!!(!(c->log_level_max <= 7))
,0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("c->log_level_max <= 7"
), "../src/core/unit.c", 5196, __PRETTY_FUNCTION__); } while (
0)
;
5197
5198 buf[0] = '0' + c->log_level_max;
5199 buf[1] = 0;
5200
5201 p = strjoina("/run/systemd/units/log-level-max:", u->id)({ const char *_appendees_[] = { "/run/systemd/units/log-level-max:"
, u->id }; char *_d_, *_p_; size_t _len_ = 0; size_t _i_; for
(_i_ = 0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
5202 r = symlink_atomic(buf, p);
5203 if (r < 0)
5204 return log_unit_debug_errno(u, r, "Failed to create maximum log level symlink %s: %m", p)({ const Unit *_u = (u); _u ? log_object_internal(7, r, "../src/core/unit.c"
, 5204, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to create maximum log level symlink %s: %m", p) : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((7))), r, "../src/core/unit.c"
, 5204, __func__, "Failed to create maximum log level symlink %s: %m"
, p); })
;
5205
5206 u->exported_log_level_max = true1;
5207 return 0;
5208}
5209
5210static int unit_export_log_extra_fields(Unit *u, const ExecContext *c) {
5211 _cleanup_close___attribute__((cleanup(closep))) int fd = -1;
5212 struct iovec *iovec;
5213 const char *p;
5214 char *pattern;
5215 le64_t *sizes;
5216 ssize_t n;
5217 size_t i;
5218 int r;
5219
5220 if (u->exported_log_extra_fields)
5221 return 0;
5222
5223 if (c->n_log_extra_fields <= 0)
5224 return 0;
5225
5226 sizes = newa(le64_t, c->n_log_extra_fields)({ do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof
(le64_t), c->n_log_extra_fields))),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("!size_multiply_overflow(sizeof(le64_t), c->n_log_extra_fields)"
), "../src/core/unit.c", 5226, __PRETTY_FUNCTION__); } while (
0); (le64_t*) __builtin_alloca (sizeof(le64_t)*(c->n_log_extra_fields
)); })
;
5227 iovec = newa(struct iovec, c->n_log_extra_fields * 2)({ do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof
(struct iovec), c->n_log_extra_fields * 2))),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("!size_multiply_overflow(sizeof(struct iovec), c->n_log_extra_fields * 2)"
), "../src/core/unit.c", 5227, __PRETTY_FUNCTION__); } while (
0); (struct iovec*) __builtin_alloca (sizeof(struct iovec)*(c
->n_log_extra_fields * 2)); })
;
5228
5229 for (i = 0; i < c->n_log_extra_fields; i++) {
5230 sizes[i] = htole64(c->log_extra_fields[i].iov_len);
5231
5232 iovec[i*2] = IOVEC_MAKE(sizes + i, sizeof(le64_t))(struct iovec) { .iov_base = (sizes + i), .iov_len = (sizeof(
le64_t)) }
;
5233 iovec[i*2+1] = c->log_extra_fields[i];
5234 }
5235
5236 p = strjoina("/run/systemd/units/log-extra-fields:", u->id)({ const char *_appendees_[] = { "/run/systemd/units/log-extra-fields:"
, u->id }; char *_d_, *_p_; size_t _len_ = 0; size_t _i_; for
(_i_ = 0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
5237 pattern = strjoina(p, ".XXXXXX")({ const char *_appendees_[] = { p, ".XXXXXX" }; char *_d_, *
_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__
(__builtin_choose_expr( !__builtin_types_compatible_p(typeof
(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
5238
5239 fd = mkostemp_safe(pattern);
5240 if (fd < 0)
5241 return log_unit_debug_errno(u, fd, "Failed to create extra fields file %s: %m", p)({ const Unit *_u = (u); _u ? log_object_internal(7, fd, "../src/core/unit.c"
, 5241, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to create extra fields file %s: %m", p) : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((7))), fd, "../src/core/unit.c"
, 5241, __func__, "Failed to create extra fields file %s: %m"
, p); })
;
5242
5243 n = writev(fd, iovec, c->n_log_extra_fields*2);
5244 if (n < 0) {
5245 r = log_unit_debug_errno(u, errno, "Failed to write extra fields: %m")({ const Unit *_u = (u); _u ? log_object_internal(7, (*__errno_location
()), "../src/core/unit.c", 5245, __func__, _u->manager->
unit_log_field, _u->id, _u->manager->invocation_log_field
, _u->invocation_id_string, "Failed to write extra fields: %m"
) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7
))), (*__errno_location ()), "../src/core/unit.c", 5245, __func__
, "Failed to write extra fields: %m"); })
;
5246 goto fail;
5247 }
5248
5249 (void) fchmod(fd, 0644);
5250
5251 if (rename(pattern, p) < 0) {
5252 r = log_unit_debug_errno(u, errno, "Failed to rename extra fields file: %m")({ const Unit *_u = (u); _u ? log_object_internal(7, (*__errno_location
()), "../src/core/unit.c", 5252, __func__, _u->manager->
unit_log_field, _u->id, _u->manager->invocation_log_field
, _u->invocation_id_string, "Failed to rename extra fields file: %m"
) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7
))), (*__errno_location ()), "../src/core/unit.c", 5252, __func__
, "Failed to rename extra fields file: %m"); })
;
5253 goto fail;
5254 }
5255
5256 u->exported_log_extra_fields = true1;
5257 return 0;
5258
5259fail:
5260 (void) unlink(pattern);
5261 return r;
5262}
5263
5264static int unit_export_log_rate_limit_interval(Unit *u, const ExecContext *c) {
5265 _cleanup_free___attribute__((cleanup(freep))) char *buf = NULL((void*)0);
5266 const char *p;
5267 int r;
5268
5269 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 5269, __PRETTY_FUNCTION__
); } while (0)
;
5270 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/core/unit.c", 5270, __PRETTY_FUNCTION__
); } while (0)
;
5271
5272 if (u->exported_log_rate_limit_interval)
5273 return 0;
5274
5275 if (c->log_rate_limit_interval_usec == 0)
5276 return 0;
5277
5278 p = strjoina("/run/systemd/units/log-rate-limit-interval:", u->id)({ const char *_appendees_[] = { "/run/systemd/units/log-rate-limit-interval:"
, u->id }; char *_d_, *_p_; size_t _len_ = 0; size_t _i_; for
(_i_ = 0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
5279
5280 if (asprintf(&buf, "%" PRIu64"l" "u", c->log_rate_limit_interval_usec) < 0)
5281 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/core/unit.c", 5281
, __func__)
;
5282
5283 r = symlink_atomic(buf, p);
5284 if (r < 0)
5285 return log_unit_debug_errno(u, r, "Failed to create log rate limit interval symlink %s: %m", p)({ const Unit *_u = (u); _u ? log_object_internal(7, r, "../src/core/unit.c"
, 5285, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to create log rate limit interval symlink %s: %m", p
) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7
))), r, "../src/core/unit.c", 5285, __func__, "Failed to create log rate limit interval symlink %s: %m"
, p); })
;
5286
5287 u->exported_log_rate_limit_interval = true1;
5288 return 0;
5289}
5290
5291static int unit_export_log_rate_limit_burst(Unit *u, const ExecContext *c) {
5292 _cleanup_free___attribute__((cleanup(freep))) char *buf = NULL((void*)0);
5293 const char *p;
5294 int r;
5295
5296 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 5296, __PRETTY_FUNCTION__
); } while (0)
;
5297 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/core/unit.c", 5297, __PRETTY_FUNCTION__
); } while (0)
;
5298
5299 if (u->exported_log_rate_limit_burst)
5300 return 0;
5301
5302 if (c->log_rate_limit_burst == 0)
5303 return 0;
5304
5305 p = strjoina("/run/systemd/units/log-rate-limit-burst:", u->id)({ const char *_appendees_[] = { "/run/systemd/units/log-rate-limit-burst:"
, u->id }; char *_d_, *_p_; size_t _len_ = 0; size_t _i_; for
(_i_ = 0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
5306
5307 if (asprintf(&buf, "%u", c->log_rate_limit_burst) < 0)
5308 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/core/unit.c", 5308
, __func__)
;
5309
5310 r = symlink_atomic(buf, p);
5311 if (r < 0)
5312 return log_unit_debug_errno(u, r, "Failed to create log rate limit burst symlink %s: %m", p)({ const Unit *_u = (u); _u ? log_object_internal(7, r, "../src/core/unit.c"
, 5312, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to create log rate limit burst symlink %s: %m", p) :
log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7)))
, r, "../src/core/unit.c", 5312, __func__, "Failed to create log rate limit burst symlink %s: %m"
, p); })
;
5313
5314 u->exported_log_rate_limit_burst = true1;
5315 return 0;
5316}
5317
5318void unit_export_state_files(Unit *u) {
5319 const ExecContext *c;
5320
5321 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 5321, __PRETTY_FUNCTION__
); } while (0)
;
5322
5323 if (!u->id)
5324 return;
5325
5326 if (!MANAGER_IS_SYSTEM(u->manager)((u->manager)->unit_file_scope == UNIT_FILE_SYSTEM))
5327 return;
5328
5329 if (u->manager->test_run_flags != 0)
5330 return;
5331
5332 /* Exports a couple of unit properties to /run/systemd/units/, so that journald can quickly query this data
5333 * from there. Ideally, journald would use IPC to query this, like everybody else, but that's hard, as long as
5334 * the IPC system itself and PID 1 also log to the journal.
5335 *
5336 * Note that these files really shouldn't be considered API for anyone else, as use a runtime file system as
5337 * IPC replacement is not compatible with today's world of file system namespaces. However, this doesn't really
5338 * apply to communication between the journal and systemd, as we assume that these two daemons live in the same
5339 * namespace at least.
5340 *
5341 * Note that some of the "files" exported here are actually symlinks and not regular files. Symlinks work
5342 * better for storing small bits of data, in particular as we can write them with two system calls, and read
5343 * them with one. */
5344
5345 (void) unit_export_invocation_id(u);
5346
5347 c = unit_get_exec_context(u);
5348 if (c) {
5349 (void) unit_export_log_level_max(u, c);
5350 (void) unit_export_log_extra_fields(u, c);
5351 (void) unit_export_log_rate_limit_interval(u, c);
5352 (void) unit_export_log_rate_limit_burst(u, c);
5353 }
5354}
5355
5356void unit_unlink_state_files(Unit *u) {
5357 const char *p;
5358
5359 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 5359, __PRETTY_FUNCTION__
); } while (0)
;
5360
5361 if (!u->id)
5362 return;
5363
5364 if (!MANAGER_IS_SYSTEM(u->manager)((u->manager)->unit_file_scope == UNIT_FILE_SYSTEM))
5365 return;
5366
5367 /* Undoes the effect of unit_export_state() */
5368
5369 if (u->exported_invocation_id) {
5370 p = strjoina("/run/systemd/units/invocation:", u->id)({ const char *_appendees_[] = { "/run/systemd/units/invocation:"
, u->id }; char *_d_, *_p_; size_t _len_ = 0; size_t _i_; for
(_i_ = 0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
5371 (void) unlink(p);
5372
5373 u->exported_invocation_id = false0;
5374 }
5375
5376 if (u->exported_log_level_max) {
5377 p = strjoina("/run/systemd/units/log-level-max:", u->id)({ const char *_appendees_[] = { "/run/systemd/units/log-level-max:"
, u->id }; char *_d_, *_p_; size_t _len_ = 0; size_t _i_; for
(_i_ = 0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
5378 (void) unlink(p);
5379
5380 u->exported_log_level_max = false0;
5381 }
5382
5383 if (u->exported_log_extra_fields) {
5384 p = strjoina("/run/systemd/units/extra-fields:", u->id)({ const char *_appendees_[] = { "/run/systemd/units/extra-fields:"
, u->id }; char *_d_, *_p_; size_t _len_ = 0; size_t _i_; for
(_i_ = 0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
5385 (void) unlink(p);
5386
5387 u->exported_log_extra_fields = false0;
5388 }
5389
5390 if (u->exported_log_rate_limit_interval) {
5391 p = strjoina("/run/systemd/units/log-rate-limit-interval:", u->id)({ const char *_appendees_[] = { "/run/systemd/units/log-rate-limit-interval:"
, u->id }; char *_d_, *_p_; size_t _len_ = 0; size_t _i_; for
(_i_ = 0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
5392 (void) unlink(p);
5393
5394 u->exported_log_rate_limit_interval = false0;
5395 }
5396
5397 if (u->exported_log_rate_limit_burst) {
5398 p = strjoina("/run/systemd/units/log-rate-limit-burst:", u->id)({ const char *_appendees_[] = { "/run/systemd/units/log-rate-limit-burst:"
, u->id }; char *_d_, *_p_; size_t _len_ = 0; size_t _i_; for
(_i_ = 0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
5399 (void) unlink(p);
5400
5401 u->exported_log_rate_limit_burst = false0;
5402 }
5403}
5404
5405int unit_prepare_exec(Unit *u) {
5406 int r;
5407
5408 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 5408, __PRETTY_FUNCTION__
); } while (0)
;
5409
5410 /* Prepares everything so that we can fork of a process for this unit */
5411
5412 (void) unit_realize_cgroup(u);
5413
5414 if (u->reset_accounting) {
5415 (void) unit_reset_cpu_accounting(u);
5416 (void) unit_reset_ip_accounting(u);
5417 u->reset_accounting = false0;
5418 }
5419
5420 unit_export_state_files(u);
5421
5422 r = unit_setup_exec_runtime(u);
5423 if (r < 0)
5424 return r;
5425
5426 r = unit_setup_dynamic_creds(u);
5427 if (r < 0)
5428 return r;
5429
5430 return 0;
5431}
5432
5433static void log_leftover(pid_t pid, int sig, void *userdata) {
5434 _cleanup_free___attribute__((cleanup(freep))) char *comm = NULL((void*)0);
5435
5436 (void) get_process_comm(pid, &comm);
5437
5438 if (comm && comm[0] == '(') /* Most likely our own helper process (PAM?), ignore */
5439 return;
5440
5441 log_unit_warning(userdata,({ const Unit *_u = (userdata); _u ? log_object_internal(4, 0
, "../src/core/unit.c", 5444, __func__, _u->manager->unit_log_field
, _u->id, _u->manager->invocation_log_field, _u->
invocation_id_string, "Found left-over process " "%" "i" " (%s) in control group while starting unit. Ignoring.\n"
"This usually indicates unclean termination of a previous run, or service implementation deficiencies."
, pid, strna(comm)) : log_internal_realm(((LOG_REALM_SYSTEMD)
<< 10 | ((4))), 0, "../src/core/unit.c", 5444, __func__
, "Found left-over process " "%" "i" " (%s) in control group while starting unit. Ignoring.\n"
"This usually indicates unclean termination of a previous run, or service implementation deficiencies."
, pid, strna(comm)); })
5442 "Found left-over process " PID_FMT " (%s) in control group while starting unit. Ignoring.\n"({ const Unit *_u = (userdata); _u ? log_object_internal(4, 0
, "../src/core/unit.c", 5444, __func__, _u->manager->unit_log_field
, _u->id, _u->manager->invocation_log_field, _u->
invocation_id_string, "Found left-over process " "%" "i" " (%s) in control group while starting unit. Ignoring.\n"
"This usually indicates unclean termination of a previous run, or service implementation deficiencies."
, pid, strna(comm)) : log_internal_realm(((LOG_REALM_SYSTEMD)
<< 10 | ((4))), 0, "../src/core/unit.c", 5444, __func__
, "Found left-over process " "%" "i" " (%s) in control group while starting unit. Ignoring.\n"
"This usually indicates unclean termination of a previous run, or service implementation deficiencies."
, pid, strna(comm)); })
5443 "This usually indicates unclean termination of a previous run, or service implementation deficiencies.",({ const Unit *_u = (userdata); _u ? log_object_internal(4, 0
, "../src/core/unit.c", 5444, __func__, _u->manager->unit_log_field
, _u->id, _u->manager->invocation_log_field, _u->
invocation_id_string, "Found left-over process " "%" "i" " (%s) in control group while starting unit. Ignoring.\n"
"This usually indicates unclean termination of a previous run, or service implementation deficiencies."
, pid, strna(comm)) : log_internal_realm(((LOG_REALM_SYSTEMD)
<< 10 | ((4))), 0, "../src/core/unit.c", 5444, __func__
, "Found left-over process " "%" "i" " (%s) in control group while starting unit. Ignoring.\n"
"This usually indicates unclean termination of a previous run, or service implementation deficiencies."
, pid, strna(comm)); })
5444 pid, strna(comm))({ const Unit *_u = (userdata); _u ? log_object_internal(4, 0
, "../src/core/unit.c", 5444, __func__, _u->manager->unit_log_field
, _u->id, _u->manager->invocation_log_field, _u->
invocation_id_string, "Found left-over process " "%" "i" " (%s) in control group while starting unit. Ignoring.\n"
"This usually indicates unclean termination of a previous run, or service implementation deficiencies."
, pid, strna(comm)) : log_internal_realm(((LOG_REALM_SYSTEMD)
<< 10 | ((4))), 0, "../src/core/unit.c", 5444, __func__
, "Found left-over process " "%" "i" " (%s) in control group while starting unit. Ignoring.\n"
"This usually indicates unclean termination of a previous run, or service implementation deficiencies."
, pid, strna(comm)); })
;
5445}
5446
5447void unit_warn_leftover_processes(Unit *u) {
5448 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 5448, __PRETTY_FUNCTION__
); } while (0)
;
5449
5450 (void) unit_pick_cgroup_path(u);
5451
5452 if (!u->cgroup_path)
5453 return;
5454
5455 (void) cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER"_systemd", u->cgroup_path, 0, 0, NULL((void*)0), log_leftover, u);
5456}
5457
5458bool_Bool unit_needs_console(Unit *u) {
5459 ExecContext *ec;
5460 UnitActiveState state;
5461
5462 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 5462, __PRETTY_FUNCTION__
); } while (0)
;
5463
5464 state = unit_active_state(u);
5465
5466 if (UNIT_IS_INACTIVE_OR_FAILED(state))
5467 return false0;
5468
5469 if (UNIT_VTABLE(u)unit_vtable[(u)->type]->needs_console)
5470 return UNIT_VTABLE(u)unit_vtable[(u)->type]->needs_console(u);
5471
5472 /* If this unit type doesn't implement this call, let's use a generic fallback implementation: */
5473 ec = unit_get_exec_context(u);
5474 if (!ec)
5475 return false0;
5476
5477 return exec_context_may_touch_console(ec);
5478}
5479
5480const char *unit_label_path(Unit *u) {
5481 const char *p;
5482
5483 /* Returns the file system path to use for MAC access decisions, i.e. the file to read the SELinux label off
5484 * when validating access checks. */
5485
5486 p = u->source_path ?: u->fragment_path;
5487 if (!p)
5488 return NULL((void*)0);
5489
5490 /* If a unit is masked, then don't read the SELinux label of /dev/null, as that really makes no sense */
5491 if (path_equal(p, "/dev/null"))
5492 return NULL((void*)0);
5493
5494 return p;
5495}
5496
5497int unit_pid_attachable(Unit *u, pid_t pid, sd_bus_error *error) {
5498 int r;
5499
5500 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 5500, __PRETTY_FUNCTION__
); } while (0)
;
5501
5502 /* Checks whether the specified PID is generally good for attaching, i.e. a valid PID, not our manager itself,
5503 * and not a kernel thread either */
5504
5505 /* First, a simple range check */
5506 if (!pid_is_valid(pid))
5507 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS"org.freedesktop.DBus.Error.InvalidArgs", "Process identifier " PID_FMT"%" "i" " is not valid.", pid);
5508
5509 /* Some extra safety check */
5510 if (pid == 1 || pid == getpid_cached())
5511 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS"org.freedesktop.DBus.Error.InvalidArgs", "Process " PID_FMT"%" "i" " is a manager process, refusing.", pid);
5512
5513 /* Don't even begin to bother with kernel threads */
5514 r = is_kernel_thread(pid);
5515 if (r == -ESRCH3)
5516 return sd_bus_error_setf(error, SD_BUS_ERROR_UNIX_PROCESS_ID_UNKNOWN"org.freedesktop.DBus.Error.UnixProcessIdUnknown", "Process with ID " PID_FMT"%" "i" " does not exist.", pid);
5517 if (r < 0)
5518 return sd_bus_error_set_errnof(error, r, "Failed to determine whether process " PID_FMT"%" "i" " is a kernel thread: %m", pid);
5519 if (r > 0)
5520 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS"org.freedesktop.DBus.Error.InvalidArgs", "Process " PID_FMT"%" "i" " is a kernel thread, refusing.", pid);
5521
5522 return 0;
5523}
5524
5525void unit_log_success(Unit *u) {
5526 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 5526, __PRETTY_FUNCTION__
); } while (0)
;
5527
5528 log_struct(LOG_INFO,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (6)), 0
, "../src/core/unit.c", 5532, __func__, "MESSAGE_ID=" "7a" "d2"
"d1" "89" "f7" "e9" "4e" "70" "a3" "8c" "78" "13" "54" "91" "24"
"48", (u)->manager->unit_log_format_string, (u)->id
, (u)->manager->invocation_log_format_string, (u)->invocation_id_string
, "MESSAGE=%s: " "Succeeded.", (u)->id, ((void*)0))
5529 "MESSAGE_ID=" SD_MESSAGE_UNIT_SUCCESS_STR,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (6)), 0
, "../src/core/unit.c", 5532, __func__, "MESSAGE_ID=" "7a" "d2"
"d1" "89" "f7" "e9" "4e" "70" "a3" "8c" "78" "13" "54" "91" "24"
"48", (u)->manager->unit_log_format_string, (u)->id
, (u)->manager->invocation_log_format_string, (u)->invocation_id_string
, "MESSAGE=%s: " "Succeeded.", (u)->id, ((void*)0))
5530 LOG_UNIT_ID(u),log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (6)), 0
, "../src/core/unit.c", 5532, __func__, "MESSAGE_ID=" "7a" "d2"
"d1" "89" "f7" "e9" "4e" "70" "a3" "8c" "78" "13" "54" "91" "24"
"48", (u)->manager->unit_log_format_string, (u)->id
, (u)->manager->invocation_log_format_string, (u)->invocation_id_string
, "MESSAGE=%s: " "Succeeded.", (u)->id, ((void*)0))
5531 LOG_UNIT_INVOCATION_ID(u),log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (6)), 0
, "../src/core/unit.c", 5532, __func__, "MESSAGE_ID=" "7a" "d2"
"d1" "89" "f7" "e9" "4e" "70" "a3" "8c" "78" "13" "54" "91" "24"
"48", (u)->manager->unit_log_format_string, (u)->id
, (u)->manager->invocation_log_format_string, (u)->invocation_id_string
, "MESSAGE=%s: " "Succeeded.", (u)->id, ((void*)0))
5532 LOG_UNIT_MESSAGE(u, "Succeeded."))log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (6)), 0
, "../src/core/unit.c", 5532, __func__, "MESSAGE_ID=" "7a" "d2"
"d1" "89" "f7" "e9" "4e" "70" "a3" "8c" "78" "13" "54" "91" "24"
"48", (u)->manager->unit_log_format_string, (u)->id
, (u)->manager->invocation_log_format_string, (u)->invocation_id_string
, "MESSAGE=%s: " "Succeeded.", (u)->id, ((void*)0))
;
5533}
5534
5535void unit_log_failure(Unit *u, const char *result) {
5536 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 5536, __PRETTY_FUNCTION__
); } while (0)
;
5537 assert(result)do { if ((__builtin_expect(!!(!(result)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("result"), "../src/core/unit.c", 5537, __PRETTY_FUNCTION__
); } while (0)
;
5538
5539 log_struct(LOG_WARNING,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (4)), 0
, "../src/core/unit.c", 5544, __func__, "MESSAGE_ID=" "d9" "b3"
"73" "ed" "55" "a6" "4f" "eb" "82" "42" "e0" "2d" "be" "79" "a4"
"9c", (u)->manager->unit_log_format_string, (u)->id
, (u)->manager->invocation_log_format_string, (u)->invocation_id_string
, "MESSAGE=%s: " "Failed with result '%s'.", (u)->id, result
, "UNIT_RESULT=%s", result, ((void*)0))
5540 "MESSAGE_ID=" SD_MESSAGE_UNIT_FAILURE_RESULT_STR,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (4)), 0
, "../src/core/unit.c", 5544, __func__, "MESSAGE_ID=" "d9" "b3"
"73" "ed" "55" "a6" "4f" "eb" "82" "42" "e0" "2d" "be" "79" "a4"
"9c", (u)->manager->unit_log_format_string, (u)->id
, (u)->manager->invocation_log_format_string, (u)->invocation_id_string
, "MESSAGE=%s: " "Failed with result '%s'.", (u)->id, result
, "UNIT_RESULT=%s", result, ((void*)0))
5541 LOG_UNIT_ID(u),log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (4)), 0
, "../src/core/unit.c", 5544, __func__, "MESSAGE_ID=" "d9" "b3"
"73" "ed" "55" "a6" "4f" "eb" "82" "42" "e0" "2d" "be" "79" "a4"
"9c", (u)->manager->unit_log_format_string, (u)->id
, (u)->manager->invocation_log_format_string, (u)->invocation_id_string
, "MESSAGE=%s: " "Failed with result '%s'.", (u)->id, result
, "UNIT_RESULT=%s", result, ((void*)0))
5542 LOG_UNIT_INVOCATION_ID(u),log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (4)), 0
, "../src/core/unit.c", 5544, __func__, "MESSAGE_ID=" "d9" "b3"
"73" "ed" "55" "a6" "4f" "eb" "82" "42" "e0" "2d" "be" "79" "a4"
"9c", (u)->manager->unit_log_format_string, (u)->id
, (u)->manager->invocation_log_format_string, (u)->invocation_id_string
, "MESSAGE=%s: " "Failed with result '%s'.", (u)->id, result
, "UNIT_RESULT=%s", result, ((void*)0))
5543 LOG_UNIT_MESSAGE(u, "Failed with result '%s'.", result),log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (4)), 0
, "../src/core/unit.c", 5544, __func__, "MESSAGE_ID=" "d9" "b3"
"73" "ed" "55" "a6" "4f" "eb" "82" "42" "e0" "2d" "be" "79" "a4"
"9c", (u)->manager->unit_log_format_string, (u)->id
, (u)->manager->invocation_log_format_string, (u)->invocation_id_string
, "MESSAGE=%s: " "Failed with result '%s'.", (u)->id, result
, "UNIT_RESULT=%s", result, ((void*)0))
5544 "UNIT_RESULT=%s", result)log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (4)), 0
, "../src/core/unit.c", 5544, __func__, "MESSAGE_ID=" "d9" "b3"
"73" "ed" "55" "a6" "4f" "eb" "82" "42" "e0" "2d" "be" "79" "a4"
"9c", (u)->manager->unit_log_format_string, (u)->id
, (u)->manager->invocation_log_format_string, (u)->invocation_id_string
, "MESSAGE=%s: " "Failed with result '%s'.", (u)->id, result
, "UNIT_RESULT=%s", result, ((void*)0))
;
5545}
5546
5547void unit_log_skip(Unit *u, const char *result) {
5548 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 5548, __PRETTY_FUNCTION__
); } while (0)
;
5549 assert(result)do { if ((__builtin_expect(!!(!(result)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("result"), "../src/core/unit.c", 5549, __PRETTY_FUNCTION__
); } while (0)
;
5550
5551 log_struct(LOG_INFO,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (6)), 0
, "../src/core/unit.c", 5556, __func__, "MESSAGE_ID=" "0e" "42"
"84" "a0" "ca" "ca" "4b" "fc" "81" "c0" "bb" "67" "86" "97" "26"
"73", (u)->manager->unit_log_format_string, (u)->id
, (u)->manager->invocation_log_format_string, (u)->invocation_id_string
, "MESSAGE=%s: " "Skipped due to '%s'.", (u)->id, result, "UNIT_RESULT=%s"
, result, ((void*)0))
5552 "MESSAGE_ID=" SD_MESSAGE_UNIT_SKIPPED_STR,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (6)), 0
, "../src/core/unit.c", 5556, __func__, "MESSAGE_ID=" "0e" "42"
"84" "a0" "ca" "ca" "4b" "fc" "81" "c0" "bb" "67" "86" "97" "26"
"73", (u)->manager->unit_log_format_string, (u)->id
, (u)->manager->invocation_log_format_string, (u)->invocation_id_string
, "MESSAGE=%s: " "Skipped due to '%s'.", (u)->id, result, "UNIT_RESULT=%s"
, result, ((void*)0))
5553 LOG_UNIT_ID(u),log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (6)), 0
, "../src/core/unit.c", 5556, __func__, "MESSAGE_ID=" "0e" "42"
"84" "a0" "ca" "ca" "4b" "fc" "81" "c0" "bb" "67" "86" "97" "26"
"73", (u)->manager->unit_log_format_string, (u)->id
, (u)->manager->invocation_log_format_string, (u)->invocation_id_string
, "MESSAGE=%s: " "Skipped due to '%s'.", (u)->id, result, "UNIT_RESULT=%s"
, result, ((void*)0))
5554 LOG_UNIT_INVOCATION_ID(u),log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (6)), 0
, "../src/core/unit.c", 5556, __func__, "MESSAGE_ID=" "0e" "42"
"84" "a0" "ca" "ca" "4b" "fc" "81" "c0" "bb" "67" "86" "97" "26"
"73", (u)->manager->unit_log_format_string, (u)->id
, (u)->manager->invocation_log_format_string, (u)->invocation_id_string
, "MESSAGE=%s: " "Skipped due to '%s'.", (u)->id, result, "UNIT_RESULT=%s"
, result, ((void*)0))
5555 LOG_UNIT_MESSAGE(u, "Skipped due to '%s'.", result),log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (6)), 0
, "../src/core/unit.c", 5556, __func__, "MESSAGE_ID=" "0e" "42"
"84" "a0" "ca" "ca" "4b" "fc" "81" "c0" "bb" "67" "86" "97" "26"
"73", (u)->manager->unit_log_format_string, (u)->id
, (u)->manager->invocation_log_format_string, (u)->invocation_id_string
, "MESSAGE=%s: " "Skipped due to '%s'.", (u)->id, result, "UNIT_RESULT=%s"
, result, ((void*)0))
5556 "UNIT_RESULT=%s", result)log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (6)), 0
, "../src/core/unit.c", 5556, __func__, "MESSAGE_ID=" "0e" "42"
"84" "a0" "ca" "ca" "4b" "fc" "81" "c0" "bb" "67" "86" "97" "26"
"73", (u)->manager->unit_log_format_string, (u)->id
, (u)->manager->invocation_log_format_string, (u)->invocation_id_string
, "MESSAGE=%s: " "Skipped due to '%s'.", (u)->id, result, "UNIT_RESULT=%s"
, result, ((void*)0))
;
5557}
5558
5559bool_Bool unit_can_freeze(Unit *u) {
5560 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 5560, __PRETTY_FUNCTION__
); } while (0)
;
5561
5562 if (UNIT_VTABLE(u)unit_vtable[(u)->type]->can_freeze)
5563 return UNIT_VTABLE(u)unit_vtable[(u)->type]->can_freeze(u);
5564
5565 return UNIT_VTABLE(u)unit_vtable[(u)->type]->freeze;
5566}
5567
5568void unit_frozen(Unit *u) {
5569 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 5569, __PRETTY_FUNCTION__
); } while (0)
;
5570
5571 u->freezer_state = FREEZER_FROZEN;
5572
5573 bus_unit_send_pending_freezer_message(u);
5574}
5575
5576void unit_thawed(Unit *u) {
5577 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 5577, __PRETTY_FUNCTION__
); } while (0)
;
5578
5579 u->freezer_state = FREEZER_RUNNING;
5580
5581 bus_unit_send_pending_freezer_message(u);
5582}
5583
5584static int unit_freezer_action(Unit *u, FreezerAction action) {
5585 UnitActiveState s;
5586 int (*method)(Unit*);
5587 int r;
5588
5589 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/unit.c", 5589, __PRETTY_FUNCTION__
); } while (0)
;
5590 assert(IN_SET(action, FREEZER_FREEZE, FREEZER_THAW))do { if ((__builtin_expect(!!(!(({ _Bool _found = 0; static __attribute__
((unused)) char _static_assert__macros_need_to_be_extended[20
- sizeof((int[]){FREEZER_FREEZE, FREEZER_THAW})/sizeof(int)]
; switch(action) { case FREEZER_FREEZE: case FREEZER_THAW: _found
= 1; break; default: break; } _found; }))),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("IN_SET(action, FREEZER_FREEZE, FREEZER_THAW)"
), "../src/core/unit.c", 5590, __PRETTY_FUNCTION__); } while (
0)
;
5591
5592 method = action == FREEZER_FREEZE ? UNIT_VTABLE(u)unit_vtable[(u)->type]->freeze : UNIT_VTABLE(u)unit_vtable[(u)->type]->thaw;
5593 if (!method || !cg_freezer_supported())
5594 return -EOPNOTSUPP95;
5595
5596 if (u->job)
5597 return -EBUSY16;
5598
5599 if (u->load_state != UNIT_LOADED)
5600 return -EHOSTDOWN112;
5601
5602 s = unit_active_state(u);
5603 if (s != UNIT_ACTIVE)
5604 return -EHOSTDOWN112;
5605
5606 if (IN_SET(u->freezer_state, FREEZER_FREEZING, FREEZER_THAWING)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){FREEZER_FREEZING, FREEZER_THAWING})/sizeof
(int)]; switch(u->freezer_state) { case FREEZER_FREEZING: case
FREEZER_THAWING: _found = 1; break; default: break; } _found
; })
)
5607 return -EALREADY114;
5608
5609 r = method(u);
5610 if (r <= 0)
5611 return r;
5612
5613 return 1;
5614}
5615
5616int unit_freeze(Unit *u) {
5617 return unit_freezer_action(u, FREEZER_FREEZE);
5618}
5619
5620int unit_thaw(Unit *u) {
5621 return unit_freezer_action(u, FREEZER_THAW);
5622}
5623
5624/* Wrappers around low-level cgroup freezer operations common for service and scope units */
5625int unit_freeze_vtable_common(Unit *u) {
5626 return unit_cgroup_freezer_action(u, FREEZER_FREEZE);
5627}
5628
5629int unit_thaw_vtable_common(Unit *u) {
5630 return unit_cgroup_freezer_action(u, FREEZER_THAW);
5631}
5632
5633static const char* const collect_mode_table[_COLLECT_MODE_MAX] = {
5634 [COLLECT_INACTIVE] = "inactive",
5635 [COLLECT_INACTIVE_OR_FAILED] = "inactive-or-failed",
5636};
5637
5638DEFINE_STRING_TABLE_LOOKUP(collect_mode, CollectMode)const char *collect_mode_to_string(CollectMode i) { if (i <
0 || i >= (CollectMode) __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(collect_mode_table), typeof
(&*(collect_mode_table))), sizeof(collect_mode_table)/sizeof
((collect_mode_table)[0]), ((void)0)))) return ((void*)0); return
collect_mode_table[i]; } CollectMode collect_mode_from_string
(const char *s) { return (CollectMode) string_table_lookup(collect_mode_table
, __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(collect_mode_table), typeof(&*(collect_mode_table
))), sizeof(collect_mode_table)/sizeof((collect_mode_table)[0
]), ((void)0))), s); }
;