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