]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/target.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / core / target.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
a7334b09
LP
2/***
3 This file is part of systemd.
4
5 Copyright 2010 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
a7334b09
LP
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 15 Lesser General Public License for more details.
a7334b09 16
5430f7f2 17 You should have received a copy of the GNU Lesser General Public License
a7334b09
LP
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
4139c1b2 21#include "dbus-target.h"
07630cea 22#include "log.h"
514f4ef5 23#include "special.h"
07630cea 24#include "string-util.h"
b2bb3dbe 25#include "unit-name.h"
07630cea
LP
26#include "unit.h"
27#include "target.h"
c22cbe26 28
fa068367
LP
29static const UnitActiveState state_translation_table[_TARGET_STATE_MAX] = {
30 [TARGET_DEAD] = UNIT_INACTIVE,
31 [TARGET_ACTIVE] = UNIT_ACTIVE
32};
33
fa068367
LP
34static void target_set_state(Target *t, TargetState state) {
35 TargetState old_state;
36 assert(t);
37
38 old_state = t->state;
39 t->state = state;
40
e537352b 41 if (state != old_state)
40d50879 42 log_debug("%s changed %s -> %s",
1124fe6f 43 UNIT(t)->id,
a16e1123
LP
44 target_state_to_string(old_state),
45 target_state_to_string(state));
c22cbe26 46
e2f3b44c 47 unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], true);
fa068367
LP
48}
49
a40eb732 50static int target_add_default_dependencies(Target *t) {
1850161f 51
21256a2b
LP
52 static const UnitDependency deps[] = {
53 UNIT_REQUIRES,
21256a2b 54 UNIT_REQUISITE,
21256a2b 55 UNIT_WANTS,
1850161f
LP
56 UNIT_BINDS_TO,
57 UNIT_PART_OF
21256a2b
LP
58 };
59
bba34eed 60 int r;
21256a2b 61 unsigned k;
bba34eed 62
98bc2000 63 assert(t);
a40eb732 64
41c237af
IP
65 if (!UNIT(t)->default_dependencies)
66 return 0;
67
eef85c4a
LP
68 /* Imply ordering for requirement dependencies on target units. Note that when the user created a contradicting
69 * ordering manually we won't add anything in here to make sure we don't create a loop. */
bba34eed 70
eef85c4a
LP
71 for (k = 0; k < ELEMENTSOF(deps); k++) {
72 Unit *other;
73 Iterator i;
74 void *v;
75
76 HASHMAP_FOREACH_KEY(v, other, UNIT(t)->dependencies[deps[k]], i) {
1850161f
LP
77 r = unit_add_default_target_dependency(other, UNIT(t));
78 if (r < 0)
21256a2b 79 return r;
1850161f 80 }
eef85c4a 81 }
bba34eed 82
33e28180
LP
83 if (unit_has_name(UNIT(t), SPECIAL_SHUTDOWN_TARGET))
84 return 0;
85
b401e1fb 86 /* Make sure targets are unloaded on shutdown */
eef85c4a 87 return unit_add_two_dependencies_by_name(UNIT(t), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true, UNIT_DEPENDENCY_DEFAULT);
a40eb732
LP
88}
89
90static int target_load(Unit *u) {
91 Target *t = TARGET(u);
92 int r;
93
94 assert(t);
95
1850161f
LP
96 r = unit_load_fragment_and_dropin(u);
97 if (r < 0)
a40eb732
LP
98 return r;
99
100 /* This is a new unit? Then let's add in some extras */
41c237af 101 if (u->load_state == UNIT_LOADED) {
1850161f
LP
102 r = target_add_default_dependencies(t);
103 if (r < 0)
104 return r;
a40eb732
LP
105 }
106
107 return 0;
108}
109
be847e82 110static int target_coldplug(Unit *u) {
a16e1123
LP
111 Target *t = TARGET(u);
112
113 assert(t);
114 assert(t->state == TARGET_DEAD);
115
116 if (t->deserialized_state != t->state)
117 target_set_state(t, t->deserialized_state);
118
119 return 0;
120}
121
122static void target_dump(Unit *u, FILE *f, const char *prefix) {
123 Target *t = TARGET(u);
124
125 assert(t);
126 assert(f);
127
128 fprintf(f,
129 "%sTarget State: %s\n",
130 prefix, target_state_to_string(t->state));
131}
132
fa068367
LP
133static int target_start(Unit *u) {
134 Target *t = TARGET(u);
4b58153d 135 int r;
fa068367
LP
136
137 assert(t);
138 assert(t->state == TARGET_DEAD);
139
4b58153d
LP
140 r = unit_acquire_invocation_id(u);
141 if (r < 0)
142 return r;
143
fa068367 144 target_set_state(t, TARGET_ACTIVE);
82a2b6bb 145 return 1;
fa068367 146}
c22cbe26 147
fa068367
LP
148static int target_stop(Unit *u) {
149 Target *t = TARGET(u);
150
151 assert(t);
152 assert(t->state == TARGET_ACTIVE);
153
154 target_set_state(t, TARGET_DEAD);
82a2b6bb 155 return 1;
c22cbe26
LP
156}
157
a16e1123
LP
158static int target_serialize(Unit *u, FILE *f, FDSet *fds) {
159 Target *s = TARGET(u);
160
161 assert(s);
162 assert(f);
163 assert(fds);
164
165 unit_serialize_item(u, f, "state", target_state_to_string(s->state));
166 return 0;
167}
168
169static int target_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
170 Target *s = TARGET(u);
171
172 assert(u);
173 assert(key);
174 assert(value);
175 assert(fds);
176
177 if (streq(key, "state")) {
178 TargetState state;
179
1850161f
LP
180 state = target_state_from_string(value);
181 if (state < 0)
a16e1123
LP
182 log_debug("Failed to parse state value %s", value);
183 else
184 s->deserialized_state = state;
185
186 } else
187 log_debug("Unknown serialization key '%s'", key);
188
189 return 0;
190}
191
44a6b1b6 192_pure_ static UnitActiveState target_active_state(Unit *u) {
fa068367
LP
193 assert(u);
194
195 return state_translation_table[TARGET(u)->state];
c22cbe26
LP
196}
197
44a6b1b6 198_pure_ static const char *target_sub_state_to_string(Unit *u) {
10a94420
LP
199 assert(u);
200
a16e1123 201 return target_state_to_string(TARGET(u)->state);
10a94420
LP
202}
203
87f0e418 204const UnitVTable target_vtable = {
7d17cfbc 205 .object_size = sizeof(Target),
718db961 206
f975e971
LP
207 .sections =
208 "Unit\0"
209 "Target\0"
210 "Install\0",
c22cbe26 211
a40eb732 212 .load = target_load,
a16e1123 213 .coldplug = target_coldplug,
fa068367
LP
214
215 .dump = target_dump,
216
217 .start = target_start,
218 .stop = target_stop,
c22cbe26 219
a16e1123
LP
220 .serialize = target_serialize,
221 .deserialize_item = target_deserialize_item,
222
10a94420 223 .active_state = target_active_state,
4139c1b2
LP
224 .sub_state_to_string = target_sub_state_to_string,
225
718db961 226 .bus_vtable = bus_target_vtable,
c6918296
MS
227
228 .status_message_formats = {
229 .finished_start_job = {
230 [JOB_DONE] = "Reached target %s.",
c6918296
MS
231 },
232 .finished_stop_job = {
233 [JOB_DONE] = "Stopped target %s.",
234 },
235 },
c22cbe26 236};