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