chiark / gitweb /
Prep v228: Apply more cosmetic changes found in upstream.
[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 /// UNNEEDED by elogind
126 #if 0
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 #endif // 0
246
247 int unit_name_build(const char *prefix, const char *instance, const char *suffix, char **ret) {
248         char *s;
249
250         assert(prefix);
251         assert(suffix);
252         assert(ret);
253
254         if (!unit_prefix_is_valid(prefix))
255                 return -EINVAL;
256
257         if (instance && !unit_instance_is_valid(instance))
258                 return -EINVAL;
259
260         if (!unit_suffix_is_valid(suffix))
261                 return -EINVAL;
262
263         if (!instance)
264                 s = strappend(prefix, suffix);
265         else
266                 s = strjoin(prefix, "@", instance, suffix, NULL);
267         if (!s)
268                 return -ENOMEM;
269
270         *ret = s;
271         return 0;
272 }
273
274 /// UNNEEDED by elogind
275 #if 0
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 /// UNNEEDED by elogind
840 #if 0
841 static const char* const unit_load_state_table[_UNIT_LOAD_STATE_MAX] = {
842         [UNIT_STUB] = "stub",
843         [UNIT_LOADED] = "loaded",
844         [UNIT_NOT_FOUND] = "not-found",
845         [UNIT_ERROR] = "error",
846         [UNIT_MERGED] = "merged",
847         [UNIT_MASKED] = "masked"
848 };
849
850 DEFINE_STRING_TABLE_LOOKUP(unit_load_state, UnitLoadState);
851
852 static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = {
853         [UNIT_ACTIVE] = "active",
854         [UNIT_RELOADING] = "reloading",
855         [UNIT_INACTIVE] = "inactive",
856         [UNIT_FAILED] = "failed",
857         [UNIT_ACTIVATING] = "activating",
858         [UNIT_DEACTIVATING] = "deactivating"
859 };
860
861 DEFINE_STRING_TABLE_LOOKUP(unit_active_state, UnitActiveState);
862
863 static const char* const automount_state_table[_AUTOMOUNT_STATE_MAX] = {
864         [AUTOMOUNT_DEAD] = "dead",
865         [AUTOMOUNT_WAITING] = "waiting",
866         [AUTOMOUNT_RUNNING] = "running",
867         [AUTOMOUNT_FAILED] = "failed"
868 };
869
870 DEFINE_STRING_TABLE_LOOKUP(automount_state, AutomountState);
871
872 static const char* const busname_state_table[_BUSNAME_STATE_MAX] = {
873         [BUSNAME_DEAD] = "dead",
874         [BUSNAME_MAKING] = "making",
875         [BUSNAME_REGISTERED] = "registered",
876         [BUSNAME_LISTENING] = "listening",
877         [BUSNAME_RUNNING] = "running",
878         [BUSNAME_SIGTERM] = "sigterm",
879         [BUSNAME_SIGKILL] = "sigkill",
880         [BUSNAME_FAILED] = "failed",
881 };
882
883 DEFINE_STRING_TABLE_LOOKUP(busname_state, BusNameState);
884
885 static const char* const device_state_table[_DEVICE_STATE_MAX] = {
886         [DEVICE_DEAD] = "dead",
887         [DEVICE_TENTATIVE] = "tentative",
888         [DEVICE_PLUGGED] = "plugged",
889 };
890
891 DEFINE_STRING_TABLE_LOOKUP(device_state, DeviceState);
892
893 static const char* const mount_state_table[_MOUNT_STATE_MAX] = {
894         [MOUNT_DEAD] = "dead",
895         [MOUNT_MOUNTING] = "mounting",
896         [MOUNT_MOUNTING_DONE] = "mounting-done",
897         [MOUNT_MOUNTED] = "mounted",
898         [MOUNT_REMOUNTING] = "remounting",
899         [MOUNT_UNMOUNTING] = "unmounting",
900         [MOUNT_MOUNTING_SIGTERM] = "mounting-sigterm",
901         [MOUNT_MOUNTING_SIGKILL] = "mounting-sigkill",
902         [MOUNT_REMOUNTING_SIGTERM] = "remounting-sigterm",
903         [MOUNT_REMOUNTING_SIGKILL] = "remounting-sigkill",
904         [MOUNT_UNMOUNTING_SIGTERM] = "unmounting-sigterm",
905         [MOUNT_UNMOUNTING_SIGKILL] = "unmounting-sigkill",
906         [MOUNT_FAILED] = "failed"
907 };
908
909 DEFINE_STRING_TABLE_LOOKUP(mount_state, MountState);
910
911 static const char* const path_state_table[_PATH_STATE_MAX] = {
912         [PATH_DEAD] = "dead",
913         [PATH_WAITING] = "waiting",
914         [PATH_RUNNING] = "running",
915         [PATH_FAILED] = "failed"
916 };
917
918 DEFINE_STRING_TABLE_LOOKUP(path_state, PathState);
919
920 static const char* const scope_state_table[_SCOPE_STATE_MAX] = {
921         [SCOPE_DEAD] = "dead",
922         [SCOPE_RUNNING] = "running",
923         [SCOPE_ABANDONED] = "abandoned",
924         [SCOPE_STOP_SIGTERM] = "stop-sigterm",
925         [SCOPE_STOP_SIGKILL] = "stop-sigkill",
926         [SCOPE_FAILED] = "failed",
927 };
928
929 DEFINE_STRING_TABLE_LOOKUP(scope_state, ScopeState);
930
931 static const char* const service_state_table[_SERVICE_STATE_MAX] = {
932         [SERVICE_DEAD] = "dead",
933         [SERVICE_START_PRE] = "start-pre",
934         [SERVICE_START] = "start",
935         [SERVICE_START_POST] = "start-post",
936         [SERVICE_RUNNING] = "running",
937         [SERVICE_EXITED] = "exited",
938         [SERVICE_RELOAD] = "reload",
939         [SERVICE_STOP] = "stop",
940         [SERVICE_STOP_SIGABRT] = "stop-sigabrt",
941         [SERVICE_STOP_SIGTERM] = "stop-sigterm",
942         [SERVICE_STOP_SIGKILL] = "stop-sigkill",
943         [SERVICE_STOP_POST] = "stop-post",
944         [SERVICE_FINAL_SIGTERM] = "final-sigterm",
945         [SERVICE_FINAL_SIGKILL] = "final-sigkill",
946         [SERVICE_FAILED] = "failed",
947         [SERVICE_AUTO_RESTART] = "auto-restart",
948 };
949
950 DEFINE_STRING_TABLE_LOOKUP(service_state, ServiceState);
951
952 static const char* const slice_state_table[_SLICE_STATE_MAX] = {
953         [SLICE_DEAD] = "dead",
954         [SLICE_ACTIVE] = "active"
955 };
956
957 DEFINE_STRING_TABLE_LOOKUP(slice_state, SliceState);
958
959 static const char* const socket_state_table[_SOCKET_STATE_MAX] = {
960         [SOCKET_DEAD] = "dead",
961         [SOCKET_START_PRE] = "start-pre",
962         [SOCKET_START_CHOWN] = "start-chown",
963         [SOCKET_START_POST] = "start-post",
964         [SOCKET_LISTENING] = "listening",
965         [SOCKET_RUNNING] = "running",
966         [SOCKET_STOP_PRE] = "stop-pre",
967         [SOCKET_STOP_PRE_SIGTERM] = "stop-pre-sigterm",
968         [SOCKET_STOP_PRE_SIGKILL] = "stop-pre-sigkill",
969         [SOCKET_STOP_POST] = "stop-post",
970         [SOCKET_FINAL_SIGTERM] = "final-sigterm",
971         [SOCKET_FINAL_SIGKILL] = "final-sigkill",
972         [SOCKET_FAILED] = "failed"
973 };
974
975 DEFINE_STRING_TABLE_LOOKUP(socket_state, SocketState);
976
977 static const char* const swap_state_table[_SWAP_STATE_MAX] = {
978         [SWAP_DEAD] = "dead",
979         [SWAP_ACTIVATING] = "activating",
980         [SWAP_ACTIVATING_DONE] = "activating-done",
981         [SWAP_ACTIVE] = "active",
982         [SWAP_DEACTIVATING] = "deactivating",
983         [SWAP_ACTIVATING_SIGTERM] = "activating-sigterm",
984         [SWAP_ACTIVATING_SIGKILL] = "activating-sigkill",
985         [SWAP_DEACTIVATING_SIGTERM] = "deactivating-sigterm",
986         [SWAP_DEACTIVATING_SIGKILL] = "deactivating-sigkill",
987         [SWAP_FAILED] = "failed"
988 };
989
990 DEFINE_STRING_TABLE_LOOKUP(swap_state, SwapState);
991
992 static const char* const target_state_table[_TARGET_STATE_MAX] = {
993         [TARGET_DEAD] = "dead",
994         [TARGET_ACTIVE] = "active"
995 };
996
997 DEFINE_STRING_TABLE_LOOKUP(target_state, TargetState);
998
999 static const char* const timer_state_table[_TIMER_STATE_MAX] = {
1000         [TIMER_DEAD] = "dead",
1001         [TIMER_WAITING] = "waiting",
1002         [TIMER_RUNNING] = "running",
1003         [TIMER_ELAPSED] = "elapsed",
1004         [TIMER_FAILED] = "failed"
1005 };
1006
1007 DEFINE_STRING_TABLE_LOOKUP(timer_state, TimerState);
1008
1009 static const char* const unit_dependency_table[_UNIT_DEPENDENCY_MAX] = {
1010         [UNIT_REQUIRES] = "Requires",
1011         [UNIT_REQUISITE] = "Requisite",
1012         [UNIT_WANTS] = "Wants",
1013         [UNIT_BINDS_TO] = "BindsTo",
1014         [UNIT_PART_OF] = "PartOf",
1015         [UNIT_REQUIRED_BY] = "RequiredBy",
1016         [UNIT_REQUISITE_OF] = "RequisiteOf",
1017         [UNIT_WANTED_BY] = "WantedBy",
1018         [UNIT_BOUND_BY] = "BoundBy",
1019         [UNIT_CONSISTS_OF] = "ConsistsOf",
1020         [UNIT_CONFLICTS] = "Conflicts",
1021         [UNIT_CONFLICTED_BY] = "ConflictedBy",
1022         [UNIT_BEFORE] = "Before",
1023         [UNIT_AFTER] = "After",
1024         [UNIT_ON_FAILURE] = "OnFailure",
1025         [UNIT_TRIGGERS] = "Triggers",
1026         [UNIT_TRIGGERED_BY] = "TriggeredBy",
1027         [UNIT_PROPAGATES_RELOAD_TO] = "PropagatesReloadTo",
1028         [UNIT_RELOAD_PROPAGATED_FROM] = "ReloadPropagatedFrom",
1029         [UNIT_JOINS_NAMESPACE_OF] = "JoinsNamespaceOf",
1030         [UNIT_REFERENCES] = "References",
1031         [UNIT_REFERENCED_BY] = "ReferencedBy",
1032 };
1033
1034 DEFINE_STRING_TABLE_LOOKUP(unit_dependency, UnitDependency);
1035 #endif // 0