]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/target.c
util-lib: split our string related calls from util.[ch] into its own file string...
[thirdparty/systemd.git] / src / core / target.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
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
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
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
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include "dbus-target.h"
23 #include "log.h"
24 #include "special.h"
25 #include "string-util.h"
26 #include "unit-name.h"
27 #include "unit.h"
28 #include "target.h"
29
30 static const UnitActiveState state_translation_table[_TARGET_STATE_MAX] = {
31 [TARGET_DEAD] = UNIT_INACTIVE,
32 [TARGET_ACTIVE] = UNIT_ACTIVE
33 };
34
35 static void target_set_state(Target *t, TargetState state) {
36 TargetState old_state;
37 assert(t);
38
39 old_state = t->state;
40 t->state = state;
41
42 if (state != old_state)
43 log_debug("%s changed %s -> %s",
44 UNIT(t)->id,
45 target_state_to_string(old_state),
46 target_state_to_string(state));
47
48 unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], true);
49 }
50
51 static int target_add_default_dependencies(Target *t) {
52
53 static const UnitDependency deps[] = {
54 UNIT_REQUIRES,
55 UNIT_REQUIRES_OVERRIDABLE,
56 UNIT_REQUISITE,
57 UNIT_REQUISITE_OVERRIDABLE,
58 UNIT_WANTS,
59 UNIT_BINDS_TO,
60 UNIT_PART_OF
61 };
62
63 Iterator i;
64 Unit *other;
65 int r;
66 unsigned k;
67
68 assert(t);
69
70 /* Imply ordering for requirement dependencies on target
71 * units. Note that when the user created a contradicting
72 * ordering manually we won't add anything in here to make
73 * sure we don't create a loop. */
74
75 for (k = 0; k < ELEMENTSOF(deps); k++)
76 SET_FOREACH(other, UNIT(t)->dependencies[deps[k]], i) {
77 r = unit_add_default_target_dependency(other, UNIT(t));
78 if (r < 0)
79 return r;
80 }
81
82 /* Make sure targets are unloaded on shutdown */
83 return unit_add_dependency_by_name(UNIT(t), UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
84 }
85
86 static int target_load(Unit *u) {
87 Target *t = TARGET(u);
88 int r;
89
90 assert(t);
91
92 r = unit_load_fragment_and_dropin(u);
93 if (r < 0)
94 return r;
95
96 /* This is a new unit? Then let's add in some extras */
97 if (u->load_state == UNIT_LOADED && u->default_dependencies) {
98 r = target_add_default_dependencies(t);
99 if (r < 0)
100 return r;
101 }
102
103 return 0;
104 }
105
106 static int target_coldplug(Unit *u) {
107 Target *t = TARGET(u);
108
109 assert(t);
110 assert(t->state == TARGET_DEAD);
111
112 if (t->deserialized_state != t->state)
113 target_set_state(t, t->deserialized_state);
114
115 return 0;
116 }
117
118 static void target_dump(Unit *u, FILE *f, const char *prefix) {
119 Target *t = TARGET(u);
120
121 assert(t);
122 assert(f);
123
124 fprintf(f,
125 "%sTarget State: %s\n",
126 prefix, target_state_to_string(t->state));
127 }
128
129 static int target_start(Unit *u) {
130 Target *t = TARGET(u);
131
132 assert(t);
133 assert(t->state == TARGET_DEAD);
134
135 target_set_state(t, TARGET_ACTIVE);
136 return 1;
137 }
138
139 static int target_stop(Unit *u) {
140 Target *t = TARGET(u);
141
142 assert(t);
143 assert(t->state == TARGET_ACTIVE);
144
145 target_set_state(t, TARGET_DEAD);
146 return 1;
147 }
148
149 static int target_serialize(Unit *u, FILE *f, FDSet *fds) {
150 Target *s = TARGET(u);
151
152 assert(s);
153 assert(f);
154 assert(fds);
155
156 unit_serialize_item(u, f, "state", target_state_to_string(s->state));
157 return 0;
158 }
159
160 static int target_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
161 Target *s = TARGET(u);
162
163 assert(u);
164 assert(key);
165 assert(value);
166 assert(fds);
167
168 if (streq(key, "state")) {
169 TargetState state;
170
171 state = target_state_from_string(value);
172 if (state < 0)
173 log_debug("Failed to parse state value %s", value);
174 else
175 s->deserialized_state = state;
176
177 } else
178 log_debug("Unknown serialization key '%s'", key);
179
180 return 0;
181 }
182
183 _pure_ static UnitActiveState target_active_state(Unit *u) {
184 assert(u);
185
186 return state_translation_table[TARGET(u)->state];
187 }
188
189 _pure_ static const char *target_sub_state_to_string(Unit *u) {
190 assert(u);
191
192 return target_state_to_string(TARGET(u)->state);
193 }
194
195 const UnitVTable target_vtable = {
196 .object_size = sizeof(Target),
197
198 .sections =
199 "Unit\0"
200 "Target\0"
201 "Install\0",
202
203 .load = target_load,
204 .coldplug = target_coldplug,
205
206 .dump = target_dump,
207
208 .start = target_start,
209 .stop = target_stop,
210
211 .serialize = target_serialize,
212 .deserialize_item = target_deserialize_item,
213
214 .active_state = target_active_state,
215 .sub_state_to_string = target_sub_state_to_string,
216
217 .bus_vtable = bus_target_vtable,
218
219 .status_message_formats = {
220 .finished_start_job = {
221 [JOB_DONE] = "Reached target %s.",
222 },
223 .finished_stop_job = {
224 [JOB_DONE] = "Stopped target %s.",
225 },
226 },
227 };