]> git.ipfire.org Git - thirdparty/systemd.git/blame - util.c
strv: add various strv calls
[thirdparty/systemd.git] / util.c
CommitLineData
60918275
LP
1/*-*- Mode: C; c-basic-offset: 8 -*-*/
2
a7334b09
LP
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 General Public License as published by
10 the Free Software Foundation; either version 2 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 General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
60918275
LP
22#include <assert.h>
23#include <string.h>
24#include <unistd.h>
25#include <errno.h>
85261803 26#include <stdlib.h>
034c6ed7
LP
27#include <signal.h>
28#include <stdio.h>
1dccbe19
LP
29#include <syslog.h>
30#include <sched.h>
31#include <sys/resource.h>
ef886c6a 32#include <linux/sched.h>
a9f5d454
LP
33#include <sys/types.h>
34#include <sys/stat.h>
60918275
LP
35
36#include "macro.h"
37#include "util.h"
1dccbe19
LP
38#include "ioprio.h"
39#include "missing.h"
a9f5d454 40#include "log.h"
60918275 41
47be870b 42usec_t now(clockid_t clock_id) {
60918275
LP
43 struct timespec ts;
44
47be870b 45 assert_se(clock_gettime(clock_id, &ts) == 0);
60918275
LP
46
47 return timespec_load(&ts);
48}
49
50usec_t timespec_load(const struct timespec *ts) {
51 assert(ts);
52
53 return
54 (usec_t) ts->tv_sec * USEC_PER_SEC +
55 (usec_t) ts->tv_nsec / NSEC_PER_USEC;
56}
57
58struct timespec *timespec_store(struct timespec *ts, usec_t u) {
59 assert(ts);
60
61 ts->tv_sec = (time_t) (u / USEC_PER_SEC);
62 ts->tv_nsec = (long int) ((u % USEC_PER_SEC) * NSEC_PER_USEC);
63
64 return ts;
65}
66
67usec_t timeval_load(const struct timeval *tv) {
68 assert(tv);
69
70 return
71 (usec_t) tv->tv_sec * USEC_PER_SEC +
72 (usec_t) tv->tv_usec;
73}
74
75struct timeval *timeval_store(struct timeval *tv, usec_t u) {
76 assert(tv);
77
78 tv->tv_sec = (time_t) (u / USEC_PER_SEC);
79 tv->tv_usec = (suseconds_t) (u % USEC_PER_SEC);
80
81 return tv;
82}
83
84bool endswith(const char *s, const char *postfix) {
85 size_t sl, pl;
86
87 assert(s);
88 assert(postfix);
89
90 sl = strlen(s);
91 pl = strlen(postfix);
92
93 if (sl < pl)
94 return false;
95
96 return memcmp(s + sl - pl, postfix, pl) == 0;
97}
98
99bool startswith(const char *s, const char *prefix) {
100 size_t sl, pl;
101
102 assert(s);
103 assert(prefix);
104
105 sl = strlen(s);
106 pl = strlen(prefix);
107
108 if (sl < pl)
109 return false;
110
111 return memcmp(s, prefix, pl) == 0;
112}
113
79d6d816
LP
114bool first_word(const char *s, const char *word) {
115 size_t sl, wl;
116
117 assert(s);
118 assert(word);
119
120 sl = strlen(s);
121 wl = strlen(word);
122
123 if (sl < wl)
124 return false;
125
126 if (memcmp(s, word, wl) != 0)
127 return false;
128
129 return (s[wl] == 0 ||
130 strchr(WHITESPACE, s[wl]));
131}
132
42f4e3c4 133int close_nointr(int fd) {
60918275
LP
134 assert(fd >= 0);
135
136 for (;;) {
137 int r;
138
139 if ((r = close(fd)) >= 0)
140 return r;
141
142 if (errno != EINTR)
143 return r;
144 }
145}
85261803 146
85f136b5
LP
147void close_nointr_nofail(int fd) {
148
149 /* like close_nointr() but cannot fail, and guarantees errno
150 * is unchanged */
151
152 assert_se(close_nointr(fd) == 0);
153}
154
85261803
LP
155int parse_boolean(const char *v) {
156 assert(v);
157
44d8db9e 158 if (streq(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || !strcasecmp(v, "on"))
85261803 159 return 1;
44d8db9e 160 else if (streq(v, "0") || v[0] == 'n' || v[0] == 'N' || v[0] == 'f' || v[0] == 'F' || !strcasecmp(v, "off"))
85261803
LP
161 return 0;
162
163 return -EINVAL;
164}
165
166int safe_atou(const char *s, unsigned *ret_u) {
167 char *x = NULL;
034c6ed7 168 unsigned long l;
85261803
LP
169
170 assert(s);
171 assert(ret_u);
172
173 errno = 0;
174 l = strtoul(s, &x, 0);
175
176 if (!x || *x || errno)
177 return errno ? -errno : -EINVAL;
178
034c6ed7 179 if ((unsigned long) (unsigned) l != l)
85261803
LP
180 return -ERANGE;
181
182 *ret_u = (unsigned) l;
183 return 0;
184}
185
186int safe_atoi(const char *s, int *ret_i) {
187 char *x = NULL;
034c6ed7 188 long l;
85261803
LP
189
190 assert(s);
191 assert(ret_i);
192
193 errno = 0;
194 l = strtol(s, &x, 0);
195
196 if (!x || *x || errno)
197 return errno ? -errno : -EINVAL;
198
034c6ed7 199 if ((long) (int) l != l)
85261803
LP
200 return -ERANGE;
201
034c6ed7
LP
202 *ret_i = (int) l;
203 return 0;
204}
205
206int safe_atolu(const char *s, long unsigned *ret_lu) {
207 char *x = NULL;
208 unsigned long l;
209
210 assert(s);
211 assert(ret_lu);
212
213 errno = 0;
214 l = strtoul(s, &x, 0);
215
216 if (!x || *x || errno)
217 return errno ? -errno : -EINVAL;
218
219 *ret_lu = l;
220 return 0;
221}
222
223int safe_atoli(const char *s, long int *ret_li) {
224 char *x = NULL;
225 long l;
226
227 assert(s);
228 assert(ret_li);
229
230 errno = 0;
231 l = strtol(s, &x, 0);
232
233 if (!x || *x || errno)
234 return errno ? -errno : -EINVAL;
235
236 *ret_li = l;
237 return 0;
238}
239
240int safe_atollu(const char *s, long long unsigned *ret_llu) {
241 char *x = NULL;
242 unsigned long long l;
243
244 assert(s);
245 assert(ret_llu);
246
247 errno = 0;
248 l = strtoull(s, &x, 0);
249
250 if (!x || *x || errno)
251 return errno ? -errno : -EINVAL;
252
253 *ret_llu = l;
254 return 0;
255}
256
257int safe_atolli(const char *s, long long int *ret_lli) {
258 char *x = NULL;
259 long long l;
260
261 assert(s);
262 assert(ret_lli);
263
264 errno = 0;
265 l = strtoll(s, &x, 0);
266
267 if (!x || *x || errno)
268 return errno ? -errno : -EINVAL;
269
270 *ret_lli = l;
85261803
LP
271 return 0;
272}
a41e8209 273
a41e8209
LP
274/* Split a string into words. */
275char *split_spaces(const char *c, size_t *l, char **state) {
276 char *current;
277
278 current = *state ? *state : (char*) c;
279
280 if (!*current || *c == 0)
281 return NULL;
282
283 current += strspn(current, WHITESPACE);
284 *l = strcspn(current, WHITESPACE);
285 *state = current+*l;
286
287 return (char*) current;
288}
034c6ed7 289
82919e3d
LP
290/* Split a path into filenames. */
291char *split_slash(const char *c, size_t *l, char **state) {
292 char *current;
293
294 current = *state ? *state : (char*) c;
295
296 if (!*current || *c == 0)
297 return NULL;
298
299 current += strspn(current, "/");
300 *l = strcspn(current, "/");
301 *state = current+*l;
302
303 return (char*) current;
304}
305
034c6ed7
LP
306/* Split a string into words, but consider strings enclosed in '' and
307 * "" as words even if they include spaces. */
308char *split_quoted(const char *c, size_t *l, char **state) {
309 char *current;
310
311 current = *state ? *state : (char*) c;
312
313 if (!*current || *c == 0)
314 return NULL;
315
316 current += strspn(current, WHITESPACE);
317
318 if (*current == '\'') {
319 current ++;
320 *l = strcspn(current, "'");
321 *state = current+*l;
322
323 if (**state == '\'')
324 (*state)++;
325 } else if (*current == '\"') {
326 current ++;
b858b600 327 *l = strcspn(current, "\"");
034c6ed7
LP
328 *state = current+*l;
329
330 if (**state == '\"')
331 (*state)++;
332 } else {
333 *l = strcspn(current, WHITESPACE);
334 *state = current+*l;
335 }
336
44d8db9e
LP
337 /* FIXME: Cannot deal with strings that have spaces AND ticks
338 * in them */
339
034c6ed7
LP
340 return (char*) current;
341}
342
034c6ed7
LP
343int get_parent_of_pid(pid_t pid, pid_t *_ppid) {
344 int r;
345 FILE *f;
346 char fn[132], line[256], *p;
347 long long unsigned ppid;
348
349 assert(pid >= 0);
350 assert(_ppid);
351
352 assert_se(snprintf(fn, sizeof(fn)-1, "/proc/%llu/stat", (unsigned long long) pid) < (int) (sizeof(fn)-1));
353 fn[sizeof(fn)-1] = 0;
354
355 if (!(f = fopen(fn, "r")))
356 return -errno;
357
358 if (!(fgets(line, sizeof(line), f))) {
359 r = -errno;
360 fclose(f);
361 return r;
362 }
363
364 fclose(f);
365
366 /* Let's skip the pid and comm fields. The latter is enclosed
367 * in () but does not escape any () in its value, so let's
368 * skip over it manually */
369
370 if (!(p = strrchr(line, ')')))
371 return -EIO;
372
373 p++;
374
375 if (sscanf(p, " "
376 "%*c " /* state */
377 "%llu ", /* ppid */
378 &ppid) != 1)
379 return -EIO;
380
381 if ((long long unsigned) (pid_t) ppid != ppid)
382 return -ERANGE;
383
384 *_ppid = (pid_t) ppid;
385
386 return 0;
387}
388
389int write_one_line_file(const char *fn, const char *line) {
390 FILE *f;
391 int r;
392
393 assert(fn);
394 assert(line);
395
396 if (!(f = fopen(fn, "we")))
397 return -errno;
398
399 if (fputs(line, f) < 0) {
400 r = -errno;
401 goto finish;
402 }
403
404 r = 0;
405finish:
406 fclose(f);
407 return r;
408}
409
410int read_one_line_file(const char *fn, char **line) {
411 FILE *f;
412 int r;
413 char t[64], *c;
414
415 assert(fn);
416 assert(line);
417
418 if (!(f = fopen(fn, "re")))
419 return -errno;
420
421 if (!(fgets(t, sizeof(t), f))) {
422 r = -errno;
423 goto finish;
424 }
425
426 if (!(c = strdup(t))) {
427 r = -ENOMEM;
428 goto finish;
429 }
430
431 *line = c;
432 r = 0;
433
434finish:
435 fclose(f);
436 return r;
437}
44d8db9e
LP
438
439char *strappend(const char *s, const char *suffix) {
440 size_t a, b;
441 char *r;
442
443 assert(s);
444 assert(suffix);
445
446 a = strlen(s);
447 b = strlen(suffix);
448
449 if (!(r = new(char, a+b+1)))
450 return NULL;
451
452 memcpy(r, s, a);
453 memcpy(r+a, suffix, b);
454 r[a+b] = 0;
455
456 return r;
457}
87f0e418
LP
458
459int readlink_malloc(const char *p, char **r) {
460 size_t l = 100;
461
462 assert(p);
463 assert(r);
464
465 for (;;) {
466 char *c;
467 ssize_t n;
468
469 if (!(c = new(char, l)))
470 return -ENOMEM;
471
472 if ((n = readlink(p, c, l-1)) < 0) {
473 int ret = -errno;
474 free(c);
475 return ret;
476 }
477
478 if ((size_t) n < l-1) {
479 c[n] = 0;
480 *r = c;
481 return 0;
482 }
483
484 free(c);
485 l *= 2;
486 }
487}
488
489char *file_name_from_path(const char *p) {
490 char *r;
491
492 assert(p);
493
494 if ((r = strrchr(p, '/')))
495 return r + 1;
496
497 return (char*) p;
498}
0301abf4
LP
499
500bool path_is_absolute(const char *p) {
501 assert(p);
502
503 return p[0] == '/';
504}
505
506bool is_path(const char *p) {
507
508 return !!strchr(p, '/');
509}
510
511char *path_make_absolute(const char *p, const char *prefix) {
512 char *r;
513
514 assert(p);
515
516 if (path_is_absolute(p) || !prefix)
517 return strdup(p);
518
519 if (asprintf(&r, "%s/%s", prefix, p) < 0)
520 return NULL;
521
522 return r;
523}
2a987ee8
LP
524
525int reset_all_signal_handlers(void) {
526 int sig;
527
528 for (sig = 1; sig < _NSIG; sig++) {
529 struct sigaction sa;
530
531 if (sig == SIGKILL || sig == SIGSTOP)
532 continue;
533
534 zero(sa);
535 sa.sa_handler = SIG_DFL;
431c32bf 536 sa.sa_flags = SA_RESTART;
2a987ee8
LP
537
538 /* On Linux the first two RT signals are reserved by
539 * glibc, and sigaction() will return EINVAL for them. */
540 if ((sigaction(sig, &sa, NULL) < 0))
541 if (errno != EINVAL)
542 return -errno;
543 }
544
545 return 0;
546}
4a72ff34
LP
547
548char *strstrip(char *s) {
549 char *e, *l = NULL;
550
551 /* Drops trailing whitespace. Modifies the string in
552 * place. Returns pointer to first non-space character */
553
554 s += strspn(s, WHITESPACE);
555
556 for (e = s; *e; e++)
557 if (!strchr(WHITESPACE, *e))
558 l = e;
559
560 if (l)
561 *(l+1) = 0;
562 else
563 *s = 0;
564
565 return s;
566
567}
568
569char *file_in_same_dir(const char *path, const char *filename) {
570 char *e, *r;
571 size_t k;
572
573 assert(path);
574 assert(filename);
575
576 /* This removes the last component of path and appends
577 * filename, unless the latter is absolute anyway or the
578 * former isn't */
579
580 if (path_is_absolute(filename))
581 return strdup(filename);
582
583 if (!(e = strrchr(path, '/')))
584 return strdup(filename);
585
586 k = strlen(filename);
587 if (!(r = new(char, e-path+1+k+1)))
588 return NULL;
589
590 memcpy(r, path, e-path+1);
591 memcpy(r+(e-path)+1, filename, k+1);
592
593 return r;
594}
fb624d04 595
a9f5d454
LP
596int mkdir_parents(const char *path, mode_t mode) {
597 const char *p, *e;
598
599 assert(path);
600
601 /* Creates every parent directory in the path except the last
602 * component. */
603
604 p = path + strspn(path, "/");
605 for (;;) {
606 int r;
607 char *t;
608
609 e = p + strcspn(p, "/");
610 p = e + strspn(e, "/");
611
612 /* Is this the last component? If so, then we're
613 * done */
614 if (*p == 0)
615 return 0;
616
617 if (!(t = strndup(path, e - path)))
618 return -ENOMEM;
619
620 r = mkdir(t, mode);
621
622 free(t);
623
624 if (r < 0 && errno != EEXIST)
625 return -errno;
626 }
627}
628
fb624d04
LP
629char hexchar(int x) {
630 static const char table[16] = "0123456789abcdef";
631
632 return table[x & 15];
633}
4fe88d28
LP
634
635int unhexchar(char c) {
636
637 if (c >= '0' && c <= '9')
638 return c - '0';
639
640 if (c >= 'a' && c <= 'f')
ea430986 641 return c - 'a' + 10;
4fe88d28
LP
642
643 if (c >= 'A' && c <= 'F')
ea430986 644 return c - 'A' + 10;
4fe88d28
LP
645
646 return -1;
647}
648
649char octchar(int x) {
650 return '0' + (x & 7);
651}
652
653int unoctchar(char c) {
654
655 if (c >= '0' && c <= '7')
656 return c - '0';
657
658 return -1;
659}
660
661char *cescape(const char *s) {
662 char *r, *t;
663 const char *f;
664
665 assert(s);
666
667 /* Does C style string escaping. */
668
669 if (!(r = new(char, strlen(s)*4 + 1)))
670 return NULL;
671
672 for (f = s, t = r; *f; f++)
673
674 switch (*f) {
675
676 case '\a':
677 *(t++) = '\\';
678 *(t++) = 'a';
679 break;
680 case '\b':
681 *(t++) = '\\';
682 *(t++) = 'b';
683 break;
684 case '\f':
685 *(t++) = '\\';
686 *(t++) = 'f';
687 break;
688 case '\n':
689 *(t++) = '\\';
690 *(t++) = 'n';
691 break;
692 case '\r':
693 *(t++) = '\\';
694 *(t++) = 'r';
695 break;
696 case '\t':
697 *(t++) = '\\';
698 *(t++) = 't';
699 break;
700 case '\v':
701 *(t++) = '\\';
702 *(t++) = 'v';
703 break;
704 case '\\':
705 *(t++) = '\\';
706 *(t++) = '\\';
707 break;
708 case '"':
709 *(t++) = '\\';
710 *(t++) = '"';
711 break;
712 case '\'':
713 *(t++) = '\\';
714 *(t++) = '\'';
715 break;
716
717 default:
718 /* For special chars we prefer octal over
719 * hexadecimal encoding, simply because glib's
720 * g_strescape() does the same */
721 if ((*f < ' ') || (*f >= 127)) {
722 *(t++) = '\\';
723 *(t++) = octchar((unsigned char) *f >> 6);
724 *(t++) = octchar((unsigned char) *f >> 3);
725 *(t++) = octchar((unsigned char) *f);
726 } else
727 *(t++) = *f;
728 break;
729 }
730
731 *t = 0;
732
733 return r;
734}
735
736char *cunescape(const char *s) {
737 char *r, *t;
738 const char *f;
739
740 assert(s);
741
742 /* Undoes C style string escaping */
743
744 if (!(r = new(char, strlen(s)+1)))
745 return r;
746
747 for (f = s, t = r; *f; f++) {
748
749 if (*f != '\\') {
750 *(t++) = *f;
751 continue;
752 }
753
754 f++;
755
756 switch (*f) {
757
758 case 'a':
759 *(t++) = '\a';
760 break;
761 case 'b':
762 *(t++) = '\b';
763 break;
764 case 'f':
765 *(t++) = '\f';
766 break;
767 case 'n':
768 *(t++) = '\n';
769 break;
770 case 'r':
771 *(t++) = '\r';
772 break;
773 case 't':
774 *(t++) = '\t';
775 break;
776 case 'v':
777 *(t++) = '\v';
778 break;
779 case '\\':
780 *(t++) = '\\';
781 break;
782 case '"':
783 *(t++) = '"';
784 break;
785 case '\'':
786 *(t++) = '\'';
787 break;
788
789 case 'x': {
790 /* hexadecimal encoding */
791 int a, b;
792
793 if ((a = unhexchar(f[1])) < 0 ||
794 (b = unhexchar(f[2])) < 0) {
795 /* Invalid escape code, let's take it literal then */
796 *(t++) = '\\';
797 *(t++) = 'x';
798 } else {
799 *(t++) = (char) ((a << 4) | b);
800 f += 2;
801 }
802
803 break;
804 }
805
806 case '0':
807 case '1':
808 case '2':
809 case '3':
810 case '4':
811 case '5':
812 case '6':
813 case '7': {
814 /* octal encoding */
815 int a, b, c;
816
817 if ((a = unoctchar(f[0])) < 0 ||
818 (b = unoctchar(f[1])) < 0 ||
819 (c = unoctchar(f[2])) < 0) {
820 /* Invalid escape code, let's take it literal then */
821 *(t++) = '\\';
822 *(t++) = f[0];
823 } else {
824 *(t++) = (char) ((a << 6) | (b << 3) | c);
825 f += 2;
826 }
827
828 break;
829 }
830
831 case 0:
832 /* premature end of string.*/
833 *(t++) = '\\';
834 goto finish;
835
836 default:
837 /* Invalid escape code, let's take it literal then */
838 *(t++) = '\\';
839 *(t++) = 'f';
840 break;
841 }
842 }
843
844finish:
845 *t = 0;
846 return r;
847}
848
849
850char *xescape(const char *s, const char *bad) {
851 char *r, *t;
852 const char *f;
853
854 /* Escapes all chars in bad, in addition to \ and all special
855 * chars, in \xFF style escaping. May be reversed with
856 * cunescape. */
857
858 if (!(r = new(char, strlen(s)*4+1)))
859 return NULL;
860
861 for (f = s, t = r; *f; f++) {
862
863 if (*f < ' ' || *f >= 127 ||
864 *f == '\\' || strchr(bad, *f)) {
865 *(t++) = '\\';
866 *(t++) = 'x';
867 *(t++) = hexchar(*f >> 4);
868 *(t++) = hexchar(*f);
869 } else
870 *(t++) = *f;
871 }
872
873 *t = 0;
874
875 return r;
876}
877
ea430986 878char *bus_path_escape(const char *s) {
ea430986
LP
879 char *r, *t;
880 const char *f;
881
47be870b
LP
882 assert(s);
883
ea430986
LP
884 /* Escapes all chars that D-Bus' object path cannot deal
885 * with. Can be reverse with bus_path_unescape() */
886
887 if (!(r = new(char, strlen(s)*3+1)))
888 return NULL;
889
890 for (f = s, t = r; *f; f++) {
891
892 if (!(*f >= 'A' && *f <= 'Z') &&
893 !(*f >= 'a' && *f <= 'z') &&
894 !(*f >= '0' && *f <= '9')) {
895 *(t++) = '_';
896 *(t++) = hexchar(*f >> 4);
897 *(t++) = hexchar(*f);
898 } else
899 *(t++) = *f;
900 }
901
902 *t = 0;
903
904 return r;
905}
906
907char *bus_path_unescape(const char *s) {
ea430986
LP
908 char *r, *t;
909 const char *f;
910
47be870b
LP
911 assert(s);
912
ea430986
LP
913 if (!(r = new(char, strlen(s)+1)))
914 return NULL;
915
916 for (f = s, t = r; *f; f++) {
917
918 if (*f == '_') {
919 int a, b;
920
921 if ((a = unhexchar(f[1])) < 0 ||
922 (b = unhexchar(f[2])) < 0) {
923 /* Invalid escape code, let's take it literal then */
924 *(t++) = '_';
925 } else {
926 *(t++) = (char) ((a << 4) | b);
927 f += 2;
928 }
929 } else
930 *(t++) = *f;
931 }
932
933 *t = 0;
934
935 return r;
936}
937
4fe88d28
LP
938char *path_kill_slashes(char *path) {
939 char *f, *t;
940 bool slash = false;
941
942 /* Removes redundant inner and trailing slashes. Modifies the
943 * passed string in-place.
944 *
945 * ///foo///bar/ becomes /foo/bar
946 */
947
948 for (f = path, t = path; *f; f++) {
949
950 if (*f == '/') {
951 slash = true;
952 continue;
953 }
954
955 if (slash) {
956 slash = false;
957 *(t++) = '/';
958 }
959
960 *(t++) = *f;
961 }
962
963 /* Special rule, if we are talking of the root directory, a
964 trailing slash is good */
965
966 if (t == path && slash)
967 *(t++) = '/';
968
969 *t = 0;
970 return path;
971}
972
973bool path_startswith(const char *path, const char *prefix) {
974 assert(path);
975 assert(prefix);
976
977 if ((path[0] == '/') != (prefix[0] == '/'))
978 return false;
979
980 for (;;) {
981 size_t a, b;
982
983 path += strspn(path, "/");
984 prefix += strspn(prefix, "/");
985
986 if (*prefix == 0)
987 return true;
988
989 if (*path == 0)
990 return false;
991
992 a = strcspn(path, "/");
993 b = strcspn(prefix, "/");
994
995 if (a != b)
996 return false;
997
998 if (memcmp(path, prefix, a) != 0)
999 return false;
1000
1001 path += a;
1002 prefix += b;
1003 }
1004}
1005
1006char *ascii_strlower(char *path) {
1007 char *p;
1008
1009 assert(path);
1010
1011 for (p = path; *p; p++)
1012 if (*p >= 'A' && *p <= 'Z')
1013 *p = *p - 'A' + 'a';
1014
1015 return p;
1016}
1dccbe19
LP
1017
1018static const char *const ioprio_class_table[] = {
1019 [IOPRIO_CLASS_NONE] = "none",
1020 [IOPRIO_CLASS_RT] = "realtime",
1021 [IOPRIO_CLASS_BE] = "best-effort",
1022 [IOPRIO_CLASS_IDLE] = "idle"
1023};
1024
1025DEFINE_STRING_TABLE_LOOKUP(ioprio_class, int);
1026
1027static const char *const sigchld_code_table[] = {
1028 [CLD_EXITED] = "exited",
1029 [CLD_KILLED] = "killed",
1030 [CLD_DUMPED] = "dumped",
1031 [CLD_TRAPPED] = "trapped",
1032 [CLD_STOPPED] = "stopped",
1033 [CLD_CONTINUED] = "continued",
1034};
1035
1036DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
1037
1038static const char *const log_facility_table[LOG_NFACILITIES] = {
1039 [LOG_FAC(LOG_KERN)] = "kern",
1040 [LOG_FAC(LOG_USER)] = "user",
1041 [LOG_FAC(LOG_MAIL)] = "mail",
1042 [LOG_FAC(LOG_DAEMON)] = "daemon",
1043 [LOG_FAC(LOG_AUTH)] = "auth",
1044 [LOG_FAC(LOG_SYSLOG)] = "syslog",
1045 [LOG_FAC(LOG_LPR)] = "lpr",
1046 [LOG_FAC(LOG_NEWS)] = "news",
1047 [LOG_FAC(LOG_UUCP)] = "uucp",
1048 [LOG_FAC(LOG_CRON)] = "cron",
1049 [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
1050 [LOG_FAC(LOG_FTP)] = "ftp",
1051 [LOG_FAC(LOG_LOCAL0)] = "local0",
1052 [LOG_FAC(LOG_LOCAL1)] = "local1",
1053 [LOG_FAC(LOG_LOCAL2)] = "local2",
1054 [LOG_FAC(LOG_LOCAL3)] = "local3",
1055 [LOG_FAC(LOG_LOCAL4)] = "local4",
1056 [LOG_FAC(LOG_LOCAL5)] = "local5",
1057 [LOG_FAC(LOG_LOCAL6)] = "local6",
1058 [LOG_FAC(LOG_LOCAL7)] = "local7"
1059};
1060
1061DEFINE_STRING_TABLE_LOOKUP(log_facility, int);
1062
1063static const char *const log_level_table[] = {
1064 [LOG_EMERG] = "emerg",
1065 [LOG_ALERT] = "alert",
1066 [LOG_CRIT] = "crit",
1067 [LOG_ERR] = "err",
1068 [LOG_WARNING] = "warning",
1069 [LOG_NOTICE] = "notice",
1070 [LOG_INFO] = "info",
1071 [LOG_DEBUG] = "debug"
1072};
1073
1074DEFINE_STRING_TABLE_LOOKUP(log_level, int);
1075
1076static const char* const sched_policy_table[] = {
1077 [SCHED_OTHER] = "other",
1078 [SCHED_BATCH] = "batch",
1079 [SCHED_IDLE] = "idle",
1080 [SCHED_FIFO] = "fifo",
1081 [SCHED_RR] = "rr"
1082};
1083
1084DEFINE_STRING_TABLE_LOOKUP(sched_policy, int);
1085
1086static const char* const rlimit_table[] = {
1087 [RLIMIT_CPU] = "LimitCPU",
1088 [RLIMIT_FSIZE] = "LimitFSIZE",
1089 [RLIMIT_DATA] = "LimitDATA",
1090 [RLIMIT_STACK] = "LimitSTACK",
1091 [RLIMIT_CORE] = "LimitCORE",
1092 [RLIMIT_RSS] = "LimitRSS",
1093 [RLIMIT_NOFILE] = "LimitNOFILE",
1094 [RLIMIT_AS] = "LimitAS",
1095 [RLIMIT_NPROC] = "LimitNPROC",
1096 [RLIMIT_MEMLOCK] = "LimitMEMLOCK",
1097 [RLIMIT_LOCKS] = "LimitLOCKS",
1098 [RLIMIT_SIGPENDING] = "LimitSIGPENDING",
1099 [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE",
1100 [RLIMIT_NICE] = "LimitNICE",
1101 [RLIMIT_RTPRIO] = "LimitRTPRIO",
1102 [RLIMIT_RTTIME] = "LimitRTTIME"
1103};
1104
1105DEFINE_STRING_TABLE_LOOKUP(rlimit, int);