chiark / gitweb /
1b0f21604570421fc15e505262a41675cefdfb67
[elogind.git] / src / basic / util.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 <ctype.h>
23 //#include <dirent.h>
24 //#include <errno.h>
25 //#include <fcntl.h>
26 //#include <glob.h>
27 #include <grp.h>
28 #include <langinfo.h>
29 //#include <libintl.h>
30 //#include <limits.h>
31 #include <linux/magic.h>
32 //#include <linux/sched.h>
33 //#include <locale.h>
34 #include <netinet/ip.h>
35 #include <poll.h>
36 #include <pwd.h>
37 #include <sched.h>
38 //#include <signal.h>
39 //#include <stdarg.h>
40 //#include <stdio.h>
41 //#include <stdlib.h>
42 //#include <string.h>
43 //#include <sys/file.h>
44 //#include <sys/ioctl.h>
45 //#include <sys/mman.h>
46 //#include <sys/mount.h>
47 //#include <sys/personality.h>
48 #include <sys/prctl.h>
49 //#include <sys/resource.h>
50 //#include <sys/stat.h>
51 //#include <sys/statvfs.h>
52 //#include <sys/time.h>
53 //#include <sys/types.h>
54 //#include <sys/utsname.h>
55 //#include <sys/vfs.h>
56 //#include <sys/wait.h>
57 #include <sys/xattr.h>
58 //#include <syslog.h>
59 //#include <unistd.h>
60
61 /* When we include libgen.h because we need dirname() we immediately
62  * undefine basename() since libgen.h defines it as a macro to the
63  * POSIX version which is really broken. We prefer GNU basename(). */
64 //#include <libgen.h>
65 //#undef basename
66
67 #ifdef HAVE_SYS_AUXV_H
68 #include <sys/auxv.h>
69 #endif
70
71 /* We include linux/fs.h as last of the system headers, as it
72  * otherwise conflicts with sys/mount.h. Yay, Linux is great! */
73 //#include <linux/fs.h>
74
75 #include "build.h"
76 //#include "def.h"
77 //#include "device-nodes.h"
78 //#include "env-util.h"
79 //#include "exit-status.h"
80 #include "fileio.h"
81 //#include "formats-util.h"
82 #include "gunicode.h"
83 #include "hashmap.h"
84 #include "hostname-util.h"
85 //#include "ioprio.h"
86 //#include "log.h"
87 //#include "macro.h"
88 //#include "missing.h"
89 #include "mkdir.h"
90 #include "path-util.h"
91 #include "process-util.h"
92 #include "random-util.h"
93 #include "signal-util.h"
94 #include "sparse-endian.h"
95 #include "strv.h"
96 //#include "terminal-util.h"
97 #include "utf8.h"
98 #include "util.h"
99 #include "virt.h"
100 #include "set.h"
101
102 /* Put this test here for a lack of better place */
103 assert_cc(EAGAIN == EWOULDBLOCK);
104
105 int saved_argc = 0;
106 char **saved_argv = NULL;
107
108 size_t page_size(void) {
109         static thread_local size_t pgsz = 0;
110         long r;
111
112         if (_likely_(pgsz > 0))
113                 return pgsz;
114
115         r = sysconf(_SC_PAGESIZE);
116         assert(r > 0);
117
118         pgsz = (size_t) r;
119         return pgsz;
120 }
121
122 int strcmp_ptr(const char *a, const char *b) {
123
124         /* Like strcmp(), but tries to make sense of NULL pointers */
125         if (a && b)
126                 return strcmp(a, b);
127
128         if (!a && b)
129                 return -1;
130
131         if (a && !b)
132                 return 1;
133
134         return 0;
135 }
136
137 bool streq_ptr(const char *a, const char *b) {
138         return strcmp_ptr(a, b) == 0;
139 }
140
141 char* endswith(const char *s, const char *postfix) {
142         size_t sl, pl;
143
144         assert(s);
145         assert(postfix);
146
147         sl = strlen(s);
148         pl = strlen(postfix);
149
150         if (pl == 0)
151                 return (char*) s + sl;
152
153         if (sl < pl)
154                 return NULL;
155
156         if (memcmp(s + sl - pl, postfix, pl) != 0)
157                 return NULL;
158
159         return (char*) s + sl - pl;
160 }
161
162 char* endswith_no_case(const char *s, const char *postfix) {
163         size_t sl, pl;
164
165         assert(s);
166         assert(postfix);
167
168         sl = strlen(s);
169         pl = strlen(postfix);
170
171         if (pl == 0)
172                 return (char*) s + sl;
173
174         if (sl < pl)
175                 return NULL;
176
177         if (strcasecmp(s + sl - pl, postfix) != 0)
178                 return NULL;
179
180         return (char*) s + sl - pl;
181 }
182
183 char* first_word(const char *s, const char *word) {
184         size_t sl, wl;
185         const char *p;
186
187         assert(s);
188         assert(word);
189
190         /* Checks if the string starts with the specified word, either
191          * followed by NUL or by whitespace. Returns a pointer to the
192          * NUL or the first character after the whitespace. */
193
194         sl = strlen(s);
195         wl = strlen(word);
196
197         if (sl < wl)
198                 return NULL;
199
200         if (wl == 0)
201                 return (char*) s;
202
203         if (memcmp(s, word, wl) != 0)
204                 return NULL;
205
206         p = s + wl;
207         if (*p == 0)
208                 return (char*) p;
209
210         if (!strchr(WHITESPACE, *p))
211                 return NULL;
212
213         p += strspn(p, WHITESPACE);
214         return (char*) p;
215 }
216
217 size_t cescape_char(char c, char *buf) {
218         char * buf_old = buf;
219
220         switch (c) {
221
222                 case '\a':
223                         *(buf++) = '\\';
224                         *(buf++) = 'a';
225                         break;
226                 case '\b':
227                         *(buf++) = '\\';
228                         *(buf++) = 'b';
229                         break;
230                 case '\f':
231                         *(buf++) = '\\';
232                         *(buf++) = 'f';
233                         break;
234                 case '\n':
235                         *(buf++) = '\\';
236                         *(buf++) = 'n';
237                         break;
238                 case '\r':
239                         *(buf++) = '\\';
240                         *(buf++) = 'r';
241                         break;
242                 case '\t':
243                         *(buf++) = '\\';
244                         *(buf++) = 't';
245                         break;
246                 case '\v':
247                         *(buf++) = '\\';
248                         *(buf++) = 'v';
249                         break;
250                 case '\\':
251                         *(buf++) = '\\';
252                         *(buf++) = '\\';
253                         break;
254                 case '"':
255                         *(buf++) = '\\';
256                         *(buf++) = '"';
257                         break;
258                 case '\'':
259                         *(buf++) = '\\';
260                         *(buf++) = '\'';
261                         break;
262
263                 default:
264                         /* For special chars we prefer octal over
265                          * hexadecimal encoding, simply because glib's
266                          * g_strescape() does the same */
267                         if ((c < ' ') || (c >= 127)) {
268                                 *(buf++) = '\\';
269                                 *(buf++) = octchar((unsigned char) c >> 6);
270                                 *(buf++) = octchar((unsigned char) c >> 3);
271                                 *(buf++) = octchar((unsigned char) c);
272                         } else
273                                 *(buf++) = c;
274                         break;
275         }
276
277         return buf - buf_old;
278 }
279
280 int close_nointr(int fd) {
281         assert(fd >= 0);
282
283         if (close(fd) >= 0)
284                 return 0;
285
286         /*
287          * Just ignore EINTR; a retry loop is the wrong thing to do on
288          * Linux.
289          *
290          * http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
291          * https://bugzilla.gnome.org/show_bug.cgi?id=682819
292          * http://utcc.utoronto.ca/~cks/space/blog/unix/CloseEINTR
293          * https://sites.google.com/site/michaelsafyan/software-engineering/checkforeintrwheninvokingclosethinkagain
294          */
295         if (errno == EINTR)
296                 return 0;
297
298         return -errno;
299 }
300
301 int safe_close(int fd) {
302
303         /*
304          * Like close_nointr() but cannot fail. Guarantees errno is
305          * unchanged. Is a NOP with negative fds passed, and returns
306          * -1, so that it can be used in this syntax:
307          *
308          * fd = safe_close(fd);
309          */
310
311         if (fd >= 0) {
312                 PROTECT_ERRNO;
313
314                 /* The kernel might return pretty much any error code
315                  * via close(), but the fd will be closed anyway. The
316                  * only condition we want to check for here is whether
317                  * the fd was invalid at all... */
318
319                 assert_se(close_nointr(fd) != -EBADF);
320         }
321
322         return -1;
323 }
324
325 void close_many(const int fds[], unsigned n_fd) {
326         unsigned i;
327
328         assert(fds || n_fd <= 0);
329
330         for (i = 0; i < n_fd; i++)
331                 safe_close(fds[i]);
332 }
333
334 int fclose_nointr(FILE *f) {
335         assert(f);
336
337         /* Same as close_nointr(), but for fclose() */
338
339         if (fclose(f) == 0)
340                 return 0;
341
342         if (errno == EINTR)
343                 return 0;
344
345         return -errno;
346 }
347
348 FILE* safe_fclose(FILE *f) {
349
350         /* Same as safe_close(), but for fclose() */
351
352         if (f) {
353                 PROTECT_ERRNO;
354
355                 assert_se(fclose_nointr(f) != EBADF);
356         }
357
358         return NULL;
359 }
360
361 DIR* safe_closedir(DIR *d) {
362
363         if (d) {
364                 PROTECT_ERRNO;
365
366                 assert_se(closedir(d) >= 0 || errno != EBADF);
367         }
368
369         return NULL;
370 }
371
372 int unlink_noerrno(const char *path) {
373         PROTECT_ERRNO;
374         int r;
375
376         r = unlink(path);
377         if (r < 0)
378                 return -errno;
379
380         return 0;
381 }
382
383 int parse_boolean(const char *v) {
384         assert(v);
385
386         if (streq(v, "1") || strcaseeq(v, "yes") || strcaseeq(v, "y") || strcaseeq(v, "true") || strcaseeq(v, "t") || strcaseeq(v, "on"))
387                 return 1;
388         else if (streq(v, "0") || strcaseeq(v, "no") || strcaseeq(v, "n") || strcaseeq(v, "false") || strcaseeq(v, "f") || strcaseeq(v, "off"))
389                 return 0;
390
391         return -EINVAL;
392 }
393
394 int parse_pid(const char *s, pid_t* ret_pid) {
395         unsigned long ul = 0;
396         pid_t pid;
397         int r;
398
399         assert(s);
400         assert(ret_pid);
401
402         r = safe_atolu(s, &ul);
403         if (r < 0)
404                 return r;
405
406         pid = (pid_t) ul;
407
408         if ((unsigned long) pid != ul)
409                 return -ERANGE;
410
411         if (pid <= 0)
412                 return -ERANGE;
413
414         *ret_pid = pid;
415         return 0;
416 }
417
418 bool uid_is_valid(uid_t uid) {
419
420         /* Some libc APIs use UID_INVALID as special placeholder */
421         if (uid == (uid_t) 0xFFFFFFFF)
422                 return false;
423
424         /* A long time ago UIDs where 16bit, hence explicitly avoid the 16bit -1 too */
425         if (uid == (uid_t) 0xFFFF)
426                 return false;
427
428         return true;
429 }
430
431 int parse_uid(const char *s, uid_t* ret_uid) {
432         unsigned long ul = 0;
433         uid_t uid;
434         int r;
435
436         assert(s);
437
438         r = safe_atolu(s, &ul);
439         if (r < 0)
440                 return r;
441
442         uid = (uid_t) ul;
443
444         if ((unsigned long) uid != ul)
445                 return -ERANGE;
446
447         if (!uid_is_valid(uid))
448                 return -ENXIO; /* we return ENXIO instead of EINVAL
449                                 * here, to make it easy to distuingish
450                                 * invalid numeric uids invalid
451                                 * strings. */
452
453         if (ret_uid)
454                 *ret_uid = uid;
455
456         return 0;
457 }
458
459 int safe_atou(const char *s, unsigned *ret_u) {
460         char *x = NULL;
461         unsigned long l;
462
463         assert(s);
464         assert(ret_u);
465
466         errno = 0;
467         l = strtoul(s, &x, 0);
468
469         if (!x || x == s || *x || errno)
470                 return errno > 0 ? -errno : -EINVAL;
471
472         if ((unsigned long) (unsigned) l != l)
473                 return -ERANGE;
474
475         *ret_u = (unsigned) l;
476         return 0;
477 }
478
479 int safe_atoi(const char *s, int *ret_i) {
480         char *x = NULL;
481         long l;
482
483         assert(s);
484         assert(ret_i);
485
486         errno = 0;
487         l = strtol(s, &x, 0);
488
489         if (!x || x == s || *x || errno)
490                 return errno > 0 ? -errno : -EINVAL;
491
492         if ((long) (int) l != l)
493                 return -ERANGE;
494
495         *ret_i = (int) l;
496         return 0;
497 }
498
499 int safe_atou8(const char *s, uint8_t *ret) {
500         char *x = NULL;
501         unsigned long l;
502
503         assert(s);
504         assert(ret);
505
506         errno = 0;
507         l = strtoul(s, &x, 0);
508
509         if (!x || x == s || *x || errno)
510                 return errno > 0 ? -errno : -EINVAL;
511
512         if ((unsigned long) (uint8_t) l != l)
513                 return -ERANGE;
514
515         *ret = (uint8_t) l;
516         return 0;
517 }
518
519 int safe_atou16(const char *s, uint16_t *ret) {
520         char *x = NULL;
521         unsigned long l;
522
523         assert(s);
524         assert(ret);
525
526         errno = 0;
527         l = strtoul(s, &x, 0);
528
529         if (!x || x == s || *x || errno)
530                 return errno > 0 ? -errno : -EINVAL;
531
532         if ((unsigned long) (uint16_t) l != l)
533                 return -ERANGE;
534
535         *ret = (uint16_t) l;
536         return 0;
537 }
538
539 int safe_atoi16(const char *s, int16_t *ret) {
540         char *x = NULL;
541         long l;
542
543         assert(s);
544         assert(ret);
545
546         errno = 0;
547         l = strtol(s, &x, 0);
548
549         if (!x || x == s || *x || errno)
550                 return errno > 0 ? -errno : -EINVAL;
551
552         if ((long) (int16_t) l != l)
553                 return -ERANGE;
554
555         *ret = (int16_t) l;
556         return 0;
557 }
558
559 int safe_atollu(const char *s, long long unsigned *ret_llu) {
560         char *x = NULL;
561         unsigned long long l;
562
563         assert(s);
564         assert(ret_llu);
565
566         errno = 0;
567         l = strtoull(s, &x, 0);
568
569         if (!x || x == s || *x || errno)
570                 return errno ? -errno : -EINVAL;
571
572         *ret_llu = l;
573         return 0;
574 }
575
576 int safe_atolli(const char *s, long long int *ret_lli) {
577         char *x = NULL;
578         long long l;
579
580         assert(s);
581         assert(ret_lli);
582
583         errno = 0;
584         l = strtoll(s, &x, 0);
585
586         if (!x || x == s || *x || errno)
587                 return errno ? -errno : -EINVAL;
588
589         *ret_lli = l;
590         return 0;
591 }
592
593 int safe_atod(const char *s, double *ret_d) {
594         char *x = NULL;
595         double d = 0;
596         locale_t loc;
597
598         assert(s);
599         assert(ret_d);
600
601         loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0);
602         if (loc == (locale_t) 0)
603                 return -errno;
604
605         errno = 0;
606         d = strtod_l(s, &x, loc);
607
608         if (!x || x == s || *x || errno) {
609                 freelocale(loc);
610                 return errno ? -errno : -EINVAL;
611         }
612
613         freelocale(loc);
614         *ret_d = (double) d;
615         return 0;
616 }
617
618 static size_t strcspn_escaped(const char *s, const char *reject) {
619         bool escaped = false;
620         int n;
621
622         for (n=0; s[n]; n++) {
623                 if (escaped)
624                         escaped = false;
625                 else if (s[n] == '\\')
626                         escaped = true;
627                 else if (strchr(reject, s[n]))
628                         break;
629         }
630
631         /* if s ends in \, return index of previous char */
632         return n - escaped;
633 }
634
635 /* Split a string into words. */
636 const char* split(const char **state, size_t *l, const char *separator, bool quoted) {
637         const char *current;
638
639         current = *state;
640
641         if (!*current) {
642                 assert(**state == '\0');
643                 return NULL;
644         }
645
646         current += strspn(current, separator);
647         if (!*current) {
648                 *state = current;
649                 return NULL;
650         }
651
652         if (quoted && strchr("\'\"", *current)) {
653                 char quotechars[2] = {*current, '\0'};
654
655                 *l = strcspn_escaped(current + 1, quotechars);
656                 if (current[*l + 1] == '\0' || current[*l + 1] != quotechars[0] ||
657                     (current[*l + 2] && !strchr(separator, current[*l + 2]))) {
658                         /* right quote missing or garbage at the end */
659                         *state = current;
660                         return NULL;
661                 }
662                 *state = current++ + *l + 2;
663         } else if (quoted) {
664                 *l = strcspn_escaped(current, separator);
665                 if (current[*l] && !strchr(separator, current[*l])) {
666                         /* unfinished escape */
667                         *state = current;
668                         return NULL;
669                 }
670                 *state = current + *l;
671         } else {
672                 *l = strcspn(current, separator);
673                 *state = current + *l;
674         }
675
676         return current;
677 }
678
679 int fchmod_umask(int fd, mode_t m) {
680         mode_t u;
681         int r;
682
683         u = umask(0777);
684         r = fchmod(fd, m & (~u)) < 0 ? -errno : 0;
685         umask(u);
686
687         return r;
688 }
689
690 char *truncate_nl(char *s) {
691         assert(s);
692
693         s[strcspn(s, NEWLINE)] = 0;
694         return s;
695 }
696
697 char *strnappend(const char *s, const char *suffix, size_t b) {
698         size_t a;
699         char *r;
700
701         if (!s && !suffix)
702                 return strdup("");
703
704         if (!s)
705                 return strndup(suffix, b);
706
707         if (!suffix)
708                 return strdup(s);
709
710         assert(s);
711         assert(suffix);
712
713         a = strlen(s);
714         if (b > ((size_t) -1) - a)
715                 return NULL;
716
717         r = new(char, a+b+1);
718         if (!r)
719                 return NULL;
720
721         memcpy(r, s, a);
722         memcpy(r+a, suffix, b);
723         r[a+b] = 0;
724
725         return r;
726 }
727
728 char *strappend(const char *s, const char *suffix) {
729         return strnappend(s, suffix, suffix ? strlen(suffix) : 0);
730 }
731
732 int readlinkat_malloc(int fd, const char *p, char **ret) {
733         size_t l = 100;
734         int r;
735
736         assert(p);
737         assert(ret);
738
739         for (;;) {
740                 char *c;
741                 ssize_t n;
742
743                 c = new(char, l);
744                 if (!c)
745                         return -ENOMEM;
746
747                 n = readlinkat(fd, p, c, l-1);
748                 if (n < 0) {
749                         r = -errno;
750                         free(c);
751                         return r;
752                 }
753
754                 if ((size_t) n < l-1) {
755                         c[n] = 0;
756                         *ret = c;
757                         return 0;
758                 }
759
760                 free(c);
761                 l *= 2;
762         }
763 }
764
765 int readlink_malloc(const char *p, char **ret) {
766         return readlinkat_malloc(AT_FDCWD, p, ret);
767 }
768
769 /// UNNEEDED by elogind
770 #if 0
771 int readlink_value(const char *p, char **ret) {
772         _cleanup_free_ char *link = NULL;
773         char *value;
774         int r;
775
776         r = readlink_malloc(p, &link);
777         if (r < 0)
778                 return r;
779
780         value = basename(link);
781         if (!value)
782                 return -ENOENT;
783
784         value = strdup(value);
785         if (!value)
786                 return -ENOMEM;
787
788         *ret = value;
789
790         return 0;
791 }
792 #endif // 0
793
794 int readlink_and_make_absolute(const char *p, char **r) {
795         _cleanup_free_ char *target = NULL;
796         char *k;
797         int j;
798
799         assert(p);
800         assert(r);
801
802         j = readlink_malloc(p, &target);
803         if (j < 0)
804                 return j;
805
806         k = file_in_same_dir(p, target);
807         if (!k)
808                 return -ENOMEM;
809
810         *r = k;
811         return 0;
812 }
813
814 /// UNNEEDED by elogind
815 #if 0
816 int readlink_and_canonicalize(const char *p, char **r) {
817         char *t, *s;
818         int j;
819
820         assert(p);
821         assert(r);
822
823         j = readlink_and_make_absolute(p, &t);
824         if (j < 0)
825                 return j;
826
827         s = canonicalize_file_name(t);
828         if (s) {
829                 free(t);
830                 *r = s;
831         } else
832                 *r = t;
833
834         path_kill_slashes(*r);
835
836         return 0;
837 }
838 #endif // 0
839
840 char *strstrip(char *s) {
841         char *e;
842
843         /* Drops trailing whitespace. Modifies the string in
844          * place. Returns pointer to first non-space character */
845
846         s += strspn(s, WHITESPACE);
847
848         for (e = strchr(s, 0); e > s; e --)
849                 if (!strchr(WHITESPACE, e[-1]))
850                         break;
851
852         *e = 0;
853
854         return s;
855 }
856
857 /// UNNEEDED by elogind
858 #if 0
859 char *delete_chars(char *s, const char *bad) {
860         char *f, *t;
861
862         /* Drops all whitespace, regardless where in the string */
863
864         for (f = s, t = s; *f; f++) {
865                 if (strchr(bad, *f))
866                         continue;
867
868                 *(t++) = *f;
869         }
870
871         *t = 0;
872
873         return s;
874 }
875 #endif // 0
876
877 char *file_in_same_dir(const char *path, const char *filename) {
878         char *e, *ret;
879         size_t k;
880
881         assert(path);
882         assert(filename);
883
884         /* This removes the last component of path and appends
885          * filename, unless the latter is absolute anyway or the
886          * former isn't */
887
888         if (path_is_absolute(filename))
889                 return strdup(filename);
890
891         e = strrchr(path, '/');
892         if (!e)
893                 return strdup(filename);
894
895         k = strlen(filename);
896         ret = new(char, (e + 1 - path) + k + 1);
897         if (!ret)
898                 return NULL;
899
900         memcpy(mempcpy(ret, path, e + 1 - path), filename, k + 1);
901         return ret;
902 }
903
904 /// UNNEEDED by elogind
905 #if 0
906 int rmdir_parents(const char *path, const char *stop) {
907         size_t l;
908         int r = 0;
909
910         assert(path);
911         assert(stop);
912
913         l = strlen(path);
914
915         /* Skip trailing slashes */
916         while (l > 0 && path[l-1] == '/')
917                 l--;
918
919         while (l > 0) {
920                 char *t;
921
922                 /* Skip last component */
923                 while (l > 0 && path[l-1] != '/')
924                         l--;
925
926                 /* Skip trailing slashes */
927                 while (l > 0 && path[l-1] == '/')
928                         l--;
929
930                 if (l <= 0)
931                         break;
932
933                 if (!(t = strndup(path, l)))
934                         return -ENOMEM;
935
936                 if (path_startswith(stop, t)) {
937                         free(t);
938                         return 0;
939                 }
940
941                 r = rmdir(t);
942                 free(t);
943
944                 if (r < 0)
945                         if (errno != ENOENT)
946                                 return -errno;
947         }
948
949         return 0;
950 }
951 #endif // 0
952
953 char hexchar(int x) {
954         static const char table[16] = "0123456789abcdef";
955
956         return table[x & 15];
957 }
958
959 int unhexchar(char c) {
960
961         if (c >= '0' && c <= '9')
962                 return c - '0';
963
964         if (c >= 'a' && c <= 'f')
965                 return c - 'a' + 10;
966
967         if (c >= 'A' && c <= 'F')
968                 return c - 'A' + 10;
969
970         return -EINVAL;
971 }
972
973 char *hexmem(const void *p, size_t l) {
974         char *r, *z;
975         const uint8_t *x;
976
977         z = r = malloc(l * 2 + 1);
978         if (!r)
979                 return NULL;
980
981         for (x = p; x < (const uint8_t*) p + l; x++) {
982                 *(z++) = hexchar(*x >> 4);
983                 *(z++) = hexchar(*x & 15);
984         }
985
986         *z = 0;
987         return r;
988 }
989
990 int unhexmem(const char *p, size_t l, void **mem, size_t *len) {
991         _cleanup_free_ uint8_t *r = NULL;
992         uint8_t *z;
993         const char *x;
994
995         assert(mem);
996         assert(len);
997         assert(p);
998
999         z = r = malloc((l + 1) / 2 + 1);
1000         if (!r)
1001                 return -ENOMEM;
1002
1003         for (x = p; x < p + l; x += 2) {
1004                 int a, b;
1005
1006                 a = unhexchar(x[0]);
1007                 if (a < 0)
1008                         return a;
1009                 else if (x+1 < p + l) {
1010                         b = unhexchar(x[1]);
1011                         if (b < 0)
1012                                 return b;
1013                 } else
1014                         b = 0;
1015
1016                 *(z++) = (uint8_t) a << 4 | (uint8_t) b;
1017         }
1018
1019         *z = 0;
1020
1021         *mem = r;
1022         r = NULL;
1023         *len = (l + 1) / 2;
1024
1025         return 0;
1026 }
1027
1028 /* https://tools.ietf.org/html/rfc4648#section-6
1029  * Notice that base32hex differs from base32 in the alphabet it uses.
1030  * The distinction is that the base32hex representation preserves the
1031  * order of the underlying data when compared as bytestrings, this is
1032  * useful when representing NSEC3 hashes, as one can then verify the
1033  * order of hashes directly from their representation. */
1034 char base32hexchar(int x) {
1035         static const char table[32] = "0123456789"
1036                                       "ABCDEFGHIJKLMNOPQRSTUV";
1037
1038         return table[x & 31];
1039 }
1040
1041 int unbase32hexchar(char c) {
1042         unsigned offset;
1043
1044         if (c >= '0' && c <= '9')
1045                 return c - '0';
1046
1047         offset = '9' - '0' + 1;
1048
1049         if (c >= 'A' && c <= 'V')
1050                 return c - 'A' + offset;
1051
1052         return -EINVAL;
1053 }
1054
1055 char *base32hexmem(const void *p, size_t l, bool padding) {
1056         char *r, *z;
1057         const uint8_t *x;
1058         size_t len;
1059
1060         if (padding)
1061                 /* five input bytes makes eight output bytes, padding is added so we must round up */
1062                 len = 8 * (l + 4) / 5;
1063         else {
1064                 /* same, but round down as there is no padding */
1065                 len = 8 * l / 5;
1066
1067                 switch (l % 5) {
1068                 case 4:
1069                         len += 7;
1070                         break;
1071                 case 3:
1072                         len += 5;
1073                         break;
1074                 case 2:
1075                         len += 4;
1076                         break;
1077                 case 1:
1078                         len += 2;
1079                         break;
1080                 }
1081         }
1082
1083         z = r = malloc(len + 1);
1084         if (!r)
1085                 return NULL;
1086
1087         for (x = p; x < (const uint8_t*) p + (l / 5) * 5; x += 5) {
1088                 /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ
1089                    x[3] == QQQQQQQQ; x[4] == WWWWWWWW */
1090                 *(z++) = base32hexchar(x[0] >> 3);                    /* 000XXXXX */
1091                 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6);  /* 000XXXYY */
1092                 *(z++) = base32hexchar((x[1] & 63) >> 1);             /* 000YYYYY */
1093                 *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4);  /* 000YZZZZ */
1094                 *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */
1095                 *(z++) = base32hexchar((x[3] & 127) >> 2);            /* 000QQQQQ */
1096                 *(z++) = base32hexchar((x[3] & 3) << 3 | x[4] >> 5);  /* 000QQWWW */
1097                 *(z++) = base32hexchar((x[4] & 31));                  /* 000WWWWW */
1098         }
1099
1100         switch (l % 5) {
1101         case 4:
1102                 *(z++) = base32hexchar(x[0] >> 3);                    /* 000XXXXX */
1103                 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6);  /* 000XXXYY */
1104                 *(z++) = base32hexchar((x[1] & 63) >> 1);             /* 000YYYYY */
1105                 *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4);   /* 000YZZZZ */
1106                 *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */
1107                 *(z++) = base32hexchar((x[3] & 127) >> 2);            /* 000QQQQQ */
1108                 *(z++) = base32hexchar((x[3] & 3) << 3);              /* 000QQ000 */
1109                 if (padding)
1110                         *(z++) = '=';
1111
1112                 break;
1113
1114         case 3:
1115                 *(z++) = base32hexchar(x[0] >> 3);                   /* 000XXXXX */
1116                 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
1117                 *(z++) = base32hexchar((x[1] & 63) >> 1);            /* 000YYYYY */
1118                 *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
1119                 *(z++) = base32hexchar((x[2] & 15) << 1);            /* 000ZZZZ0 */
1120                 if (padding) {
1121                         *(z++) = '=';
1122                         *(z++) = '=';
1123                         *(z++) = '=';
1124                 }
1125
1126                 break;
1127
1128         case 2:
1129                 *(z++) = base32hexchar(x[0] >> 3);                   /* 000XXXXX */
1130                 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
1131                 *(z++) = base32hexchar((x[1] & 63) >> 1);            /* 000YYYYY */
1132                 *(z++) = base32hexchar((x[1] & 1) << 4);             /* 000Y0000 */
1133                 if (padding) {
1134                         *(z++) = '=';
1135                         *(z++) = '=';
1136                         *(z++) = '=';
1137                         *(z++) = '=';
1138                 }
1139
1140                 break;
1141
1142         case 1:
1143                 *(z++) = base32hexchar(x[0] >> 3);       /* 000XXXXX */
1144                 *(z++) = base32hexchar((x[0] & 7) << 2); /* 000XXX00 */
1145                 if (padding) {
1146                         *(z++) = '=';
1147                         *(z++) = '=';
1148                         *(z++) = '=';
1149                         *(z++) = '=';
1150                         *(z++) = '=';
1151                         *(z++) = '=';
1152                 }
1153
1154                 break;
1155         }
1156
1157         *z = 0;
1158         return r;
1159 }
1160
1161 int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_len) {
1162         _cleanup_free_ uint8_t *r = NULL;
1163         int a, b, c, d, e, f, g, h;
1164         uint8_t *z;
1165         const char *x;
1166         size_t len;
1167         unsigned pad = 0;
1168
1169         assert(p);
1170
1171         /* padding ensures any base32hex input has input divisible by 8 */
1172         if (padding && l % 8 != 0)
1173                 return -EINVAL;
1174
1175         if (padding) {
1176                 /* strip the padding */
1177                 while (l > 0 && p[l - 1] == '=' && pad < 7) {
1178                         pad ++;
1179                         l --;
1180                 }
1181         }
1182
1183         /* a group of eight input bytes needs five output bytes, in case of
1184            padding we need to add some extra bytes */
1185         len = (l / 8) * 5;
1186
1187         switch (l % 8) {
1188         case 7:
1189                 len += 4;
1190                 break;
1191         case 5:
1192                 len += 3;
1193                 break;
1194         case 4:
1195                 len += 2;
1196                 break;
1197         case 2:
1198                 len += 1;
1199                 break;
1200         case 0:
1201                 break;
1202         default:
1203                 return -EINVAL;
1204         }
1205
1206         z = r = malloc(len + 1);
1207         if (!r)
1208                 return -ENOMEM;
1209
1210         for (x = p; x < p + (l / 8) * 8; x += 8) {
1211                 /* a == 000XXXXX; b == 000YYYYY; c == 000ZZZZZ; d == 000WWWWW
1212                    e == 000SSSSS; f == 000QQQQQ; g == 000VVVVV; h == 000RRRRR */
1213                 a = unbase32hexchar(x[0]);
1214                 if (a < 0)
1215                         return -EINVAL;
1216
1217                 b = unbase32hexchar(x[1]);
1218                 if (b < 0)
1219                         return -EINVAL;
1220
1221                 c = unbase32hexchar(x[2]);
1222                 if (c < 0)
1223                         return -EINVAL;
1224
1225                 d = unbase32hexchar(x[3]);
1226                 if (d < 0)
1227                         return -EINVAL;
1228
1229                 e = unbase32hexchar(x[4]);
1230                 if (e < 0)
1231                         return -EINVAL;
1232
1233                 f = unbase32hexchar(x[5]);
1234                 if (f < 0)
1235                         return -EINVAL;
1236
1237                 g = unbase32hexchar(x[6]);
1238                 if (g < 0)
1239                         return -EINVAL;
1240
1241                 h = unbase32hexchar(x[7]);
1242                 if (h < 0)
1243                         return -EINVAL;
1244
1245                 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2;                    /* XXXXXYYY */
1246                 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
1247                 *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1;                    /* WWWWSSSS */
1248                 *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */
1249                 *(z++) = (uint8_t) g << 5 | (uint8_t) h;                         /* VVVRRRRR */
1250         }
1251
1252         switch (l % 8) {
1253         case 7:
1254                 a = unbase32hexchar(x[0]);
1255                 if (a < 0)
1256                         return -EINVAL;
1257
1258                 b = unbase32hexchar(x[1]);
1259                 if (b < 0)
1260                         return -EINVAL;
1261
1262                 c = unbase32hexchar(x[2]);
1263                 if (c < 0)
1264                         return -EINVAL;
1265
1266                 d = unbase32hexchar(x[3]);
1267                 if (d < 0)
1268                         return -EINVAL;
1269
1270                 e = unbase32hexchar(x[4]);
1271                 if (e < 0)
1272                         return -EINVAL;
1273
1274                 f = unbase32hexchar(x[5]);
1275                 if (f < 0)
1276                         return -EINVAL;
1277
1278                 g = unbase32hexchar(x[6]);
1279                 if (g < 0)
1280                         return -EINVAL;
1281
1282                 /* g == 000VV000 */
1283                 if (g & 7)
1284                         return -EINVAL;
1285
1286                 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2;                    /* XXXXXYYY */
1287                 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
1288                 *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1;                    /* WWWWSSSS */
1289                 *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */
1290
1291                 break;
1292         case 5:
1293                 a = unbase32hexchar(x[0]);
1294                 if (a < 0)
1295                         return -EINVAL;
1296
1297                 b = unbase32hexchar(x[1]);
1298                 if (b < 0)
1299                         return -EINVAL;
1300
1301                 c = unbase32hexchar(x[2]);
1302                 if (c < 0)
1303                         return -EINVAL;
1304
1305                 d = unbase32hexchar(x[3]);
1306                 if (d < 0)
1307                         return -EINVAL;
1308
1309                 e = unbase32hexchar(x[4]);
1310                 if (e < 0)
1311                         return -EINVAL;
1312
1313                 /* e == 000SSSS0 */
1314                 if (e & 1)
1315                         return -EINVAL;
1316
1317                 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2;                    /* XXXXXYYY */
1318                 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
1319                 *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1;                    /* WWWWSSSS */
1320
1321                 break;
1322         case 4:
1323                 a = unbase32hexchar(x[0]);
1324                 if (a < 0)
1325                         return -EINVAL;
1326
1327                 b = unbase32hexchar(x[1]);
1328                 if (b < 0)
1329                         return -EINVAL;
1330
1331                 c = unbase32hexchar(x[2]);
1332                 if (c < 0)
1333                         return -EINVAL;
1334
1335                 d = unbase32hexchar(x[3]);
1336                 if (d < 0)
1337                         return -EINVAL;
1338
1339                 /* d == 000W0000 */
1340                 if (d & 15)
1341                         return -EINVAL;
1342
1343                 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2;                    /* XXXXXYYY */
1344                 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
1345
1346                 break;
1347         case 2:
1348                 a = unbase32hexchar(x[0]);
1349                 if (a < 0)
1350                         return -EINVAL;
1351
1352                 b = unbase32hexchar(x[1]);
1353                 if (b < 0)
1354                         return -EINVAL;
1355
1356                 /* b == 000YYY00 */
1357                 if (b & 3)
1358                         return -EINVAL;
1359
1360                 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
1361
1362                 break;
1363         case 0:
1364                 break;
1365         default:
1366                 return -EINVAL;
1367         }
1368
1369         *z = 0;
1370
1371         *mem = r;
1372         r = NULL;
1373         *_len = len;
1374
1375         return 0;
1376 }
1377
1378 /* https://tools.ietf.org/html/rfc4648#section-4 */
1379 char base64char(int x) {
1380         static const char table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1381                                       "abcdefghijklmnopqrstuvwxyz"
1382                                       "0123456789+/";
1383         return table[x & 63];
1384 }
1385
1386 int unbase64char(char c) {
1387         unsigned offset;
1388
1389         if (c >= 'A' && c <= 'Z')
1390                 return c - 'A';
1391
1392         offset = 'Z' - 'A' + 1;
1393
1394         if (c >= 'a' && c <= 'z')
1395                 return c - 'a' + offset;
1396
1397         offset += 'z' - 'a' + 1;
1398
1399         if (c >= '0' && c <= '9')
1400                 return c - '0' + offset;
1401
1402         offset += '9' - '0' + 1;
1403
1404         if (c == '+')
1405                 return offset;
1406
1407         offset ++;
1408
1409         if (c == '/')
1410                 return offset;
1411
1412         return -EINVAL;
1413 }
1414
1415 char *base64mem(const void *p, size_t l) {
1416         char *r, *z;
1417         const uint8_t *x;
1418
1419         /* three input bytes makes four output bytes, padding is added so we must round up */
1420         z = r = malloc(4 * (l + 2) / 3 + 1);
1421         if (!r)
1422                 return NULL;
1423
1424         for (x = p; x < (const uint8_t*) p + (l / 3) * 3; x += 3) {
1425                 /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ */
1426                 *(z++) = base64char(x[0] >> 2);                    /* 00XXXXXX */
1427                 *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4);  /* 00XXYYYY */
1428                 *(z++) = base64char((x[1] & 15) << 2 | x[2] >> 6); /* 00YYYYZZ */
1429                 *(z++) = base64char(x[2] & 63);                    /* 00ZZZZZZ */
1430         }
1431
1432         switch (l % 3) {
1433         case 2:
1434                 *(z++) = base64char(x[0] >> 2);                   /* 00XXXXXX */
1435                 *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */
1436                 *(z++) = base64char((x[1] & 15) << 2);            /* 00YYYY00 */
1437                 *(z++) = '=';
1438
1439                 break;
1440         case 1:
1441                 *(z++) = base64char(x[0] >> 2);        /* 00XXXXXX */
1442                 *(z++) = base64char((x[0] & 3) << 4);  /* 00XX0000 */
1443                 *(z++) = '=';
1444                 *(z++) = '=';
1445
1446                 break;
1447         }
1448
1449         *z = 0;
1450         return r;
1451 }
1452
1453 int unbase64mem(const char *p, size_t l, void **mem, size_t *_len) {
1454         _cleanup_free_ uint8_t *r = NULL;
1455         int a, b, c, d;
1456         uint8_t *z;
1457         const char *x;
1458         size_t len;
1459
1460         assert(p);
1461
1462         /* padding ensures any base63 input has input divisible by 4 */
1463         if (l % 4 != 0)
1464                 return -EINVAL;
1465
1466         /* strip the padding */
1467         if (l > 0 && p[l - 1] == '=')
1468                 l --;
1469         if (l > 0 && p[l - 1] == '=')
1470                 l --;
1471
1472         /* a group of four input bytes needs three output bytes, in case of
1473            padding we need to add two or three extra bytes */
1474         len = (l / 4) * 3 + (l % 4 ? (l % 4) - 1 : 0);
1475
1476         z = r = malloc(len + 1);
1477         if (!r)
1478                 return -ENOMEM;
1479
1480         for (x = p; x < p + (l / 4) * 4; x += 4) {
1481                 /* a == 00XXXXXX; b == 00YYYYYY; c == 00ZZZZZZ; d == 00WWWWWW */
1482                 a = unbase64char(x[0]);
1483                 if (a < 0)
1484                         return -EINVAL;
1485
1486                 b = unbase64char(x[1]);
1487                 if (b < 0)
1488                         return -EINVAL;
1489
1490                 c = unbase64char(x[2]);
1491                 if (c < 0)
1492                         return -EINVAL;
1493
1494                 d = unbase64char(x[3]);
1495                 if (d < 0)
1496                         return -EINVAL;
1497
1498                 *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
1499                 *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
1500                 *(z++) = (uint8_t) c << 6 | (uint8_t) d;      /* ZZWWWWWW */
1501         }
1502
1503         switch (l % 4) {
1504         case 3:
1505                 a = unbase64char(x[0]);
1506                 if (a < 0)
1507                         return -EINVAL;
1508
1509                 b = unbase64char(x[1]);
1510                 if (b < 0)
1511                         return -EINVAL;
1512
1513                 c = unbase64char(x[2]);
1514                 if (c < 0)
1515                         return -EINVAL;
1516
1517                 /* c == 00ZZZZ00 */
1518                 if (c & 3)
1519                         return -EINVAL;
1520
1521                 *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
1522                 *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
1523
1524                 break;
1525         case 2:
1526                 a = unbase64char(x[0]);
1527                 if (a < 0)
1528                         return -EINVAL;
1529
1530                 b = unbase64char(x[1]);
1531                 if (b < 0)
1532                         return -EINVAL;
1533
1534                 /* b == 00YY0000 */
1535                 if (b & 15)
1536                         return -EINVAL;
1537
1538                 *(z++) = (uint8_t) a << 2 | (uint8_t) (b >> 4); /* XXXXXXYY */
1539
1540                 break;
1541         case 0:
1542
1543                 break;
1544         default:
1545                 return -EINVAL;
1546         }
1547
1548         *z = 0;
1549
1550         *mem = r;
1551         r = NULL;
1552         *_len = len;
1553
1554         return 0;
1555 }
1556
1557 char octchar(int x) {
1558         return '0' + (x & 7);
1559 }
1560
1561 int unoctchar(char c) {
1562
1563         if (c >= '0' && c <= '7')
1564                 return c - '0';
1565
1566         return -EINVAL;
1567 }
1568
1569 char decchar(int x) {
1570         return '0' + (x % 10);
1571 }
1572
1573 int undecchar(char c) {
1574
1575         if (c >= '0' && c <= '9')
1576                 return c - '0';
1577
1578         return -EINVAL;
1579 }
1580
1581 char *cescape(const char *s) {
1582         char *r, *t;
1583         const char *f;
1584
1585         assert(s);
1586
1587         /* Does C style string escaping. May be reversed with
1588          * cunescape(). */
1589
1590         r = new(char, strlen(s)*4 + 1);
1591         if (!r)
1592                 return NULL;
1593
1594         for (f = s, t = r; *f; f++)
1595                 t += cescape_char(*f, t);
1596
1597         *t = 0;
1598
1599         return r;
1600 }
1601
1602 static int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode) {
1603         int r = 1;
1604
1605         assert(p);
1606         assert(*p);
1607         assert(ret);
1608
1609         /* Unescapes C style. Returns the unescaped character in ret,
1610          * unless we encountered a \u sequence in which case the full
1611          * unicode character is returned in ret_unicode, instead. */
1612
1613         if (length != (size_t) -1 && length < 1)
1614                 return -EINVAL;
1615
1616         switch (p[0]) {
1617
1618         case 'a':
1619                 *ret = '\a';
1620                 break;
1621         case 'b':
1622                 *ret = '\b';
1623                 break;
1624         case 'f':
1625                 *ret = '\f';
1626                 break;
1627         case 'n':
1628                 *ret = '\n';
1629                 break;
1630         case 'r':
1631                 *ret = '\r';
1632                 break;
1633         case 't':
1634                 *ret = '\t';
1635                 break;
1636         case 'v':
1637                 *ret = '\v';
1638                 break;
1639         case '\\':
1640                 *ret = '\\';
1641                 break;
1642         case '"':
1643                 *ret = '"';
1644                 break;
1645         case '\'':
1646                 *ret = '\'';
1647                 break;
1648
1649         case 's':
1650                 /* This is an extension of the XDG syntax files */
1651                 *ret = ' ';
1652                 break;
1653
1654         case 'x': {
1655                 /* hexadecimal encoding */
1656                 int a, b;
1657
1658                 if (length != (size_t) -1 && length < 3)
1659                         return -EINVAL;
1660
1661                 a = unhexchar(p[1]);
1662                 if (a < 0)
1663                         return -EINVAL;
1664
1665                 b = unhexchar(p[2]);
1666                 if (b < 0)
1667                         return -EINVAL;
1668
1669                 /* Don't allow NUL bytes */
1670                 if (a == 0 && b == 0)
1671                         return -EINVAL;
1672
1673                 *ret = (char) ((a << 4U) | b);
1674                 r = 3;
1675                 break;
1676         }
1677
1678         case 'u': {
1679                 /* C++11 style 16bit unicode */
1680
1681                 int a[4];
1682                 unsigned i;
1683                 uint32_t c;
1684
1685                 if (length != (size_t) -1 && length < 5)
1686                         return -EINVAL;
1687
1688                 for (i = 0; i < 4; i++) {
1689                         a[i] = unhexchar(p[1 + i]);
1690                         if (a[i] < 0)
1691                                 return a[i];
1692                 }
1693
1694                 c = ((uint32_t) a[0] << 12U) | ((uint32_t) a[1] << 8U) | ((uint32_t) a[2] << 4U) | (uint32_t) a[3];
1695
1696                 /* Don't allow 0 chars */
1697                 if (c == 0)
1698                         return -EINVAL;
1699
1700                 if (c < 128)
1701                         *ret = c;
1702                 else {
1703                         if (!ret_unicode)
1704                                 return -EINVAL;
1705
1706                         *ret = 0;
1707                         *ret_unicode = c;
1708                 }
1709
1710                 r = 5;
1711                 break;
1712         }
1713
1714         case 'U': {
1715                 /* C++11 style 32bit unicode */
1716
1717                 int a[8];
1718                 unsigned i;
1719                 uint32_t c;
1720
1721                 if (length != (size_t) -1 && length < 9)
1722                         return -EINVAL;
1723
1724                 for (i = 0; i < 8; i++) {
1725                         a[i] = unhexchar(p[1 + i]);
1726                         if (a[i] < 0)
1727                                 return a[i];
1728                 }
1729
1730                 c = ((uint32_t) a[0] << 28U) | ((uint32_t) a[1] << 24U) | ((uint32_t) a[2] << 20U) | ((uint32_t) a[3] << 16U) |
1731                     ((uint32_t) a[4] << 12U) | ((uint32_t) a[5] <<  8U) | ((uint32_t) a[6] <<  4U) |  (uint32_t) a[7];
1732
1733                 /* Don't allow 0 chars */
1734                 if (c == 0)
1735                         return -EINVAL;
1736
1737                 /* Don't allow invalid code points */
1738                 if (!unichar_is_valid(c))
1739                         return -EINVAL;
1740
1741                 if (c < 128)
1742                         *ret = c;
1743                 else {
1744                         if (!ret_unicode)
1745                                 return -EINVAL;
1746
1747                         *ret = 0;
1748                         *ret_unicode = c;
1749                 }
1750
1751                 r = 9;
1752                 break;
1753         }
1754
1755         case '0':
1756         case '1':
1757         case '2':
1758         case '3':
1759         case '4':
1760         case '5':
1761         case '6':
1762         case '7': {
1763                 /* octal encoding */
1764                 int a, b, c;
1765                 uint32_t m;
1766
1767                 if (length != (size_t) -1 && length < 3)
1768                         return -EINVAL;
1769
1770                 a = unoctchar(p[0]);
1771                 if (a < 0)
1772                         return -EINVAL;
1773
1774                 b = unoctchar(p[1]);
1775                 if (b < 0)
1776                         return -EINVAL;
1777
1778                 c = unoctchar(p[2]);
1779                 if (c < 0)
1780                         return -EINVAL;
1781
1782                 /* don't allow NUL bytes */
1783                 if (a == 0 && b == 0 && c == 0)
1784                         return -EINVAL;
1785
1786                 /* Don't allow bytes above 255 */
1787                 m = ((uint32_t) a << 6U) | ((uint32_t) b << 3U) | (uint32_t) c;
1788                 if (m > 255)
1789                         return -EINVAL;
1790
1791                 *ret = m;
1792                 r = 3;
1793                 break;
1794         }
1795
1796         default:
1797                 return -EINVAL;
1798         }
1799
1800         return r;
1801 }
1802
1803 int cunescape_length_with_prefix(const char *s, size_t length, const char *prefix, UnescapeFlags flags, char **ret) {
1804         char *r, *t;
1805         const char *f;
1806         size_t pl;
1807
1808         assert(s);
1809         assert(ret);
1810
1811         /* Undoes C style string escaping, and optionally prefixes it. */
1812
1813         pl = prefix ? strlen(prefix) : 0;
1814
1815         r = new(char, pl+length+1);
1816         if (!r)
1817                 return -ENOMEM;
1818
1819         if (prefix)
1820                 memcpy(r, prefix, pl);
1821
1822         for (f = s, t = r + pl; f < s + length; f++) {
1823                 size_t remaining;
1824                 uint32_t u;
1825                 char c;
1826                 int k;
1827
1828                 remaining = s + length - f;
1829                 assert(remaining > 0);
1830
1831                 if (*f != '\\') {
1832                         /* A literal literal, copy verbatim */
1833                         *(t++) = *f;
1834                         continue;
1835                 }
1836
1837                 if (remaining == 1) {
1838                         if (flags & UNESCAPE_RELAX) {
1839                                 /* A trailing backslash, copy verbatim */
1840                                 *(t++) = *f;
1841                                 continue;
1842                         }
1843
1844                         free(r);
1845                         return -EINVAL;
1846                 }
1847
1848                 k = cunescape_one(f + 1, remaining - 1, &c, &u);
1849                 if (k < 0) {
1850                         if (flags & UNESCAPE_RELAX) {
1851                                 /* Invalid escape code, let's take it literal then */
1852                                 *(t++) = '\\';
1853                                 continue;
1854                         }
1855
1856                         free(r);
1857                         return k;
1858                 }
1859
1860                 if (c != 0)
1861                         /* Non-Unicode? Let's encode this directly */
1862                         *(t++) = c;
1863                 else
1864                         /* Unicode? Then let's encode this in UTF-8 */
1865                         t += utf8_encode_unichar(t, u);
1866
1867                 f += k;
1868         }
1869
1870         *t = 0;
1871
1872         *ret = r;
1873         return t - r;
1874 }
1875
1876 int cunescape_length(const char *s, size_t length, UnescapeFlags flags, char **ret) {
1877         return cunescape_length_with_prefix(s, length, NULL, flags, ret);
1878 }
1879
1880 int cunescape(const char *s, UnescapeFlags flags, char **ret) {
1881         return cunescape_length(s, strlen(s), flags, ret);
1882 }
1883
1884 char *xescape(const char *s, const char *bad) {
1885         char *r, *t;
1886         const char *f;
1887
1888         /* Escapes all chars in bad, in addition to \ and all special
1889          * chars, in \xFF style escaping. May be reversed with
1890          * cunescape(). */
1891
1892         r = new(char, strlen(s) * 4 + 1);
1893         if (!r)
1894                 return NULL;
1895
1896         for (f = s, t = r; *f; f++) {
1897
1898                 if ((*f < ' ') || (*f >= 127) ||
1899                     (*f == '\\') || strchr(bad, *f)) {
1900                         *(t++) = '\\';
1901                         *(t++) = 'x';
1902                         *(t++) = hexchar(*f >> 4);
1903                         *(t++) = hexchar(*f);
1904                 } else
1905                         *(t++) = *f;
1906         }
1907
1908         *t = 0;
1909
1910         return r;
1911 }
1912
1913 /// UNNEEDED by elogind
1914 #if 0
1915 char *ascii_strlower(char *t) {
1916         char *p;
1917
1918         assert(t);
1919
1920         for (p = t; *p; p++)
1921                 if (*p >= 'A' && *p <= 'Z')
1922                         *p = *p - 'A' + 'a';
1923
1924         return t;
1925 }
1926 #endif // 0
1927
1928 _pure_ static bool hidden_file_allow_backup(const char *filename) {
1929         assert(filename);
1930
1931         return
1932                 filename[0] == '.' ||
1933                 streq(filename, "lost+found") ||
1934                 streq(filename, "aquota.user") ||
1935                 streq(filename, "aquota.group") ||
1936                 endswith(filename, ".rpmnew") ||
1937                 endswith(filename, ".rpmsave") ||
1938                 endswith(filename, ".rpmorig") ||
1939                 endswith(filename, ".dpkg-old") ||
1940                 endswith(filename, ".dpkg-new") ||
1941                 endswith(filename, ".dpkg-tmp") ||
1942                 endswith(filename, ".dpkg-dist") ||
1943                 endswith(filename, ".dpkg-bak") ||
1944                 endswith(filename, ".dpkg-backup") ||
1945                 endswith(filename, ".dpkg-remove") ||
1946                 endswith(filename, ".swp");
1947 }
1948
1949 bool hidden_file(const char *filename) {
1950         assert(filename);
1951
1952         if (endswith(filename, "~"))
1953                 return true;
1954
1955         return hidden_file_allow_backup(filename);
1956 }
1957
1958 int fd_nonblock(int fd, bool nonblock) {
1959         int flags, nflags;
1960
1961         assert(fd >= 0);
1962
1963         flags = fcntl(fd, F_GETFL, 0);
1964         if (flags < 0)
1965                 return -errno;
1966
1967         if (nonblock)
1968                 nflags = flags | O_NONBLOCK;
1969         else
1970                 nflags = flags & ~O_NONBLOCK;
1971
1972         if (nflags == flags)
1973                 return 0;
1974
1975         if (fcntl(fd, F_SETFL, nflags) < 0)
1976                 return -errno;
1977
1978         return 0;
1979 }
1980
1981 int fd_cloexec(int fd, bool cloexec) {
1982         int flags, nflags;
1983
1984         assert(fd >= 0);
1985
1986         flags = fcntl(fd, F_GETFD, 0);
1987         if (flags < 0)
1988                 return -errno;
1989
1990         if (cloexec)
1991                 nflags = flags | FD_CLOEXEC;
1992         else
1993                 nflags = flags & ~FD_CLOEXEC;
1994
1995         if (nflags == flags)
1996                 return 0;
1997
1998         if (fcntl(fd, F_SETFD, nflags) < 0)
1999                 return -errno;
2000
2001         return 0;
2002 }
2003
2004 _pure_ static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
2005         unsigned i;
2006
2007         assert(n_fdset == 0 || fdset);
2008
2009         for (i = 0; i < n_fdset; i++)
2010                 if (fdset[i] == fd)
2011                         return true;
2012
2013         return false;
2014 }
2015
2016 int close_all_fds(const int except[], unsigned n_except) {
2017         _cleanup_closedir_ DIR *d = NULL;
2018         struct dirent *de;
2019         int r = 0;
2020
2021         assert(n_except == 0 || except);
2022
2023         d = opendir("/proc/self/fd");
2024         if (!d) {
2025                 int fd;
2026                 struct rlimit rl;
2027
2028                 /* When /proc isn't available (for example in chroots)
2029                  * the fallback is brute forcing through the fd
2030                  * table */
2031
2032                 assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0);
2033                 for (fd = 3; fd < (int) rl.rlim_max; fd ++) {
2034
2035                         if (fd_in_set(fd, except, n_except))
2036                                 continue;
2037
2038                         if (close_nointr(fd) < 0)
2039                                 if (errno != EBADF && r == 0)
2040                                         r = -errno;
2041                 }
2042
2043                 return r;
2044         }
2045
2046         while ((de = readdir(d))) {
2047                 int fd = -1;
2048
2049                 if (hidden_file(de->d_name))
2050                         continue;
2051
2052                 if (safe_atoi(de->d_name, &fd) < 0)
2053                         /* Let's better ignore this, just in case */
2054                         continue;
2055
2056                 if (fd < 3)
2057                         continue;
2058
2059                 if (fd == dirfd(d))
2060                         continue;
2061
2062                 if (fd_in_set(fd, except, n_except))
2063                         continue;
2064
2065                 if (close_nointr(fd) < 0) {
2066                         /* Valgrind has its own FD and doesn't want to have it closed */
2067                         if (errno != EBADF && r == 0)
2068                                 r = -errno;
2069                 }
2070         }
2071
2072         return r;
2073 }
2074
2075 bool chars_intersect(const char *a, const char *b) {
2076         const char *p;
2077
2078         /* Returns true if any of the chars in a are in b. */
2079         for (p = a; *p; p++)
2080                 if (strchr(b, *p))
2081                         return true;
2082
2083         return false;
2084 }
2085
2086 /// UNNEEDED by elogind
2087 #if 0
2088 bool fstype_is_network(const char *fstype) {
2089         static const char table[] =
2090                 "afs\0"
2091                 "cifs\0"
2092                 "smbfs\0"
2093                 "sshfs\0"
2094                 "ncpfs\0"
2095                 "ncp\0"
2096                 "nfs\0"
2097                 "nfs4\0"
2098                 "gfs\0"
2099                 "gfs2\0"
2100                 "glusterfs\0";
2101
2102         const char *x;
2103
2104         x = startswith(fstype, "fuse.");
2105         if (x)
2106                 fstype = x;
2107
2108         return nulstr_contains(table, fstype);
2109 }
2110 #endif // 0
2111
2112 int flush_fd(int fd) {
2113         struct pollfd pollfd = {
2114                 .fd = fd,
2115                 .events = POLLIN,
2116         };
2117
2118         for (;;) {
2119                 char buf[LINE_MAX];
2120                 ssize_t l;
2121                 int r;
2122
2123                 r = poll(&pollfd, 1, 0);
2124                 if (r < 0) {
2125                         if (errno == EINTR)
2126                                 continue;
2127
2128                         return -errno;
2129
2130                 } else if (r == 0)
2131                         return 0;
2132
2133                 l = read(fd, buf, sizeof(buf));
2134                 if (l < 0) {
2135
2136                         if (errno == EINTR)
2137                                 continue;
2138
2139                         if (errno == EAGAIN)
2140                                 return 0;
2141
2142                         return -errno;
2143                 } else if (l == 0)
2144                         return 0;
2145         }
2146 }
2147
2148 void safe_close_pair(int p[]) {
2149         assert(p);
2150
2151         if (p[0] == p[1]) {
2152                 /* Special case pairs which use the same fd in both
2153                  * directions... */
2154                 p[0] = p[1] = safe_close(p[0]);
2155                 return;
2156         }
2157
2158         p[0] = safe_close(p[0]);
2159         p[1] = safe_close(p[1]);
2160 }
2161
2162 ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) {
2163         uint8_t *p = buf;
2164         ssize_t n = 0;
2165
2166         assert(fd >= 0);
2167         assert(buf);
2168
2169         /* If called with nbytes == 0, let's call read() at least
2170          * once, to validate the operation */
2171
2172         if (nbytes > (size_t) SSIZE_MAX)
2173                 return -EINVAL;
2174
2175         do {
2176                 ssize_t k;
2177
2178                 k = read(fd, p, nbytes);
2179                 if (k < 0) {
2180                         if (errno == EINTR)
2181                                 continue;
2182
2183                         if (errno == EAGAIN && do_poll) {
2184
2185                                 /* We knowingly ignore any return value here,
2186                                  * and expect that any error/EOF is reported
2187                                  * via read() */
2188
2189                                 (void) fd_wait_for_event(fd, POLLIN, USEC_INFINITY);
2190                                 continue;
2191                         }
2192
2193                         return n > 0 ? n : -errno;
2194                 }
2195
2196                 if (k == 0)
2197                         return n;
2198
2199                 assert((size_t) k <= nbytes);
2200
2201                 p += k;
2202                 nbytes -= k;
2203                 n += k;
2204         } while (nbytes > 0);
2205
2206         return n;
2207 }
2208
2209 int loop_read_exact(int fd, void *buf, size_t nbytes, bool do_poll) {
2210         ssize_t n;
2211
2212         n = loop_read(fd, buf, nbytes, do_poll);
2213         if (n < 0)
2214                 return (int) n;
2215         if ((size_t) n != nbytes)
2216                 return -EIO;
2217
2218         return 0;
2219 }
2220
2221 int loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
2222         const uint8_t *p = buf;
2223
2224         assert(fd >= 0);
2225         assert(buf);
2226
2227         if (nbytes > (size_t) SSIZE_MAX)
2228                 return -EINVAL;
2229
2230         do {
2231                 ssize_t k;
2232
2233                 k = write(fd, p, nbytes);
2234                 if (k < 0) {
2235                         if (errno == EINTR)
2236                                 continue;
2237
2238                         if (errno == EAGAIN && do_poll) {
2239                                 /* We knowingly ignore any return value here,
2240                                  * and expect that any error/EOF is reported
2241                                  * via write() */
2242
2243                                 (void) fd_wait_for_event(fd, POLLOUT, USEC_INFINITY);
2244                                 continue;
2245                         }
2246
2247                         return -errno;
2248                 }
2249
2250                 if (_unlikely_(nbytes > 0 && k == 0)) /* Can't really happen */
2251                         return -EIO;
2252
2253                 assert((size_t) k <= nbytes);
2254
2255                 p += k;
2256                 nbytes -= k;
2257         } while (nbytes > 0);
2258
2259         return 0;
2260 }
2261
2262 int parse_size(const char *t, uint64_t base, uint64_t *size) {
2263
2264         /* Soo, sometimes we want to parse IEC binary suffixes, and
2265          * sometimes SI decimal suffixes. This function can parse
2266          * both. Which one is the right way depends on the
2267          * context. Wikipedia suggests that SI is customary for
2268          * hardware metrics and network speeds, while IEC is
2269          * customary for most data sizes used by software and volatile
2270          * (RAM) memory. Hence be careful which one you pick!
2271          *
2272          * In either case we use just K, M, G as suffix, and not Ki,
2273          * Mi, Gi or so (as IEC would suggest). That's because that's
2274          * frickin' ugly. But this means you really need to make sure
2275          * to document which base you are parsing when you use this
2276          * call. */
2277
2278         struct table {
2279                 const char *suffix;
2280                 unsigned long long factor;
2281         };
2282
2283         static const struct table iec[] = {
2284                 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
2285                 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
2286                 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
2287                 { "G", 1024ULL*1024ULL*1024ULL },
2288                 { "M", 1024ULL*1024ULL },
2289                 { "K", 1024ULL },
2290                 { "B", 1ULL },
2291                 { "",  1ULL },
2292         };
2293
2294         static const struct table si[] = {
2295                 { "E", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
2296                 { "P", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
2297                 { "T", 1000ULL*1000ULL*1000ULL*1000ULL },
2298                 { "G", 1000ULL*1000ULL*1000ULL },
2299                 { "M", 1000ULL*1000ULL },
2300                 { "K", 1000ULL },
2301                 { "B", 1ULL },
2302                 { "",  1ULL },
2303         };
2304
2305         const struct table *table;
2306         const char *p;
2307         unsigned long long r = 0;
2308         unsigned n_entries, start_pos = 0;
2309
2310         assert(t);
2311         assert(base == 1000 || base == 1024);
2312         assert(size);
2313
2314         if (base == 1000) {
2315                 table = si;
2316                 n_entries = ELEMENTSOF(si);
2317         } else {
2318                 table = iec;
2319                 n_entries = ELEMENTSOF(iec);
2320         }
2321
2322         p = t;
2323         do {
2324                 unsigned long long l, tmp;
2325                 double frac = 0;
2326                 char *e;
2327                 unsigned i;
2328
2329                 p += strspn(p, WHITESPACE);
2330                 if (*p == '-')
2331                         return -ERANGE;
2332
2333                 errno = 0;
2334                 l = strtoull(p, &e, 10);
2335                 if (errno > 0)
2336                         return -errno;
2337                 if (e == p)
2338                         return -EINVAL;
2339
2340                 if (*e == '.') {
2341                         e++;
2342
2343                         /* strtoull() itself would accept space/+/- */
2344                         if (*e >= '0' && *e <= '9') {
2345                                 unsigned long long l2;
2346                                 char *e2;
2347
2348                                 l2 = strtoull(e, &e2, 10);
2349                                 if (errno > 0)
2350                                         return -errno;
2351
2352                                 /* Ignore failure. E.g. 10.M is valid */
2353                                 frac = l2;
2354                                 for (; e < e2; e++)
2355                                         frac /= 10;
2356                         }
2357                 }
2358
2359                 e += strspn(e, WHITESPACE);
2360
2361                 for (i = start_pos; i < n_entries; i++)
2362                         if (startswith(e, table[i].suffix))
2363                                 break;
2364
2365                 if (i >= n_entries)
2366                         return -EINVAL;
2367
2368                 if (l + (frac > 0) > ULLONG_MAX / table[i].factor)
2369                                         return -ERANGE;
2370
2371                                 tmp = l * table[i].factor + (unsigned long long) (frac * table[i].factor);
2372                                 if (tmp > ULLONG_MAX - r)
2373                                         return -ERANGE;
2374
2375                                 r += tmp;
2376                 if ((unsigned long long) (uint64_t) r != r)
2377                                         return -ERANGE;
2378
2379                                 p = e + strlen(table[i].suffix);
2380
2381                                 start_pos = i + 1;
2382
2383         } while (*p);
2384
2385         *size = r;
2386
2387         return 0;
2388 }
2389
2390 bool is_device_path(const char *path) {
2391
2392         /* Returns true on paths that refer to a device, either in
2393          * sysfs or in /dev */
2394
2395         return
2396                 path_startswith(path, "/dev/") ||
2397                 path_startswith(path, "/sys/");
2398 }
2399
2400 /// UNNEEDED by elogind
2401 #if 0
2402 int dir_is_empty(const char *path) {
2403         _cleanup_closedir_ DIR *d;
2404
2405         d = opendir(path);
2406         if (!d)
2407                 return -errno;
2408
2409         for (;;) {
2410                 struct dirent *de;
2411
2412                 errno = 0;
2413                 de = readdir(d);
2414                 if (!de && errno != 0)
2415                         return -errno;
2416
2417                 if (!de)
2418                         return 1;
2419
2420                 if (!hidden_file(de->d_name))
2421                         return 0;
2422         }
2423 }
2424
2425 char* dirname_malloc(const char *path) {
2426         char *d, *dir, *dir2;
2427
2428         d = strdup(path);
2429         if (!d)
2430                 return NULL;
2431         dir = dirname(d);
2432         assert(dir);
2433
2434         if (dir != d) {
2435                 dir2 = strdup(dir);
2436                 free(d);
2437                 return dir2;
2438         }
2439
2440         return dir;
2441 }
2442
2443 void rename_process(const char name[8]) {
2444         assert(name);
2445
2446         /* This is a like a poor man's setproctitle(). It changes the
2447          * comm field, argv[0], and also the glibc's internally used
2448          * name of the process. For the first one a limit of 16 chars
2449          * applies, to the second one usually one of 10 (i.e. length
2450          * of "/sbin/init"), to the third one one of 7 (i.e. length of
2451          * "systemd"). If you pass a longer string it will be
2452          * truncated */
2453
2454         prctl(PR_SET_NAME, name);
2455
2456         if (program_invocation_name)
2457                 strncpy(program_invocation_name, name, strlen(program_invocation_name));
2458
2459         if (saved_argc > 0) {
2460                 int i;
2461
2462                 if (saved_argv[0])
2463                         strncpy(saved_argv[0], name, strlen(saved_argv[0]));
2464
2465                 for (i = 1; i < saved_argc; i++) {
2466                         if (!saved_argv[i])
2467                                 break;
2468
2469                         memzero(saved_argv[i], strlen(saved_argv[i]));
2470                 }
2471         }
2472 }
2473 #endif // 0
2474
2475 char *lookup_uid(uid_t uid) {
2476         long bufsize;
2477         char *name;
2478         _cleanup_free_ char *buf = NULL;
2479         struct passwd pwbuf, *pw = NULL;
2480
2481         /* Shortcut things to avoid NSS lookups */
2482         if (uid == 0)
2483                 return strdup("root");
2484
2485         bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
2486         if (bufsize <= 0)
2487                 bufsize = 4096;
2488
2489         buf = malloc(bufsize);
2490         if (!buf)
2491                 return NULL;
2492
2493         if (getpwuid_r(uid, &pwbuf, buf, bufsize, &pw) == 0 && pw)
2494                 return strdup(pw->pw_name);
2495
2496         if (asprintf(&name, UID_FMT, uid) < 0)
2497                 return NULL;
2498
2499         return name;
2500 }
2501
2502 /// UNNEEDED by elogind
2503 #if 0
2504 char* getlogname_malloc(void) {
2505         uid_t uid;
2506         struct stat st;
2507
2508         if (isatty(STDIN_FILENO) && fstat(STDIN_FILENO, &st) >= 0)
2509                 uid = st.st_uid;
2510         else
2511                 uid = getuid();
2512
2513         return lookup_uid(uid);
2514 }
2515
2516 char *getusername_malloc(void) {
2517         const char *e;
2518
2519         e = getenv("USER");
2520         if (e)
2521                 return strdup(e);
2522
2523         return lookup_uid(getuid());
2524 }
2525 #endif // 0
2526
2527 bool is_temporary_fs(const struct statfs *s) {
2528         assert(s);
2529
2530         return F_TYPE_EQUAL(s->f_type, TMPFS_MAGIC) ||
2531                F_TYPE_EQUAL(s->f_type, RAMFS_MAGIC);
2532 }
2533
2534 int fd_is_temporary_fs(int fd) {
2535         struct statfs s;
2536
2537         if (fstatfs(fd, &s) < 0)
2538                 return -errno;
2539
2540         return is_temporary_fs(&s);
2541 }
2542
2543 int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
2544         assert(path);
2545
2546         /* Under the assumption that we are running privileged we
2547          * first change the access mode and only then hand out
2548          * ownership to avoid a window where access is too open. */
2549
2550         if (mode != MODE_INVALID)
2551                 if (chmod(path, mode) < 0)
2552                         return -errno;
2553
2554         if (uid != UID_INVALID || gid != GID_INVALID)
2555                 if (chown(path, uid, gid) < 0)
2556                         return -errno;
2557
2558         return 0;
2559 }
2560
2561 /// UNNEEDED by elogind
2562 #if 0
2563 int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid) {
2564         assert(fd >= 0);
2565
2566         /* Under the assumption that we are running privileged we
2567          * first change the access mode and only then hand out
2568          * ownership to avoid a window where access is too open. */
2569
2570         if (mode != MODE_INVALID)
2571                 if (fchmod(fd, mode) < 0)
2572                         return -errno;
2573
2574         if (uid != UID_INVALID || gid != GID_INVALID)
2575                 if (fchown(fd, uid, gid) < 0)
2576                         return -errno;
2577
2578         return 0;
2579 }
2580
2581 #endif // 0
2582
2583 int files_same(const char *filea, const char *fileb) {
2584         struct stat a, b;
2585
2586         if (stat(filea, &a) < 0)
2587                 return -errno;
2588
2589         if (stat(fileb, &b) < 0)
2590                 return -errno;
2591
2592         return a.st_dev == b.st_dev &&
2593                a.st_ino == b.st_ino;
2594 }
2595
2596 int running_in_chroot(void) {
2597         int ret;
2598
2599         ret = files_same("/proc/1/root", "/");
2600         if (ret < 0)
2601                 return ret;
2602
2603         return ret == 0;
2604 }
2605
2606 static char *ascii_ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
2607         size_t x;
2608         char *r;
2609
2610         assert(s);
2611         assert(percent <= 100);
2612         assert(new_length >= 3);
2613
2614         if (old_length <= 3 || old_length <= new_length)
2615                 return strndup(s, old_length);
2616
2617         r = new0(char, new_length+1);
2618         if (!r)
2619                 return NULL;
2620
2621         x = (new_length * percent) / 100;
2622
2623         if (x > new_length - 3)
2624                 x = new_length - 3;
2625
2626         memcpy(r, s, x);
2627         r[x] = '.';
2628         r[x+1] = '.';
2629         r[x+2] = '.';
2630         memcpy(r + x + 3,
2631                s + old_length - (new_length - x - 3),
2632                new_length - x - 3);
2633
2634         return r;
2635 }
2636
2637 char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
2638         size_t x;
2639         char *e;
2640         const char *i, *j;
2641         unsigned k, len, len2;
2642
2643         assert(s);
2644         assert(percent <= 100);
2645         assert(new_length >= 3);
2646
2647         /* if no multibyte characters use ascii_ellipsize_mem for speed */
2648         if (ascii_is_valid(s))
2649                 return ascii_ellipsize_mem(s, old_length, new_length, percent);
2650
2651         if (old_length <= 3 || old_length <= new_length)
2652                 return strndup(s, old_length);
2653
2654         x = (new_length * percent) / 100;
2655
2656         if (x > new_length - 3)
2657                 x = new_length - 3;
2658
2659         k = 0;
2660         for (i = s; k < x && i < s + old_length; i = utf8_next_char(i)) {
2661                 int c;
2662
2663                 c = utf8_encoded_to_unichar(i);
2664                 if (c < 0)
2665                         return NULL;
2666                 k += unichar_iswide(c) ? 2 : 1;
2667         }
2668
2669         if (k > x) /* last character was wide and went over quota */
2670                 x ++;
2671
2672         for (j = s + old_length; k < new_length && j > i; ) {
2673                 int c;
2674
2675                 j = utf8_prev_char(j);
2676                 c = utf8_encoded_to_unichar(j);
2677                 if (c < 0)
2678                         return NULL;
2679                 k += unichar_iswide(c) ? 2 : 1;
2680         }
2681         assert(i <= j);
2682
2683         /* we don't actually need to ellipsize */
2684         if (i == j)
2685                 return memdup(s, old_length + 1);
2686
2687         /* make space for ellipsis */
2688         j = utf8_next_char(j);
2689
2690         len = i - s;
2691         len2 = s + old_length - j;
2692         e = new(char, len + 3 + len2 + 1);
2693         if (!e)
2694                 return NULL;
2695
2696         /*
2697         printf("old_length=%zu new_length=%zu x=%zu len=%u len2=%u k=%u\n",
2698                old_length, new_length, x, len, len2, k);
2699         */
2700
2701         memcpy(e, s, len);
2702         e[len]   = 0xe2; /* tri-dot ellipsis: … */
2703         e[len + 1] = 0x80;
2704         e[len + 2] = 0xa6;
2705
2706         memcpy(e + len + 3, j, len2 + 1);
2707
2708         return e;
2709 }
2710
2711 char *ellipsize(const char *s, size_t length, unsigned percent) {
2712         return ellipsize_mem(s, strlen(s), length, percent);
2713 }
2714
2715 int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode) {
2716         _cleanup_close_ int fd;
2717         int r;
2718
2719         assert(path);
2720
2721         if (parents)
2722                 mkdir_parents(path, 0755);
2723
2724         fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, mode > 0 ? mode : 0644);
2725         if (fd < 0)
2726                 return -errno;
2727
2728         if (mode > 0) {
2729                 r = fchmod(fd, mode);
2730                 if (r < 0)
2731                         return -errno;
2732         }
2733
2734         if (uid != UID_INVALID || gid != GID_INVALID) {
2735                 r = fchown(fd, uid, gid);
2736                 if (r < 0)
2737                         return -errno;
2738         }
2739
2740         if (stamp != USEC_INFINITY) {
2741                 struct timespec ts[2];
2742
2743                 timespec_store(&ts[0], stamp);
2744                 ts[1] = ts[0];
2745                 r = futimens(fd, ts);
2746         } else
2747                 r = futimens(fd, NULL);
2748         if (r < 0)
2749                 return -errno;
2750
2751         return 0;
2752 }
2753
2754 int touch(const char *path) {
2755         return touch_file(path, false, USEC_INFINITY, UID_INVALID, GID_INVALID, 0);
2756 }
2757
2758 /// UNNEEDED by elogind
2759 #if 0
2760 static char *unquote(const char *s, const char* quotes) {
2761         size_t l;
2762         assert(s);
2763
2764         /* This is rather stupid, simply removes the heading and
2765          * trailing quotes if there is one. Doesn't care about
2766          * escaping or anything.
2767          *
2768          * DON'T USE THIS FOR NEW CODE ANYMORE!*/
2769
2770         l = strlen(s);
2771         if (l < 2)
2772                 return strdup(s);
2773
2774         if (strchr(quotes, s[0]) && s[l-1] == s[0])
2775                 return strndup(s+1, l-2);
2776
2777         return strdup(s);
2778 }
2779 #endif // 0
2780
2781 noreturn void freeze(void) {
2782
2783         /* Make sure nobody waits for us on a socket anymore */
2784         close_all_fds(NULL, 0);
2785
2786         sync();
2787
2788         for (;;)
2789                 pause();
2790 }
2791
2792 bool null_or_empty(struct stat *st) {
2793         assert(st);
2794
2795         if (S_ISREG(st->st_mode) && st->st_size <= 0)
2796                 return true;
2797
2798         if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
2799                 return true;
2800
2801         return false;
2802 }
2803
2804 int null_or_empty_path(const char *fn) {
2805         struct stat st;
2806
2807         assert(fn);
2808
2809         if (stat(fn, &st) < 0)
2810                 return -errno;
2811
2812         return null_or_empty(&st);
2813 }
2814
2815 /// UNNEEDED by elogind
2816 #if 0
2817 int null_or_empty_fd(int fd) {
2818         struct stat st;
2819
2820         assert(fd >= 0);
2821
2822         if (fstat(fd, &st) < 0)
2823                 return -errno;
2824
2825         return null_or_empty(&st);
2826 }
2827 #endif // 0
2828
2829 DIR *xopendirat(int fd, const char *name, int flags) {
2830         int nfd;
2831         DIR *d;
2832
2833         assert(!(flags & O_CREAT));
2834
2835         nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags, 0);
2836         if (nfd < 0)
2837                 return NULL;
2838
2839         d = fdopendir(nfd);
2840         if (!d) {
2841                 safe_close(nfd);
2842                 return NULL;
2843         }
2844
2845         return d;
2846 }
2847
2848 /// UNNEEDED by elogind
2849 #if 0
2850 static char *tag_to_udev_node(const char *tagvalue, const char *by) {
2851         _cleanup_free_ char *t = NULL, *u = NULL;
2852         size_t enc_len;
2853
2854         u = unquote(tagvalue, QUOTES);
2855         if (!u)
2856                 return NULL;
2857
2858         enc_len = strlen(u) * 4 + 1;
2859         t = new(char, enc_len);
2860         if (!t)
2861                 return NULL;
2862
2863         if (encode_devnode_name(u, t, enc_len) < 0)
2864                 return NULL;
2865
2866         return strjoin("/dev/disk/by-", by, "/", t, NULL);
2867 }
2868
2869 char *fstab_node_to_udev_node(const char *p) {
2870         assert(p);
2871
2872         if (startswith(p, "LABEL="))
2873                 return tag_to_udev_node(p+6, "label");
2874
2875         if (startswith(p, "UUID="))
2876                 return tag_to_udev_node(p+5, "uuid");
2877
2878         if (startswith(p, "PARTUUID="))
2879                 return tag_to_udev_node(p+9, "partuuid");
2880
2881         if (startswith(p, "PARTLABEL="))
2882                 return tag_to_udev_node(p+10, "partlabel");
2883
2884         return strdup(p);
2885 }
2886 #endif // 0
2887
2888 bool dirent_is_file(const struct dirent *de) {
2889         assert(de);
2890
2891         if (hidden_file(de->d_name))
2892                 return false;
2893
2894         if (de->d_type != DT_REG &&
2895             de->d_type != DT_LNK &&
2896             de->d_type != DT_UNKNOWN)
2897                 return false;
2898
2899         return true;
2900 }
2901
2902 bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
2903         assert(de);
2904
2905         if (de->d_type != DT_REG &&
2906             de->d_type != DT_LNK &&
2907             de->d_type != DT_UNKNOWN)
2908                 return false;
2909
2910         if (hidden_file_allow_backup(de->d_name))
2911                 return false;
2912
2913         return endswith(de->d_name, suffix);
2914 }
2915
2916 static int do_execute(char **directories, usec_t timeout, char *argv[]) {
2917         _cleanup_hashmap_free_free_ Hashmap *pids = NULL;
2918         _cleanup_set_free_free_ Set *seen = NULL;
2919         char **directory;
2920
2921         /* We fork this all off from a child process so that we can
2922          * somewhat cleanly make use of SIGALRM to set a time limit */
2923
2924         (void) reset_all_signal_handlers();
2925         (void) reset_signal_mask();
2926
2927         assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
2928
2929         pids = hashmap_new(NULL);
2930         if (!pids)
2931                 return log_oom();
2932
2933         seen = set_new(&string_hash_ops);
2934         if (!seen)
2935                 return log_oom();
2936
2937         STRV_FOREACH(directory, directories) {
2938                 _cleanup_closedir_ DIR *d;
2939                 struct dirent *de;
2940
2941                 d = opendir(*directory);
2942                 if (!d) {
2943                         if (errno == ENOENT)
2944                                 continue;
2945
2946                         return log_error_errno(errno, "Failed to open directory %s: %m", *directory);
2947                 }
2948
2949                 FOREACH_DIRENT(de, d, break) {
2950                         _cleanup_free_ char *path = NULL;
2951                         pid_t pid;
2952                         int r;
2953
2954                         if (!dirent_is_file(de))
2955                                 continue;
2956
2957                         if (set_contains(seen, de->d_name)) {
2958                                 log_debug("%1$s/%2$s skipped (%2$s was already seen).", *directory, de->d_name);
2959                                 continue;
2960                         }
2961
2962                         r = set_put_strdup(seen, de->d_name);
2963                         if (r < 0)
2964                                 return log_oom();
2965
2966                         path = strjoin(*directory, "/", de->d_name, NULL);
2967                         if (!path)
2968                                 return log_oom();
2969
2970                         if (null_or_empty_path(path)) {
2971                                 log_debug("%s is empty (a mask).", path);
2972                                 continue;
2973                         }
2974
2975                         pid = fork();
2976                         if (pid < 0) {
2977                                 log_error_errno(errno, "Failed to fork: %m");
2978                                 continue;
2979                         } else if (pid == 0) {
2980                                 char *_argv[2];
2981
2982                                 assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
2983
2984                                 if (!argv) {
2985                                         _argv[0] = path;
2986                                         _argv[1] = NULL;
2987                                         argv = _argv;
2988                                 } else
2989                                         argv[0] = path;
2990
2991                                 execv(path, argv);
2992                                 return log_error_errno(errno, "Failed to execute %s: %m", path);
2993                         }
2994
2995                         log_debug("Spawned %s as " PID_FMT ".", path, pid);
2996
2997                         r = hashmap_put(pids, UINT_TO_PTR(pid), path);
2998                         if (r < 0)
2999                                 return log_oom();
3000                         path = NULL;
3001                 }
3002         }
3003
3004         /* Abort execution of this process after the timout. We simply
3005          * rely on SIGALRM as default action terminating the process,
3006          * and turn on alarm(). */
3007
3008         if (timeout != USEC_INFINITY)
3009                 alarm((timeout + USEC_PER_SEC - 1) / USEC_PER_SEC);
3010
3011         while (!hashmap_isempty(pids)) {
3012                 _cleanup_free_ char *path = NULL;
3013                 pid_t pid;
3014
3015                 pid = PTR_TO_UINT(hashmap_first_key(pids));
3016                 assert(pid > 0);
3017
3018                 path = hashmap_remove(pids, UINT_TO_PTR(pid));
3019                 assert(path);
3020
3021                 wait_for_terminate_and_warn(path, pid, true);
3022         }
3023
3024         return 0;
3025 }
3026
3027 void execute_directories(const char* const* directories, usec_t timeout, char *argv[]) {
3028         pid_t executor_pid;
3029         int r;
3030         char *name;
3031         char **dirs = (char**) directories;
3032
3033         assert(!strv_isempty(dirs));
3034
3035         name = basename(dirs[0]);
3036         assert(!isempty(name));
3037
3038         /* Executes all binaries in the directories in parallel and waits
3039          * for them to finish. Optionally a timeout is applied. If a file
3040          * with the same name exists in more than one directory, the
3041          * earliest one wins. */
3042
3043         executor_pid = fork();
3044         if (executor_pid < 0) {
3045                 log_error_errno(errno, "Failed to fork: %m");
3046                 return;
3047
3048         } else if (executor_pid == 0) {
3049                 r = do_execute(dirs, timeout, argv);
3050                 _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
3051         }
3052
3053         wait_for_terminate_and_warn(name, executor_pid, true);
3054 }
3055
3056 bool nulstr_contains(const char*nulstr, const char *needle) {
3057         const char *i;
3058
3059         if (!nulstr)
3060                 return false;
3061
3062         NULSTR_FOREACH(i, nulstr)
3063                 if (streq(i, needle))
3064                         return true;
3065
3066         return false;
3067 }
3068
3069 /// UNNEEDED by elogind
3070 #if 0
3071 bool plymouth_running(void) {
3072         return access("/run/plymouth/pid", F_OK) >= 0;
3073 }
3074 #endif // 0
3075
3076 char* strshorten(char *s, size_t l) {
3077         assert(s);
3078
3079         if (l < strlen(s))
3080                 s[l] = 0;
3081
3082         return s;
3083 }
3084
3085 int pipe_eof(int fd) {
3086         struct pollfd pollfd = {
3087                 .fd = fd,
3088                 .events = POLLIN|POLLHUP,
3089         };
3090
3091         int r;
3092
3093         r = poll(&pollfd, 1, 0);
3094         if (r < 0)
3095                 return -errno;
3096
3097         if (r == 0)
3098                 return 0;
3099
3100         return pollfd.revents & POLLHUP;
3101 }
3102
3103 int fd_wait_for_event(int fd, int event, usec_t t) {
3104
3105         struct pollfd pollfd = {
3106                 .fd = fd,
3107                 .events = event,
3108         };
3109
3110         struct timespec ts;
3111         int r;
3112
3113         r = ppoll(&pollfd, 1, t == USEC_INFINITY ? NULL : timespec_store(&ts, t), NULL);
3114         if (r < 0)
3115                 return -errno;
3116
3117         if (r == 0)
3118                 return 0;
3119
3120         return pollfd.revents;
3121 }
3122
3123 int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
3124         FILE *f;
3125         char *t;
3126         int r, fd;
3127
3128         assert(path);
3129         assert(_f);
3130         assert(_temp_path);
3131
3132         r = tempfn_xxxxxx(path, NULL, &t);
3133         if (r < 0)
3134                 return r;
3135
3136         fd = mkostemp_safe(t, O_WRONLY|O_CLOEXEC);
3137         if (fd < 0) {
3138                 free(t);
3139                 return -errno;
3140         }
3141
3142         f = fdopen(fd, "we");
3143         if (!f) {
3144                 unlink_noerrno(t);
3145                 free(t);
3146                 safe_close(fd);
3147                 return -errno;
3148         }
3149
3150         *_f = f;
3151         *_temp_path = t;
3152
3153         return 0;
3154 }
3155
3156 /// UNNEEDED by elogind
3157 #if 0
3158 int symlink_atomic(const char *from, const char *to) {
3159         _cleanup_free_ char *t = NULL;
3160         int r;
3161
3162         assert(from);
3163         assert(to);
3164
3165         r = tempfn_random(to, NULL, &t);
3166         if (r < 0)
3167                 return r;
3168
3169         if (symlink(from, t) < 0)
3170                 return -errno;
3171
3172         if (rename(t, to) < 0) {
3173                 unlink_noerrno(t);
3174                 return -errno;
3175         }
3176
3177         return 0;
3178 }
3179
3180 int symlink_idempotent(const char *from, const char *to) {
3181         _cleanup_free_ char *p = NULL;
3182         int r;
3183
3184         assert(from);
3185         assert(to);
3186
3187         if (symlink(from, to) < 0) {
3188                 if (errno != EEXIST)
3189                         return -errno;
3190
3191                 r = readlink_malloc(to, &p);
3192                 if (r < 0)
3193                         return r;
3194
3195                 if (!streq(p, from))
3196                         return -EINVAL;
3197         }
3198
3199         return 0;
3200 }
3201
3202 int mknod_atomic(const char *path, mode_t mode, dev_t dev) {
3203         _cleanup_free_ char *t = NULL;
3204         int r;
3205
3206         assert(path);
3207
3208         r = tempfn_random(path, NULL, &t);
3209         if (r < 0)
3210                 return r;
3211
3212         if (mknod(t, mode, dev) < 0)
3213                 return -errno;
3214
3215         if (rename(t, path) < 0) {
3216                 unlink_noerrno(t);
3217                 return -errno;
3218         }
3219
3220         return 0;
3221 }
3222
3223 int mkfifo_atomic(const char *path, mode_t mode) {
3224         _cleanup_free_ char *t = NULL;
3225         int r;
3226
3227         assert(path);
3228
3229         r = tempfn_random(path, NULL, &t);
3230         if (r < 0)
3231                 return r;
3232
3233         if (mkfifo(t, mode) < 0)
3234                 return -errno;
3235
3236         if (rename(t, path) < 0) {
3237                 unlink_noerrno(t);
3238                 return -errno;
3239         }
3240
3241         return 0;
3242 }
3243 #endif // 0
3244
3245 bool display_is_local(const char *display) {
3246         assert(display);
3247
3248         return
3249                 display[0] == ':' &&
3250                 display[1] >= '0' &&
3251                 display[1] <= '9';
3252 }
3253
3254 int socket_from_display(const char *display, char **path) {
3255         size_t k;
3256         char *f, *c;
3257
3258         assert(display);
3259         assert(path);
3260
3261         if (!display_is_local(display))
3262                 return -EINVAL;
3263
3264         k = strspn(display+1, "0123456789");
3265
3266         f = new(char, strlen("/tmp/.X11-unix/X") + k + 1);
3267         if (!f)
3268                 return -ENOMEM;
3269
3270         c = stpcpy(f, "/tmp/.X11-unix/X");
3271         memcpy(c, display+1, k);
3272         c[k] = 0;
3273
3274         *path = f;
3275
3276         return 0;
3277 }
3278
3279 int get_user_creds(
3280                 const char **username,
3281                 uid_t *uid, gid_t *gid,
3282                 const char **home,
3283                 const char **shell) {
3284
3285         struct passwd *p;
3286         uid_t u;
3287
3288         assert(username);
3289         assert(*username);
3290
3291         /* We enforce some special rules for uid=0: in order to avoid
3292          * NSS lookups for root we hardcode its data. */
3293
3294         if (streq(*username, "root") || streq(*username, "0")) {
3295                 *username = "root";
3296
3297                 if (uid)
3298                         *uid = 0;
3299
3300                 if (gid)
3301                         *gid = 0;
3302
3303                 if (home)
3304                         *home = "/root";
3305
3306                 if (shell)
3307                         *shell = "/bin/sh";
3308
3309                 return 0;
3310         }
3311
3312         if (parse_uid(*username, &u) >= 0) {
3313                 errno = 0;
3314                 p = getpwuid(u);
3315
3316                 /* If there are multiple users with the same id, make
3317                  * sure to leave $USER to the configured value instead
3318                  * of the first occurrence in the database. However if
3319                  * the uid was configured by a numeric uid, then let's
3320                  * pick the real username from /etc/passwd. */
3321                 if (p)
3322                         *username = p->pw_name;
3323         } else {
3324                 errno = 0;
3325                 p = getpwnam(*username);
3326         }
3327
3328         if (!p)
3329                 return errno > 0 ? -errno : -ESRCH;
3330
3331         if (uid)
3332                 *uid = p->pw_uid;
3333
3334         if (gid)
3335                 *gid = p->pw_gid;
3336
3337         if (home)
3338                 *home = p->pw_dir;
3339
3340         if (shell)
3341                 *shell = p->pw_shell;
3342
3343         return 0;
3344 }
3345
3346 char* uid_to_name(uid_t uid) {
3347         struct passwd *p;
3348         char *r;
3349
3350         if (uid == 0)
3351                 return strdup("root");
3352
3353         p = getpwuid(uid);
3354         if (p)
3355                 return strdup(p->pw_name);
3356
3357         if (asprintf(&r, UID_FMT, uid) < 0)
3358                 return NULL;
3359
3360         return r;
3361 }
3362
3363 char* gid_to_name(gid_t gid) {
3364         struct group *p;
3365         char *r;
3366
3367         if (gid == 0)
3368                 return strdup("root");
3369
3370         p = getgrgid(gid);
3371         if (p)
3372                 return strdup(p->gr_name);
3373
3374         if (asprintf(&r, GID_FMT, gid) < 0)
3375                 return NULL;
3376
3377         return r;
3378 }
3379
3380 int get_group_creds(const char **groupname, gid_t *gid) {
3381         struct group *g;
3382         gid_t id;
3383
3384         assert(groupname);
3385
3386         /* We enforce some special rules for gid=0: in order to avoid
3387          * NSS lookups for root we hardcode its data. */
3388
3389         if (streq(*groupname, "root") || streq(*groupname, "0")) {
3390                 *groupname = "root";
3391
3392                 if (gid)
3393                         *gid = 0;
3394
3395                 return 0;
3396         }
3397
3398         if (parse_gid(*groupname, &id) >= 0) {
3399                 errno = 0;
3400                 g = getgrgid(id);
3401
3402                 if (g)
3403                         *groupname = g->gr_name;
3404         } else {
3405                 errno = 0;
3406                 g = getgrnam(*groupname);
3407         }
3408
3409         if (!g)
3410                 return errno > 0 ? -errno : -ESRCH;
3411
3412         if (gid)
3413                 *gid = g->gr_gid;
3414
3415         return 0;
3416 }
3417
3418 int in_gid(gid_t gid) {
3419         gid_t *gids;
3420         int ngroups_max, r, i;
3421
3422         if (getgid() == gid)
3423                 return 1;
3424
3425         if (getegid() == gid)
3426                 return 1;
3427
3428         ngroups_max = sysconf(_SC_NGROUPS_MAX);
3429         assert(ngroups_max > 0);
3430
3431         gids = alloca(sizeof(gid_t) * ngroups_max);
3432
3433         r = getgroups(ngroups_max, gids);
3434         if (r < 0)
3435                 return -errno;
3436
3437         for (i = 0; i < r; i++)
3438                 if (gids[i] == gid)
3439                         return 1;
3440
3441         return 0;
3442 }
3443
3444 /// UNNEEDED by elogind
3445 #if 0
3446 int in_group(const char *name) {
3447         int r;