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