Line data Source code
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 <errno.h>
23 : #include <string.h>
24 :
25 : #include "path-util.h"
26 : #include "bus-label.h"
27 : #include "util.h"
28 : #include "unit-name.h"
29 : #include "def.h"
30 : #include "strv.h"
31 :
32 : #define VALID_CHARS \
33 : DIGITS LETTERS \
34 : ":-_.\\"
35 :
36 10199 : bool unit_name_is_valid(const char *n, UnitNameFlags flags) {
37 : const char *e, *i, *at;
38 :
39 10199 : assert((flags & ~(UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE)) == 0);
40 :
41 10199 : if (_unlikely_(flags == 0))
42 0 : return false;
43 :
44 10199 : if (isempty(n))
45 4 : return false;
46 :
47 10195 : if (strlen(n) >= UNIT_NAME_MAX)
48 0 : return false;
49 :
50 10195 : e = strrchr(n, '.');
51 10195 : if (!e || e == n)
52 288 : return false;
53 :
54 9907 : if (unit_type_from_string(e + 1) < 0)
55 20 : return false;
56 :
57 256380 : for (i = n, at = NULL; i < e; i++) {
58 :
59 246499 : if (*i == '@' && !at)
60 156 : at = i;
61 :
62 246499 : if (!strchr("@" VALID_CHARS, *i))
63 6 : return false;
64 : }
65 :
66 9881 : if (at == n)
67 2 : return false;
68 :
69 9879 : if (flags & UNIT_NAME_PLAIN)
70 6014 : if (!at)
71 5872 : return true;
72 :
73 4007 : if (flags & UNIT_NAME_INSTANCE)
74 2715 : if (at && e > at + 1)
75 58 : return true;
76 :
77 3949 : if (flags & UNIT_NAME_TEMPLATE)
78 1378 : if (at && e == at + 1)
79 86 : return true;
80 :
81 3863 : return false;
82 : }
83 :
84 25 : bool unit_prefix_is_valid(const char *p) {
85 :
86 : /* We don't allow additional @ in the prefix string */
87 :
88 25 : if (isempty(p))
89 1 : return false;
90 :
91 24 : return in_charset(p, VALID_CHARS);
92 : }
93 :
94 16 : bool unit_instance_is_valid(const char *i) {
95 :
96 : /* The max length depends on the length of the string, so we
97 : * don't really check this here. */
98 :
99 16 : if (isempty(i))
100 1 : return false;
101 :
102 : /* We allow additional @ in the instance string, we do not
103 : * allow them in the prefix! */
104 :
105 15 : return in_charset(i, "@" VALID_CHARS);
106 : }
107 :
108 1512 : bool unit_suffix_is_valid(const char *s) {
109 1512 : if (isempty(s))
110 0 : return false;
111 :
112 1512 : if (s[0] != '.')
113 0 : return false;
114 :
115 1512 : if (unit_type_from_string(s + 1) < 0)
116 1 : return false;
117 :
118 1511 : return true;
119 : }
120 :
121 30 : int unit_name_to_prefix(const char *n, char **ret) {
122 : const char *p;
123 : char *s;
124 :
125 30 : assert(n);
126 30 : assert(ret);
127 :
128 30 : if (!unit_name_is_valid(n, UNIT_NAME_ANY))
129 2 : return -EINVAL;
130 :
131 28 : p = strchr(n, '@');
132 28 : if (!p)
133 25 : p = strrchr(n, '.');
134 :
135 28 : assert_se(p);
136 :
137 28 : s = strndup(n, p - n);
138 28 : if (!s)
139 0 : return -ENOMEM;
140 :
141 28 : *ret = s;
142 28 : return 0;
143 : }
144 :
145 895 : int unit_name_to_instance(const char *n, char **instance) {
146 : const char *p, *d;
147 : char *i;
148 :
149 895 : assert(n);
150 895 : assert(instance);
151 :
152 895 : if (!unit_name_is_valid(n, UNIT_NAME_ANY))
153 2 : return -EINVAL;
154 :
155 : /* Everything past the first @ and before the last . is the instance */
156 893 : p = strchr(n, '@');
157 893 : if (!p) {
158 883 : *instance = NULL;
159 883 : return 0;
160 : }
161 :
162 10 : p++;
163 :
164 10 : d = strrchr(p, '.');
165 10 : if (!d)
166 0 : return -EINVAL;
167 :
168 10 : i = strndup(p, d-p);
169 10 : if (!i)
170 0 : return -ENOMEM;
171 :
172 10 : *instance = i;
173 10 : return 1;
174 : }
175 :
176 4 : int unit_name_to_prefix_and_instance(const char *n, char **ret) {
177 : const char *d;
178 : char *s;
179 :
180 4 : assert(n);
181 4 : assert(ret);
182 :
183 4 : if (!unit_name_is_valid(n, UNIT_NAME_ANY))
184 0 : return -EINVAL;
185 :
186 4 : d = strrchr(n, '.');
187 4 : if (!d)
188 0 : return -EINVAL;
189 :
190 4 : s = strndup(n, d - n);
191 4 : if (!s)
192 0 : return -ENOMEM;
193 :
194 4 : *ret = s;
195 4 : return 0;
196 : }
197 :
198 1381 : UnitType unit_name_to_type(const char *n) {
199 : const char *e;
200 :
201 1381 : assert(n);
202 :
203 1381 : if (!unit_name_is_valid(n, UNIT_NAME_ANY))
204 137 : return _UNIT_TYPE_INVALID;
205 :
206 1244 : assert_se(e = strrchr(n, '.'));
207 :
208 1244 : return unit_type_from_string(e + 1);
209 : }
210 :
211 8 : int unit_name_change_suffix(const char *n, const char *suffix, char **ret) {
212 : char *e, *s;
213 : size_t a, b;
214 :
215 8 : assert(n);
216 8 : assert(suffix);
217 8 : assert(ret);
218 :
219 8 : if (!unit_name_is_valid(n, UNIT_NAME_ANY))
220 0 : return -EINVAL;
221 :
222 8 : if (!unit_suffix_is_valid(suffix))
223 0 : return -EINVAL;
224 :
225 8 : assert_se(e = strrchr(n, '.'));
226 :
227 8 : a = e - n;
228 8 : b = strlen(suffix);
229 :
230 8 : s = new(char, a + b + 1);
231 8 : if (!s)
232 0 : return -ENOMEM;
233 :
234 8 : strcpy(mempcpy(s, n, a), suffix);
235 8 : *ret = s;
236 :
237 8 : return 0;
238 : }
239 :
240 3 : int unit_name_build(const char *prefix, const char *instance, const char *suffix, char **ret) {
241 : char *s;
242 :
243 3 : assert(prefix);
244 3 : assert(suffix);
245 3 : assert(ret);
246 :
247 3 : if (!unit_prefix_is_valid(prefix))
248 0 : return -EINVAL;
249 :
250 3 : if (instance && !unit_instance_is_valid(instance))
251 0 : return -EINVAL;
252 :
253 3 : if (!unit_suffix_is_valid(suffix))
254 0 : return -EINVAL;
255 :
256 3 : if (!instance)
257 1 : s = strappend(prefix, suffix);
258 : else
259 2 : s = strjoin(prefix, "@", instance, suffix, NULL);
260 3 : if (!s)
261 0 : return -ENOMEM;
262 :
263 3 : *ret = s;
264 3 : return 0;
265 : }
266 :
267 783 : static char *do_escape_char(char c, char *t) {
268 783 : assert(t);
269 :
270 783 : *(t++) = '\\';
271 783 : *(t++) = 'x';
272 783 : *(t++) = hexchar(c >> 4);
273 783 : *(t++) = hexchar(c);
274 :
275 783 : return t;
276 : }
277 :
278 1109 : static char *do_escape(const char *f, char *t) {
279 1109 : assert(f);
280 1109 : assert(t);
281 :
282 : /* do not create units with a leading '.', like for "/.dotdir" mount points */
283 1109 : if (*f == '.') {
284 0 : t = do_escape_char(*f, t);
285 0 : f++;
286 : }
287 :
288 30984 : for (; *f; f++) {
289 29875 : if (*f == '/')
290 2745 : *(t++) = '-';
291 27130 : else if (*f == '-' || *f == '\\' || !strchr(VALID_CHARS, *f))
292 763 : t = do_escape_char(*f, t);
293 : else
294 26367 : *(t++) = *f;
295 : }
296 :
297 1109 : return t;
298 : }
299 :
300 1109 : char *unit_name_escape(const char *f) {
301 : char *r, *t;
302 :
303 1109 : assert(f);
304 :
305 1109 : r = new(char, strlen(f)*4+1);
306 1109 : if (!r)
307 0 : return NULL;
308 :
309 1109 : t = do_escape(f, r);
310 1109 : *t = 0;
311 :
312 1109 : return r;
313 : }
314 :
315 27 : int unit_name_unescape(const char *f, char **ret) {
316 54 : _cleanup_free_ char *r = NULL;
317 : char *t;
318 :
319 27 : assert(f);
320 :
321 27 : r = strdup(f);
322 27 : if (!r)
323 0 : return -ENOMEM;
324 :
325 235 : for (t = r; *f; f++) {
326 208 : if (*f == '-')
327 29 : *(t++) = '/';
328 179 : else if (*f == '\\') {
329 : int a, b;
330 :
331 2 : if (f[1] != 'x')
332 0 : return -EINVAL;
333 :
334 2 : a = unhexchar(f[2]);
335 2 : if (a < 0)
336 0 : return -EINVAL;
337 :
338 2 : b = unhexchar(f[3]);
339 2 : if (b < 0)
340 0 : return -EINVAL;
341 :
342 2 : *(t++) = (char) (((uint8_t) a << 4U) | (uint8_t) b);
343 2 : f += 3;
344 : } else
345 177 : *(t++) = *f;
346 : }
347 :
348 27 : *t = 0;
349 :
350 27 : *ret = r;
351 27 : r = NULL;
352 :
353 27 : return 0;
354 : }
355 :
356 1347 : int unit_name_path_escape(const char *f, char **ret) {
357 : char *p, *s;
358 :
359 1347 : assert(f);
360 1347 : assert(ret);
361 :
362 1347 : p = strdupa(f);
363 1347 : if (!p)
364 0 : return -ENOMEM;
365 :
366 1347 : path_kill_slashes(p);
367 :
368 1347 : if (STR_IN_SET(p, "/", ""))
369 236 : s = strdup("-");
370 : else {
371 : char *e;
372 :
373 1111 : if (!path_is_safe(p))
374 3 : return -EINVAL;
375 :
376 : /* Truncate trailing slashes */
377 1108 : e = endswith(p, "/");
378 1108 : if (e)
379 0 : *e = 0;
380 :
381 : /* Truncate leading slashes */
382 1108 : if (p[0] == '/')
383 1108 : p++;
384 :
385 1108 : s = unit_name_escape(p);
386 : }
387 1344 : if (!s)
388 0 : return -ENOMEM;
389 :
390 1344 : *ret = s;
391 1344 : return 0;
392 : }
393 :
394 32 : int unit_name_path_unescape(const char *f, char **ret) {
395 : char *s;
396 : int r;
397 :
398 32 : assert(f);
399 :
400 32 : if (isempty(f))
401 1 : return -EINVAL;
402 :
403 31 : if (streq(f, "-")) {
404 7 : s = strdup("/");
405 7 : if (!s)
406 0 : return -ENOMEM;
407 : } else {
408 : char *w;
409 :
410 24 : r = unit_name_unescape(f, &w);
411 24 : if (r < 0)
412 10 : return r;
413 :
414 : /* Don't accept trailing or leading slashes */
415 24 : if (startswith(w, "/") || endswith(w, "/")) {
416 6 : free(w);
417 6 : return -EINVAL;
418 : }
419 :
420 : /* Prefix a slash again */
421 18 : s = strappend("/", w);
422 18 : free(w);
423 18 : if (!s)
424 0 : return -ENOMEM;
425 :
426 18 : if (!path_is_safe(s)) {
427 4 : free(s);
428 4 : return -EINVAL;
429 : }
430 : }
431 :
432 21 : if (ret)
433 21 : *ret = s;
434 : else
435 0 : free(s);
436 :
437 21 : return 0;
438 : }
439 :
440 8 : int unit_name_replace_instance(const char *f, const char *i, char **ret) {
441 : const char *p, *e;
442 : char *s;
443 : size_t a, b;
444 :
445 8 : assert(f);
446 8 : assert(i);
447 8 : assert(ret);
448 :
449 8 : if (!unit_name_is_valid(f, UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE))
450 6 : return -EINVAL;
451 2 : if (!unit_instance_is_valid(i))
452 0 : return -EINVAL;
453 :
454 2 : assert_se(p = strchr(f, '@'));
455 2 : assert_se(e = strrchr(f, '.'));
456 :
457 2 : a = p - f;
458 2 : b = strlen(i);
459 :
460 2 : s = new(char, a + 1 + b + strlen(e) + 1);
461 2 : if (!s)
462 0 : return -ENOMEM;
463 :
464 2 : strcpy(mempcpy(mempcpy(s, f, a + 1), i, b), e);
465 :
466 2 : *ret = s;
467 2 : return 0;
468 : }
469 :
470 2 : int unit_name_template(const char *f, char **ret) {
471 : const char *p, *e;
472 : char *s;
473 : size_t a;
474 :
475 2 : assert(f);
476 2 : assert(ret);
477 :
478 2 : if (!unit_name_is_valid(f, UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE))
479 1 : return -EINVAL;
480 :
481 1 : assert_se(p = strchr(f, '@'));
482 1 : assert_se(e = strrchr(f, '.'));
483 :
484 1 : a = p - f;
485 :
486 1 : s = new(char, a + 1 + strlen(e) + 1);
487 1 : if (!s)
488 0 : return -ENOMEM;
489 :
490 1 : strcpy(mempcpy(s, f, a + 1), e);
491 :
492 1 : *ret = s;
493 1 : return 0;
494 : }
495 :
496 1340 : int unit_name_from_path(const char *path, const char *suffix, char **ret) {
497 2680 : _cleanup_free_ char *p = NULL;
498 1340 : char *s = NULL;
499 : int r;
500 :
501 1340 : assert(path);
502 1340 : assert(suffix);
503 1340 : assert(ret);
504 :
505 1340 : if (!unit_suffix_is_valid(suffix))
506 0 : return -EINVAL;
507 :
508 1340 : r = unit_name_path_escape(path, &p);
509 1340 : if (r < 0)
510 2 : return r;
511 :
512 1338 : s = strappend(p, suffix);
513 1338 : if (!s)
514 0 : return -ENOMEM;
515 :
516 1338 : *ret = s;
517 1338 : return 0;
518 : }
519 :
520 8 : int unit_name_from_path_instance(const char *prefix, const char *path, const char *suffix, char **ret) {
521 16 : _cleanup_free_ char *p = NULL;
522 : char *s;
523 : int r;
524 :
525 8 : assert(prefix);
526 8 : assert(path);
527 8 : assert(suffix);
528 8 : assert(ret);
529 :
530 8 : if (!unit_prefix_is_valid(prefix))
531 0 : return -EINVAL;
532 :
533 8 : if (!unit_suffix_is_valid(suffix))
534 1 : return -EINVAL;
535 :
536 7 : r = unit_name_path_escape(path, &p);
537 7 : if (r < 0)
538 1 : return r;
539 :
540 6 : s = strjoin(prefix, "@", p, suffix, NULL);
541 6 : if (!s)
542 0 : return -ENOMEM;
543 :
544 6 : *ret = s;
545 6 : return 0;
546 : }
547 :
548 15 : int unit_name_to_path(const char *name, char **ret) {
549 30 : _cleanup_free_ char *prefix = NULL;
550 : int r;
551 :
552 15 : assert(name);
553 :
554 15 : r = unit_name_to_prefix(name, &prefix);
555 15 : if (r < 0)
556 2 : return r;
557 :
558 13 : return unit_name_path_unescape(prefix, ret);
559 : }
560 :
561 0 : char *unit_dbus_path_from_name(const char *name) {
562 0 : _cleanup_free_ char *e = NULL;
563 :
564 0 : assert(name);
565 :
566 0 : e = bus_label_escape(name);
567 0 : if (!e)
568 0 : return NULL;
569 :
570 0 : return strappend("/org/freedesktop/systemd1/unit/", e);
571 : }
572 :
573 0 : int unit_name_from_dbus_path(const char *path, char **name) {
574 : const char *e;
575 : char *n;
576 :
577 0 : e = startswith(path, "/org/freedesktop/systemd1/unit/");
578 0 : if (!e)
579 0 : return -EINVAL;
580 :
581 0 : n = bus_label_unescape(e);
582 0 : if (!n)
583 0 : return -ENOMEM;
584 :
585 0 : *name = n;
586 0 : return 0;
587 : }
588 :
589 141 : static char *do_escape_mangle(const char *f, UnitNameMangle allow_globs, char *t) {
590 : const char *valid_chars;
591 :
592 141 : assert(f);
593 141 : assert(IN_SET(allow_globs, UNIT_NAME_GLOB, UNIT_NAME_NOGLOB));
594 141 : assert(t);
595 :
596 : /* We'll only escape the obvious characters here, to play
597 : * safe. */
598 :
599 141 : valid_chars = allow_globs == UNIT_NAME_GLOB ? "@" VALID_CHARS "[]!-*?" : "@" VALID_CHARS;
600 :
601 745 : for (; *f; f++) {
602 604 : if (*f == '/')
603 5 : *(t++) = '-';
604 599 : else if (!strchr(valid_chars, *f))
605 20 : t = do_escape_char(*f, t);
606 : else
607 579 : *(t++) = *f;
608 : }
609 :
610 141 : return t;
611 : }
612 :
613 : /**
614 : * Convert a string to a unit name. /dev/blah is converted to dev-blah.device,
615 : * /blah/blah is converted to blah-blah.mount, anything else is left alone,
616 : * except that @suffix is appended if a valid unit suffix is not present.
617 : *
618 : * If @allow_globs, globs characters are preserved. Otherwise they are escaped.
619 : */
620 154 : int unit_name_mangle_with_suffix(const char *name, UnitNameMangle allow_globs, const char *suffix, char **ret) {
621 : char *s, *t;
622 : int r;
623 :
624 154 : assert(name);
625 154 : assert(suffix);
626 154 : assert(ret);
627 :
628 154 : if (isempty(name)) /* We cannot mangle empty unit names to become valid, sorry. */
629 1 : return -EINVAL;
630 :
631 153 : if (!unit_suffix_is_valid(suffix))
632 0 : return -EINVAL;
633 :
634 153 : if (unit_name_is_valid(name, UNIT_NAME_ANY)) {
635 : /* No mangling necessary... */
636 10 : s = strdup(name);
637 10 : if (!s)
638 0 : return -ENOMEM;
639 :
640 10 : *ret = s;
641 10 : return 0;
642 : }
643 :
644 143 : if (is_device_path(name)) {
645 1 : r = unit_name_from_path(name, ".device", ret);
646 1 : if (r >= 0)
647 1 : return 1;
648 0 : if (r != -EINVAL)
649 0 : return r;
650 : }
651 :
652 142 : if (path_is_absolute(name)) {
653 1 : r = unit_name_from_path(name, ".mount", ret);
654 1 : if (r >= 0)
655 1 : return 1;
656 0 : if (r != -EINVAL)
657 0 : return r;
658 : }
659 :
660 141 : s = new(char, strlen(name) * 4 + strlen(suffix) + 1);
661 141 : if (!s)
662 0 : return -ENOMEM;
663 :
664 141 : t = do_escape_mangle(name, allow_globs, s);
665 141 : *t = 0;
666 :
667 141 : if (unit_name_to_type(s) < 0)
668 137 : strcpy(t, suffix);
669 :
670 141 : *ret = s;
671 141 : return 1;
672 : }
673 :
674 21 : int slice_build_parent_slice(const char *slice, char **ret) {
675 : char *s, *dash;
676 :
677 21 : assert(slice);
678 21 : assert(ret);
679 :
680 21 : if (!slice_name_is_valid(slice))
681 5 : return -EINVAL;
682 :
683 16 : if (streq(slice, "-.slice")) {
684 11 : *ret = NULL;
685 11 : return 0;
686 : }
687 :
688 5 : s = strdup(slice);
689 5 : if (!s)
690 0 : return -ENOMEM;
691 :
692 5 : dash = strrchr(s, '-');
693 5 : if (dash)
694 3 : strcpy(dash, ".slice");
695 : else {
696 2 : free(s);
697 :
698 2 : s = strdup("-.slice");
699 2 : if (!s)
700 0 : return -ENOMEM;
701 : }
702 :
703 5 : *ret = s;
704 5 : return 1;
705 : }
706 :
707 6 : int slice_build_subslice(const char *slice, const char*name, char **ret) {
708 : char *subslice;
709 :
710 6 : assert(slice);
711 6 : assert(name);
712 6 : assert(ret);
713 :
714 6 : if (!slice_name_is_valid(slice))
715 2 : return -EINVAL;
716 :
717 4 : if (!unit_prefix_is_valid(name))
718 0 : return -EINVAL;
719 :
720 4 : if (streq(slice, "-.slice"))
721 1 : subslice = strappend(name, ".slice");
722 : else {
723 : char *e;
724 :
725 3 : assert_se(e = endswith(slice, ".slice"));
726 :
727 3 : subslice = new(char, (e - slice) + 1 + strlen(name) + 6 + 1);
728 3 : if (!subslice)
729 0 : return -ENOMEM;
730 :
731 3 : stpcpy(stpcpy(stpcpy(mempcpy(subslice, slice, e - slice), "-"), name), ".slice");
732 : }
733 :
734 4 : *ret = subslice;
735 4 : return 0;
736 : }
737 :
738 51 : bool slice_name_is_valid(const char *name) {
739 : const char *p, *e;
740 51 : bool dash = false;
741 :
742 51 : if (!unit_name_is_valid(name, UNIT_NAME_PLAIN))
743 4 : return false;
744 :
745 47 : if (streq(name, "-.slice"))
746 23 : return true;
747 :
748 24 : e = endswith(name, ".slice");
749 24 : if (!e)
750 3 : return false;
751 :
752 161 : for (p = name; p < e; p++) {
753 :
754 146 : if (*p == '-') {
755 :
756 : /* Don't allow initial dash */
757 27 : if (p == name)
758 3 : return false;
759 :
760 : /* Don't allow multiple dashes */
761 24 : if (dash)
762 3 : return false;
763 :
764 21 : dash = true;
765 : } else
766 119 : dash = false;
767 : }
768 :
769 : /* Don't allow trailing hash */
770 15 : if (dash)
771 2 : return false;
772 :
773 13 : return true;
774 : }
775 :
776 : static const char* const unit_type_table[_UNIT_TYPE_MAX] = {
777 : [UNIT_SERVICE] = "service",
778 : [UNIT_SOCKET] = "socket",
779 : [UNIT_BUSNAME] = "busname",
780 : [UNIT_TARGET] = "target",
781 : [UNIT_SNAPSHOT] = "snapshot",
782 : [UNIT_DEVICE] = "device",
783 : [UNIT_MOUNT] = "mount",
784 : [UNIT_AUTOMOUNT] = "automount",
785 : [UNIT_SWAP] = "swap",
786 : [UNIT_TIMER] = "timer",
787 : [UNIT_PATH] = "path",
788 : [UNIT_SLICE] = "slice",
789 : [UNIT_SCOPE] = "scope"
790 : };
791 :
792 12693 : DEFINE_STRING_TABLE_LOOKUP(unit_type, UnitType);
793 :
794 : static const char* const unit_load_state_table[_UNIT_LOAD_STATE_MAX] = {
795 : [UNIT_STUB] = "stub",
796 : [UNIT_LOADED] = "loaded",
797 : [UNIT_NOT_FOUND] = "not-found",
798 : [UNIT_ERROR] = "error",
799 : [UNIT_MERGED] = "merged",
800 : [UNIT_MASKED] = "masked"
801 : };
802 :
803 341 : DEFINE_STRING_TABLE_LOOKUP(unit_load_state, UnitLoadState);
804 :
805 : static const char* const unit_dependency_table[_UNIT_DEPENDENCY_MAX] = {
806 : [UNIT_REQUIRES] = "Requires",
807 : [UNIT_REQUIRES_OVERRIDABLE] = "RequiresOverridable",
808 : [UNIT_REQUISITE] = "Requisite",
809 : [UNIT_REQUISITE_OVERRIDABLE] = "RequisiteOverridable",
810 : [UNIT_WANTS] = "Wants",
811 : [UNIT_BINDS_TO] = "BindsTo",
812 : [UNIT_PART_OF] = "PartOf",
813 : [UNIT_REQUIRED_BY] = "RequiredBy",
814 : [UNIT_REQUIRED_BY_OVERRIDABLE] = "RequiredByOverridable",
815 : [UNIT_REQUISITE_OF] = "RequisiteOf",
816 : [UNIT_REQUISITE_OF_OVERRIDABLE] = "RequisiteOfOverridable",
817 : [UNIT_WANTED_BY] = "WantedBy",
818 : [UNIT_BOUND_BY] = "BoundBy",
819 : [UNIT_CONSISTS_OF] = "ConsistsOf",
820 : [UNIT_CONFLICTS] = "Conflicts",
821 : [UNIT_CONFLICTED_BY] = "ConflictedBy",
822 : [UNIT_BEFORE] = "Before",
823 : [UNIT_AFTER] = "After",
824 : [UNIT_ON_FAILURE] = "OnFailure",
825 : [UNIT_TRIGGERS] = "Triggers",
826 : [UNIT_TRIGGERED_BY] = "TriggeredBy",
827 : [UNIT_PROPAGATES_RELOAD_TO] = "PropagatesReloadTo",
828 : [UNIT_RELOAD_PROPAGATED_FROM] = "ReloadPropagatedFrom",
829 : [UNIT_JOINS_NAMESPACE_OF] = "JoinsNamespaceOf",
830 : [UNIT_REFERENCES] = "References",
831 : [UNIT_REFERENCED_BY] = "ReferencedBy",
832 : };
833 :
834 1398 : DEFINE_STRING_TABLE_LOOKUP(unit_dependency, UnitDependency);
|