]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/unit-name.c
util-lib: move string table stuff into its own string-table.[ch]
[thirdparty/systemd.git] / src / basic / unit-name.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 <errno.h>
23 #include <string.h>
24
25 #include "bus-label.h"
26 #include "def.h"
27 #include "hexdecoct.h"
28 #include "path-util.h"
29 #include "string-table.h"
30 #include "string-util.h"
31 #include "strv.h"
32 #include "unit-name.h"
33 #include "util.h"
34
35 #define VALID_CHARS \
36 DIGITS LETTERS \
37 ":-_.\\"
38
39 bool unit_name_is_valid(const char *n, UnitNameFlags flags) {
40 const char *e, *i, *at;
41
42 assert((flags & ~(UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE)) == 0);
43
44 if (_unlikely_(flags == 0))
45 return false;
46
47 if (isempty(n))
48 return false;
49
50 if (strlen(n) >= UNIT_NAME_MAX)
51 return false;
52
53 e = strrchr(n, '.');
54 if (!e || e == n)
55 return false;
56
57 if (unit_type_from_string(e + 1) < 0)
58 return false;
59
60 for (i = n, at = NULL; i < e; i++) {
61
62 if (*i == '@' && !at)
63 at = i;
64
65 if (!strchr("@" VALID_CHARS, *i))
66 return false;
67 }
68
69 if (at == n)
70 return false;
71
72 if (flags & UNIT_NAME_PLAIN)
73 if (!at)
74 return true;
75
76 if (flags & UNIT_NAME_INSTANCE)
77 if (at && e > at + 1)
78 return true;
79
80 if (flags & UNIT_NAME_TEMPLATE)
81 if (at && e == at + 1)
82 return true;
83
84 return false;
85 }
86
87 bool unit_prefix_is_valid(const char *p) {
88
89 /* We don't allow additional @ in the prefix string */
90
91 if (isempty(p))
92 return false;
93
94 return in_charset(p, VALID_CHARS);
95 }
96
97 bool unit_instance_is_valid(const char *i) {
98
99 /* The max length depends on the length of the string, so we
100 * don't really check this here. */
101
102 if (isempty(i))
103 return false;
104
105 /* We allow additional @ in the instance string, we do not
106 * allow them in the prefix! */
107
108 return in_charset(i, "@" VALID_CHARS);
109 }
110
111 bool unit_suffix_is_valid(const char *s) {
112 if (isempty(s))
113 return false;
114
115 if (s[0] != '.')
116 return false;
117
118 if (unit_type_from_string(s + 1) < 0)
119 return false;
120
121 return true;
122 }
123
124 int unit_name_to_prefix(const char *n, char **ret) {
125 const char *p;
126 char *s;
127
128 assert(n);
129 assert(ret);
130
131 if (!unit_name_is_valid(n, UNIT_NAME_ANY))
132 return -EINVAL;
133
134 p = strchr(n, '@');
135 if (!p)
136 p = strrchr(n, '.');
137
138 assert_se(p);
139
140 s = strndup(n, p - n);
141 if (!s)
142 return -ENOMEM;
143
144 *ret = s;
145 return 0;
146 }
147
148 int unit_name_to_instance(const char *n, char **instance) {
149 const char *p, *d;
150 char *i;
151
152 assert(n);
153 assert(instance);
154
155 if (!unit_name_is_valid(n, UNIT_NAME_ANY))
156 return -EINVAL;
157
158 /* Everything past the first @ and before the last . is the instance */
159 p = strchr(n, '@');
160 if (!p) {
161 *instance = NULL;
162 return 0;
163 }
164
165 p++;
166
167 d = strrchr(p, '.');
168 if (!d)
169 return -EINVAL;
170
171 i = strndup(p, d-p);
172 if (!i)
173 return -ENOMEM;
174
175 *instance = i;
176 return 1;
177 }
178
179 int unit_name_to_prefix_and_instance(const char *n, char **ret) {
180 const char *d;
181 char *s;
182
183 assert(n);
184 assert(ret);
185
186 if (!unit_name_is_valid(n, UNIT_NAME_ANY))
187 return -EINVAL;
188
189 d = strrchr(n, '.');
190 if (!d)
191 return -EINVAL;
192
193 s = strndup(n, d - n);
194 if (!s)
195 return -ENOMEM;
196
197 *ret = s;
198 return 0;
199 }
200
201 UnitType unit_name_to_type(const char *n) {
202 const char *e;
203
204 assert(n);
205
206 if (!unit_name_is_valid(n, UNIT_NAME_ANY))
207 return _UNIT_TYPE_INVALID;
208
209 assert_se(e = strrchr(n, '.'));
210
211 return unit_type_from_string(e + 1);
212 }
213
214 int unit_name_change_suffix(const char *n, const char *suffix, char **ret) {
215 char *e, *s;
216 size_t a, b;
217
218 assert(n);
219 assert(suffix);
220 assert(ret);
221
222 if (!unit_name_is_valid(n, UNIT_NAME_ANY))
223 return -EINVAL;
224
225 if (!unit_suffix_is_valid(suffix))
226 return -EINVAL;
227
228 assert_se(e = strrchr(n, '.'));
229
230 a = e - n;
231 b = strlen(suffix);
232
233 s = new(char, a + b + 1);
234 if (!s)
235 return -ENOMEM;
236
237 strcpy(mempcpy(s, n, a), suffix);
238 *ret = s;
239
240 return 0;
241 }
242
243 int unit_name_build(const char *prefix, const char *instance, const char *suffix, char **ret) {
244 char *s;
245
246 assert(prefix);
247 assert(suffix);
248 assert(ret);
249
250 if (!unit_prefix_is_valid(prefix))
251 return -EINVAL;
252
253 if (instance && !unit_instance_is_valid(instance))
254 return -EINVAL;
255
256 if (!unit_suffix_is_valid(suffix))
257 return -EINVAL;
258
259 if (!instance)
260 s = strappend(prefix, suffix);
261 else
262 s = strjoin(prefix, "@", instance, suffix, NULL);
263 if (!s)
264 return -ENOMEM;
265
266 *ret = s;
267 return 0;
268 }
269
270 static char *do_escape_char(char c, char *t) {
271 assert(t);
272
273 *(t++) = '\\';
274 *(t++) = 'x';
275 *(t++) = hexchar(c >> 4);
276 *(t++) = hexchar(c);
277
278 return t;
279 }
280
281 static char *do_escape(const char *f, char *t) {
282 assert(f);
283 assert(t);
284
285 /* do not create units with a leading '.', like for "/.dotdir" mount points */
286 if (*f == '.') {
287 t = do_escape_char(*f, t);
288 f++;
289 }
290
291 for (; *f; f++) {
292 if (*f == '/')
293 *(t++) = '-';
294 else if (*f == '-' || *f == '\\' || !strchr(VALID_CHARS, *f))
295 t = do_escape_char(*f, t);
296 else
297 *(t++) = *f;
298 }
299
300 return t;
301 }
302
303 char *unit_name_escape(const char *f) {
304 char *r, *t;
305
306 assert(f);
307
308 r = new(char, strlen(f)*4+1);
309 if (!r)
310 return NULL;
311
312 t = do_escape(f, r);
313 *t = 0;
314
315 return r;
316 }
317
318 int unit_name_unescape(const char *f, char **ret) {
319 _cleanup_free_ char *r = NULL;
320 char *t;
321
322 assert(f);
323
324 r = strdup(f);
325 if (!r)
326 return -ENOMEM;
327
328 for (t = r; *f; f++) {
329 if (*f == '-')
330 *(t++) = '/';
331 else if (*f == '\\') {
332 int a, b;
333
334 if (f[1] != 'x')
335 return -EINVAL;
336
337 a = unhexchar(f[2]);
338 if (a < 0)
339 return -EINVAL;
340
341 b = unhexchar(f[3]);
342 if (b < 0)
343 return -EINVAL;
344
345 *(t++) = (char) (((uint8_t) a << 4U) | (uint8_t) b);
346 f += 3;
347 } else
348 *(t++) = *f;
349 }
350
351 *t = 0;
352
353 *ret = r;
354 r = NULL;
355
356 return 0;
357 }
358
359 int unit_name_path_escape(const char *f, char **ret) {
360 char *p, *s;
361
362 assert(f);
363 assert(ret);
364
365 p = strdupa(f);
366 if (!p)
367 return -ENOMEM;
368
369 path_kill_slashes(p);
370
371 if (STR_IN_SET(p, "/", ""))
372 s = strdup("-");
373 else {
374 char *e;
375
376 if (!path_is_safe(p))
377 return -EINVAL;
378
379 /* Truncate trailing slashes */
380 e = endswith(p, "/");
381 if (e)
382 *e = 0;
383
384 /* Truncate leading slashes */
385 if (p[0] == '/')
386 p++;
387
388 s = unit_name_escape(p);
389 }
390 if (!s)
391 return -ENOMEM;
392
393 *ret = s;
394 return 0;
395 }
396
397 int unit_name_path_unescape(const char *f, char **ret) {
398 char *s;
399 int r;
400
401 assert(f);
402
403 if (isempty(f))
404 return -EINVAL;
405
406 if (streq(f, "-")) {
407 s = strdup("/");
408 if (!s)
409 return -ENOMEM;
410 } else {
411 char *w;
412
413 r = unit_name_unescape(f, &w);
414 if (r < 0)
415 return r;
416
417 /* Don't accept trailing or leading slashes */
418 if (startswith(w, "/") || endswith(w, "/")) {
419 free(w);
420 return -EINVAL;
421 }
422
423 /* Prefix a slash again */
424 s = strappend("/", w);
425 free(w);
426 if (!s)
427 return -ENOMEM;
428
429 if (!path_is_safe(s)) {
430 free(s);
431 return -EINVAL;
432 }
433 }
434
435 if (ret)
436 *ret = s;
437 else
438 free(s);
439
440 return 0;
441 }
442
443 int unit_name_replace_instance(const char *f, const char *i, char **ret) {
444 const char *p, *e;
445 char *s;
446 size_t a, b;
447
448 assert(f);
449 assert(i);
450 assert(ret);
451
452 if (!unit_name_is_valid(f, UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE))
453 return -EINVAL;
454 if (!unit_instance_is_valid(i))
455 return -EINVAL;
456
457 assert_se(p = strchr(f, '@'));
458 assert_se(e = strrchr(f, '.'));
459
460 a = p - f;
461 b = strlen(i);
462
463 s = new(char, a + 1 + b + strlen(e) + 1);
464 if (!s)
465 return -ENOMEM;
466
467 strcpy(mempcpy(mempcpy(s, f, a + 1), i, b), e);
468
469 *ret = s;
470 return 0;
471 }
472
473 int unit_name_template(const char *f, char **ret) {
474 const char *p, *e;
475 char *s;
476 size_t a;
477
478 assert(f);
479 assert(ret);
480
481 if (!unit_name_is_valid(f, UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE))
482 return -EINVAL;
483
484 assert_se(p = strchr(f, '@'));
485 assert_se(e = strrchr(f, '.'));
486
487 a = p - f;
488
489 s = new(char, a + 1 + strlen(e) + 1);
490 if (!s)
491 return -ENOMEM;
492
493 strcpy(mempcpy(s, f, a + 1), e);
494
495 *ret = s;
496 return 0;
497 }
498
499 int unit_name_from_path(const char *path, const char *suffix, char **ret) {
500 _cleanup_free_ char *p = NULL;
501 char *s = NULL;
502 int r;
503
504 assert(path);
505 assert(suffix);
506 assert(ret);
507
508 if (!unit_suffix_is_valid(suffix))
509 return -EINVAL;
510
511 r = unit_name_path_escape(path, &p);
512 if (r < 0)
513 return r;
514
515 s = strappend(p, suffix);
516 if (!s)
517 return -ENOMEM;
518
519 *ret = s;
520 return 0;
521 }
522
523 int unit_name_from_path_instance(const char *prefix, const char *path, const char *suffix, char **ret) {
524 _cleanup_free_ char *p = NULL;
525 char *s;
526 int r;
527
528 assert(prefix);
529 assert(path);
530 assert(suffix);
531 assert(ret);
532
533 if (!unit_prefix_is_valid(prefix))
534 return -EINVAL;
535
536 if (!unit_suffix_is_valid(suffix))
537 return -EINVAL;
538
539 r = unit_name_path_escape(path, &p);
540 if (r < 0)
541 return r;
542
543 s = strjoin(prefix, "@", p, suffix, NULL);
544 if (!s)
545 return -ENOMEM;
546
547 *ret = s;
548 return 0;
549 }
550
551 int unit_name_to_path(const char *name, char **ret) {
552 _cleanup_free_ char *prefix = NULL;
553 int r;
554
555 assert(name);
556
557 r = unit_name_to_prefix(name, &prefix);
558 if (r < 0)
559 return r;
560
561 return unit_name_path_unescape(prefix, ret);
562 }
563
564 char *unit_dbus_path_from_name(const char *name) {
565 _cleanup_free_ char *e = NULL;
566
567 assert(name);
568
569 e = bus_label_escape(name);
570 if (!e)
571 return NULL;
572
573 return strappend("/org/freedesktop/systemd1/unit/", e);
574 }
575
576 int unit_name_from_dbus_path(const char *path, char **name) {
577 const char *e;
578 char *n;
579
580 e = startswith(path, "/org/freedesktop/systemd1/unit/");
581 if (!e)
582 return -EINVAL;
583
584 n = bus_label_unescape(e);
585 if (!n)
586 return -ENOMEM;
587
588 *name = n;
589 return 0;
590 }
591
592 const char* unit_dbus_interface_from_type(UnitType t) {
593
594 static const char *const table[_UNIT_TYPE_MAX] = {
595 [UNIT_SERVICE] = "org.freedesktop.systemd1.Service",
596 [UNIT_SOCKET] = "org.freedesktop.systemd1.Socket",
597 [UNIT_BUSNAME] = "org.freedesktop.systemd1.BusName",
598 [UNIT_TARGET] = "org.freedesktop.systemd1.Target",
599 [UNIT_SNAPSHOT] = "org.freedesktop.systemd1.Snapshot",
600 [UNIT_DEVICE] = "org.freedesktop.systemd1.Device",
601 [UNIT_MOUNT] = "org.freedesktop.systemd1.Mount",
602 [UNIT_AUTOMOUNT] = "org.freedesktop.systemd1.Automount",
603 [UNIT_SWAP] = "org.freedesktop.systemd1.Swap",
604 [UNIT_TIMER] = "org.freedesktop.systemd1.Timer",
605 [UNIT_PATH] = "org.freedesktop.systemd1.Path",
606 [UNIT_SLICE] = "org.freedesktop.systemd1.Slice",
607 [UNIT_SCOPE] = "org.freedesktop.systemd1.Scope",
608 };
609
610 if (t < 0)
611 return NULL;
612 if (t >= _UNIT_TYPE_MAX)
613 return NULL;
614
615 return table[t];
616 }
617
618 const char *unit_dbus_interface_from_name(const char *name) {
619 UnitType t;
620
621 t = unit_name_to_type(name);
622 if (t < 0)
623 return NULL;
624
625 return unit_dbus_interface_from_type(t);
626 }
627
628 static char *do_escape_mangle(const char *f, UnitNameMangle allow_globs, char *t) {
629 const char *valid_chars;
630
631 assert(f);
632 assert(IN_SET(allow_globs, UNIT_NAME_GLOB, UNIT_NAME_NOGLOB));
633 assert(t);
634
635 /* We'll only escape the obvious characters here, to play
636 * safe. */
637
638 valid_chars = allow_globs == UNIT_NAME_GLOB ? "@" VALID_CHARS "[]!-*?" : "@" VALID_CHARS;
639
640 for (; *f; f++) {
641 if (*f == '/')
642 *(t++) = '-';
643 else if (!strchr(valid_chars, *f))
644 t = do_escape_char(*f, t);
645 else
646 *(t++) = *f;
647 }
648
649 return t;
650 }
651
652 /**
653 * Convert a string to a unit name. /dev/blah is converted to dev-blah.device,
654 * /blah/blah is converted to blah-blah.mount, anything else is left alone,
655 * except that @suffix is appended if a valid unit suffix is not present.
656 *
657 * If @allow_globs, globs characters are preserved. Otherwise they are escaped.
658 */
659 int unit_name_mangle_with_suffix(const char *name, UnitNameMangle allow_globs, const char *suffix, char **ret) {
660 char *s, *t;
661 int r;
662
663 assert(name);
664 assert(suffix);
665 assert(ret);
666
667 if (isempty(name)) /* We cannot mangle empty unit names to become valid, sorry. */
668 return -EINVAL;
669
670 if (!unit_suffix_is_valid(suffix))
671 return -EINVAL;
672
673 if (unit_name_is_valid(name, UNIT_NAME_ANY)) {
674 /* No mangling necessary... */
675 s = strdup(name);
676 if (!s)
677 return -ENOMEM;
678
679 *ret = s;
680 return 0;
681 }
682
683 if (is_device_path(name)) {
684 r = unit_name_from_path(name, ".device", ret);
685 if (r >= 0)
686 return 1;
687 if (r != -EINVAL)
688 return r;
689 }
690
691 if (path_is_absolute(name)) {
692 r = unit_name_from_path(name, ".mount", ret);
693 if (r >= 0)
694 return 1;
695 if (r != -EINVAL)
696 return r;
697 }
698
699 s = new(char, strlen(name) * 4 + strlen(suffix) + 1);
700 if (!s)
701 return -ENOMEM;
702
703 t = do_escape_mangle(name, allow_globs, s);
704 *t = 0;
705
706 if (unit_name_to_type(s) < 0)
707 strcpy(t, suffix);
708
709 *ret = s;
710 return 1;
711 }
712
713 int slice_build_parent_slice(const char *slice, char **ret) {
714 char *s, *dash;
715 int r;
716
717 assert(slice);
718 assert(ret);
719
720 if (!slice_name_is_valid(slice))
721 return -EINVAL;
722
723 if (streq(slice, "-.slice")) {
724 *ret = NULL;
725 return 0;
726 }
727
728 s = strdup(slice);
729 if (!s)
730 return -ENOMEM;
731
732 dash = strrchr(s, '-');
733 if (dash)
734 strcpy(dash, ".slice");
735 else {
736 r = free_and_strdup(&s, "-.slice");
737 if (r < 0) {
738 free(s);
739 return r;
740 }
741 }
742
743 *ret = s;
744 return 1;
745 }
746
747 int slice_build_subslice(const char *slice, const char*name, char **ret) {
748 char *subslice;
749
750 assert(slice);
751 assert(name);
752 assert(ret);
753
754 if (!slice_name_is_valid(slice))
755 return -EINVAL;
756
757 if (!unit_prefix_is_valid(name))
758 return -EINVAL;
759
760 if (streq(slice, "-.slice"))
761 subslice = strappend(name, ".slice");
762 else {
763 char *e;
764
765 assert_se(e = endswith(slice, ".slice"));
766
767 subslice = new(char, (e - slice) + 1 + strlen(name) + 6 + 1);
768 if (!subslice)
769 return -ENOMEM;
770
771 stpcpy(stpcpy(stpcpy(mempcpy(subslice, slice, e - slice), "-"), name), ".slice");
772 }
773
774 *ret = subslice;
775 return 0;
776 }
777
778 bool slice_name_is_valid(const char *name) {
779 const char *p, *e;
780 bool dash = false;
781
782 if (!unit_name_is_valid(name, UNIT_NAME_PLAIN))
783 return false;
784
785 if (streq(name, "-.slice"))
786 return true;
787
788 e = endswith(name, ".slice");
789 if (!e)
790 return false;
791
792 for (p = name; p < e; p++) {
793
794 if (*p == '-') {
795
796 /* Don't allow initial dash */
797 if (p == name)
798 return false;
799
800 /* Don't allow multiple dashes */
801 if (dash)
802 return false;
803
804 dash = true;
805 } else
806 dash = false;
807 }
808
809 /* Don't allow trailing hash */
810 if (dash)
811 return false;
812
813 return true;
814 }
815
816 static const char* const unit_type_table[_UNIT_TYPE_MAX] = {
817 [UNIT_SERVICE] = "service",
818 [UNIT_SOCKET] = "socket",
819 [UNIT_BUSNAME] = "busname",
820 [UNIT_TARGET] = "target",
821 [UNIT_SNAPSHOT] = "snapshot",
822 [UNIT_DEVICE] = "device",
823 [UNIT_MOUNT] = "mount",
824 [UNIT_AUTOMOUNT] = "automount",
825 [UNIT_SWAP] = "swap",
826 [UNIT_TIMER] = "timer",
827 [UNIT_PATH] = "path",
828 [UNIT_SLICE] = "slice",
829 [UNIT_SCOPE] = "scope",
830 };
831
832 DEFINE_STRING_TABLE_LOOKUP(unit_type, UnitType);
833
834 static const char* const unit_load_state_table[_UNIT_LOAD_STATE_MAX] = {
835 [UNIT_STUB] = "stub",
836 [UNIT_LOADED] = "loaded",
837 [UNIT_NOT_FOUND] = "not-found",
838 [UNIT_ERROR] = "error",
839 [UNIT_MERGED] = "merged",
840 [UNIT_MASKED] = "masked"
841 };
842
843 DEFINE_STRING_TABLE_LOOKUP(unit_load_state, UnitLoadState);
844
845 static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = {
846 [UNIT_ACTIVE] = "active",
847 [UNIT_RELOADING] = "reloading",
848 [UNIT_INACTIVE] = "inactive",
849 [UNIT_FAILED] = "failed",
850 [UNIT_ACTIVATING] = "activating",
851 [UNIT_DEACTIVATING] = "deactivating"
852 };
853
854 DEFINE_STRING_TABLE_LOOKUP(unit_active_state, UnitActiveState);
855
856 static const char* const automount_state_table[_AUTOMOUNT_STATE_MAX] = {
857 [AUTOMOUNT_DEAD] = "dead",
858 [AUTOMOUNT_WAITING] = "waiting",
859 [AUTOMOUNT_RUNNING] = "running",
860 [AUTOMOUNT_FAILED] = "failed"
861 };
862
863 DEFINE_STRING_TABLE_LOOKUP(automount_state, AutomountState);
864
865 static const char* const busname_state_table[_BUSNAME_STATE_MAX] = {
866 [BUSNAME_DEAD] = "dead",
867 [BUSNAME_MAKING] = "making",
868 [BUSNAME_REGISTERED] = "registered",
869 [BUSNAME_LISTENING] = "listening",
870 [BUSNAME_RUNNING] = "running",
871 [BUSNAME_SIGTERM] = "sigterm",
872 [BUSNAME_SIGKILL] = "sigkill",
873 [BUSNAME_FAILED] = "failed",
874 };
875
876 DEFINE_STRING_TABLE_LOOKUP(busname_state, BusNameState);
877
878 static const char* const device_state_table[_DEVICE_STATE_MAX] = {
879 [DEVICE_DEAD] = "dead",
880 [DEVICE_TENTATIVE] = "tentative",
881 [DEVICE_PLUGGED] = "plugged",
882 };
883
884 DEFINE_STRING_TABLE_LOOKUP(device_state, DeviceState);
885
886 static const char* const mount_state_table[_MOUNT_STATE_MAX] = {
887 [MOUNT_DEAD] = "dead",
888 [MOUNT_MOUNTING] = "mounting",
889 [MOUNT_MOUNTING_DONE] = "mounting-done",
890 [MOUNT_MOUNTED] = "mounted",
891 [MOUNT_REMOUNTING] = "remounting",
892 [MOUNT_UNMOUNTING] = "unmounting",
893 [MOUNT_MOUNTING_SIGTERM] = "mounting-sigterm",
894 [MOUNT_MOUNTING_SIGKILL] = "mounting-sigkill",
895 [MOUNT_REMOUNTING_SIGTERM] = "remounting-sigterm",
896 [MOUNT_REMOUNTING_SIGKILL] = "remounting-sigkill",
897 [MOUNT_UNMOUNTING_SIGTERM] = "unmounting-sigterm",
898 [MOUNT_UNMOUNTING_SIGKILL] = "unmounting-sigkill",
899 [MOUNT_FAILED] = "failed"
900 };
901
902 DEFINE_STRING_TABLE_LOOKUP(mount_state, MountState);
903
904 static const char* const path_state_table[_PATH_STATE_MAX] = {
905 [PATH_DEAD] = "dead",
906 [PATH_WAITING] = "waiting",
907 [PATH_RUNNING] = "running",
908 [PATH_FAILED] = "failed"
909 };
910
911 DEFINE_STRING_TABLE_LOOKUP(path_state, PathState);
912
913 static const char* const scope_state_table[_SCOPE_STATE_MAX] = {
914 [SCOPE_DEAD] = "dead",
915 [SCOPE_RUNNING] = "running",
916 [SCOPE_ABANDONED] = "abandoned",
917 [SCOPE_STOP_SIGTERM] = "stop-sigterm",
918 [SCOPE_STOP_SIGKILL] = "stop-sigkill",
919 [SCOPE_FAILED] = "failed",
920 };
921
922 DEFINE_STRING_TABLE_LOOKUP(scope_state, ScopeState);
923
924 static const char* const service_state_table[_SERVICE_STATE_MAX] = {
925 [SERVICE_DEAD] = "dead",
926 [SERVICE_START_PRE] = "start-pre",
927 [SERVICE_START] = "start",
928 [SERVICE_START_POST] = "start-post",
929 [SERVICE_RUNNING] = "running",
930 [SERVICE_EXITED] = "exited",
931 [SERVICE_RELOAD] = "reload",
932 [SERVICE_STOP] = "stop",
933 [SERVICE_STOP_SIGABRT] = "stop-sigabrt",
934 [SERVICE_STOP_SIGTERM] = "stop-sigterm",
935 [SERVICE_STOP_SIGKILL] = "stop-sigkill",
936 [SERVICE_STOP_POST] = "stop-post",
937 [SERVICE_FINAL_SIGTERM] = "final-sigterm",
938 [SERVICE_FINAL_SIGKILL] = "final-sigkill",
939 [SERVICE_FAILED] = "failed",
940 [SERVICE_AUTO_RESTART] = "auto-restart",
941 };
942
943 DEFINE_STRING_TABLE_LOOKUP(service_state, ServiceState);
944
945 static const char* const slice_state_table[_SLICE_STATE_MAX] = {
946 [SLICE_DEAD] = "dead",
947 [SLICE_ACTIVE] = "active"
948 };
949
950 DEFINE_STRING_TABLE_LOOKUP(slice_state, SliceState);
951
952 static const char* const snapshot_state_table[_SNAPSHOT_STATE_MAX] = {
953 [SNAPSHOT_DEAD] = "dead",
954 [SNAPSHOT_ACTIVE] = "active"
955 };
956
957 DEFINE_STRING_TABLE_LOOKUP(snapshot_state, SnapshotState);
958
959 static const char* const socket_state_table[_SOCKET_STATE_MAX] = {
960 [SOCKET_DEAD] = "dead",
961 [SOCKET_START_PRE] = "start-pre",
962 [SOCKET_START_CHOWN] = "start-chown",
963 [SOCKET_START_POST] = "start-post",
964 [SOCKET_LISTENING] = "listening",
965 [SOCKET_RUNNING] = "running",
966 [SOCKET_STOP_PRE] = "stop-pre",
967 [SOCKET_STOP_PRE_SIGTERM] = "stop-pre-sigterm",
968 [SOCKET_STOP_PRE_SIGKILL] = "stop-pre-sigkill",
969 [SOCKET_STOP_POST] = "stop-post",
970 [SOCKET_FINAL_SIGTERM] = "final-sigterm",
971 [SOCKET_FINAL_SIGKILL] = "final-sigkill",
972 [SOCKET_FAILED] = "failed"
973 };
974
975 DEFINE_STRING_TABLE_LOOKUP(socket_state, SocketState);
976
977 static const char* const swap_state_table[_SWAP_STATE_MAX] = {
978 [SWAP_DEAD] = "dead",
979 [SWAP_ACTIVATING] = "activating",
980 [SWAP_ACTIVATING_DONE] = "activating-done",
981 [SWAP_ACTIVE] = "active",
982 [SWAP_DEACTIVATING] = "deactivating",
983 [SWAP_ACTIVATING_SIGTERM] = "activating-sigterm",
984 [SWAP_ACTIVATING_SIGKILL] = "activating-sigkill",
985 [SWAP_DEACTIVATING_SIGTERM] = "deactivating-sigterm",
986 [SWAP_DEACTIVATING_SIGKILL] = "deactivating-sigkill",
987 [SWAP_FAILED] = "failed"
988 };
989
990 DEFINE_STRING_TABLE_LOOKUP(swap_state, SwapState);
991
992 static const char* const target_state_table[_TARGET_STATE_MAX] = {
993 [TARGET_DEAD] = "dead",
994 [TARGET_ACTIVE] = "active"
995 };
996
997 DEFINE_STRING_TABLE_LOOKUP(target_state, TargetState);
998
999 static const char* const timer_state_table[_TIMER_STATE_MAX] = {
1000 [TIMER_DEAD] = "dead",
1001 [TIMER_WAITING] = "waiting",
1002 [TIMER_RUNNING] = "running",
1003 [TIMER_ELAPSED] = "elapsed",
1004 [TIMER_FAILED] = "failed"
1005 };
1006
1007 DEFINE_STRING_TABLE_LOOKUP(timer_state, TimerState);
1008
1009 static const char* const unit_dependency_table[_UNIT_DEPENDENCY_MAX] = {
1010 [UNIT_REQUIRES] = "Requires",
1011 [UNIT_REQUIRES_OVERRIDABLE] = "RequiresOverridable",
1012 [UNIT_REQUISITE] = "Requisite",
1013 [UNIT_REQUISITE_OVERRIDABLE] = "RequisiteOverridable",
1014 [UNIT_WANTS] = "Wants",
1015 [UNIT_BINDS_TO] = "BindsTo",
1016 [UNIT_PART_OF] = "PartOf",
1017 [UNIT_REQUIRED_BY] = "RequiredBy",
1018 [UNIT_REQUIRED_BY_OVERRIDABLE] = "RequiredByOverridable",
1019 [UNIT_REQUISITE_OF] = "RequisiteOf",
1020 [UNIT_REQUISITE_OF_OVERRIDABLE] = "RequisiteOfOverridable",
1021 [UNIT_WANTED_BY] = "WantedBy",
1022 [UNIT_BOUND_BY] = "BoundBy",
1023 [UNIT_CONSISTS_OF] = "ConsistsOf",
1024 [UNIT_CONFLICTS] = "Conflicts",
1025 [UNIT_CONFLICTED_BY] = "ConflictedBy",
1026 [UNIT_BEFORE] = "Before",
1027 [UNIT_AFTER] = "After",
1028 [UNIT_ON_FAILURE] = "OnFailure",
1029 [UNIT_TRIGGERS] = "Triggers",
1030 [UNIT_TRIGGERED_BY] = "TriggeredBy",
1031 [UNIT_PROPAGATES_RELOAD_TO] = "PropagatesReloadTo",
1032 [UNIT_RELOAD_PROPAGATED_FROM] = "ReloadPropagatedFrom",
1033 [UNIT_JOINS_NAMESPACE_OF] = "JoinsNamespaceOf",
1034 [UNIT_REFERENCES] = "References",
1035 [UNIT_REFERENCED_BY] = "ReferencedBy",
1036 };
1037
1038 DEFINE_STRING_TABLE_LOOKUP(unit_dependency, UnitDependency);