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 /* Not much initialization happening here at this time */
70 n->meta.type = _NAME_TYPE_INVALID;
71 n->meta.state = NAME_STUB;
73 /* We don't link the name here, that is left for name_link() */
78 int name_link(Name *n) {
83 assert(!n->meta.linked);
85 STRV_FOREACH(t, n->meta.names)
86 if ((r = hashmap_put(n->meta.manager->names, *t, n)) < 0)
89 if (n->meta.state == NAME_STUB)
90 LIST_PREPEND(Meta, n->meta.manager->load_queue, &n->meta);
92 n->meta.linked = true;
98 STRV_FOREACH_BACKWARDS(t, n->meta.names)
99 hashmap_remove(n->meta.manager->names, *t);
104 void name_free(Name *name) {
108 /* Detach from next 'bigger' objects */
110 if (name->meta.linked) {
113 STRV_FOREACH(t, name->meta.names)
114 hashmap_remove(name->meta.manager->names, *t);
117 job_free(name->meta.job);
120 /* Free data and next 'smaller' objects */
123 job_free(name->meta.job);
125 /* FIXME: Other names pointing to us should probably drop their refs to us when we get destructed */
126 set_free(name->meta.requires);
127 set_free(name->meta.soft_requires);
128 set_free(name->meta.wants);
129 set_free(name->meta.requisite);
130 set_free(name->meta.soft_requires);
131 set_free(name->meta.conflicts);
132 set_free(name->meta.before);
133 set_free(name->meta.after);
135 switch (name->meta.type) {
139 Socket *s = SOCKET(name);
141 for (i = 0; i < s->n_fds; i++)
142 nointr_close(s->fds[i]);
147 Device *d = DEVICE(name);
154 Mount *m = MOUNT(name);
160 case NAME_AUTOMOUNT: {
161 Automount *a = AUTOMOUNT(name);
171 free(name->meta.description);
172 strv_free(name->meta.names);
177 bool name_is_ready(Name *name) {
181 if (name->meta.state != NAME_LOADED)
184 assert(name->meta.type < _NAME_TYPE_MAX);
186 switch (name->meta.type) {
188 Service *s = SERVICE(name);
191 s->state == SERVICE_RUNNING ||
192 s->state == SERVICE_RELOAD_PRE ||
193 s->state == SERVICE_RELOAD ||
194 s->state == SERVICE_RELOAD_POST;
198 Timer *t = TIMER(name);
201 t->state == TIMER_WAITING ||
202 t->state == TIMER_RUNNING;
206 Socket *s = SOCKET(name);
209 s->state == SOCKET_LISTENING ||
210 s->state == SOCKET_RUNNING;
214 return MILESTONE(name)->state == MILESTONE_ACTIVE;
217 return DEVICE(name)->state == DEVICE_AVAILABLE;
220 return MOUNT(name)->state == MOUNT_MOUNTED;
222 case NAME_AUTOMOUNT: {
223 Automount *a = AUTOMOUNT(name);
226 a->state == AUTOMOUNT_WAITING ||
227 a->state == AUTOMOUNT_RUNNING;
231 return SNAPSHOT(name)->state == SNAPSHOT_ACTIVE;
235 case _NAME_TYPE_INVALID:
239 assert_not_reached("Unknown name type.");
243 static int ensure_in_set(Set **s, void *data) {
250 if (!(*s = set_new(trivial_hash_func, trivial_compare_func)))
253 if ((r = set_put(*s, data) < 0))
260 int name_augment(Name *n) {
267 /* Adds in the missing links to make all dependencies both-ways */
269 SET_FOREACH(other, n->meta.before, state)
270 if ((r = ensure_in_set(&other->meta.after, n) < 0))
272 SET_FOREACH(other, n->meta.after, state)
273 if ((r = ensure_in_set(&other->meta.before, n) < 0))
276 SET_FOREACH(other, n->meta.conflicts, state)
277 if ((r = ensure_in_set(&other->meta.conflicts, n) < 0))
280 SET_FOREACH(other, n->meta.requires, state)
281 if ((r = ensure_in_set(&other->meta.required_by, n) < 0))
283 SET_FOREACH(other, n->meta.soft_requires, state)
284 if ((r = ensure_in_set(&other->meta.required_by, n) < 0))
286 SET_FOREACH(other, n->meta.requisite, state)
287 if ((r = ensure_in_set(&other->meta.required_by, n) < 0))
289 SET_FOREACH(other, n->meta.soft_requisite, state)
290 if ((r = ensure_in_set(&other->meta.required_by, n) < 0))