]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/unit-name.c
Merge pull request #1880 from fsateler/sysctl-doc
[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_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_DEVICE] = "device",
822 [UNIT_MOUNT] = "mount",
823 [UNIT_AUTOMOUNT] = "automount",
824 [UNIT_SWAP] = "swap",
825 [UNIT_TIMER] = "timer",
826 [UNIT_PATH] = "path",
827 [UNIT_SLICE] = "slice",
828 [UNIT_SCOPE] = "scope",
829 };
830
831 DEFINE_STRING_TABLE_LOOKUP(unit_type, UnitType);
832
833 static const char* const unit_load_state_table[_UNIT_LOAD_STATE_MAX] = {
834 [UNIT_STUB] = "stub",
835 [UNIT_LOADED] = "loaded",
836 [UNIT_NOT_FOUND] = "not-found",
837 [UNIT_ERROR] = "error",
838 [UNIT_MERGED] = "merged",
839 [UNIT_MASKED] = "masked"
840 };
841
842 DEFINE_STRING_TABLE_LOOKUP(unit_load_state, UnitLoadState);
843
844 static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = {
845 [UNIT_ACTIVE] = "active",
846 [UNIT_RELOADING] = "reloading",
847 [UNIT_INACTIVE] = "inactive",
848 [UNIT_FAILED] = "failed",
849 [UNIT_ACTIVATING] = "activating",
850 [UNIT_DEACTIVATING] = "deactivating"
851 };
852
853 DEFINE_STRING_TABLE_LOOKUP(unit_active_state, UnitActiveState);
854
855 static const char* const automount_state_table[_AUTOMOUNT_STATE_MAX] = {
856 [AUTOMOUNT_DEAD] = "dead",
857 [AUTOMOUNT_WAITING] = "waiting",
858 [AUTOMOUNT_RUNNING] = "running",
859 [AUTOMOUNT_FAILED] = "failed"
860 };
861
862 DEFINE_STRING_TABLE_LOOKUP(automount_state, AutomountState);
863
864 static const char* const busname_state_table[_BUSNAME_STATE_MAX] = {
865 [BUSNAME_DEAD] = "dead",
866 [BUSNAME_MAKING] = "making",
867 [BUSNAME_REGISTERED] = "registered",
868 [BUSNAME_LISTENING] = "listening",
869 [BUSNAME_RUNNING] = "running",
870 [BUSNAME_SIGTERM] = "sigterm",
871 [BUSNAME_SIGKILL] = "sigkill",
872 [BUSNAME_FAILED] = "failed",
873 };
874
875 DEFINE_STRING_TABLE_LOOKUP(busname_state, BusNameState);
876
877 static const char* const device_state_table[_DEVICE_STATE_MAX] = {
878 [DEVICE_DEAD] = "dead",
879 [DEVICE_TENTATIVE] = "tentative",
880 [DEVICE_PLUGGED] = "plugged",
881 };
882
883 DEFINE_STRING_TABLE_LOOKUP(device_state, DeviceState);
884
885 static const char* const mount_state_table[_MOUNT_STATE_MAX] = {
886 [MOUNT_DEAD] = "dead",
887 [MOUNT_MOUNTING] = "mounting",
888 [MOUNT_MOUNTING_DONE] = "mounting-done",
889 [MOUNT_MOUNTED] = "mounted",
890 [MOUNT_REMOUNTING] = "remounting",
891 [MOUNT_UNMOUNTING] = "unmounting",
892 [MOUNT_MOUNTING_SIGTERM] = "mounting-sigterm",
893 [MOUNT_MOUNTING_SIGKILL] = "mounting-sigkill",
894 [MOUNT_REMOUNTING_SIGTERM] = "remounting-sigterm",
895 [MOUNT_REMOUNTING_SIGKILL] = "remounting-sigkill",
896 [MOUNT_UNMOUNTING_SIGTERM] = "unmounting-sigterm",
897 [MOUNT_UNMOUNTING_SIGKILL] = "unmounting-sigkill",
898 [MOUNT_FAILED] = "failed"
899 };
900
901 DEFINE_STRING_TABLE_LOOKUP(mount_state, MountState);
902
903 static const char* const path_state_table[_PATH_STATE_MAX] = {
904 [PATH_DEAD] = "dead",
905 [PATH_WAITING] = "waiting",
906 [PATH_RUNNING] = "running",
907 [PATH_FAILED] = "failed"
908 };
909
910 DEFINE_STRING_TABLE_LOOKUP(path_state, PathState);
911
912 static const char* const scope_state_table[_SCOPE_STATE_MAX] = {
913 [SCOPE_DEAD] = "dead",
914 [SCOPE_RUNNING] = "running",
915 [SCOPE_ABANDONED] = "abandoned",
916 [SCOPE_STOP_SIGTERM] = "stop-sigterm",
917 [SCOPE_STOP_SIGKILL] = "stop-sigkill",
918 [SCOPE_FAILED] = "failed",
919 };
920
921 DEFINE_STRING_TABLE_LOOKUP(scope_state, ScopeState);
922
923 static const char* const service_state_table[_SERVICE_STATE_MAX] = {
924 [SERVICE_DEAD] = "dead",
925 [SERVICE_START_PRE] = "start-pre",
926 [SERVICE_START] = "start",
927 [SERVICE_START_POST] = "start-post",
928 [SERVICE_RUNNING] = "running",
929 [SERVICE_EXITED] = "exited",
930 [SERVICE_RELOAD] = "reload",
931 [SERVICE_STOP] = "stop",
932 [SERVICE_STOP_SIGABRT] = "stop-sigabrt",
933 [SERVICE_STOP_SIGTERM] = "stop-sigterm",
934 [SERVICE_STOP_SIGKILL] = "stop-sigkill",
935 [SERVICE_STOP_POST] = "stop-post",
936 [SERVICE_FINAL_SIGTERM] = "final-sigterm",
937 [SERVICE_FINAL_SIGKILL] = "final-sigkill",
938 [SERVICE_FAILED] = "failed",
939 [SERVICE_AUTO_RESTART] = "auto-restart",
940 };
941
942 DEFINE_STRING_TABLE_LOOKUP(service_state, ServiceState);
943
944 static const char* const slice_state_table[_SLICE_STATE_MAX] = {
945 [SLICE_DEAD] = "dead",
946 [SLICE_ACTIVE] = "active"
947 };
948
949 DEFINE_STRING_TABLE_LOOKUP(slice_state, SliceState);
950
951 static const char* const socket_state_table[_SOCKET_STATE_MAX] = {
952 [SOCKET_DEAD] = "dead",
953 [SOCKET_START_PRE] = "start-pre",
954 [SOCKET_START_CHOWN] = "start-chown",
955 [SOCKET_START_POST] = "start-post",
956 [SOCKET_LISTENING] = "listening",
957 [SOCKET_RUNNING] = "running",
958 [SOCKET_STOP_PRE] = "stop-pre",
959 [SOCKET_STOP_PRE_SIGTERM] = "stop-pre-sigterm",
960 [SOCKET_STOP_PRE_SIGKILL] = "stop-pre-sigkill",
961 [SOCKET_STOP_POST] = "stop-post",
962 [SOCKET_FINAL_SIGTERM] = "final-sigterm",
963 [SOCKET_FINAL_SIGKILL] = "final-sigkill",
964 [SOCKET_FAILED] = "failed"
965 };
966
967 DEFINE_STRING_TABLE_LOOKUP(socket_state, SocketState);
968
969 static const char* const swap_state_table[_SWAP_STATE_MAX] = {
970 [SWAP_DEAD] = "dead",
971 [SWAP_ACTIVATING] = "activating",
972 [SWAP_ACTIVATING_DONE] = "activating-done",
973 [SWAP_ACTIVE] = "active",
974 [SWAP_DEACTIVATING] = "deactivating",
975 [SWAP_ACTIVATING_SIGTERM] = "activating-sigterm",
976 [SWAP_ACTIVATING_SIGKILL] = "activating-sigkill",
977 [SWAP_DEACTIVATING_SIGTERM] = "deactivating-sigterm",
978 [SWAP_DEACTIVATING_SIGKILL] = "deactivating-sigkill",
979 [SWAP_FAILED] = "failed"
980 };
981
982 DEFINE_STRING_TABLE_LOOKUP(swap_state, SwapState);
983
984 static const char* const target_state_table[_TARGET_STATE_MAX] = {
985 [TARGET_DEAD] = "dead",
986 [TARGET_ACTIVE] = "active"
987 };
988
989 DEFINE_STRING_TABLE_LOOKUP(target_state, TargetState);
990
991 static const char* const timer_state_table[_TIMER_STATE_MAX] = {
992 [TIMER_DEAD] = "dead",
993 [TIMER_WAITING] = "waiting",
994 [TIMER_RUNNING] = "running",
995 [TIMER_ELAPSED] = "elapsed",
996 [TIMER_FAILED] = "failed"
997 };
998
999 DEFINE_STRING_TABLE_LOOKUP(timer_state, TimerState);
1000
1001 static const char* const unit_dependency_table[_UNIT_DEPENDENCY_MAX] = {
1002 [UNIT_REQUIRES] = "Requires",
1003 [UNIT_REQUISITE] = "Requisite",
1004 [UNIT_WANTS] = "Wants",
1005 [UNIT_BINDS_TO] = "BindsTo",
1006 [UNIT_PART_OF] = "PartOf",
1007 [UNIT_REQUIRED_BY] = "RequiredBy",
1008 [UNIT_REQUISITE_OF] = "RequisiteOf",
1009 [UNIT_WANTED_BY] = "WantedBy",
1010 [UNIT_BOUND_BY] = "BoundBy",
1011 [UNIT_CONSISTS_OF] = "ConsistsOf",
1012 [UNIT_CONFLICTS] = "Conflicts",
1013 [UNIT_CONFLICTED_BY] = "ConflictedBy",
1014 [UNIT_BEFORE] = "Before",
1015 [UNIT_AFTER] = "After",
1016 [UNIT_ON_FAILURE] = "OnFailure",
1017 [UNIT_TRIGGERS] = "Triggers",
1018 [UNIT_TRIGGERED_BY] = "TriggeredBy",
1019 [UNIT_PROPAGATES_RELOAD_TO] = "PropagatesReloadTo",
1020 [UNIT_RELOAD_PROPAGATED_FROM] = "ReloadPropagatedFrom",
1021 [UNIT_JOINS_NAMESPACE_OF] = "JoinsNamespaceOf",
1022 [UNIT_REFERENCES] = "References",
1023 [UNIT_REFERENCED_BY] = "ReferencedBy",
1024 };
1025
1026 DEFINE_STRING_TABLE_LOOKUP(unit_dependency, UnitDependency);