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