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