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