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