]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/unit.c
TODO: add dbus runtime depedency
[thirdparty/systemd.git] / src / core / unit.c
CommitLineData
d6c9574f 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
87f0e418 2
a7334b09
LP
3/***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
a7334b09
LP
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 16 Lesser General Public License for more details.
a7334b09 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
a7334b09
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
87f0e418
LP
22#include <assert.h>
23#include <errno.h>
24#include <string.h>
25#include <sys/epoll.h>
26#include <sys/timerfd.h>
27#include <sys/poll.h>
0301abf4
LP
28#include <stdlib.h>
29#include <unistd.h>
45fb0699 30#include <sys/stat.h>
87f0e418 31
718db961
LP
32#include "sd-id128.h"
33#include "sd-messages.h"
87f0e418
LP
34#include "set.h"
35#include "unit.h"
36#include "macro.h"
37#include "strv.h"
9eb977db 38#include "path-util.h"
87f0e418
LP
39#include "load-fragment.h"
40#include "load-dropin.h"
41#include "log.h"
9e2f7c11 42#include "unit-name.h"
4139c1b2 43#include "dbus-unit.h"
514f4ef5 44#include "special.h"
c6c18be3 45#include "cgroup-util.h"
4927fcae 46#include "missing.h"
71645aca 47#include "mkdir.h"
a5c32cff
HH
48#include "label.h"
49#include "fileio-label.h"
814cc562 50#include "bus-errors.h"
718db961 51#include "dbus.h"
87f0e418
LP
52
53const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = {
54 [UNIT_SERVICE] = &service_vtable,
55 [UNIT_TIMER] = &timer_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,
07b0b134 61 [UNIT_SNAPSHOT] = &snapshot_vtable,
01f78473 62 [UNIT_SWAP] = &swap_vtable,
a016b922 63 [UNIT_PATH] = &path_vtable,
6c12b52e
LP
64 [UNIT_SLICE] = &slice_vtable,
65 [UNIT_SCOPE] = &scope_vtable
87f0e418
LP
66};
67
7d17cfbc 68Unit *unit_new(Manager *m, size_t size) {
87f0e418
LP
69 Unit *u;
70
71 assert(m);
ac155bb8 72 assert(size >= sizeof(Unit));
87f0e418 73
7d17cfbc
MS
74 u = malloc0(size);
75 if (!u)
87f0e418
LP
76 return NULL;
77
ac155bb8
MS
78 u->names = set_new(string_hash_func, string_compare_func);
79 if (!u->names) {
87f0e418
LP
80 free(u);
81 return NULL;
82 }
83
ac155bb8
MS
84 u->manager = m;
85 u->type = _UNIT_TYPE_INVALID;
86 u->deserialized_job = _JOB_TYPE_INVALID;
87 u->default_dependencies = true;
88 u->unit_file_state = _UNIT_FILE_STATE_INVALID;
d420282b 89 u->on_failure_job_mode = JOB_REPLACE;
87f0e418
LP
90
91 return u;
92}
93
f278026d
LP
94bool unit_has_name(Unit *u, const char *name) {
95 assert(u);
96 assert(name);
97
ac155bb8 98 return !!set_get(u->names, (char*) name);
f278026d
LP
99}
100
87f0e418
LP
101int unit_add_name(Unit *u, const char *text) {
102 UnitType t;
276c3e78 103 char *s, *i = NULL;
87f0e418
LP
104 int r;
105
106 assert(u);
107 assert(text);
108
9e2f7c11 109 if (unit_name_is_template(text)) {
ac155bb8 110 if (!u->instance)
9e2f7c11 111 return -EINVAL;
87f0e418 112
ac155bb8 113 s = unit_name_replace_instance(text, u->instance);
9e2f7c11
LP
114 } else
115 s = strdup(text);
87f0e418 116
9e2f7c11
LP
117 if (!s)
118 return -ENOMEM;
87f0e418 119
b9c0d441 120 if (!unit_name_is_valid(s, false)) {
9e2f7c11
LP
121 r = -EINVAL;
122 goto fail;
123 }
e537352b 124
9e2f7c11 125 assert_se((t = unit_name_to_type(s)) >= 0);
87f0e418 126
ac155bb8 127 if (u->type != _UNIT_TYPE_INVALID && t != u->type) {
9e2f7c11
LP
128 r = -EINVAL;
129 goto fail;
130 }
87f0e418 131
e48614c4
ZJS
132 r = unit_name_to_instance(s, &i);
133 if (r < 0)
9e2f7c11 134 goto fail;
87f0e418 135
796ba554
LP
136 if (i && unit_vtable[t]->no_instances) {
137 r = -EINVAL;
9e2f7c11 138 goto fail;
796ba554 139 }
9e2f7c11 140
276c3e78
LP
141 /* Ensure that this unit is either instanced or not instanced,
142 * but not both. */
ac155bb8 143 if (u->type != _UNIT_TYPE_INVALID && !u->instance != !i) {
9e2f7c11
LP
144 r = -EINVAL;
145 goto fail;
146 }
147
148 if (unit_vtable[t]->no_alias &&
ac155bb8
MS
149 !set_isempty(u->names) &&
150 !set_get(u->names, s)) {
9e2f7c11
LP
151 r = -EEXIST;
152 goto fail;
153 }
154
ac155bb8 155 if (hashmap_size(u->manager->units) >= MANAGER_MAX_NAMES) {
4f0f902f
LP
156 r = -E2BIG;
157 goto fail;
158 }
159
e48614c4
ZJS
160 r = set_put(u->names, s);
161 if (r < 0) {
9e2f7c11
LP
162 if (r == -EEXIST)
163 r = 0;
164 goto fail;
87f0e418
LP
165 }
166
e48614c4
ZJS
167 r = hashmap_put(u->manager->units, s, u);
168 if (r < 0) {
ac155bb8 169 set_remove(u->names, s);
9e2f7c11 170 goto fail;
87f0e418
LP
171 }
172
ac155bb8 173 if (u->type == _UNIT_TYPE_INVALID) {
ef734fd6 174
ac155bb8
MS
175 u->type = t;
176 u->id = s;
177 u->instance = i;
9e2f7c11 178
71fda00f 179 LIST_PREPEND(units_by_type, u->manager->units_by_type[t], u);
e537352b
LP
180
181 if (UNIT_VTABLE(u)->init)
182 UNIT_VTABLE(u)->init(u);
9e2f7c11
LP
183 } else
184 free(i);
87f0e418 185
c1e1601e 186 unit_add_to_dbus_queue(u);
87f0e418 187 return 0;
9e2f7c11
LP
188
189fail:
190 free(s);
191 free(i);
192
193 return r;
87f0e418
LP
194}
195
0ae97ec1 196int unit_choose_id(Unit *u, const char *name) {
68eda4bd
RC
197 char *s, *i;
198 _cleanup_free_ char *t = NULL;
276c3e78 199 int r;
0ae97ec1
LP
200
201 assert(u);
202 assert(name);
203
9e2f7c11
LP
204 if (unit_name_is_template(name)) {
205
ac155bb8 206 if (!u->instance)
9e2f7c11
LP
207 return -EINVAL;
208
e48614c4
ZJS
209 t = unit_name_replace_instance(name, u->instance);
210 if (!t)
9e2f7c11
LP
211 return -ENOMEM;
212
213 name = t;
214 }
215
0ae97ec1 216 /* Selects one of the names of this unit as the id */
ac155bb8 217 s = set_get(u->names, (char*) name);
0ae97ec1 218
9e2f7c11 219 if (!s)
0ae97ec1
LP
220 return -ENOENT;
221
e48614c4
ZJS
222 r = unit_name_to_instance(s, &i);
223 if (r < 0)
276c3e78
LP
224 return r;
225
ac155bb8 226 u->id = s;
276c3e78 227
ac155bb8
MS
228 free(u->instance);
229 u->instance = i;
276c3e78 230
c1e1601e 231 unit_add_to_dbus_queue(u);
9e2f7c11 232
0ae97ec1
LP
233 return 0;
234}
235
f50e0a01
LP
236int unit_set_description(Unit *u, const char *description) {
237 char *s;
238
239 assert(u);
240
8aec412f
LP
241 if (isempty(description))
242 s = NULL;
243 else {
244 s = strdup(description);
245 if (!s)
246 return -ENOMEM;
247 }
f50e0a01 248
ac155bb8
MS
249 free(u->description);
250 u->description = s;
c1e1601e
LP
251
252 unit_add_to_dbus_queue(u);
f50e0a01
LP
253 return 0;
254}
255
701cc384
LP
256bool unit_check_gc(Unit *u) {
257 assert(u);
258
ac155bb8 259 if (u->load_state == UNIT_STUB)
b86d44e5
LP
260 return true;
261
701cc384
LP
262 if (UNIT_VTABLE(u)->no_gc)
263 return true;
264
ac155bb8 265 if (u->no_gc)
6c073082
LP
266 return true;
267
ac155bb8 268 if (u->job)
701cc384
LP
269 return true;
270
e0209d83
MS
271 if (u->nop_job)
272 return true;
273
701cc384
LP
274 if (unit_active_state(u) != UNIT_INACTIVE)
275 return true;
276
9d576438
LP
277 if (u->refs)
278 return true;
279
701cc384
LP
280 if (UNIT_VTABLE(u)->check_gc)
281 if (UNIT_VTABLE(u)->check_gc(u))
282 return true;
283
284 return false;
285}
286
87f0e418
LP
287void unit_add_to_load_queue(Unit *u) {
288 assert(u);
ac155bb8 289 assert(u->type != _UNIT_TYPE_INVALID);
87f0e418 290
ac155bb8 291 if (u->load_state != UNIT_STUB || u->in_load_queue)
87f0e418
LP
292 return;
293
71fda00f 294 LIST_PREPEND(load_queue, u->manager->load_queue, u);
ac155bb8 295 u->in_load_queue = true;
87f0e418
LP
296}
297
23a177ef
LP
298void unit_add_to_cleanup_queue(Unit *u) {
299 assert(u);
300
ac155bb8 301 if (u->in_cleanup_queue)
23a177ef
LP
302 return;
303
71fda00f 304 LIST_PREPEND(cleanup_queue, u->manager->cleanup_queue, u);
ac155bb8 305 u->in_cleanup_queue = true;
23a177ef
LP
306}
307
701cc384
LP
308void unit_add_to_gc_queue(Unit *u) {
309 assert(u);
310
ac155bb8 311 if (u->in_gc_queue || u->in_cleanup_queue)
701cc384
LP
312 return;
313
314 if (unit_check_gc(u))
315 return;
316
71fda00f 317 LIST_PREPEND(gc_queue, u->manager->gc_queue, u);
ac155bb8 318 u->in_gc_queue = true;
701cc384 319
ac155bb8 320 u->manager->n_in_gc_queue ++;
701cc384
LP
321}
322
c1e1601e
LP
323void unit_add_to_dbus_queue(Unit *u) {
324 assert(u);
ac155bb8 325 assert(u->type != _UNIT_TYPE_INVALID);
c1e1601e 326
ac155bb8 327 if (u->load_state == UNIT_STUB || u->in_dbus_queue)
c1e1601e
LP
328 return;
329
a567261a 330 /* Shortcut things if nobody cares */
718db961 331 if (set_isempty(u->manager->subscribed)) {
ac155bb8 332 u->sent_dbus_new_signal = true;
94b6dfa2
LP
333 return;
334 }
335
71fda00f 336 LIST_PREPEND(dbus_queue, u->manager->dbus_unit_queue, u);
ac155bb8 337 u->in_dbus_queue = true;
c1e1601e
LP
338}
339
87f0e418
LP
340static void bidi_set_free(Unit *u, Set *s) {
341 Iterator i;
342 Unit *other;
343
344 assert(u);
345
346 /* Frees the set and makes sure we are dropped from the
347 * inverse pointers */
348
349 SET_FOREACH(other, s, i) {
350 UnitDependency d;
351
352 for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++)
ac155bb8 353 set_remove(other->dependencies[d], u);
701cc384
LP
354
355 unit_add_to_gc_queue(other);
87f0e418
LP
356 }
357
358 set_free(s);
359}
360
c2756a68
LP
361static void unit_remove_transient(Unit *u) {
362 char **i;
363
364 assert(u);
365
366 if (!u->transient)
367 return;
368
369 if (u->fragment_path)
370 unlink(u->fragment_path);
371
372 STRV_FOREACH(i, u->dropin_paths) {
373 _cleanup_free_ char *p = NULL;
374 int r;
375
376 unlink(*i);
377
378 r = path_get_parent(*i, &p);
379 if (r >= 0)
380 rmdir(p);
381 }
382}
383
a57f7e2c
LP
384static void unit_free_requires_mounts_for(Unit *u) {
385 char **j;
386
387 STRV_FOREACH(j, u->requires_mounts_for) {
388 char s[strlen(*j) + 1];
389
390 PATH_FOREACH_PREFIX_MORE(s, *j) {
391 char *y;
392 Set *x;
393
394 x = hashmap_get2(u->manager->units_requiring_mounts_for, s, (void**) &y);
395 if (!x)
396 continue;
397
398 set_remove(x, u);
399
400 if (set_isempty(x)) {
401 hashmap_remove(u->manager->units_requiring_mounts_for, y);
402 free(y);
403 set_free(x);
404 }
405 }
406 }
407
408 strv_free(u->requires_mounts_for);
409 u->requires_mounts_for = NULL;
410}
411
87f0e418
LP
412void unit_free(Unit *u) {
413 UnitDependency d;
414 Iterator i;
415 char *t;
416
417 assert(u);
418
c2756a68
LP
419 if (u->manager->n_reloading <= 0)
420 unit_remove_transient(u);
421
c1e1601e
LP
422 bus_unit_send_removed_signal(u);
423
ac155bb8 424 if (u->load_state != UNIT_STUB)
a013b84b
LP
425 if (UNIT_VTABLE(u)->done)
426 UNIT_VTABLE(u)->done(u);
427
a57f7e2c
LP
428 unit_free_requires_mounts_for(u);
429
ac155bb8
MS
430 SET_FOREACH(t, u->names, i)
431 hashmap_remove_value(u->manager->units, t, u);
87f0e418 432
97e7d748
MS
433 if (u->job) {
434 Job *j = u->job;
435 job_uninstall(j);
436 job_free(j);
437 }
964e0949 438
e0209d83
MS
439 if (u->nop_job) {
440 Job *j = u->nop_job;
441 job_uninstall(j);
442 job_free(j);
443 }
444
964e0949 445 for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++)
ac155bb8 446 bidi_set_free(u, u->dependencies[d]);
964e0949 447
ac155bb8 448 if (u->type != _UNIT_TYPE_INVALID)
71fda00f 449 LIST_REMOVE(units_by_type, u->manager->units_by_type[u->type], u);
ef734fd6 450
ac155bb8 451 if (u->in_load_queue)
71fda00f 452 LIST_REMOVE(load_queue, u->manager->load_queue, u);
87f0e418 453
ac155bb8 454 if (u->in_dbus_queue)
71fda00f 455 LIST_REMOVE(dbus_queue, u->manager->dbus_unit_queue, u);
c1e1601e 456
ac155bb8 457 if (u->in_cleanup_queue)
71fda00f 458 LIST_REMOVE(cleanup_queue, u->manager->cleanup_queue, u);
23a177ef 459
ac155bb8 460 if (u->in_gc_queue) {
71fda00f 461 LIST_REMOVE(gc_queue, u->manager->gc_queue, u);
ac155bb8 462 u->manager->n_in_gc_queue--;
701cc384
LP
463 }
464
4ad49000 465 if (u->in_cgroup_queue)
71fda00f 466 LIST_REMOVE(cgroup_queue, u->manager->cgroup_queue, u);
87f0e418 467
72673e86
LP
468 if (u->cgroup_path) {
469 hashmap_remove(u->manager->cgroup_unit, u->cgroup_path);
470 free(u->cgroup_path);
471 }
472
ac155bb8 473 free(u->description);
49dbfa7b 474 strv_free(u->documentation);
ac155bb8 475 free(u->fragment_path);
1b64d026 476 free(u->source_path);
ae7a7182 477 strv_free(u->dropin_paths);
ac155bb8 478 free(u->instance);
87f0e418 479
ac155bb8 480 set_free_free(u->names);
87f0e418 481
ac155bb8 482 condition_free_list(u->conditions);
52661efd 483
702a2d8f
LP
484 unit_ref_unset(&u->slice);
485
ac155bb8
MS
486 while (u->refs)
487 unit_ref_unset(u->refs);
57020a3a 488
87f0e418
LP
489 free(u);
490}
491
492UnitActiveState unit_active_state(Unit *u) {
493 assert(u);
494
ac155bb8 495 if (u->load_state == UNIT_MERGED)
6124958c
LP
496 return unit_active_state(unit_follow_merge(u));
497
498 /* After a reload it might happen that a unit is not correctly
499 * loaded but still has a process around. That's why we won't
fdf20a31 500 * shortcut failed loading to UNIT_INACTIVE_FAILED. */
87f0e418
LP
501
502 return UNIT_VTABLE(u)->active_state(u);
503}
504
10a94420
LP
505const char* unit_sub_state_to_string(Unit *u) {
506 assert(u);
507
508 return UNIT_VTABLE(u)->sub_state_to_string(u);
509}
510
23a177ef
LP
511static void complete_move(Set **s, Set **other) {
512 assert(s);
513 assert(other);
87f0e418 514
23a177ef
LP
515 if (!*other)
516 return;
87f0e418
LP
517
518 if (*s)
23a177ef
LP
519 set_move(*s, *other);
520 else {
521 *s = *other;
522 *other = NULL;
523 }
524}
87f0e418 525
23a177ef
LP
526static void merge_names(Unit *u, Unit *other) {
527 char *t;
528 Iterator i;
87f0e418 529
23a177ef
LP
530 assert(u);
531 assert(other);
532
ac155bb8 533 complete_move(&u->names, &other->names);
23a177ef 534
ac155bb8
MS
535 set_free_free(other->names);
536 other->names = NULL;
537 other->id = NULL;
23a177ef 538
ac155bb8
MS
539 SET_FOREACH(t, u->names, i)
540 assert_se(hashmap_replace(u->manager->units, t, u) == 0);
87f0e418
LP
541}
542
23a177ef
LP
543static void merge_dependencies(Unit *u, Unit *other, UnitDependency d) {
544 Iterator i;
545 Unit *back;
87f0e418 546 int r;
23a177ef
LP
547
548 assert(u);
549 assert(other);
550 assert(d < _UNIT_DEPENDENCY_MAX);
551
83a95334 552 /* Fix backwards pointers */
ac155bb8 553 SET_FOREACH(back, other->dependencies[d], i) {
23a177ef
LP
554 UnitDependency k;
555
e48614c4
ZJS
556 for (k = 0; k < _UNIT_DEPENDENCY_MAX; k++) {
557 r = set_remove_and_put(back->dependencies[k], other, u);
558 if (r == -EEXIST)
559 set_remove(back->dependencies[k], other);
560 else
561 assert(r >= 0 || r == -ENOENT);
562 }
23a177ef
LP
563 }
564
ac155bb8 565 complete_move(&u->dependencies[d], &other->dependencies[d]);
23a177ef 566
ac155bb8
MS
567 set_free(other->dependencies[d]);
568 other->dependencies[d] = NULL;
23a177ef
LP
569}
570
571int unit_merge(Unit *u, Unit *other) {
87f0e418
LP
572 UnitDependency d;
573
574 assert(u);
575 assert(other);
ac155bb8
MS
576 assert(u->manager == other->manager);
577 assert(u->type != _UNIT_TYPE_INVALID);
87f0e418 578
cc916967
LP
579 other = unit_follow_merge(other);
580
23a177ef
LP
581 if (other == u)
582 return 0;
583
ac155bb8 584 if (u->type != other->type)
9e2f7c11
LP
585 return -EINVAL;
586
ac155bb8 587 if (!u->instance != !other->instance)
87f0e418
LP
588 return -EINVAL;
589
ac155bb8 590 if (other->load_state != UNIT_STUB &&
c2756a68 591 other->load_state != UNIT_NOT_FOUND)
23a177ef 592 return -EEXIST;
87f0e418 593
ac155bb8 594 if (other->job)
819e213f
LP
595 return -EEXIST;
596
e0209d83
MS
597 if (other->nop_job)
598 return -EEXIST;
599
fdf20a31 600 if (!UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other)))
819e213f
LP
601 return -EEXIST;
602
87f0e418 603 /* Merge names */
23a177ef 604 merge_names(u, other);
87f0e418 605
57020a3a 606 /* Redirect all references */
ac155bb8
MS
607 while (other->refs)
608 unit_ref_set(other->refs, u);
57020a3a 609
87f0e418
LP
610 /* Merge dependencies */
611 for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++)
23a177ef 612 merge_dependencies(u, other, d);
87f0e418 613
ac155bb8
MS
614 other->load_state = UNIT_MERGED;
615 other->merged_into = u;
23a177ef 616
3616a49c
LP
617 /* If there is still some data attached to the other node, we
618 * don't need it anymore, and can free it. */
ac155bb8 619 if (other->load_state != UNIT_STUB)
3616a49c
LP
620 if (UNIT_VTABLE(other)->done)
621 UNIT_VTABLE(other)->done(other);
622
623 unit_add_to_dbus_queue(u);
23a177ef
LP
624 unit_add_to_cleanup_queue(other);
625
626 return 0;
627}
628
629int unit_merge_by_name(Unit *u, const char *name) {
630 Unit *other;
9e2f7c11 631 int r;
68eda4bd 632 _cleanup_free_ char *s = NULL;
23a177ef
LP
633
634 assert(u);
635 assert(name);
636
9e2f7c11 637 if (unit_name_is_template(name)) {
ac155bb8 638 if (!u->instance)
9e2f7c11
LP
639 return -EINVAL;
640
e48614c4
ZJS
641 s = unit_name_replace_instance(name, u->instance);
642 if (!s)
9e2f7c11
LP
643 return -ENOMEM;
644
645 name = s;
646 }
647
c2756a68
LP
648 other = manager_get_unit(u->manager, name);
649 if (!other)
9e2f7c11
LP
650 r = unit_add_name(u, name);
651 else
652 r = unit_merge(u, other);
23a177ef 653
9e2f7c11 654 return r;
23a177ef
LP
655}
656
657Unit* unit_follow_merge(Unit *u) {
658 assert(u);
659
ac155bb8
MS
660 while (u->load_state == UNIT_MERGED)
661 assert_se(u = u->merged_into);
23a177ef
LP
662
663 return u;
664}
665
666int unit_add_exec_dependencies(Unit *u, ExecContext *c) {
667 int r;
668
669 assert(u);
670 assert(c);
671
ecc6e2b8
LP
672 if (c->std_output != EXEC_OUTPUT_KMSG &&
673 c->std_output != EXEC_OUTPUT_SYSLOG &&
706343f4 674 c->std_output != EXEC_OUTPUT_JOURNAL &&
28dbc1e8
LP
675 c->std_output != EXEC_OUTPUT_KMSG_AND_CONSOLE &&
676 c->std_output != EXEC_OUTPUT_SYSLOG_AND_CONSOLE &&
706343f4 677 c->std_output != EXEC_OUTPUT_JOURNAL_AND_CONSOLE &&
ecc6e2b8 678 c->std_error != EXEC_OUTPUT_KMSG &&
085c98af 679 c->std_error != EXEC_OUTPUT_SYSLOG &&
706343f4 680 c->std_error != EXEC_OUTPUT_JOURNAL &&
085c98af 681 c->std_error != EXEC_OUTPUT_KMSG_AND_CONSOLE &&
706343f4 682 c->std_error != EXEC_OUTPUT_JOURNAL_AND_CONSOLE &&
28dbc1e8 683 c->std_error != EXEC_OUTPUT_SYSLOG_AND_CONSOLE)
23a177ef
LP
684 return 0;
685
686 /* If syslog or kernel logging is requested, make sure our own
687 * logging daemon is run first. */
688
9d246da3
MS
689 if (u->manager->running_as == SYSTEMD_SYSTEM) {
690 r = unit_add_dependency_by_name(u, UNIT_AFTER, SPECIAL_JOURNALD_SOCKET, NULL, true);
691 if (r < 0)
23a177ef 692 return r;
9d246da3 693 }
23a177ef 694
87f0e418
LP
695 return 0;
696}
697
87f0e418
LP
698const char *unit_description(Unit *u) {
699 assert(u);
700
ac155bb8
MS
701 if (u->description)
702 return u->description;
87f0e418 703
ac155bb8 704 return strna(u->id);
87f0e418
LP
705}
706
707void unit_dump(Unit *u, FILE *f, const char *prefix) {
49dbfa7b 708 char *t, **j;
87f0e418
LP
709 UnitDependency d;
710 Iterator i;
68eda4bd 711 _cleanup_free_ char *p2 = NULL;
47be870b 712 const char *prefix2;
173e3821
LP
713 char
714 timestamp1[FORMAT_TIMESTAMP_MAX],
715 timestamp2[FORMAT_TIMESTAMP_MAX],
716 timestamp3[FORMAT_TIMESTAMP_MAX],
faf919f1
LP
717 timestamp4[FORMAT_TIMESTAMP_MAX],
718 timespan[FORMAT_TIMESPAN_MAX];
a7f241db 719 Unit *following;
eeaedb7c
LP
720 _cleanup_set_free_ Set *following_set = NULL;
721 int r;
87f0e418
LP
722
723 assert(u);
ac155bb8 724 assert(u->type >= 0);
87f0e418
LP
725
726 if (!prefix)
727 prefix = "";
47be870b
LP
728 p2 = strappend(prefix, "\t");
729 prefix2 = p2 ? p2 : prefix;
87f0e418
LP
730
731 fprintf(f,
40d50879 732 "%s-> Unit %s:\n"
87f0e418 733 "%s\tDescription: %s\n"
9e2f7c11 734 "%s\tInstance: %s\n"
87f0e418 735 "%s\tUnit Load State: %s\n"
2fad8195 736 "%s\tUnit Active State: %s\n"
173e3821 737 "%s\tInactive Exit Timestamp: %s\n"
2fad8195 738 "%s\tActive Enter Timestamp: %s\n"
701cc384 739 "%s\tActive Exit Timestamp: %s\n"
173e3821 740 "%s\tInactive Enter Timestamp: %s\n"
45fb0699 741 "%s\tGC Check Good: %s\n"
9444b1f2 742 "%s\tNeed Daemon Reload: %s\n"
c2756a68 743 "%s\tTransient: %s\n"
4ad49000
LP
744 "%s\tSlice: %s\n"
745 "%s\tCGroup: %s\n"
746 "%s\tCGroup realized: %s\n"
6414b7c9
DS
747 "%s\tCGroup mask: 0x%x\n"
748 "%s\tCGroup members mask: 0x%x\n",
ac155bb8 749 prefix, u->id,
87f0e418 750 prefix, unit_description(u),
ac155bb8
MS
751 prefix, strna(u->instance),
752 prefix, unit_load_state_to_string(u->load_state),
2fad8195 753 prefix, unit_active_state_to_string(unit_active_state(u)),
ac155bb8
MS
754 prefix, strna(format_timestamp(timestamp1, sizeof(timestamp1), u->inactive_exit_timestamp.realtime)),
755 prefix, strna(format_timestamp(timestamp2, sizeof(timestamp2), u->active_enter_timestamp.realtime)),
756 prefix, strna(format_timestamp(timestamp3, sizeof(timestamp3), u->active_exit_timestamp.realtime)),
757 prefix, strna(format_timestamp(timestamp4, sizeof(timestamp4), u->inactive_enter_timestamp.realtime)),
45fb0699 758 prefix, yes_no(unit_check_gc(u)),
9444b1f2 759 prefix, yes_no(unit_need_daemon_reload(u)),
c2756a68 760 prefix, yes_no(u->transient),
4ad49000
LP
761 prefix, strna(unit_slice_name(u)),
762 prefix, strna(u->cgroup_path),
763 prefix, yes_no(u->cgroup_realized),
6414b7c9
DS
764 prefix, u->cgroup_mask,
765 prefix, u->cgroup_members_mask);
0301abf4 766
ac155bb8 767 SET_FOREACH(t, u->names, i)
87f0e418
LP
768 fprintf(f, "%s\tName: %s\n", prefix, t);
769
49dbfa7b
LP
770 STRV_FOREACH(j, u->documentation)
771 fprintf(f, "%s\tDocumentation: %s\n", prefix, *j);
772
eeaedb7c
LP
773 following = unit_following(u);
774 if (following)
ac155bb8 775 fprintf(f, "%s\tFollowing: %s\n", prefix, following->id);
8fe914ec 776
eeaedb7c
LP
777 r = unit_following_set(u, &following_set);
778 if (r >= 0) {
779 Unit *other;
780
781 SET_FOREACH(other, following_set, i)
782 fprintf(f, "%s\tFollowing Set Member: %s\n", prefix, other->id);
783 }
784
ac155bb8
MS
785 if (u->fragment_path)
786 fprintf(f, "%s\tFragment Path: %s\n", prefix, u->fragment_path);
23a177ef 787
1b64d026
LP
788 if (u->source_path)
789 fprintf(f, "%s\tSource Path: %s\n", prefix, u->source_path);
790
ae7a7182 791 STRV_FOREACH(j, u->dropin_paths)
2875e22b 792 fprintf(f, "%s\tDropIn Path: %s\n", prefix, *j);
ae7a7182 793
ac155bb8 794 if (u->job_timeout > 0)
2fa4092c 795 fprintf(f, "%s\tJob Timeout: %s\n", prefix, format_timespan(timespan, sizeof(timespan), u->job_timeout, 0));
faf919f1 796
ac155bb8 797 condition_dump_list(u->conditions, f, prefix);
52661efd 798
ac155bb8 799 if (dual_timestamp_is_set(&u->condition_timestamp))
2791a8f8
LP
800 fprintf(f,
801 "%s\tCondition Timestamp: %s\n"
802 "%s\tCondition Result: %s\n",
ac155bb8
MS
803 prefix, strna(format_timestamp(timestamp1, sizeof(timestamp1), u->condition_timestamp.realtime)),
804 prefix, yes_no(u->condition_result));
2791a8f8 805
87f0e418
LP
806 for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) {
807 Unit *other;
808
ac155bb8
MS
809 SET_FOREACH(other, u->dependencies[d], i)
810 fprintf(f, "%s\t%s: %s\n", prefix, unit_dependency_to_string(d), other->id);
87f0e418
LP
811 }
812
7c8fa05c 813 if (!strv_isempty(u->requires_mounts_for)) {
7c8fa05c
LP
814 fprintf(f,
815 "%s\tRequiresMountsFor:", prefix);
816
817 STRV_FOREACH(j, u->requires_mounts_for)
818 fprintf(f, " %s", *j);
819
820 fputs("\n", f);
821 }
822
ac155bb8 823 if (u->load_state == UNIT_LOADED) {
ab1f0633 824
b0650475 825 fprintf(f,
a40eb732 826 "%s\tStopWhenUnneeded: %s\n"
b5e9dba8
LP
827 "%s\tRefuseManualStart: %s\n"
828 "%s\tRefuseManualStop: %s\n"
222ae6a8 829 "%s\tDefaultDependencies: %s\n"
d420282b 830 "%s\tOnFailureJobMode: %s\n"
7a6000a6
LP
831 "%s\tIgnoreOnIsolate: %s\n"
832 "%s\tIgnoreOnSnapshot: %s\n",
ac155bb8
MS
833 prefix, yes_no(u->stop_when_unneeded),
834 prefix, yes_no(u->refuse_manual_start),
835 prefix, yes_no(u->refuse_manual_stop),
836 prefix, yes_no(u->default_dependencies),
d420282b 837 prefix, job_mode_to_string(u->on_failure_job_mode),
ac155bb8
MS
838 prefix, yes_no(u->ignore_on_isolate),
839 prefix, yes_no(u->ignore_on_snapshot));
840
23a177ef
LP
841 if (UNIT_VTABLE(u)->dump)
842 UNIT_VTABLE(u)->dump(u, f, prefix2);
b0650475 843
ac155bb8 844 } else if (u->load_state == UNIT_MERGED)
b0650475
LP
845 fprintf(f,
846 "%s\tMerged into: %s\n",
ac155bb8
MS
847 prefix, u->merged_into->id);
848 else if (u->load_state == UNIT_ERROR)
849 fprintf(f, "%s\tLoad Error Code: %s\n", prefix, strerror(-u->load_error));
8821a00f 850
87f0e418 851
ac155bb8
MS
852 if (u->job)
853 job_dump(u->job, f, prefix2);
87f0e418 854
e0209d83
MS
855 if (u->nop_job)
856 job_dump(u->nop_job, f, prefix2);
857
87f0e418
LP
858}
859
860/* Common implementation for multiple backends */
e537352b 861int unit_load_fragment_and_dropin(Unit *u) {
23a177ef
LP
862 int r;
863
864 assert(u);
23a177ef 865
e48614c4 866 /* Load a .{service,socket,...} file */
4ad49000
LP
867 r = unit_load_fragment(u);
868 if (r < 0)
23a177ef
LP
869 return r;
870
ac155bb8 871 if (u->load_state == UNIT_STUB)
23a177ef
LP
872 return -ENOENT;
873
874 /* Load drop-in directory data */
4ad49000
LP
875 r = unit_load_dropin(unit_follow_merge(u));
876 if (r < 0)
23a177ef
LP
877 return r;
878
879 return 0;
880}
881
882/* Common implementation for multiple backends */
e537352b 883int unit_load_fragment_and_dropin_optional(Unit *u) {
23a177ef 884 int r;
87f0e418
LP
885
886 assert(u);
887
23a177ef
LP
888 /* Same as unit_load_fragment_and_dropin(), but whether
889 * something can be loaded or not doesn't matter. */
890
891 /* Load a .service file */
4ad49000
LP
892 r = unit_load_fragment(u);
893 if (r < 0)
87f0e418
LP
894 return r;
895
ac155bb8
MS
896 if (u->load_state == UNIT_STUB)
897 u->load_state = UNIT_LOADED;
d46de8a1 898
87f0e418 899 /* Load drop-in directory data */
4ad49000
LP
900 r = unit_load_dropin(unit_follow_merge(u));
901 if (r < 0)
87f0e418
LP
902 return r;
903
23a177ef 904 return 0;
87f0e418
LP
905}
906
bba34eed 907int unit_add_default_target_dependency(Unit *u, Unit *target) {
98bc2000
LP
908 assert(u);
909 assert(target);
910
ac155bb8 911 if (target->type != UNIT_TARGET)
98bc2000
LP
912 return 0;
913
35b8ca3a 914 /* Only add the dependency if both units are loaded, so that
bba34eed 915 * that loop check below is reliable */
ac155bb8
MS
916 if (u->load_state != UNIT_LOADED ||
917 target->load_state != UNIT_LOADED)
bba34eed
LP
918 return 0;
919
21256a2b
LP
920 /* If either side wants no automatic dependencies, then let's
921 * skip this */
ac155bb8
MS
922 if (!u->default_dependencies ||
923 !target->default_dependencies)
21256a2b
LP
924 return 0;
925
98bc2000 926 /* Don't create loops */
ac155bb8 927 if (set_get(target->dependencies[UNIT_BEFORE], u))
98bc2000
LP
928 return 0;
929
930 return unit_add_dependency(target, UNIT_AFTER, u, true);
931}
932
933static int unit_add_default_dependencies(Unit *u) {
a016b922 934
21256a2b
LP
935 static const UnitDependency deps[] = {
936 UNIT_REQUIRED_BY,
937 UNIT_REQUIRED_BY_OVERRIDABLE,
938 UNIT_WANTED_BY,
939 UNIT_BOUND_BY
940 };
941
bba34eed 942 Unit *target;
98bc2000
LP
943 Iterator i;
944 int r;
21256a2b 945 unsigned k;
98bc2000
LP
946
947 assert(u);
948
21256a2b 949 for (k = 0; k < ELEMENTSOF(deps); k++)
a016b922
LP
950 SET_FOREACH(target, u->dependencies[deps[k]], i) {
951 r = unit_add_default_target_dependency(u, target);
952 if (r < 0)
21256a2b 953 return r;
a016b922
LP
954 }
955
4ad49000
LP
956 if (u->default_dependencies && unit_get_cgroup_context(u)) {
957 if (UNIT_ISSET(u->slice))
958 r = unit_add_two_dependencies(u, UNIT_AFTER, UNIT_WANTS, UNIT_DEREF(u->slice), true);
959 else
960 r = unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_WANTS, SPECIAL_ROOT_SLICE, NULL, true);
961
a016b922
LP
962 if (r < 0)
963 return r;
964 }
b81884e7 965
98bc2000
LP
966 return 0;
967}
968
9588bc32
LP
969static int unit_add_mount_links(Unit *u) {
970 char **i;
971 int r;
972
973 assert(u);
974
975 STRV_FOREACH(i, u->requires_mounts_for) {
976 char prefix[strlen(*i) + 1];
977
978 PATH_FOREACH_PREFIX_MORE(prefix, *i) {
979 Unit *m;
980
981 r = manager_get_unit_by_path(u->manager, prefix, ".mount", &m);
982 if (r < 0)
983 return r;
984 if (r == 0)
985 continue;
986 if (m == u)
987 continue;
988
989 if (m->load_state != UNIT_LOADED)
990 continue;
991
992 r = unit_add_dependency(u, UNIT_AFTER, m, true);
993 if (r < 0)
994 return r;
995
996 if (m->fragment_path) {
997 r = unit_add_dependency(u, UNIT_REQUIRES, m, true);
998 if (r < 0)
999 return r;
1000 }
1001 }
1002 }
1003
1004 return 0;
1005}
1006
87f0e418
LP
1007int unit_load(Unit *u) {
1008 int r;
1009
1010 assert(u);
1011
ac155bb8 1012 if (u->in_load_queue) {
71fda00f 1013 LIST_REMOVE(load_queue, u->manager->load_queue, u);
ac155bb8 1014 u->in_load_queue = false;
87f0e418
LP
1015 }
1016
ac155bb8 1017 if (u->type == _UNIT_TYPE_INVALID)
e537352b
LP
1018 return -EINVAL;
1019
ac155bb8 1020 if (u->load_state != UNIT_STUB)
87f0e418
LP
1021 return 0;
1022
c2756a68
LP
1023 if (UNIT_VTABLE(u)->load) {
1024 r = UNIT_VTABLE(u)->load(u);
1025 if (r < 0)
87f0e418 1026 goto fail;
c2756a68 1027 }
23a177ef 1028
ac155bb8 1029 if (u->load_state == UNIT_STUB) {
23a177ef
LP
1030 r = -ENOENT;
1031 goto fail;
1032 }
1033
7c8fa05c 1034 if (u->load_state == UNIT_LOADED) {
c2756a68
LP
1035
1036 if (u->default_dependencies) {
1037 r = unit_add_default_dependencies(u);
1038 if (r < 0)
1039 goto fail;
1040 }
1041
6414b7c9
DS
1042 unit_update_member_masks(u);
1043
7c8fa05c
LP
1044 r = unit_add_mount_links(u);
1045 if (r < 0)
c2756a68 1046 goto fail;
7c8fa05c 1047
d420282b 1048 if (u->on_failure_job_mode == JOB_ISOLATE &&
c2756a68 1049 set_size(u->dependencies[UNIT_ON_FAILURE]) > 1) {
f68319bb 1050
c2756a68 1051 log_error_unit(u->id,
d420282b 1052 "More than one OnFailure= dependencies specified for %s but OnFailureJobMode=isolate set. Refusing.", u->id);
f68319bb 1053
c2756a68
LP
1054 r = -EINVAL;
1055 goto fail;
1056 }
f68319bb
LP
1057 }
1058
ac155bb8 1059 assert((u->load_state != UNIT_MERGED) == !u->merged_into);
23a177ef
LP
1060
1061 unit_add_to_dbus_queue(unit_follow_merge(u));
701cc384 1062 unit_add_to_gc_queue(u);
87f0e418 1063
87f0e418
LP
1064 return 0;
1065
1066fail:
c2756a68 1067 u->load_state = u->load_state == UNIT_STUB ? UNIT_NOT_FOUND : UNIT_ERROR;
ac155bb8 1068 u->load_error = r;
c1e1601e 1069 unit_add_to_dbus_queue(u);
9a46fc3b 1070 unit_add_to_gc_queue(u);
23a177ef 1071
c1b6628d
ZJS
1072 log_debug_unit(u->id, "Failed to load configuration for %s: %s",
1073 u->id, strerror(-r));
23a177ef 1074
87f0e418
LP
1075 return r;
1076}
1077
9588bc32 1078static bool unit_condition_test(Unit *u) {
90bbc946
LP
1079 assert(u);
1080
ac155bb8 1081 dual_timestamp_get(&u->condition_timestamp);
4b744dfa 1082 u->condition_result = condition_test_list(u->id, u->conditions);
90bbc946 1083
ac155bb8 1084 return u->condition_result;
90bbc946
LP
1085}
1086
44a6b1b6 1087_pure_ static const char* unit_get_status_message_format(Unit *u, JobType t) {
c6918296 1088 const UnitStatusMessageFormats *format_table;
877d54e9
LP
1089
1090 assert(u);
1091 assert(t >= 0);
1092 assert(t < _JOB_TYPE_MAX);
1093
1094 if (t != JOB_START && t != JOB_STOP)
1095 return NULL;
c6918296
MS
1096
1097 format_table = &UNIT_VTABLE(u)->status_message_formats;
1098 if (!format_table)
877d54e9
LP
1099 return NULL;
1100
1101 return format_table->starting_stopping[t == JOB_STOP];
1102}
1103
44a6b1b6 1104_pure_ static const char *unit_get_status_message_format_try_harder(Unit *u, JobType t) {
877d54e9
LP
1105 const char *format;
1106
1107 assert(u);
1108 assert(t >= 0);
1109 assert(t < _JOB_TYPE_MAX);
1110
1111 format = unit_get_status_message_format(u, t);
1112 if (format)
1113 return format;
1114
1115 /* Return generic strings */
1116 if (t == JOB_START)
1117 return "Starting %s.";
1118 else if (t == JOB_STOP)
1119 return "Stopping %s.";
1120 else if (t == JOB_RELOAD)
1121 return "Reloading %s.";
1122
1123 return NULL;
1124}
1125
1126static void unit_status_print_starting_stopping(Unit *u, JobType t) {
1127 const char *format;
1128
1129 assert(u);
1130
1131 /* We only print status messages for selected units on
1132 * selected operations. */
c6918296 1133
877d54e9 1134 format = unit_get_status_message_format(u, t);
c6918296
MS
1135 if (!format)
1136 return;
1137
49b1d377 1138 unit_status_printf(u, "", format);
c6918296
MS
1139}
1140
877d54e9
LP
1141#pragma GCC diagnostic push
1142#pragma GCC diagnostic ignored "-Wformat-nonliteral"
1143static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) {
1144 const char *format;
1145 char buf[LINE_MAX];
1146 sd_id128_t mid;
1147
1148 assert(u);
1149
1150 if (t != JOB_START && t != JOB_STOP && t != JOB_RELOAD)
1151 return;
1152
81270860
LP
1153 if (log_on_console())
1154 return;
1155
877d54e9
LP
1156 /* We log status messages for all units and all operations. */
1157
1158 format = unit_get_status_message_format_try_harder(u, t);
1159 if (!format)
1160 return;
1161
1162 snprintf(buf, sizeof(buf), format, unit_description(u));
1163 char_array_0(buf);
1164
1165 mid = t == JOB_START ? SD_MESSAGE_UNIT_STARTING :
1166 t == JOB_STOP ? SD_MESSAGE_UNIT_STOPPING :
1167 SD_MESSAGE_UNIT_RELOADING;
1168
bbc9006e 1169 log_struct_unit(LOG_INFO,
c1b6628d
ZJS
1170 u->id,
1171 MESSAGE_ID(mid),
1172 "MESSAGE=%s", buf,
1173 NULL);
877d54e9
LP
1174}
1175#pragma GCC diagnostic pop
1176
87f0e418 1177/* Errors:
d5159713
LP
1178 * -EBADR: This unit type does not support starting.
1179 * -EALREADY: Unit is already started.
1180 * -EAGAIN: An operation is already in progress. Retry later.
1181 * -ECANCELED: Too many requests for now.
87f0e418
LP
1182 */
1183int unit_start(Unit *u) {
1184 UnitActiveState state;
92ab323c 1185 Unit *following;
87f0e418
LP
1186
1187 assert(u);
1188
ac155bb8 1189 if (u->load_state != UNIT_LOADED)
6124958c
LP
1190 return -EINVAL;
1191
a82e5507
LP
1192 /* If this is already started, then this will succeed. Note
1193 * that this will even succeed if this unit is not startable
1194 * by the user. This is relied on to detect when we need to
1195 * wait for units and when waiting is finished. */
87f0e418
LP
1196 state = unit_active_state(u);
1197 if (UNIT_IS_ACTIVE_OR_RELOADING(state))
1198 return -EALREADY;
1199
a82e5507
LP
1200 /* If the conditions failed, don't do anything at all. If we
1201 * already are activating this call might still be useful to
1202 * speed up activation in case there is some hold-off time,
1203 * but we don't want to recheck the condition in that case. */
1204 if (state != UNIT_ACTIVATING &&
1205 !unit_condition_test(u)) {
c1b6628d 1206 log_debug_unit(u->id, "Starting of %s requested but condition failed. Ignoring.", u->id);
52661efd
LP
1207 return -EALREADY;
1208 }
1209
92ab323c 1210 /* Forward to the main object, if we aren't it. */
52990c2e
ZJS
1211 following = unit_following(u);
1212 if (following) {
c1b6628d
ZJS
1213 log_debug_unit(u->id, "Redirecting start request from %s to %s.",
1214 u->id, following->id);
92ab323c
LP
1215 return unit_start(following);
1216 }
1217
877d54e9
LP
1218 unit_status_log_starting_stopping_reloading(u, JOB_START);
1219 unit_status_print_starting_stopping(u, JOB_START);
c6918296 1220
92ab323c
LP
1221 /* If it is stopped, but we cannot start it, then fail */
1222 if (!UNIT_VTABLE(u)->start)
1223 return -EBADR;
1224
87f0e418
LP
1225 /* We don't suppress calls to ->start() here when we are
1226 * already starting, to allow this request to be used as a
1227 * "hurry up" call, for example when the unit is in some "auto
1228 * restart" state where it waits for a holdoff timer to elapse
1229 * before it will start again. */
1230
c1e1601e 1231 unit_add_to_dbus_queue(u);
9e58ff9c 1232
87f0e418
LP
1233 return UNIT_VTABLE(u)->start(u);
1234}
1235
1236bool unit_can_start(Unit *u) {
1237 assert(u);
1238
1239 return !!UNIT_VTABLE(u)->start;
1240}
1241
2528a7a6
LP
1242bool unit_can_isolate(Unit *u) {
1243 assert(u);
1244
1245 return unit_can_start(u) &&
ac155bb8 1246 u->allow_isolate;
2528a7a6
LP
1247}
1248
87f0e418
LP
1249/* Errors:
1250 * -EBADR: This unit type does not support stopping.
1251 * -EALREADY: Unit is already stopped.
1252 * -EAGAIN: An operation is already in progress. Retry later.
1253 */
1254int unit_stop(Unit *u) {
1255 UnitActiveState state;
92ab323c 1256 Unit *following;
87f0e418
LP
1257
1258 assert(u);
1259
87f0e418 1260 state = unit_active_state(u);
fdf20a31 1261 if (UNIT_IS_INACTIVE_OR_FAILED(state))
87f0e418
LP
1262 return -EALREADY;
1263
92ab323c 1264 if ((following = unit_following(u))) {
c1b6628d
ZJS
1265 log_debug_unit(u->id, "Redirecting stop request from %s to %s.",
1266 u->id, following->id);
92ab323c
LP
1267 return unit_stop(following);
1268 }
1269
877d54e9
LP
1270 unit_status_log_starting_stopping_reloading(u, JOB_STOP);
1271 unit_status_print_starting_stopping(u, JOB_STOP);
c6918296 1272
7898b0cf
LP
1273 if (!UNIT_VTABLE(u)->stop)
1274 return -EBADR;
1275
c1e1601e 1276 unit_add_to_dbus_queue(u);
9e58ff9c 1277
87f0e418
LP
1278 return UNIT_VTABLE(u)->stop(u);
1279}
1280
1281/* Errors:
1282 * -EBADR: This unit type does not support reloading.
1283 * -ENOEXEC: Unit is not started.
1284 * -EAGAIN: An operation is already in progress. Retry later.
1285 */
1286int unit_reload(Unit *u) {
1287 UnitActiveState state;
92ab323c 1288 Unit *following;
87f0e418
LP
1289
1290 assert(u);
1291
ac155bb8 1292 if (u->load_state != UNIT_LOADED)
6124958c
LP
1293 return -EINVAL;
1294
87f0e418
LP
1295 if (!unit_can_reload(u))
1296 return -EBADR;
1297
1298 state = unit_active_state(u);
e364ad06 1299 if (state == UNIT_RELOADING)
87f0e418
LP
1300 return -EALREADY;
1301
e364ad06 1302 if (state != UNIT_ACTIVE)
87f0e418
LP
1303 return -ENOEXEC;
1304
e48614c4
ZJS
1305 following = unit_following(u);
1306 if (following) {
c1b6628d
ZJS
1307 log_debug_unit(u->id, "Redirecting reload request from %s to %s.",
1308 u->id, following->id);
92ab323c
LP
1309 return unit_reload(following);
1310 }
1311
877d54e9
LP
1312 unit_status_log_starting_stopping_reloading(u, JOB_RELOAD);
1313
c1e1601e 1314 unit_add_to_dbus_queue(u);
87f0e418
LP
1315 return UNIT_VTABLE(u)->reload(u);
1316}
1317
1318bool unit_can_reload(Unit *u) {
1319 assert(u);
1320
1321 if (!UNIT_VTABLE(u)->reload)
1322 return false;
1323
1324 if (!UNIT_VTABLE(u)->can_reload)
1325 return true;
1326
1327 return UNIT_VTABLE(u)->can_reload(u);
1328}
1329
b4a16b7b 1330static void unit_check_unneeded(Unit *u) {
f3bff0eb
LP
1331 Iterator i;
1332 Unit *other;
1333
1334 assert(u);
1335
1336 /* If this service shall be shut down when unneeded then do
1337 * so. */
1338
ac155bb8 1339 if (!u->stop_when_unneeded)
f3bff0eb
LP
1340 return;
1341
1342 if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u)))
1343 return;
1344
ac155bb8 1345 SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY], i)
31afa0a4 1346 if (unit_active_or_pending(other))
f3bff0eb
LP
1347 return;
1348
ac155bb8 1349 SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY_OVERRIDABLE], i)
31afa0a4 1350 if (unit_active_or_pending(other))
f3bff0eb
LP
1351 return;
1352
ac155bb8 1353 SET_FOREACH(other, u->dependencies[UNIT_WANTED_BY], i)
31afa0a4 1354 if (unit_active_or_pending(other))
f3bff0eb
LP
1355 return;
1356
ac155bb8 1357 SET_FOREACH(other, u->dependencies[UNIT_BOUND_BY], i)
31afa0a4 1358 if (unit_active_or_pending(other))
b81884e7
LP
1359 return;
1360
c1b6628d 1361 log_info_unit(u->id, "Service %s is not needed anymore. Stopping.", u->id);
f3bff0eb
LP
1362
1363 /* Ok, nobody needs us anymore. Sniff. Then let's commit suicide */
ac155bb8 1364 manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, true, NULL, NULL);
f3bff0eb
LP
1365}
1366
87f0e418
LP
1367static void retroactively_start_dependencies(Unit *u) {
1368 Iterator i;
1369 Unit *other;
1370
1371 assert(u);
1372 assert(UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u)));
1373
ac155bb8
MS
1374 SET_FOREACH(other, u->dependencies[UNIT_REQUIRES], i)
1375 if (!set_get(u->dependencies[UNIT_AFTER], other) &&
b81884e7 1376 !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
ac155bb8 1377 manager_add_job(u->manager, JOB_START, other, JOB_REPLACE, true, NULL, NULL);
b81884e7 1378
7f2cddae 1379 SET_FOREACH(other, u->dependencies[UNIT_BINDS_TO], i)
ac155bb8 1380 if (!set_get(u->dependencies[UNIT_AFTER], other) &&
b81884e7 1381 !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
ac155bb8 1382 manager_add_job(u->manager, JOB_START, other, JOB_REPLACE, true, NULL, NULL);
87f0e418 1383
ac155bb8
MS
1384 SET_FOREACH(other, u->dependencies[UNIT_REQUIRES_OVERRIDABLE], i)
1385 if (!set_get(u->dependencies[UNIT_AFTER], other) &&
b81884e7 1386 !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
ac155bb8 1387 manager_add_job(u->manager, JOB_START, other, JOB_FAIL, false, NULL, NULL);
87f0e418 1388
ac155bb8
MS
1389 SET_FOREACH(other, u->dependencies[UNIT_WANTS], i)
1390 if (!set_get(u->dependencies[UNIT_AFTER], other) &&
b81884e7 1391 !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
ac155bb8 1392 manager_add_job(u->manager, JOB_START, other, JOB_FAIL, false, NULL, NULL);
87f0e418 1393
ac155bb8 1394 SET_FOREACH(other, u->dependencies[UNIT_CONFLICTS], i)
b81884e7 1395 if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
ac155bb8 1396 manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, true, NULL, NULL);
69dd2852 1397
ac155bb8 1398 SET_FOREACH(other, u->dependencies[UNIT_CONFLICTED_BY], i)
b81884e7 1399 if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
ac155bb8 1400 manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, true, NULL, NULL);
87f0e418
LP
1401}
1402
1403static void retroactively_stop_dependencies(Unit *u) {
1404 Iterator i;
1405 Unit *other;
1406
1407 assert(u);
1408 assert(UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(u)));
1409
b81884e7 1410 /* Pull down units which are bound to us recursively if enabled */
ac155bb8 1411 SET_FOREACH(other, u->dependencies[UNIT_BOUND_BY], i)
b81884e7 1412 if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
ac155bb8 1413 manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, true, NULL, NULL);
cd0504d0
MS
1414}
1415
1416static void check_unneeded_dependencies(Unit *u) {
1417 Iterator i;
1418 Unit *other;
1419
1420 assert(u);
1421 assert(UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(u)));
f3bff0eb
LP
1422
1423 /* Garbage collect services that might not be needed anymore, if enabled */
ac155bb8 1424 SET_FOREACH(other, u->dependencies[UNIT_REQUIRES], i)
87f0e418 1425 if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
b4a16b7b 1426 unit_check_unneeded(other);
ac155bb8 1427 SET_FOREACH(other, u->dependencies[UNIT_REQUIRES_OVERRIDABLE], i)
f3bff0eb 1428 if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
b4a16b7b 1429 unit_check_unneeded(other);
ac155bb8 1430 SET_FOREACH(other, u->dependencies[UNIT_WANTS], i)
f3bff0eb 1431 if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
b4a16b7b 1432 unit_check_unneeded(other);
ac155bb8 1433 SET_FOREACH(other, u->dependencies[UNIT_REQUISITE], i)
f3bff0eb 1434 if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
b4a16b7b 1435 unit_check_unneeded(other);
ac155bb8 1436 SET_FOREACH(other, u->dependencies[UNIT_REQUISITE_OVERRIDABLE], i)
f3bff0eb 1437 if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
b4a16b7b 1438 unit_check_unneeded(other);
7f2cddae 1439 SET_FOREACH(other, u->dependencies[UNIT_BINDS_TO], i)
b81884e7
LP
1440 if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
1441 unit_check_unneeded(other);
87f0e418
LP
1442}
1443
3ecaa09b 1444void unit_start_on_failure(Unit *u) {
c0daa706
LP
1445 Unit *other;
1446 Iterator i;
1447
1448 assert(u);
1449
ac155bb8 1450 if (set_size(u->dependencies[UNIT_ON_FAILURE]) <= 0)
222ae6a8
LP
1451 return;
1452
c1b6628d 1453 log_info_unit(u->id, "Triggering OnFailure= dependencies of %s.", u->id);
222ae6a8 1454
ac155bb8 1455 SET_FOREACH(other, u->dependencies[UNIT_ON_FAILURE], i) {
222ae6a8
LP
1456 int r;
1457
d420282b 1458 r = manager_add_job(u->manager, JOB_START, other, u->on_failure_job_mode, true, NULL, NULL);
c1b6628d
ZJS
1459 if (r < 0)
1460 log_error_unit(u->id, "Failed to enqueue OnFailure= job: %s", strerror(-r));
222ae6a8 1461 }
c0daa706
LP
1462}
1463
3ecaa09b
LP
1464void unit_trigger_notify(Unit *u) {
1465 Unit *other;
1466 Iterator i;
1467
1468 assert(u);
1469
1470 SET_FOREACH(other, u->dependencies[UNIT_TRIGGERED_BY], i)
1471 if (UNIT_VTABLE(other)->trigger_notify)
1472 UNIT_VTABLE(other)->trigger_notify(other, u);
1473}
1474
e2f3b44c 1475void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_success) {
546ac4f0 1476 Manager *m;
7e6e7b06 1477 bool unexpected;
a096ed36 1478
87f0e418
LP
1479 assert(u);
1480 assert(os < _UNIT_ACTIVE_STATE_MAX);
1481 assert(ns < _UNIT_ACTIVE_STATE_MAX);
87f0e418 1482
8e471ccd
LP
1483 /* Note that this is called for all low-level state changes,
1484 * even if they might map to the same high-level
1485 * UnitActiveState! That means that ns == os is OK an expected
c5315881 1486 * behavior here. For example: if a mount point is remounted
cd6d0a45 1487 * this function will be called too! */
87f0e418 1488
546ac4f0
MS
1489 m = u->manager;
1490
1491 if (m->n_reloading <= 0) {
bdbf9951 1492 dual_timestamp ts;
173e3821 1493
bdbf9951 1494 dual_timestamp_get(&ts);
173e3821 1495
bdbf9951 1496 if (UNIT_IS_INACTIVE_OR_FAILED(os) && !UNIT_IS_INACTIVE_OR_FAILED(ns))
ac155bb8 1497 u->inactive_exit_timestamp = ts;
bdbf9951 1498 else if (!UNIT_IS_INACTIVE_OR_FAILED(os) && UNIT_IS_INACTIVE_OR_FAILED(ns))
ac155bb8 1499 u->inactive_enter_timestamp = ts;
bdbf9951
LP
1500
1501 if (!UNIT_IS_ACTIVE_OR_RELOADING(os) && UNIT_IS_ACTIVE_OR_RELOADING(ns))
ac155bb8 1502 u->active_enter_timestamp = ts;
bdbf9951 1503 else if (UNIT_IS_ACTIVE_OR_RELOADING(os) && !UNIT_IS_ACTIVE_OR_RELOADING(ns))
ac155bb8 1504 u->active_exit_timestamp = ts;
bdbf9951 1505 }
87f0e418 1506
fdf20a31 1507 if (UNIT_IS_INACTIVE_OR_FAILED(ns))
4ad49000 1508 unit_destroy_cgroup(u);
fb385181 1509
9cd86184
OB
1510 /* Note that this doesn't apply to RemainAfterExit services exiting
1511 * sucessfully, since there's no change of state in that case. Which is
1512 * why it is handled in service_set_state() */
7ed9f6cd
MS
1513 if (UNIT_IS_INACTIVE_OR_FAILED(os) != UNIT_IS_INACTIVE_OR_FAILED(ns)) {
1514 ExecContext *ec = unit_get_exec_context(u);
1515 if (ec && exec_context_may_touch_console(ec)) {
31a7eb86
ZJS
1516 if (UNIT_IS_INACTIVE_OR_FAILED(ns)) {
1517 m->n_on_console --;
1518
1519 if (m->n_on_console == 0)
1520 /* unset no_console_output flag, since the console is free */
2f38577f 1521 m->no_console_output = false;
31a7eb86
ZJS
1522 } else
1523 m->n_on_console ++;
7ed9f6cd
MS
1524 }
1525 }
1526
ac155bb8 1527 if (u->job) {
7e6e7b06 1528 unexpected = false;
87f0e418 1529
ac155bb8 1530 if (u->job->state == JOB_WAITING)
87f0e418
LP
1531
1532 /* So we reached a different state for this
1533 * job. Let's see if we can run it now if it
1534 * failed previously due to EAGAIN. */
ac155bb8 1535 job_add_to_run_queue(u->job);
87f0e418 1536
b410e6b9 1537 /* Let's check whether this state change constitutes a
35b8ca3a 1538 * finished job, or maybe contradicts a running job and
b410e6b9 1539 * hence needs to invalidate jobs. */
87f0e418 1540
ac155bb8 1541 switch (u->job->type) {
87f0e418 1542
b410e6b9
LP
1543 case JOB_START:
1544 case JOB_VERIFY_ACTIVE:
87f0e418 1545
b410e6b9 1546 if (UNIT_IS_ACTIVE_OR_RELOADING(ns))
5273510e 1547 job_finish_and_invalidate(u->job, JOB_DONE, true);
ac155bb8 1548 else if (u->job->state == JOB_RUNNING && ns != UNIT_ACTIVATING) {
b410e6b9 1549 unexpected = true;
41b02ec7 1550
fdf20a31 1551 if (UNIT_IS_INACTIVE_OR_FAILED(ns))
5273510e 1552 job_finish_and_invalidate(u->job, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE, true);
b410e6b9 1553 }
87f0e418 1554
b410e6b9 1555 break;
87f0e418 1556
b410e6b9
LP
1557 case JOB_RELOAD:
1558 case JOB_RELOAD_OR_START:
87f0e418 1559
ac155bb8 1560 if (u->job->state == JOB_RUNNING) {
a096ed36 1561 if (ns == UNIT_ACTIVE)
5273510e 1562 job_finish_and_invalidate(u->job, reload_success ? JOB_DONE : JOB_FAILED, true);
032ff4af 1563 else if (ns != UNIT_ACTIVATING && ns != UNIT_RELOADING) {
a096ed36 1564 unexpected = true;
41b02ec7 1565
fdf20a31 1566 if (UNIT_IS_INACTIVE_OR_FAILED(ns))
5273510e 1567 job_finish_and_invalidate(u->job, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE, true);
a096ed36 1568 }
b410e6b9 1569 }
87f0e418 1570
b410e6b9 1571 break;
87f0e418 1572
b410e6b9
LP
1573 case JOB_STOP:
1574 case JOB_RESTART:
1575 case JOB_TRY_RESTART:
87f0e418 1576
fdf20a31 1577 if (UNIT_IS_INACTIVE_OR_FAILED(ns))
5273510e 1578 job_finish_and_invalidate(u->job, JOB_DONE, true);
ac155bb8 1579 else if (u->job->state == JOB_RUNNING && ns != UNIT_DEACTIVATING) {
b410e6b9 1580 unexpected = true;
5273510e 1581 job_finish_and_invalidate(u->job, JOB_FAILED, true);
b410e6b9 1582 }
87f0e418 1583
b410e6b9 1584 break;
87f0e418 1585
b410e6b9
LP
1586 default:
1587 assert_not_reached("Job type unknown");
87f0e418 1588 }
87f0e418 1589
7e6e7b06
LP
1590 } else
1591 unexpected = true;
1592
546ac4f0 1593 if (m->n_reloading <= 0) {
f3bff0eb 1594
bdbf9951
LP
1595 /* If this state change happened without being
1596 * requested by a job, then let's retroactively start
1597 * or stop dependencies. We skip that step when
1598 * deserializing, since we don't want to create any
1599 * additional jobs just because something is already
1600 * activated. */
1601
1602 if (unexpected) {
1603 if (UNIT_IS_INACTIVE_OR_FAILED(os) && UNIT_IS_ACTIVE_OR_ACTIVATING(ns))
1604 retroactively_start_dependencies(u);
1605 else if (UNIT_IS_ACTIVE_OR_ACTIVATING(os) && UNIT_IS_INACTIVE_OR_DEACTIVATING(ns))
1606 retroactively_stop_dependencies(u);
1607 }
5de9682c 1608
cd0504d0
MS
1609 /* stop unneeded units regardless if going down was expected or not */
1610 if (UNIT_IS_ACTIVE_OR_ACTIVATING(os) && UNIT_IS_INACTIVE_OR_DEACTIVATING(ns))
1611 check_unneeded_dependencies(u);
1612
bdbf9951 1613 if (ns != os && ns == UNIT_FAILED) {
c1b6628d 1614 log_notice_unit(u->id,
fcf8c440 1615 "Unit %s entered failed state.", u->id);
3ecaa09b 1616 unit_start_on_failure(u);
cd6d0a45 1617 }
3b2775c5 1618 }
e537352b 1619
3b2775c5
LP
1620 /* Some names are special */
1621 if (UNIT_IS_ACTIVE_OR_RELOADING(ns)) {
1622
1623 if (unit_has_name(u, SPECIAL_DBUS_SERVICE))
1624 /* The bus just might have become available,
1625 * hence try to connect to it, if we aren't
1626 * yet connected. */
546ac4f0 1627 bus_init(m, true);
3b2775c5 1628
ac155bb8 1629 if (u->type == UNIT_SERVICE &&
3b2775c5 1630 !UNIT_IS_ACTIVE_OR_RELOADING(os) &&
546ac4f0 1631 m->n_reloading <= 0) {
3b2775c5 1632 /* Write audit record if we have just finished starting up */
546ac4f0 1633 manager_send_unit_audit(m, u, AUDIT_SERVICE_START, true);
ac155bb8 1634 u->in_audit = true;
3b2775c5 1635 }
e983b760 1636
3b2775c5 1637 if (!UNIT_IS_ACTIVE_OR_RELOADING(os))
546ac4f0 1638 manager_send_unit_plymouth(m, u);
bdbf9951 1639
3b2775c5 1640 } else {
bdbf9951 1641
3b2775c5
LP
1642 /* We don't care about D-Bus here, since we'll get an
1643 * asynchronous notification for it anyway. */
cd6d0a45 1644
ac155bb8 1645 if (u->type == UNIT_SERVICE &&
3b2775c5
LP
1646 UNIT_IS_INACTIVE_OR_FAILED(ns) &&
1647 !UNIT_IS_INACTIVE_OR_FAILED(os) &&
546ac4f0 1648 m->n_reloading <= 0) {
4927fcae 1649
3b2775c5
LP
1650 /* Hmm, if there was no start record written
1651 * write it now, so that we always have a nice
1652 * pair */
ac155bb8 1653 if (!u->in_audit) {
546ac4f0 1654 manager_send_unit_audit(m, u, AUDIT_SERVICE_START, ns == UNIT_INACTIVE);
cd6d0a45 1655
3b2775c5 1656 if (ns == UNIT_INACTIVE)
546ac4f0 1657 manager_send_unit_audit(m, u, AUDIT_SERVICE_STOP, true);
3b2775c5
LP
1658 } else
1659 /* Write audit record if we have just finished shutting down */
546ac4f0 1660 manager_send_unit_audit(m, u, AUDIT_SERVICE_STOP, ns == UNIT_INACTIVE);
bdbf9951 1661
ac155bb8 1662 u->in_audit = false;
cd6d0a45 1663 }
f278026d
LP
1664 }
1665
546ac4f0 1666 manager_recheck_journal(m);
3ecaa09b 1667 unit_trigger_notify(u);
3b2775c5 1668
f3bff0eb
LP
1669 /* Maybe we finished startup and are now ready for being
1670 * stopped because unneeded? */
bf6dcfa6
OS
1671 if (u->manager->n_reloading <= 0)
1672 unit_check_unneeded(u);
c1e1601e
LP
1673
1674 unit_add_to_dbus_queue(u);
701cc384 1675 unit_add_to_gc_queue(u);
87f0e418
LP
1676}
1677
87f0e418
LP
1678int unit_watch_pid(Unit *u, pid_t pid) {
1679 assert(u);
1680 assert(pid >= 1);
1681
05e343b7
LP
1682 /* Watch a specific PID. We only support one unit watching
1683 * each PID for now. */
1684
ac155bb8 1685 return hashmap_put(u->manager->watch_pids, LONG_TO_PTR(pid), u);
87f0e418
LP
1686}
1687
1688void unit_unwatch_pid(Unit *u, pid_t pid) {
1689 assert(u);
1690 assert(pid >= 1);
1691
ac155bb8 1692 hashmap_remove_value(u->manager->watch_pids, LONG_TO_PTR(pid), u);
87f0e418
LP
1693}
1694
87f0e418
LP
1695bool unit_job_is_applicable(Unit *u, JobType j) {
1696 assert(u);
1697 assert(j >= 0 && j < _JOB_TYPE_MAX);
1698
1699 switch (j) {
1700
1701 case JOB_VERIFY_ACTIVE:
1702 case JOB_START:
57339f47 1703 case JOB_STOP:
e0209d83 1704 case JOB_NOP:
87f0e418
LP
1705 return true;
1706
87f0e418
LP
1707 case JOB_RESTART:
1708 case JOB_TRY_RESTART:
1709 return unit_can_start(u);
1710
1711 case JOB_RELOAD:
1712 return unit_can_reload(u);
1713
1714 case JOB_RELOAD_OR_START:
1715 return unit_can_reload(u) && unit_can_start(u);
1716
1717 default:
1718 assert_not_reached("Invalid job type");
1719 }
1720}
1721
701cc384 1722int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_reference) {
87f0e418
LP
1723
1724 static const UnitDependency inverse_table[_UNIT_DEPENDENCY_MAX] = {
1725 [UNIT_REQUIRES] = UNIT_REQUIRED_BY,
9e2f7c11 1726 [UNIT_REQUIRES_OVERRIDABLE] = UNIT_REQUIRED_BY_OVERRIDABLE,
87f0e418
LP
1727 [UNIT_WANTS] = UNIT_WANTED_BY,
1728 [UNIT_REQUISITE] = UNIT_REQUIRED_BY,
9e2f7c11 1729 [UNIT_REQUISITE_OVERRIDABLE] = UNIT_REQUIRED_BY_OVERRIDABLE,
7f2cddae 1730 [UNIT_BINDS_TO] = UNIT_BOUND_BY,
60649f17 1731 [UNIT_PART_OF] = UNIT_CONSISTS_OF,
87f0e418 1732 [UNIT_REQUIRED_BY] = _UNIT_DEPENDENCY_INVALID,
9e2f7c11 1733 [UNIT_REQUIRED_BY_OVERRIDABLE] = _UNIT_DEPENDENCY_INVALID,
87f0e418 1734 [UNIT_WANTED_BY] = _UNIT_DEPENDENCY_INVALID,
7f2cddae 1735 [UNIT_BOUND_BY] = UNIT_BINDS_TO,
60649f17 1736 [UNIT_CONSISTS_OF] = UNIT_PART_OF,
69dd2852
LP
1737 [UNIT_CONFLICTS] = UNIT_CONFLICTED_BY,
1738 [UNIT_CONFLICTED_BY] = UNIT_CONFLICTS,
87f0e418 1739 [UNIT_BEFORE] = UNIT_AFTER,
701cc384 1740 [UNIT_AFTER] = UNIT_BEFORE,
5de9682c 1741 [UNIT_ON_FAILURE] = _UNIT_DEPENDENCY_INVALID,
701cc384 1742 [UNIT_REFERENCES] = UNIT_REFERENCED_BY,
57020a3a
LP
1743 [UNIT_REFERENCED_BY] = UNIT_REFERENCES,
1744 [UNIT_TRIGGERS] = UNIT_TRIGGERED_BY,
4dcc1cb4 1745 [UNIT_TRIGGERED_BY] = UNIT_TRIGGERS,
7f2cddae 1746 [UNIT_PROPAGATES_RELOAD_TO] = UNIT_RELOAD_PROPAGATED_FROM,
85e9a101 1747 [UNIT_RELOAD_PROPAGATED_FROM] = UNIT_PROPAGATES_RELOAD_TO,
87f0e418 1748 };
701cc384 1749 int r, q = 0, v = 0, w = 0;
87f0e418
LP
1750
1751 assert(u);
1752 assert(d >= 0 && d < _UNIT_DEPENDENCY_MAX);
87f0e418
LP
1753 assert(other);
1754
9f151f29
LP
1755 u = unit_follow_merge(u);
1756 other = unit_follow_merge(other);
1757
87f0e418
LP
1758 /* We won't allow dependencies on ourselves. We will not
1759 * consider them an error however. */
1760 if (u == other)
1761 return 0;
1762
ac155bb8 1763 if ((r = set_ensure_allocated(&u->dependencies[d], trivial_hash_func, trivial_compare_func)) < 0)
87f0e418
LP
1764 return r;
1765
5de9682c 1766 if (inverse_table[d] != _UNIT_DEPENDENCY_INVALID)
ac155bb8 1767 if ((r = set_ensure_allocated(&other->dependencies[inverse_table[d]], trivial_hash_func, trivial_compare_func)) < 0)
5de9682c
LP
1768 return r;
1769
701cc384 1770 if (add_reference)
ac155bb8
MS
1771 if ((r = set_ensure_allocated(&u->dependencies[UNIT_REFERENCES], trivial_hash_func, trivial_compare_func)) < 0 ||
1772 (r = set_ensure_allocated(&other->dependencies[UNIT_REFERENCED_BY], trivial_hash_func, trivial_compare_func)) < 0)
701cc384 1773 return r;
87f0e418 1774
ac155bb8 1775 if ((q = set_put(u->dependencies[d], other)) < 0)
701cc384 1776 return q;
87f0e418 1777
5de9682c 1778 if (inverse_table[d] != _UNIT_DEPENDENCY_INVALID)
ac155bb8 1779 if ((v = set_put(other->dependencies[inverse_table[d]], u)) < 0) {
5de9682c
LP
1780 r = v;
1781 goto fail;
1782 }
701cc384
LP
1783
1784 if (add_reference) {
ac155bb8 1785 if ((w = set_put(u->dependencies[UNIT_REFERENCES], other)) < 0) {
701cc384
LP
1786 r = w;
1787 goto fail;
1788 }
1789
ac155bb8 1790 if ((r = set_put(other->dependencies[UNIT_REFERENCED_BY], u)) < 0)
701cc384 1791 goto fail;
87f0e418
LP
1792 }
1793
c1e1601e 1794 unit_add_to_dbus_queue(u);
87f0e418 1795 return 0;
701cc384
LP
1796
1797fail:
1798 if (q > 0)
ac155bb8 1799 set_remove(u->dependencies[d], other);
701cc384
LP
1800
1801 if (v > 0)
ac155bb8 1802 set_remove(other->dependencies[inverse_table[d]], u);
701cc384
LP
1803
1804 if (w > 0)
ac155bb8 1805 set_remove(u->dependencies[UNIT_REFERENCES], other);
701cc384
LP
1806
1807 return r;
87f0e418 1808}
0301abf4 1809
2c966c03
LP
1810int unit_add_two_dependencies(Unit *u, UnitDependency d, UnitDependency e, Unit *other, bool add_reference) {
1811 int r;
1812
1813 assert(u);
1814
1815 if ((r = unit_add_dependency(u, d, other, add_reference)) < 0)
1816 return r;
1817
1818 if ((r = unit_add_dependency(u, e, other, add_reference)) < 0)
1819 return r;
1820
1821 return 0;
1822}
1823
9e2f7c11
LP
1824static const char *resolve_template(Unit *u, const char *name, const char*path, char **p) {
1825 char *s;
1826
1827 assert(u);
1828 assert(name || path);
8afbb8e1 1829 assert(p);
9e2f7c11
LP
1830
1831 if (!name)
9eb977db 1832 name = path_get_file_name(path);
9e2f7c11
LP
1833
1834 if (!unit_name_is_template(name)) {
1835 *p = NULL;
1836 return name;
1837 }
1838
ac155bb8
MS
1839 if (u->instance)
1840 s = unit_name_replace_instance(name, u->instance);
9e2f7c11 1841 else {
ae018d9b 1842 _cleanup_free_ char *i = NULL;
9e2f7c11 1843
8afbb8e1
LP
1844 i = unit_name_to_prefix(u->id);
1845 if (!i)
9e2f7c11
LP
1846 return NULL;
1847
1848 s = unit_name_replace_instance(name, i);
9e2f7c11
LP
1849 }
1850
1851 if (!s)
1852 return NULL;
1853
1854 *p = s;
1855 return s;
1856}
1857
701cc384 1858int unit_add_dependency_by_name(Unit *u, UnitDependency d, const char *name, const char *path, bool add_reference) {
09b6b09f
LP
1859 Unit *other;
1860 int r;
8afbb8e1 1861 _cleanup_free_ char *s = NULL;
09b6b09f 1862
9e2f7c11
LP
1863 assert(u);
1864 assert(name || path);
09b6b09f 1865
8afbb8e1
LP
1866 name = resolve_template(u, name, path, &s);
1867 if (!name)
9e2f7c11 1868 return -ENOMEM;
09b6b09f 1869
8afbb8e1
LP
1870 r = manager_load_unit(u->manager, name, path, NULL, &other);
1871 if (r < 0)
1872 return r;
9e2f7c11 1873
8afbb8e1 1874 return unit_add_dependency(u, d, other, add_reference);
09b6b09f
LP
1875}
1876
2c966c03
LP
1877int unit_add_two_dependencies_by_name(Unit *u, UnitDependency d, UnitDependency e, const char *name, const char *path, bool add_reference) {
1878 Unit *other;
1879 int r;
68eda4bd 1880 _cleanup_free_ char *s = NULL;
2c966c03
LP
1881
1882 assert(u);
1883 assert(name || path);
1884
1885 if (!(name = resolve_template(u, name, path, &s)))
1886 return -ENOMEM;
1887
ac155bb8 1888 if ((r = manager_load_unit(u->manager, name, path, NULL, &other)) < 0)
68eda4bd 1889 return r;
2c966c03
LP
1890
1891 r = unit_add_two_dependencies(u, d, e, other, add_reference);
1892
2c966c03
LP
1893 return r;
1894}
1895
701cc384 1896int unit_add_dependency_by_name_inverse(Unit *u, UnitDependency d, const char *name, const char *path, bool add_reference) {
bd77d0fc
LP
1897 Unit *other;
1898 int r;
68eda4bd 1899 _cleanup_free_ char *s = NULL;
bd77d0fc 1900
9e2f7c11
LP
1901 assert(u);
1902 assert(name || path);
bd77d0fc 1903
9e2f7c11
LP
1904 if (!(name = resolve_template(u, name, path, &s)))
1905 return -ENOMEM;
bd77d0fc 1906
ac155bb8 1907 if ((r = manager_load_unit(u->manager, name, path, NULL, &other)) < 0)
68eda4bd 1908 return r;
9e2f7c11 1909
701cc384 1910 r = unit_add_dependency(other, d, u, add_reference);
9e2f7c11 1911
9e2f7c11 1912 return r;
bd77d0fc
LP
1913}
1914
2c966c03
LP
1915int unit_add_two_dependencies_by_name_inverse(Unit *u, UnitDependency d, UnitDependency e, const char *name, const char *path, bool add_reference) {
1916 Unit *other;
1917 int r;
68eda4bd 1918 _cleanup_free_ char *s = NULL;
2c966c03
LP
1919
1920 assert(u);
1921 assert(name || path);
1922
1923 if (!(name = resolve_template(u, name, path, &s)))
1924 return -ENOMEM;
1925
ac155bb8 1926 if ((r = manager_load_unit(u->manager, name, path, NULL, &other)) < 0)
68eda4bd 1927 return r;
2c966c03
LP
1928
1929 if ((r = unit_add_two_dependencies(other, d, e, u, add_reference)) < 0)
68eda4bd 1930 return r;
2c966c03 1931
2c966c03
LP
1932 return r;
1933}
1934
0301abf4 1935int set_unit_path(const char *p) {
26d04f86 1936 _cleanup_free_ char *c = NULL;
0301abf4
LP
1937
1938 /* This is mostly for debug purposes */
26d04f86
LP
1939 c = path_make_absolute_cwd(p);
1940 if (setenv("SYSTEMD_UNIT_PATH", c, 0) < 0)
1941 return -errno;
0301abf4
LP
1942
1943 return 0;
1944}
88066b3a 1945
ea430986 1946char *unit_dbus_path(Unit *u) {
ea430986
LP
1947 assert(u);
1948
ac155bb8 1949 if (!u->id)
04ade7d2
LP
1950 return NULL;
1951
48899192 1952 return unit_dbus_path_from_name(u->id);
ea430986
LP
1953}
1954
41f9172f 1955char *unit_default_cgroup_path(Unit *u) {
d7bd3de0 1956 _cleanup_free_ char *escaped = NULL, *slice = NULL;
a016b922 1957 int r;
5954c074 1958
013b87c0
LP
1959 assert(u);
1960
4ad49000
LP
1961 if (unit_has_name(u, SPECIAL_ROOT_SLICE))
1962 return strdup(u->manager->cgroup_root);
1963
1964 if (UNIT_ISSET(u->slice) && !unit_has_name(UNIT_DEREF(u->slice), SPECIAL_ROOT_SLICE)) {
a016b922
LP
1965 r = cg_slice_to_path(UNIT_DEREF(u->slice)->id, &slice);
1966 if (r < 0)
1967 return NULL;
1968 }
1969
d7bd3de0
LP
1970 escaped = cg_escape(u->id);
1971 if (!escaped)
5954c074
LP
1972 return NULL;
1973
d7bd3de0
LP
1974 if (slice)
1975 return strjoin(u->manager->cgroup_root, "/", slice, "/", escaped, NULL);
1976 else
1977 return strjoin(u->manager->cgroup_root, "/", escaped, NULL);
013b87c0
LP
1978}
1979
a016b922 1980int unit_add_default_slice(Unit *u) {
a8833944
LP
1981 _cleanup_free_ char *b = NULL;
1982 const char *slice_name;
a016b922
LP
1983 Unit *slice;
1984 int r;
1985
1986 assert(u);
1987
9444b1f2 1988 if (UNIT_ISSET(u->slice))
a016b922
LP
1989 return 0;
1990
4ad49000 1991 if (!unit_get_cgroup_context(u))
a016b922
LP
1992 return 0;
1993
a8833944
LP
1994 if (u->instance) {
1995 _cleanup_free_ char *prefix = NULL, *escaped = NULL;
68eda4bd 1996
a8833944
LP
1997 /* Implicitly place all instantiated units in their
1998 * own per-template slice */
1999
2000 prefix = unit_name_to_prefix(u->id);
2001 if (!prefix)
2002 return -ENOMEM;
2003
2004 /* The prefix is already escaped, but it might include
2005 * "-" which has a special meaning for slice units,
2006 * hence escape it here extra. */
2007 escaped = strreplace(prefix, "-", "\\x2d");
2008 if (!escaped)
2009 return -ENOMEM;
2010
2011 if (u->manager->running_as == SYSTEMD_SYSTEM)
2012 b = strjoin("system-", escaped, ".slice", NULL);
2013 else
2014 b = strappend(escaped, ".slice");
2015 if (!b)
2016 return -ENOMEM;
2017
2018 slice_name = b;
2019 } else
2020 slice_name =
2021 u->manager->running_as == SYSTEMD_SYSTEM
2022 ? SPECIAL_SYSTEM_SLICE
2023 : SPECIAL_ROOT_SLICE;
2024
2025 r = manager_load_unit(u->manager, slice_name, NULL, NULL, &slice);
a016b922
LP
2026 if (r < 0)
2027 return r;
2028
2029 unit_ref_set(&u->slice, slice);
2030 return 0;
2031}
2032
9444b1f2
LP
2033const char *unit_slice_name(Unit *u) {
2034 assert(u);
2035
2036 if (!UNIT_ISSET(u->slice))
2037 return NULL;
2038
2039 return UNIT_DEREF(u->slice)->id;
2040}
2041
f6ff8c29 2042int unit_load_related_unit(Unit *u, const char *type, Unit **_found) {
78edb35a 2043 _cleanup_free_ char *t = NULL;
f6ff8c29
LP
2044 int r;
2045
2046 assert(u);
2047 assert(type);
2048 assert(_found);
2049
78edb35a
LP
2050 t = unit_name_change_suffix(u->id, type);
2051 if (!t)
f6ff8c29
LP
2052 return -ENOMEM;
2053
2054 assert(!unit_has_name(u, t));
2055
ac155bb8 2056 r = manager_load_unit(u->manager, t, NULL, NULL, _found);
9e2f7c11 2057 assert(r < 0 || *_found != u);
f6ff8c29
LP
2058 return r;
2059}
2060
05e343b7
LP
2061int unit_watch_bus_name(Unit *u, const char *name) {
2062 assert(u);
2063 assert(name);
2064
2065 /* Watch a specific name on the bus. We only support one unit
2066 * watching each name for now. */
2067
ac155bb8 2068 return hashmap_put(u->manager->watch_bus, name, u);
05e343b7
LP
2069}
2070
2071void unit_unwatch_bus_name(Unit *u, const char *name) {
2072 assert(u);
2073 assert(name);
2074
ac155bb8 2075 hashmap_remove_value(u->manager->watch_bus, name, u);
05e343b7
LP
2076}
2077
a16e1123
LP
2078bool unit_can_serialize(Unit *u) {
2079 assert(u);
2080
2081 return UNIT_VTABLE(u)->serialize && UNIT_VTABLE(u)->deserialize_item;
2082}
2083
6b78f9b4 2084int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) {
a16e1123
LP
2085 int r;
2086
2087 assert(u);
2088 assert(f);
2089 assert(fds);
2090
2091 if (!unit_can_serialize(u))
2092 return 0;
2093
6fa48533
LP
2094 r = UNIT_VTABLE(u)->serialize(u, f, fds);
2095 if (r < 0)
a16e1123
LP
2096 return r;
2097
cca098b0 2098
6b78f9b4
LP
2099 if (serialize_jobs) {
2100 if (u->job) {
2101 fprintf(f, "job\n");
2102 job_serialize(u->job, f, fds);
2103 }
2104
2105 if (u->nop_job) {
2106 fprintf(f, "job\n");
2107 job_serialize(u->nop_job, f, fds);
2108 }
e0209d83
MS
2109 }
2110
ac155bb8
MS
2111 dual_timestamp_serialize(f, "inactive-exit-timestamp", &u->inactive_exit_timestamp);
2112 dual_timestamp_serialize(f, "active-enter-timestamp", &u->active_enter_timestamp);
2113 dual_timestamp_serialize(f, "active-exit-timestamp", &u->active_exit_timestamp);
2114 dual_timestamp_serialize(f, "inactive-enter-timestamp", &u->inactive_enter_timestamp);
2115 dual_timestamp_serialize(f, "condition-timestamp", &u->condition_timestamp);
2791a8f8 2116
ac155bb8
MS
2117 if (dual_timestamp_is_set(&u->condition_timestamp))
2118 unit_serialize_item(u, f, "condition-result", yes_no(u->condition_result));
10717a1a 2119
c2756a68
LP
2120 unit_serialize_item(u, f, "transient", yes_no(u->transient));
2121
2122 if (u->cgroup_path)
2123 unit_serialize_item(u, f, "cgroup", u->cgroup_path);
2124
a16e1123
LP
2125 /* End marker */
2126 fputc('\n', f);
2127 return 0;
2128}
2129
2130void unit_serialize_item_format(Unit *u, FILE *f, const char *key, const char *format, ...) {
2131 va_list ap;
2132
2133 assert(u);
2134 assert(f);
2135 assert(key);
2136 assert(format);
2137
2138 fputs(key, f);
2139 fputc('=', f);
2140
2141 va_start(ap, format);
2142 vfprintf(f, format, ap);
2143 va_end(ap);
2144
2145 fputc('\n', f);
2146}
2147
2148void unit_serialize_item(Unit *u, FILE *f, const char *key, const char *value) {
2149 assert(u);
2150 assert(f);
2151 assert(key);
2152 assert(value);
2153
2154 fprintf(f, "%s=%s\n", key, value);
2155}
2156
2157int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
2158 int r;
2159
2160 assert(u);
2161 assert(f);
2162 assert(fds);
2163
2164 if (!unit_can_serialize(u))
2165 return 0;
2166
2167 for (;;) {
20c03b7b 2168 char line[LINE_MAX], *l, *v;
a16e1123
LP
2169 size_t k;
2170
2171 if (!fgets(line, sizeof(line), f)) {
2172 if (feof(f))
2173 return 0;
2174 return -errno;
2175 }
2176
10f8e83c 2177 char_array_0(line);
a16e1123
LP
2178 l = strstrip(line);
2179
2180 /* End marker */
2181 if (l[0] == 0)
2182 return 0;
2183
2184 k = strcspn(l, "=");
2185
2186 if (l[k] == '=') {
2187 l[k] = 0;
2188 v = l+k+1;
2189 } else
2190 v = l+k;
2191
cca098b0 2192 if (streq(l, "job")) {
39a18c60
MS
2193 if (v[0] == '\0') {
2194 /* new-style serialized job */
2195 Job *j = job_new_raw(u);
2196 if (!j)
2197 return -ENOMEM;
2198
2199 r = job_deserialize(j, f, fds);
2200 if (r < 0) {
2201 job_free(j);
2202 return r;
2203 }
cca098b0 2204
39a18c60
MS
2205 r = hashmap_put(u->manager->jobs, UINT32_TO_PTR(j->id), j);
2206 if (r < 0) {
2207 job_free(j);
2208 return r;
2209 }
e0209d83
MS
2210
2211 r = job_install_deserialized(j);
2212 if (r < 0) {
2213 hashmap_remove(u->manager->jobs, UINT32_TO_PTR(j->id));
2214 job_free(j);
2215 return r;
2216 }
6b19ad24
MS
2217
2218 if (j->state == JOB_RUNNING)
2219 u->manager->n_running_jobs++;
39a18c60
MS
2220 } else {
2221 /* legacy */
2222 JobType type = job_type_from_string(v);
2223 if (type < 0)
2224 log_debug("Failed to parse job type value %s", v);
2225 else
2226 u->deserialized_job = type;
2227 }
cca098b0 2228 continue;
8aaf019b 2229 } else if (streq(l, "inactive-exit-timestamp")) {
ac155bb8 2230 dual_timestamp_deserialize(v, &u->inactive_exit_timestamp);
8aaf019b
LP
2231 continue;
2232 } else if (streq(l, "active-enter-timestamp")) {
ac155bb8 2233 dual_timestamp_deserialize(v, &u->active_enter_timestamp);
8aaf019b
LP
2234 continue;
2235 } else if (streq(l, "active-exit-timestamp")) {
ac155bb8 2236 dual_timestamp_deserialize(v, &u->active_exit_timestamp);
8aaf019b
LP
2237 continue;
2238 } else if (streq(l, "inactive-enter-timestamp")) {
ac155bb8 2239 dual_timestamp_deserialize(v, &u->inactive_enter_timestamp);
8aaf019b 2240 continue;
2791a8f8 2241 } else if (streq(l, "condition-timestamp")) {
ac155bb8 2242 dual_timestamp_deserialize(v, &u->condition_timestamp);
2791a8f8
LP
2243 continue;
2244 } else if (streq(l, "condition-result")) {
2245 int b;
2246
c2756a68
LP
2247 b = parse_boolean(v);
2248 if (b < 0)
2791a8f8
LP
2249 log_debug("Failed to parse condition result value %s", v);
2250 else
ac155bb8 2251 u->condition_result = b;
efbac6d2
LP
2252
2253 continue;
c2756a68
LP
2254
2255 } else if (streq(l, "transient")) {
2256 int b;
2257
2258 b = parse_boolean(v);
2259 if (b < 0)
2260 log_debug("Failed to parse transient bool %s", v);
2261 else
2262 u->transient = b;
2263
2264 continue;
2265 } else if (streq(l, "cgroup")) {
2266 char *s;
2267
2268 s = strdup(v);
f440e1bb 2269 if (!s)
c2756a68
LP
2270 return -ENOMEM;
2271
2272 free(u->cgroup_path);
2273 u->cgroup_path = s;
72673e86 2274
b58b8e11 2275 assert(hashmap_put(u->manager->cgroup_unit, s, u) == 1);
c2756a68 2276 continue;
8aaf019b 2277 }
cca098b0 2278
c2756a68
LP
2279 r = UNIT_VTABLE(u)->deserialize_item(u, l, v, fds);
2280 if (r < 0)
a16e1123
LP
2281 return r;
2282 }
2283}
2284
6e2ef85b
LP
2285int unit_add_node_link(Unit *u, const char *what, bool wants) {
2286 Unit *device;
68eda4bd 2287 _cleanup_free_ char *e = NULL;
6e2ef85b
LP
2288 int r;
2289
2290 assert(u);
2291
2292 if (!what)
2293 return 0;
2294
2295 /* Adds in links to the device node that this unit is based on */
2296
8407a5d0 2297 if (!is_device_path(what))
6e2ef85b
LP
2298 return 0;
2299
35eb6b12
LP
2300 e = unit_name_from_path(what, ".device");
2301 if (!e)
6e2ef85b
LP
2302 return -ENOMEM;
2303
ac155bb8 2304 r = manager_load_unit(u->manager, e, NULL, NULL, &device);
68eda4bd 2305
6e2ef85b
LP
2306 if (r < 0)
2307 return r;
2308
faa368e3
LP
2309 r = unit_add_two_dependencies(u, UNIT_AFTER, UNIT_BINDS_TO, device, true);
2310 if (r < 0)
6e2ef85b
LP
2311 return r;
2312
faa368e3
LP
2313 if (wants) {
2314 r = unit_add_dependency(device, UNIT_WANTS, u, false);
2315 if (r < 0)
6e2ef85b 2316 return r;
faa368e3 2317 }
6e2ef85b
LP
2318
2319 return 0;
2320}
a16e1123 2321
cca098b0
LP
2322int unit_coldplug(Unit *u) {
2323 int r;
2324
2325 assert(u);
2326
2327 if (UNIT_VTABLE(u)->coldplug)
2328 if ((r = UNIT_VTABLE(u)->coldplug(u)) < 0)
2329 return r;
2330
39a18c60
MS
2331 if (u->job) {
2332 r = job_coldplug(u->job);
2333 if (r < 0)
2334 return r;
2335 } else if (u->deserialized_job >= 0) {
2336 /* legacy */
2337 r = manager_add_job(u->manager, u->deserialized_job, u, JOB_IGNORE_REQUIREMENTS, false, NULL, NULL);
2338 if (r < 0)
cca098b0
LP
2339 return r;
2340
ac155bb8 2341 u->deserialized_job = _JOB_TYPE_INVALID;
cca098b0
LP
2342 }
2343
2344 return 0;
2345}
2346
b1e2b33c
CR
2347#pragma GCC diagnostic push
2348#pragma GCC diagnostic ignored "-Wformat-nonliteral"
49b1d377
MS
2349void unit_status_printf(Unit *u, const char *status, const char *unit_status_msg_format) {
2350 manager_status_printf(u->manager, false, status, unit_status_msg_format, unit_description(u));
2351}
b1e2b33c 2352#pragma GCC diagnostic pop
49b1d377 2353
45fb0699 2354bool unit_need_daemon_reload(Unit *u) {
ae7a7182
OS
2355 _cleanup_strv_free_ char **t = NULL;
2356 char **path;
1b64d026 2357 struct stat st;
ae7a7182 2358 unsigned loaded_cnt, current_cnt;
1b64d026 2359
45fb0699
LP
2360 assert(u);
2361
ac155bb8 2362 if (u->fragment_path) {
5f4b19f4 2363 zero(st);
ac155bb8 2364 if (stat(u->fragment_path, &st) < 0)
5f4b19f4
LP
2365 /* What, cannot access this anymore? */
2366 return true;
45fb0699 2367
ac155bb8
MS
2368 if (u->fragment_mtime > 0 &&
2369 timespec_load(&st.st_mtim) != u->fragment_mtime)
5f4b19f4
LP
2370 return true;
2371 }
2372
1b64d026
LP
2373 if (u->source_path) {
2374 zero(st);
2375 if (stat(u->source_path, &st) < 0)
2376 return true;
2377
2378 if (u->source_mtime > 0 &&
2379 timespec_load(&st.st_mtim) != u->source_mtime)
2380 return true;
2381 }
5f4b19f4 2382
ae7a7182
OS
2383 t = unit_find_dropin_paths(u);
2384 loaded_cnt = strv_length(t);
2385 current_cnt = strv_length(u->dropin_paths);
2386
2387 if (loaded_cnt == current_cnt) {
2388 if (loaded_cnt == 0)
2389 return false;
2390
2391 if (strv_overlap(u->dropin_paths, t)) {
2392 STRV_FOREACH(path, u->dropin_paths) {
2393 zero(st);
2394 if (stat(*path, &st) < 0)
2395 return true;
2396
2397 if (u->dropin_mtime > 0 &&
2398 timespec_load(&st.st_mtim) > u->dropin_mtime)
2399 return true;
2400 }
2401
2402 return false;
2403 } else
2404 return true;
2405 } else
2406 return true;
45fb0699
LP
2407}
2408
fdf20a31 2409void unit_reset_failed(Unit *u) {
5632e374
LP
2410 assert(u);
2411
fdf20a31
MM
2412 if (UNIT_VTABLE(u)->reset_failed)
2413 UNIT_VTABLE(u)->reset_failed(u);
5632e374
LP
2414}
2415
a7f241db
LP
2416Unit *unit_following(Unit *u) {
2417 assert(u);
2418
2419 if (UNIT_VTABLE(u)->following)
2420 return UNIT_VTABLE(u)->following(u);
2421
2422 return NULL;
2423}
2424
31afa0a4 2425bool unit_stop_pending(Unit *u) {
18ffdfda
LP
2426 assert(u);
2427
31afa0a4
LP
2428 /* This call does check the current state of the unit. It's
2429 * hence useful to be called from state change calls of the
2430 * unit itself, where the state isn't updated yet. This is
2431 * different from unit_inactive_or_pending() which checks both
2432 * the current state and for a queued job. */
18ffdfda 2433
31afa0a4
LP
2434 return u->job && u->job->type == JOB_STOP;
2435}
2436
2437bool unit_inactive_or_pending(Unit *u) {
2438 assert(u);
2439
2440 /* Returns true if the unit is inactive or going down */
18ffdfda 2441
d956ac29
LP
2442 if (UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(u)))
2443 return true;
2444
31afa0a4 2445 if (unit_stop_pending(u))
18ffdfda
LP
2446 return true;
2447
2448 return false;
2449}
2450
31afa0a4 2451bool unit_active_or_pending(Unit *u) {
f976f3f6
LP
2452 assert(u);
2453
f60c2665 2454 /* Returns true if the unit is active or going up */
f976f3f6
LP
2455
2456 if (UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u)))
2457 return true;
2458
ac155bb8
MS
2459 if (u->job &&
2460 (u->job->type == JOB_START ||
2461 u->job->type == JOB_RELOAD_OR_START ||
2462 u->job->type == JOB_RESTART))
f976f3f6
LP
2463 return true;
2464
2465 return false;
2466}
2467
718db961 2468int unit_kill(Unit *u, KillWho w, int signo, sd_bus_error *error) {
8a0867d6
LP
2469 assert(u);
2470 assert(w >= 0 && w < _KILL_WHO_MAX);
8a0867d6
LP
2471 assert(signo > 0);
2472 assert(signo < _NSIG);
2473
8a0867d6
LP
2474 if (!UNIT_VTABLE(u)->kill)
2475 return -ENOTSUP;
2476
c74f17d9 2477 return UNIT_VTABLE(u)->kill(u, w, signo, error);
8a0867d6
LP
2478}
2479
82659fd7
LP
2480static Set *unit_pid_set(pid_t main_pid, pid_t control_pid) {
2481 Set *pid_set;
2482 int r;
2483
2484 pid_set = set_new(trivial_hash_func, trivial_compare_func);
2485 if (!pid_set)
2486 return NULL;
2487
2488 /* Exclude the main/control pids from being killed via the cgroup */
2489 if (main_pid > 0) {
2490 r = set_put(pid_set, LONG_TO_PTR(main_pid));
2491 if (r < 0)
2492 goto fail;
2493 }
2494
2495 if (control_pid > 0) {
2496 r = set_put(pid_set, LONG_TO_PTR(control_pid));
2497 if (r < 0)
2498 goto fail;
2499 }
2500
2501 return pid_set;
2502
2503fail:
2504 set_free(pid_set);
2505 return NULL;
2506}
2507
d91c34f2
LP
2508int unit_kill_common(
2509 Unit *u,
2510 KillWho who,
2511 int signo,
2512 pid_t main_pid,
2513 pid_t control_pid,
718db961 2514 sd_bus_error *error) {
d91c34f2 2515
814cc562
MS
2516 int r = 0;
2517
2518 if (who == KILL_MAIN && main_pid <= 0) {
2519 if (main_pid < 0)
718db961 2520 sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no main processes", unit_type_to_string(u->type));
814cc562 2521 else
718db961 2522 sd_bus_error_set_const(error, BUS_ERROR_NO_SUCH_PROCESS, "No main process to kill");
814cc562
MS
2523 return -ESRCH;
2524 }
2525
2526 if (who == KILL_CONTROL && control_pid <= 0) {
2527 if (control_pid < 0)
718db961 2528 sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no control processes", unit_type_to_string(u->type));
814cc562 2529 else
718db961 2530 sd_bus_error_set_const(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill");
814cc562
MS
2531 return -ESRCH;
2532 }
2533
2534 if (who == KILL_CONTROL || who == KILL_ALL)
2535 if (control_pid > 0)
2536 if (kill(control_pid, signo) < 0)
2537 r = -errno;
2538
2539 if (who == KILL_MAIN || who == KILL_ALL)
2540 if (main_pid > 0)
2541 if (kill(main_pid, signo) < 0)
2542 r = -errno;
2543
4ad49000 2544 if (who == KILL_ALL && u->cgroup_path) {
814cc562
MS
2545 _cleanup_set_free_ Set *pid_set = NULL;
2546 int q;
2547
82659fd7
LP
2548 /* Exclude the main/control pids from being killed via the cgroup */
2549 pid_set = unit_pid_set(main_pid, control_pid);
814cc562
MS
2550 if (!pid_set)
2551 return -ENOMEM;
2552
4ad49000 2553 q = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, signo, false, true, false, pid_set);
814cc562
MS
2554 if (q < 0 && q != -EAGAIN && q != -ESRCH && q != -ENOENT)
2555 r = q;
2556 }
2557
2558 return r;
2559}
2560
6210e7fc
LP
2561int unit_following_set(Unit *u, Set **s) {
2562 assert(u);
2563 assert(s);
2564
2565 if (UNIT_VTABLE(u)->following_set)
2566 return UNIT_VTABLE(u)->following_set(u, s);
2567
2568 *s = NULL;
2569 return 0;
2570}
2571
a4375746
LP
2572UnitFileState unit_get_unit_file_state(Unit *u) {
2573 assert(u);
2574
ac155bb8
MS
2575 if (u->unit_file_state < 0 && u->fragment_path)
2576 u->unit_file_state = unit_file_get_state(
67445f4e 2577 u->manager->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER,
9eb977db 2578 NULL, path_get_file_name(u->fragment_path));
a4375746 2579
ac155bb8 2580 return u->unit_file_state;
a4375746
LP
2581}
2582
57020a3a
LP
2583Unit* unit_ref_set(UnitRef *ref, Unit *u) {
2584 assert(ref);
2585 assert(u);
2586
2587 if (ref->unit)
2588 unit_ref_unset(ref);
2589
2590 ref->unit = u;
71fda00f 2591 LIST_PREPEND(refs, u->refs, ref);
57020a3a
LP
2592 return u;
2593}
2594
2595void unit_ref_unset(UnitRef *ref) {
2596 assert(ref);
2597
2598 if (!ref->unit)
2599 return;
2600
71fda00f 2601 LIST_REMOVE(refs, ref->unit->refs, ref);
57020a3a
LP
2602 ref->unit = NULL;
2603}
2604
cba6e062
LP
2605int unit_exec_context_defaults(Unit *u, ExecContext *c) {
2606 unsigned i;
2607 int r;
2608
e06c73cc
LP
2609 assert(u);
2610 assert(c);
2611
cba6e062 2612 /* This only copies in the ones that need memory */
cba6e062
LP
2613 for (i = 0; i < RLIMIT_NLIMITS; i++)
2614 if (u->manager->rlimit[i] && !c->rlimit[i]) {
2615 c->rlimit[i] = newdup(struct rlimit, u->manager->rlimit[i], 1);
2616 if (!c->rlimit[i])
2617 return -ENOMEM;
2618 }
2619
67445f4e 2620 if (u->manager->running_as == SYSTEMD_USER &&
cba6e062 2621 !c->working_directory) {
e06c73cc 2622
cba6e062
LP
2623 r = get_home_dir(&c->working_directory);
2624 if (r < 0)
2625 return r;
2626 }
2627
2628 return 0;
e06c73cc
LP
2629}
2630
3ef63c31
LP
2631ExecContext *unit_get_exec_context(Unit *u) {
2632 size_t offset;
2633 assert(u);
2634
2635 offset = UNIT_VTABLE(u)->exec_context_offset;
2636 if (offset <= 0)
2637 return NULL;
2638
2639 return (ExecContext*) ((uint8_t*) u + offset);
2640}
2641
718db961
LP
2642KillContext *unit_get_kill_context(Unit *u) {
2643 size_t offset;
2644 assert(u);
2645
2646 offset = UNIT_VTABLE(u)->kill_context_offset;
2647 if (offset <= 0)
2648 return NULL;
2649
2650 return (KillContext*) ((uint8_t*) u + offset);
2651}
2652
4ad49000
LP
2653CGroupContext *unit_get_cgroup_context(Unit *u) {
2654 size_t offset;
2655
2656 offset = UNIT_VTABLE(u)->cgroup_context_offset;
2657 if (offset <= 0)
2658 return NULL;
2659
2660 return (CGroupContext*) ((uint8_t*) u + offset);
2661}
2662
8e2af478 2663static int drop_in_file(Unit *u, UnitSetPropertiesMode mode, const char *name, char **_p, char **_q) {
b9ec9359 2664 _cleanup_free_ char *b = NULL;
26d04f86
LP
2665 char *p, *q;
2666 int r;
2667
71645aca 2668 assert(u);
26d04f86
LP
2669 assert(name);
2670 assert(_p);
2671 assert(_q);
8e2af478 2672 assert(mode & (UNIT_PERSISTENT|UNIT_RUNTIME));
71645aca 2673
b9ec9359
LP
2674 b = xescape(name, "/.");
2675 if (!b)
2676 return -ENOMEM;
2677
2678 if (!filename_is_safe(b))
71645aca
LP
2679 return -EINVAL;
2680
26d04f86
LP
2681 if (u->manager->running_as == SYSTEMD_USER) {
2682 _cleanup_free_ char *c = NULL;
2683
2684 r = user_config_home(&c);
2685 if (r < 0)
2686 return r;
2687 if (r == 0)
2688 return -ENOENT;
2689
2690 p = strjoin(c, "/", u->id, ".d", NULL);
c2756a68 2691 } else if (mode & UNIT_PERSISTENT)
26d04f86 2692 p = strjoin("/etc/systemd/system/", u->id, ".d", NULL);
8e2af478
LP
2693 else
2694 p = strjoin("/run/systemd/system/", u->id, ".d", NULL);
71645aca
LP
2695 if (!p)
2696 return -ENOMEM;
2697
b9ec9359 2698 q = strjoin(p, "/90-", b, ".conf", NULL);
26d04f86
LP
2699 if (!q) {
2700 free(p);
71645aca 2701 return -ENOMEM;
26d04f86 2702 }
71645aca 2703
26d04f86
LP
2704 *_p = p;
2705 *_q = q;
2706 return 0;
71645aca
LP
2707}
2708
8e2af478 2709int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data) {
71645aca 2710 _cleanup_free_ char *p = NULL, *q = NULL;
26d04f86 2711 int r;
71645aca
LP
2712
2713 assert(u);
b42defe3
LP
2714 assert(name);
2715 assert(data);
71645aca 2716
8e2af478
LP
2717 if (!(mode & (UNIT_PERSISTENT|UNIT_RUNTIME)))
2718 return 0;
2719
2720 r = drop_in_file(u, mode, name, &p, &q);
26d04f86
LP
2721 if (r < 0)
2722 return r;
71645aca 2723
26d04f86 2724 mkdir_p(p, 0755);
574d5f2d 2725 return write_string_file_atomic_label(q, data);
26d04f86 2726}
71645aca 2727
b9ec9359
LP
2728int unit_write_drop_in_format(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *format, ...) {
2729 _cleanup_free_ char *p = NULL;
2730 va_list ap;
2731 int r;
2732
2733 assert(u);
2734 assert(name);
2735 assert(format);
2736
2737 if (!(mode & (UNIT_PERSISTENT|UNIT_RUNTIME)))
2738 return 0;
2739
2740 va_start(ap, format);
2741 r = vasprintf(&p, format, ap);
2742 va_end(ap);
2743
2744 if (r < 0)
2745 return -ENOMEM;
2746
2747 return unit_write_drop_in(u, mode, name, p);
2748}
2749
2750int unit_write_drop_in_private(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data) {
b42defe3
LP
2751 _cleanup_free_ char *ndata = NULL;
2752
2753 assert(u);
2754 assert(name);
2755 assert(data);
2756
2757 if (!UNIT_VTABLE(u)->private_section)
2758 return -EINVAL;
2759
b9ec9359
LP
2760 if (!(mode & (UNIT_PERSISTENT|UNIT_RUNTIME)))
2761 return 0;
2762
b42defe3
LP
2763 ndata = strjoin("[", UNIT_VTABLE(u)->private_section, "]\n", data, NULL);
2764 if (!ndata)
2765 return -ENOMEM;
2766
2767 return unit_write_drop_in(u, mode, name, ndata);
2768}
2769
b9ec9359
LP
2770int unit_write_drop_in_private_format(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *format, ...) {
2771 _cleanup_free_ char *p = NULL;
2772 va_list ap;
2773 int r;
2774
2775 assert(u);
2776 assert(name);
2777 assert(format);
2778
2779 if (!(mode & (UNIT_PERSISTENT|UNIT_RUNTIME)))
2780 return 0;
2781
2782 va_start(ap, format);
2783 r = vasprintf(&p, format, ap);
2784 va_end(ap);
2785
2786 if (r < 0)
2787 return -ENOMEM;
2788
2789 return unit_write_drop_in_private(u, mode, name, p);
2790}
2791
8e2af478 2792int unit_remove_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name) {
26d04f86
LP
2793 _cleanup_free_ char *p = NULL, *q = NULL;
2794 int r;
71645aca 2795
26d04f86 2796 assert(u);
71645aca 2797
8e2af478
LP
2798 if (!(mode & (UNIT_PERSISTENT|UNIT_RUNTIME)))
2799 return 0;
2800
2801 r = drop_in_file(u, mode, name, &p, &q);
6891529f
ZJS
2802 if (r < 0)
2803 return r;
2804
71645aca 2805 if (unlink(q) < 0)
241da328 2806 r = errno == ENOENT ? 0 : -errno;
26d04f86 2807 else
241da328 2808 r = 1;
71645aca
LP
2809
2810 rmdir(p);
26d04f86 2811 return r;
71645aca
LP
2812}
2813
c2756a68
LP
2814int unit_make_transient(Unit *u) {
2815 int r;
2816
2817 assert(u);
2818
2819 u->load_state = UNIT_STUB;
2820 u->load_error = 0;
2821 u->transient = true;
2822
2823 free(u->fragment_path);
2824 u->fragment_path = NULL;
2825
2826 if (u->manager->running_as == SYSTEMD_USER) {
2827 _cleanup_free_ char *c = NULL;
2828
2829 r = user_config_home(&c);
2830 if (r < 0)
2831 return r;
2832 if (r == 0)
2833 return -ENOENT;
2834
2835 u->fragment_path = strjoin(c, "/", u->id, NULL);
2836 if (!u->fragment_path)
2837 return -ENOMEM;
2838
2839 mkdir_p(c, 0755);
2840 } else {
2841 u->fragment_path = strappend("/run/systemd/system/", u->id);
2842 if (!u->fragment_path)
2843 return -ENOMEM;
2844
2845 mkdir_p("/run/systemd/system", 0755);
2846 }
2847
2848 return write_string_file_atomic_label(u->fragment_path, "# Transient stub");
2849}
2850
cd2086fe
LP
2851int unit_kill_context(
2852 Unit *u,
2853 KillContext *c,
2854 bool sigkill,
2855 pid_t main_pid,
2856 pid_t control_pid,
2857 bool main_pid_alien) {
2858
2859 int sig, wait_for_exit = 0, r;
2860
2861 assert(u);
2862 assert(c);
2863
2864 if (c->kill_mode == KILL_NONE)
2865 return 0;
2866
2867 sig = sigkill ? SIGKILL : c->kill_signal;
2868
2869 if (main_pid > 0) {
2870 r = kill_and_sigcont(main_pid, sig);
2871
2872 if (r < 0 && r != -ESRCH) {
2873 _cleanup_free_ char *comm = NULL;
2874 get_process_comm(main_pid, &comm);
2875
2876 log_warning_unit(u->id, "Failed to kill main process %li (%s): %s",
2877 (long) main_pid, strna(comm), strerror(-r));
82659fd7 2878 } else {
cd2086fe 2879 wait_for_exit = !main_pid_alien;
82659fd7
LP
2880
2881 if (c->send_sighup)
2882 kill(main_pid, SIGHUP);
2883 }
cd2086fe
LP
2884 }
2885
2886 if (control_pid > 0) {
2887 r = kill_and_sigcont(control_pid, sig);
2888
2889 if (r < 0 && r != -ESRCH) {
2890 _cleanup_free_ char *comm = NULL;
2891 get_process_comm(control_pid, &comm);
2892
2893 log_warning_unit(u->id,
2894 "Failed to kill control process %li (%s): %s",
2895 (long) control_pid, strna(comm), strerror(-r));
82659fd7 2896 } else {
cd2086fe 2897 wait_for_exit = true;
82659fd7
LP
2898
2899 if (c->send_sighup)
2900 kill(control_pid, SIGHUP);
2901 }
cd2086fe
LP
2902 }
2903
4ad49000 2904 if (c->kill_mode == KILL_CONTROL_GROUP && u->cgroup_path) {
cd2086fe
LP
2905 _cleanup_set_free_ Set *pid_set = NULL;
2906
82659fd7
LP
2907 /* Exclude the main/control pids from being killed via the cgroup */
2908 pid_set = unit_pid_set(main_pid, control_pid);
cd2086fe
LP
2909 if (!pid_set)
2910 return -ENOMEM;
2911
4ad49000 2912 r = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, sig, true, true, false, pid_set);
cd2086fe
LP
2913 if (r < 0) {
2914 if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
2915 log_warning_unit(u->id, "Failed to kill control group: %s", strerror(-r));
82659fd7 2916 } else if (r > 0) {
cd2086fe 2917 wait_for_exit = true;
82659fd7
LP
2918 if (c->send_sighup) {
2919 set_free(pid_set);
2920
2921 pid_set = unit_pid_set(main_pid, control_pid);
2922 if (!pid_set)
2923 return -ENOMEM;
2924
2925 cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, SIGHUP, true, true, false, pid_set);
2926 }
2927 }
cd2086fe
LP
2928 }
2929
2930 return wait_for_exit;
2931}
2932
a57f7e2c
LP
2933int unit_require_mounts_for(Unit *u, const char *path) {
2934 char prefix[strlen(path) + 1], *p;
2935 int r;
2936
2937 assert(u);
2938 assert(path);
2939
2940 /* Registers a unit for requiring a certain path and all its
2941 * prefixes. We keep a simple array of these paths in the
2942 * unit, since its usually short. However, we build a prefix
2943 * table for all possible prefixes so that new appearing mount
2944 * units can easily determine which units to make themselves a
2945 * dependency of. */
2946
2947 p = strdup(path);
2948 if (!p)
2949 return -ENOMEM;
2950
2951 path_kill_slashes(p);
2952
2953 if (!path_is_absolute(p)) {
2954 free(p);
2955 return -EINVAL;
2956 }
2957
2958 if (!path_is_safe(p)) {
2959 free(p);
2960 return -EPERM;
2961 }
2962
2963 if (strv_contains(u->requires_mounts_for, p)) {
2964 free(p);
2965 return 0;
2966 }
2967
2968 r = strv_push(&u->requires_mounts_for, p);
2969 if (r < 0) {
2970 free(p);
2971 return r;
2972 }
2973
2974 PATH_FOREACH_PREFIX_MORE(prefix, p) {
2975 Set *x;
2976
2977 x = hashmap_get(u->manager->units_requiring_mounts_for, prefix);
2978 if (!x) {
2979 char *q;
2980
2981 if (!u->manager->units_requiring_mounts_for) {
2982 u->manager->units_requiring_mounts_for = hashmap_new(string_hash_func, string_compare_func);
2983 if (!u->manager->units_requiring_mounts_for)
2984 return -ENOMEM;
2985 }
2986
2987 q = strdup(prefix);
2988 if (!q)
2989 return -ENOMEM;
2990
2991 x = set_new(NULL, NULL);
2992 if (!x) {
2993 free(q);
2994 return -ENOMEM;
2995 }
2996
2997 r = hashmap_put(u->manager->units_requiring_mounts_for, q, x);
2998 if (r < 0) {
2999 free(q);
3000 set_free(x);
3001 return r;
3002 }
3003 }
3004
3005 r = set_put(x, u);
3006 if (r < 0)
3007 return r;
3008 }
3009
3010 return 0;
3011}
3012
94f04347
LP
3013static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = {
3014 [UNIT_ACTIVE] = "active",
032ff4af 3015 [UNIT_RELOADING] = "reloading",
94f04347 3016 [UNIT_INACTIVE] = "inactive",
fdf20a31 3017 [UNIT_FAILED] = "failed",
94f04347
LP
3018 [UNIT_ACTIVATING] = "activating",
3019 [UNIT_DEACTIVATING] = "deactivating"
3020};
3021
3022DEFINE_STRING_TABLE_LOOKUP(unit_active_state, UnitActiveState);
3023
3024static const char* const unit_dependency_table[_UNIT_DEPENDENCY_MAX] = {
3025 [UNIT_REQUIRES] = "Requires",
9e2f7c11 3026 [UNIT_REQUIRES_OVERRIDABLE] = "RequiresOverridable",
94f04347 3027 [UNIT_REQUISITE] = "Requisite",
9e2f7c11 3028 [UNIT_REQUISITE_OVERRIDABLE] = "RequisiteOverridable",
ac6a4abe
MS
3029 [UNIT_WANTS] = "Wants",
3030 [UNIT_BINDS_TO] = "BindsTo",
3031 [UNIT_PART_OF] = "PartOf",
94f04347 3032 [UNIT_REQUIRED_BY] = "RequiredBy",
9e2f7c11 3033 [UNIT_REQUIRED_BY_OVERRIDABLE] = "RequiredByOverridable",
94f04347 3034 [UNIT_WANTED_BY] = "WantedBy",
ac6a4abe
MS
3035 [UNIT_BOUND_BY] = "BoundBy",
3036 [UNIT_CONSISTS_OF] = "ConsistsOf",
94f04347 3037 [UNIT_CONFLICTS] = "Conflicts",
69dd2852 3038 [UNIT_CONFLICTED_BY] = "ConflictedBy",
94f04347
LP
3039 [UNIT_BEFORE] = "Before",
3040 [UNIT_AFTER] = "After",
57020a3a
LP
3041 [UNIT_ON_FAILURE] = "OnFailure",
3042 [UNIT_TRIGGERS] = "Triggers",
4dcc1cb4 3043 [UNIT_TRIGGERED_BY] = "TriggeredBy",
7f2cddae 3044 [UNIT_PROPAGATES_RELOAD_TO] = "PropagatesReloadTo",
ac6a4abe
MS
3045 [UNIT_RELOAD_PROPAGATED_FROM] = "ReloadPropagatedFrom",
3046 [UNIT_REFERENCES] = "References",
3047 [UNIT_REFERENCED_BY] = "ReferencedBy",
94f04347
LP
3048};
3049
3050DEFINE_STRING_TABLE_LOOKUP(unit_dependency, UnitDependency);