1 /*-*- Mode: C; c-basic-offset: 8 -*-*/
12 NameType name_type_from_string(const char *n) {
14 static const char* suffixes[_NAME_TYPE_MAX] = {
15 [NAME_SERVICE] = ".service",
16 [NAME_TIMER] = ".timer",
17 [NAME_SOCKET] = ".socket",
18 [NAME_MILESTONE] = ".milestone",
19 [NAME_DEVICE] = ".device",
20 [NAME_MOUNT] = ".mount",
21 [NAME_AUTOMOUNT] = ".automount",
22 [NAME_SNAPSHOT] = ".snapshot",
27 for (t = 0; t < _NAME_TYPE_MAX; t++)
28 if (endswith(n, suffixes[t]))
31 return _NAME_TYPE_INVALID;
36 "abcdefghijklmnopqrstuvwxyz" \
37 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
40 bool name_is_valid(const char *n) {
46 t = name_type_from_string(n);
47 if (t < 0 || t >= _NAME_TYPE_MAX)
50 if (!(e = strrchr(n, '.')))
53 for (i = n; i < e; i++)
54 if (!strchr(VALID_CHARS, *i))
60 Name *name_new(Manager *m) {
65 if (!(n = new0(Name, 1)))
68 if (!(n->meta.names = set_new(string_hash_func, string_compare_func))) {
73 /* Not much initialization happening here at this time */
75 n->meta.type = _NAME_TYPE_INVALID;
76 n->meta.state = NAME_STUB;
78 /* We don't link the name here, that is left for name_link() */
83 int name_link(Name *n) {
89 assert(!set_isempty(n->meta.names));
90 assert(!n->meta.linked);
92 SET_FOREACH(t, n->meta.names, state)
93 if ((r = hashmap_put(n->meta.manager->names, t, n)) < 0)
96 if (n->meta.state == NAME_STUB)
97 LIST_PREPEND(Meta, n->meta.manager->load_queue, &n->meta);
99 n->meta.linked = true;
104 SET_FOREACH(t, n->meta.names, state)
105 assert_se(hashmap_remove(n->meta.manager->names, t) == n);
110 static void bidi_set_free(Name *name, Set *s) {
117 /* Frees the set and makes sure we are dropped from the
118 * inverse pointers */
120 SET_FOREACH(other, s, state) {
123 for (d = 0; d < _NAME_DEPENDENCY_MAX; d++)
124 set_remove(other->meta.dependencies[d], name);
130 void name_free(Name *name) {
136 /* Detach from next 'bigger' objects */
137 if (name->meta.linked) {
141 SET_FOREACH(t, name->meta.names, state)
142 assert_se(hashmap_remove(name->meta.manager->names, t) == name);
144 if (name->meta.state == NAME_STUB)
145 LIST_REMOVE(Meta, name->meta.manager->load_queue, &name->meta);
148 /* Free data and next 'smaller' objects */
150 job_free(name->meta.job);
152 for (d = 0; d < _NAME_DEPENDENCY_MAX; d++)
153 bidi_set_free(name, name->meta.dependencies[d]);
155 switch (name->meta.type) {
159 Socket *s = SOCKET(name);
161 for (i = 0; i < s->n_fds; i++)
162 nointr_close(s->fds[i]);
167 Device *d = DEVICE(name);
174 Mount *m = MOUNT(name);
180 case NAME_AUTOMOUNT: {
181 Automount *a = AUTOMOUNT(name);
191 free(name->meta.description);
193 while ((t = set_steal_first(name->meta.names)))
195 set_free(name->meta.names);
200 bool name_is_ready(Name *name) {
204 if (name->meta.state != NAME_LOADED)
207 assert(name->meta.type < _NAME_TYPE_MAX);
209 switch (name->meta.type) {
211 Service *s = SERVICE(name);
214 s->state == SERVICE_RUNNING ||
215 s->state == SERVICE_RELOAD_PRE ||
216 s->state == SERVICE_RELOAD ||
217 s->state == SERVICE_RELOAD_POST;
221 Timer *t = TIMER(name);
224 t->state == TIMER_WAITING ||
225 t->state == TIMER_RUNNING;
229 Socket *s = SOCKET(name);
232 s->state == SOCKET_LISTENING ||
233 s->state == SOCKET_RUNNING;
237 return MILESTONE(name)->state == MILESTONE_ACTIVE;
240 return DEVICE(name)->state == DEVICE_AVAILABLE;
243 return MOUNT(name)->state == MOUNT_MOUNTED;
245 case NAME_AUTOMOUNT: {
246 Automount *a = AUTOMOUNT(name);
249 a->state == AUTOMOUNT_WAITING ||
250 a->state == AUTOMOUNT_RUNNING;
254 return SNAPSHOT(name)->state == SNAPSHOT_ACTIVE;
258 case _NAME_TYPE_INVALID:
262 assert_not_reached("Unknown name type.");
266 static int ensure_in_set(Set **s, void *data) {
273 if (!(*s = set_new(trivial_hash_func, trivial_compare_func)))
276 if ((r = set_put(*s, data) < 0))
283 int name_augment(Name *n) {
290 /* Adds in the missing links to make all dependencies bidirectional */
292 SET_FOREACH(other, n->meta.dependencies[NAME_BEFORE], state)
293 if ((r = ensure_in_set(&other->meta.dependencies[NAME_AFTER], n) < 0))
295 SET_FOREACH(other, n->meta.dependencies[NAME_AFTER], state)
296 if ((r = ensure_in_set(&other->meta.dependencies[NAME_BEFORE], n) < 0))
299 SET_FOREACH(other, n->meta.dependencies[NAME_CONFLICTS], state)
300 if ((r = ensure_in_set(&other->meta.dependencies[NAME_CONFLICTS], n) < 0))
303 SET_FOREACH(other, n->meta.dependencies[NAME_REQUIRES], state)
304 if ((r = ensure_in_set(&other->meta.dependencies[NAME_REQUIRED_BY], n) < 0))
306 SET_FOREACH(other, n->meta.dependencies[NAME_REQUISITE], state)
307 if ((r = ensure_in_set(&other->meta.dependencies[NAME_REQUIRED_BY], n) < 0))
310 SET_FOREACH(other, n->meta.dependencies[NAME_WANTS], state)
311 if ((r = ensure_in_set(&other->meta.dependencies[NAME_WANTED_BY], n) < 0))
313 SET_FOREACH(other, n->meta.dependencies[NAME_SOFT_REQUIRES], state)
314 if ((r = ensure_in_set(&other->meta.dependencies[NAME_WANTED_BY], n) < 0))
316 SET_FOREACH(other, n->meta.dependencies[NAME_SOFT_REQUISITE], state)
317 if ((r = ensure_in_set(&other->meta.dependencies[NAME_WANTED_BY], n) < 0))
323 static int ensure_merge(Set **s, Set *other) {
329 return set_merge(*s, other);
331 if (!(*s = set_copy(other)))
337 int name_merge(Name *name, Name *other) {
344 assert(name->meta.manager == other->meta.manager);
346 if (name->meta.type != other->meta.type)
349 if (other->meta.state != NAME_STUB)
353 if ((r = ensure_merge(&name->meta.names, other->meta.names)) < 0)
356 /* Merge dependencies */
357 for (d = 0; d < _NAME_DEPENDENCY_MAX; d++)
358 if ((r = ensure_merge(&name->meta.dependencies[d], other->meta.dependencies[d])) < 0)