chiark / gitweb /
Prep v226: Apply missing fixes and changes to src/basic
[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  <string.h>
23 // #include  <unistd.h>
24 #include  <errno.h>
25 // #include  <stdlib.h>
26 // #include  <signal.h>
27 // #include  <libintl.h>
28 // #include  <stdio.h>
29 // #include  <syslog.h>
30 // #include  <sched.h>
31 // #include  <sys/resource.h>
32 // #include  <linux/sched.h>
33 // #include  <sys/types.h>
34 // #include  <sys/stat.h>
35 // #include  <fcntl.h>
36 // #include  <dirent.h>
37 // #include  <sys/ioctl.h>
38 // #include  <stdarg.h>
39 #include  <poll.h>
40 // #include  <ctype.h>
41 #include  <sys/prctl.h>
42 // #include  <sys/utsname.h>
43 #include  <pwd.h>
44 #include  <netinet/ip.h>
45 // #include  <sys/wait.h>
46 // #include  <sys/time.h>
47 // #include  <glob.h>
48 #include  <grp.h>
49 // #include  <sys/mman.h>
50 // #include  <sys/vfs.h>
51 // #include  <sys/mount.h>
52 #include  <linux/magic.h>
53 // #include  <limits.h>
54 #include  <langinfo.h>
55 // #include  <locale.h>
56 // #include  <sys/personality.h>
57 #include  <sys/xattr.h>
58 // #include  <sys/statvfs.h>
59 // #include  <sys/file.h>
60 #include  <linux/fs.h>
61
62 /* When we include libgen.h because we need dirname() we immediately
63  * undefine basename() since libgen.h defines it as a macro to the POSIX
64  * version which is really broken. We prefer GNU basename(). */
65 // #include <libgen.h>
66 // #undef basename
67
68 #ifdef HAVE_SYS_AUXV_H
69 #include <sys/auxv.h>
70 #endif
71
72 #include  "config.h"
73 #include  "macro.h"
74 #include  "util.h"
75 #include  "ioprio.h"
76 // #include  "missing.h"
77 // #include  "log.h"
78 #include  "strv.h"
79 #include  "mkdir.h"
80 #include  "path-util.h"
81 // #include  "exit-status.h"
82 // #include  "hashmap.h"
83 // #include  "env-util.h"
84 #include  "fileio.h"
85 // #include  "device-nodes.h"
86 #include  "utf8.h"
87 #include  "gunicode.h"
88 #include  "virt.h"
89 // #include  "def.h"
90 #include  "sparse-endian.h"
91 // #include  "formats-util.h"
92 #include  "process-util.h"
93 #include  "random-util.h"
94 // #include  "terminal-util.h"
95 #include  "hostname-util.h"
96 #include  "signal-util.h"
97
98 /* Put this test here for a lack of better place */
99 assert_cc(EAGAIN == EWOULDBLOCK);
100
101 int saved_argc = 0;
102 char **saved_argv = NULL;
103
104 size_t page_size(void) {
105         static thread_local size_t pgsz = 0;
106         long r;
107
108         if (_likely_(pgsz > 0))
109                 return pgsz;
110
111         r = sysconf(_SC_PAGESIZE);
112         assert(r > 0);
113
114         pgsz = (size_t) r;
115         return pgsz;
116 }
117
118 int strcmp_ptr(const char *a, const char *b) {
119
120         /* Like strcmp(), but tries to make sense of NULL pointers */
121         if (a && b)
122                 return strcmp(a, b);
123
124         if (!a && b)
125                 return -1;
126
127         if (a && !b)
128                 return 1;
129
130         return 0;
131 }
132
133 bool streq_ptr(const char *a, const char *b) {
134         return strcmp_ptr(a, b) == 0;
135 }
136
137 char* endswith(const char *s, const char *postfix) {
138         size_t sl, pl;
139
140         assert(s);
141         assert(postfix);
142
143         sl = strlen(s);
144         pl = strlen(postfix);
145
146         if (pl == 0)
147                 return (char*) s + sl;
148
149         if (sl < pl)
150                 return NULL;
151
152         if (memcmp(s + sl - pl, postfix, pl) != 0)
153                 return NULL;
154
155         return (char*) s + sl - pl;
156 }
157
158 char* endswith_no_case(const char *s, const char *postfix) {
159         size_t sl, pl;
160
161         assert(s);
162         assert(postfix);
163
164         sl = strlen(s);
165         pl = strlen(postfix);
166
167         if (pl == 0)
168                 return (char*) s + sl;
169
170         if (sl < pl)
171                 return NULL;
172
173         if (strcasecmp(s + sl - pl, postfix) != 0)
174                 return NULL;
175
176         return (char*) s + sl - pl;
177 }
178
179 char* first_word(const char *s, const char *word) {
180         size_t sl, wl;
181         const char *p;
182
183         assert(s);
184         assert(word);
185
186         /* Checks if the string starts with the specified word, either
187          * followed by NUL or by whitespace. Returns a pointer to the
188          * NUL or the first character after the whitespace. */
189
190         sl = strlen(s);
191         wl = strlen(word);
192
193         if (sl < wl)
194                 return NULL;
195
196         if (wl == 0)
197                 return (char*) s;
198
199         if (memcmp(s, word, wl) != 0)
200                 return NULL;
201
202         p = s + wl;
203         if (*p == 0)
204                 return (char*) p;
205
206         if (!strchr(WHITESPACE, *p))
207                 return NULL;
208
209         p += strspn(p, WHITESPACE);
210         return (char*) p;
211 }
212
213 size_t cescape_char(char c, char *buf) {
214         char * buf_old = buf;
215
216         switch (c) {
217
218                 case '\a':
219                         *(buf++) = '\\';
220                         *(buf++) = 'a';
221                         break;
222                 case '\b':
223                         *(buf++) = '\\';
224                         *(buf++) = 'b';
225                         break;
226                 case '\f':
227                         *(buf++) = '\\';
228                         *(buf++) = 'f';
229                         break;
230                 case '\n':
231                         *(buf++) = '\\';
232                         *(buf++) = 'n';
233                         break;
234                 case '\r':
235                         *(buf++) = '\\';
236                         *(buf++) = 'r';
237                         break;
238                 case '\t':
239                         *(buf++) = '\\';
240                         *(buf++) = 't';
241                         break;
242                 case '\v':
243                         *(buf++) = '\\';
244                         *(buf++) = 'v';
245                         break;
246                 case '\\':
247                         *(buf++) = '\\';
248                         *(buf++) = '\\';
249                         break;
250                 case '"':
251                         *(buf++) = '\\';
252                         *(buf++) = '"';
253                         break;
254                 case '\'':
255                         *(buf++) = '\\';
256                         *(buf++) = '\'';
257                         break;
258
259                 default:
260                         /* For special chars we prefer octal over
261                          * hexadecimal encoding, simply because glib's
262                          * g_strescape() does the same */
263                         if ((c < ' ') || (c >= 127)) {
264                                 *(buf++) = '\\';
265                                 *(buf++) = octchar((unsigned char) c >> 6);
266                                 *(buf++) = octchar((unsigned char) c >> 3);
267                                 *(buf++) = octchar((unsigned char) c);
268                         } else
269                                 *(buf++) = c;
270                         break;
271         }
272
273         return buf - buf_old;
274 }
275
276 int close_nointr(int fd) {
277         assert(fd >= 0);
278
279         if (close(fd) >= 0)
280                 return 0;
281
282         /*
283          * Just ignore EINTR; a retry loop is the wrong thing to do on
284          * Linux.
285          *
286          * http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
287          * https://bugzilla.gnome.org/show_bug.cgi?id=682819
288          * http://utcc.utoronto.ca/~cks/space/blog/unix/CloseEINTR
289          * https://sites.google.com/site/michaelsafyan/software-engineering/checkforeintrwheninvokingclosethinkagain
290          */
291         if (errno == EINTR)
292                 return 0;
293
294         return -errno;
295 }
296
297 int safe_close(int fd) {
298
299         /*
300          * Like close_nointr() but cannot fail. Guarantees errno is
301          * unchanged. Is a NOP with negative fds passed, and returns
302          * -1, so that it can be used in this syntax:
303          *
304          * fd = safe_close(fd);
305          */
306
307         if (fd >= 0) {
308                 PROTECT_ERRNO;
309
310                 /* The kernel might return pretty much any error code
311                  * via close(), but the fd will be closed anyway. The
312                  * only condition we want to check for here is whether
313                  * the fd was invalid at all... */
314
315                 assert_se(close_nointr(fd) != -EBADF);
316         }
317
318         return -1;
319 }
320
321 void close_many(const int fds[], unsigned n_fd) {
322         unsigned i;
323
324         assert(fds || n_fd <= 0);
325
326         for (i = 0; i < n_fd; i++)
327                 safe_close(fds[i]);
328 }
329
330 int unlink_noerrno(const char *path) {
331         PROTECT_ERRNO;
332         int r;
333
334         r = unlink(path);
335         if (r < 0)
336                 return -errno;
337
338         return 0;
339 }
340
341 int parse_boolean(const char *v) {
342         assert(v);
343
344         if (streq(v, "1") || strcaseeq(v, "yes") || strcaseeq(v, "y") || strcaseeq(v, "true") || strcaseeq(v, "t") || strcaseeq(v, "on"))
345                 return 1;
346         else if (streq(v, "0") || strcaseeq(v, "no") || strcaseeq(v, "n") || strcaseeq(v, "false") || strcaseeq(v, "f") || strcaseeq(v, "off"))
347                 return 0;
348
349         return -EINVAL;
350 }
351
352 int parse_pid(const char *s, pid_t* ret_pid) {
353         unsigned long ul = 0;
354         pid_t pid;
355         int r;
356
357         assert(s);
358         assert(ret_pid);
359
360         r = safe_atolu(s, &ul);
361         if (r < 0)
362                 return r;
363
364         pid = (pid_t) ul;
365
366         if ((unsigned long) pid != ul)
367                 return -ERANGE;
368
369         if (pid <= 0)
370                 return -ERANGE;
371
372         *ret_pid = pid;
373         return 0;
374 }
375
376 bool uid_is_valid(uid_t uid) {
377
378         /* Some libc APIs use UID_INVALID as special placeholder */
379         if (uid == (uid_t) 0xFFFFFFFF)
380                 return false;
381
382         /* A long time ago UIDs where 16bit, hence explicitly avoid the 16bit -1 too */
383         if (uid == (uid_t) 0xFFFF)
384                 return false;
385
386         return true;
387 }
388
389 int parse_uid(const char *s, uid_t* ret_uid) {
390         unsigned long ul = 0;
391         uid_t uid;
392         int r;
393
394         assert(s);
395
396         r = safe_atolu(s, &ul);
397         if (r < 0)
398                 return r;
399
400         uid = (uid_t) ul;
401
402         if ((unsigned long) uid != ul)
403                 return -ERANGE;
404
405         if (!uid_is_valid(uid))
406                 return -ENXIO; /* we return ENXIO instead of EINVAL
407                                 * here, to make it easy to distuingish
408                                 * invalid numeric uids invalid
409                                 * strings. */
410
411         if (ret_uid)
412                 *ret_uid = uid;
413
414         return 0;
415 }
416
417 int safe_atou(const char *s, unsigned *ret_u) {
418         char *x = NULL;
419         unsigned long l;
420
421         assert(s);
422         assert(ret_u);
423
424         errno = 0;
425         l = strtoul(s, &x, 0);
426
427         if (!x || x == s || *x || errno)
428                 return errno > 0 ? -errno : -EINVAL;
429
430         if ((unsigned long) (unsigned) l != l)
431                 return -ERANGE;
432
433         *ret_u = (unsigned) l;
434         return 0;
435 }
436
437 int safe_atoi(const char *s, int *ret_i) {
438         char *x = NULL;
439         long l;
440
441         assert(s);
442         assert(ret_i);
443
444         errno = 0;
445         l = strtol(s, &x, 0);
446
447         if (!x || x == s || *x || errno)
448                 return errno > 0 ? -errno : -EINVAL;
449
450         if ((long) (int) l != l)
451                 return -ERANGE;
452
453         *ret_i = (int) l;
454         return 0;
455 }
456
457 int safe_atou8(const char *s, uint8_t *ret) {
458         char *x = NULL;
459         unsigned long l;
460
461         assert(s);
462         assert(ret);
463
464         errno = 0;
465         l = strtoul(s, &x, 0);
466
467         if (!x || x == s || *x || errno)
468                 return errno > 0 ? -errno : -EINVAL;
469
470         if ((unsigned long) (uint8_t) l != l)
471                 return -ERANGE;
472
473         *ret = (uint8_t) l;
474         return 0;
475 }
476
477 int safe_atou16(const char *s, uint16_t *ret) {
478         char *x = NULL;
479         unsigned long l;
480
481         assert(s);
482         assert(ret);
483
484         errno = 0;
485         l = strtoul(s, &x, 0);
486
487         if (!x || x == s || *x || errno)
488                 return errno > 0 ? -errno : -EINVAL;
489
490         if ((unsigned long) (uint16_t) l != l)
491                 return -ERANGE;
492
493         *ret = (uint16_t) l;
494         return 0;
495 }
496
497 int safe_atoi16(const char *s, int16_t *ret) {
498         char *x = NULL;
499         long l;
500
501         assert(s);
502         assert(ret);
503
504         errno = 0;
505         l = strtol(s, &x, 0);
506
507         if (!x || x == s || *x || errno)
508                 return errno > 0 ? -errno : -EINVAL;
509
510         if ((long) (int16_t) l != l)
511                 return -ERANGE;
512
513         *ret = (int16_t) l;
514         return 0;
515 }
516
517 int safe_atollu(const char *s, long long unsigned *ret_llu) {
518         char *x = NULL;
519         unsigned long long l;
520
521         assert(s);
522         assert(ret_llu);
523
524         errno = 0;
525         l = strtoull(s, &x, 0);
526
527         if (!x || x == s || *x || errno)
528                 return errno ? -errno : -EINVAL;
529
530         *ret_llu = l;
531         return 0;
532 }
533
534 int safe_atolli(const char *s, long long int *ret_lli) {
535         char *x = NULL;
536         long long l;
537
538         assert(s);
539         assert(ret_lli);
540
541         errno = 0;
542         l = strtoll(s, &x, 0);
543
544         if (!x || x == s || *x || errno)
545                 return errno ? -errno : -EINVAL;
546
547         *ret_lli = l;
548         return 0;
549 }
550
551 int safe_atod(const char *s, double *ret_d) {
552         char *x = NULL;
553         double d = 0;
554         locale_t loc;
555
556         assert(s);
557         assert(ret_d);
558
559         loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0);
560         if (loc == (locale_t) 0)
561                 return -errno;
562
563         errno = 0;
564         d = strtod_l(s, &x, loc);
565
566         if (!x || x == s || *x || errno) {
567                 freelocale(loc);
568                 return errno ? -errno : -EINVAL;
569         }
570
571         freelocale(loc);
572         *ret_d = (double) d;
573         return 0;
574 }
575
576 static size_t strcspn_escaped(const char *s, const char *reject) {
577         bool escaped = false;
578         int n;
579
580         for (n=0; s[n]; n++) {
581                 if (escaped)
582                         escaped = false;
583                 else if (s[n] == '\\')
584                         escaped = true;
585                 else if (strchr(reject, s[n]))
586                         break;
587         }
588
589         /* if s ends in \, return index of previous char */
590         return n - escaped;
591 }
592
593 /* Split a string into words. */
594 const char* split(const char **state, size_t *l, const char *separator, bool quoted) {
595         const char *current;
596
597         current = *state;
598
599         if (!*current) {
600                 assert(**state == '\0');
601                 return NULL;
602         }
603
604         current += strspn(current, separator);
605         if (!*current) {
606                 *state = current;
607                 return NULL;
608         }
609
610         if (quoted && strchr("\'\"", *current)) {
611                 char quotechars[2] = {*current, '\0'};
612
613                 *l = strcspn_escaped(current + 1, quotechars);
614                 if (current[*l + 1] == '\0' || current[*l + 1] != quotechars[0] ||
615                     (current[*l + 2] && !strchr(separator, current[*l + 2]))) {
616                         /* right quote missing or garbage at the end */
617                         *state = current;
618                         return NULL;
619                 }
620                 *state = current++ + *l + 2;
621         } else if (quoted) {
622                 *l = strcspn_escaped(current, separator);
623                 if (current[*l] && !strchr(separator, current[*l])) {
624                         /* unfinished escape */
625                         *state = current;
626                         return NULL;
627                 }
628                 *state = current + *l;
629         } else {
630                 *l = strcspn(current, separator);
631                 *state = current + *l;
632         }
633
634         return current;
635 }
636
637 int fchmod_umask(int fd, mode_t m) {
638         mode_t u;
639         int r;
640
641         u = umask(0777);
642         r = fchmod(fd, m & (~u)) < 0 ? -errno : 0;
643         umask(u);
644
645         return r;
646 }
647
648 char *truncate_nl(char *s) {
649         assert(s);
650
651         s[strcspn(s, NEWLINE)] = 0;
652         return s;
653 }
654
655 char *strnappend(const char *s, const char *suffix, size_t b) {
656         size_t a;
657         char *r;
658
659         if (!s && !suffix)
660                 return strdup("");
661
662         if (!s)
663                 return strndup(suffix, b);
664
665         if (!suffix)
666                 return strdup(s);
667
668         assert(s);
669         assert(suffix);
670
671         a = strlen(s);
672         if (b > ((size_t) -1) - a)
673                 return NULL;
674
675         r = new(char, a+b+1);
676         if (!r)
677                 return NULL;
678
679         memcpy(r, s, a);
680         memcpy(r+a, suffix, b);
681         r[a+b] = 0;
682
683         return r;
684 }
685
686 char *strappend(const char *s, const char *suffix) {
687         return strnappend(s, suffix, suffix ? strlen(suffix) : 0);
688 }
689
690 int readlinkat_malloc(int fd, const char *p, char **ret) {
691         size_t l = 100;
692         int r;
693
694         assert(p);
695         assert(ret);
696
697         for (;;) {
698                 char *c;
699                 ssize_t n;
700
701                 c = new(char, l);
702                 if (!c)
703                         return -ENOMEM;
704
705                 n = readlinkat(fd, p, c, l-1);
706                 if (n < 0) {
707                         r = -errno;
708                         free(c);
709                         return r;
710                 }
711
712                 if ((size_t) n < l-1) {
713                         c[n] = 0;
714                         *ret = c;
715                         return 0;
716                 }
717
718                 free(c);
719                 l *= 2;
720         }
721 }
722
723 int readlink_malloc(const char *p, char **ret) {
724         return readlinkat_malloc(AT_FDCWD, p, ret);
725 }
726
727 /// UNNEEDED by elogind
728 #if 0
729 int readlink_value(const char *p, char **ret) {
730         _cleanup_free_ char *link = NULL;
731         char *value;
732         int r;
733
734         r = readlink_malloc(p, &link);
735         if (r < 0)
736                 return r;
737
738         value = basename(link);
739         if (!value)
740                 return -ENOENT;
741
742         value = strdup(value);
743         if (!value)
744                 return -ENOMEM;
745
746         *ret = value;
747
748         return 0;
749 }
750 #endif // 0
751
752 int readlink_and_make_absolute(const char *p, char **r) {
753         _cleanup_free_ char *target = NULL;
754         char *k;
755         int j;
756
757         assert(p);
758         assert(r);
759
760         j = readlink_malloc(p, &target);
761         if (j < 0)
762                 return j;
763
764         k = file_in_same_dir(p, target);
765         if (!k)
766                 return -ENOMEM;
767
768         *r = k;
769         return 0;
770 }
771
772 /// UNNEEDED by elogind
773 #if 0
774 int readlink_and_canonicalize(const char *p, char **r) {
775         char *t, *s;
776         int j;
777
778         assert(p);
779         assert(r);
780
781         j = readlink_and_make_absolute(p, &t);
782         if (j < 0)
783                 return j;
784
785         s = canonicalize_file_name(t);
786         if (s) {
787                 free(t);
788                 *r = s;
789         } else
790                 *r = t;
791
792         path_kill_slashes(*r);
793
794         return 0;
795 }
796 #endif // 0
797
798 char *strstrip(char *s) {
799         char *e;
800
801         /* Drops trailing whitespace. Modifies the string in
802          * place. Returns pointer to first non-space character */
803
804         s += strspn(s, WHITESPACE);
805
806         for (e = strchr(s, 0); e > s; e --)
807                 if (!strchr(WHITESPACE, e[-1]))
808                         break;
809
810         *e = 0;
811
812         return s;
813 }
814
815 /// UNNEEDED by elogind
816 #if 0
817 char *delete_chars(char *s, const char *bad) {
818         char *f, *t;
819
820         /* Drops all whitespace, regardless where in the string */
821
822         for (f = s, t = s; *f; f++) {
823                 if (strchr(bad, *f))
824                         continue;
825
826                 *(t++) = *f;
827         }
828
829         *t = 0;
830
831         return s;
832 }
833 #endif // 0
834
835 char *file_in_same_dir(const char *path, const char *filename) {
836         char *e, *ret;
837         size_t k;
838
839         assert(path);
840         assert(filename);
841
842         /* This removes the last component of path and appends
843          * filename, unless the latter is absolute anyway or the
844          * former isn't */
845
846         if (path_is_absolute(filename))
847                 return strdup(filename);
848
849         e = strrchr(path, '/');
850         if (!e)
851                 return strdup(filename);
852
853         k = strlen(filename);
854         ret = new(char, (e + 1 - path) + k + 1);
855         if (!ret)
856                 return NULL;
857
858         memcpy(mempcpy(ret, path, e + 1 - path), filename, k + 1);
859         return ret;
860 }
861
862 /// UNNEEDED by elogind
863 #if 0
864 int rmdir_parents(const char *path, const char *stop) {
865         size_t l;
866         int r = 0;
867
868         assert(path);
869         assert(stop);
870
871         l = strlen(path);
872
873         /* Skip trailing slashes */
874         while (l > 0 && path[l-1] == '/')
875                 l--;
876
877         while (l > 0) {
878                 char *t;
879
880                 /* Skip last component */
881                 while (l > 0 && path[l-1] != '/')
882                         l--;
883
884                 /* Skip trailing slashes */
885                 while (l > 0 && path[l-1] == '/')
886                         l--;
887
888                 if (l <= 0)
889                         break;
890
891                 if (!(t = strndup(path, l)))
892                         return -ENOMEM;
893
894                 if (path_startswith(stop, t)) {
895                         free(t);
896                         return 0;
897                 }
898
899                 r = rmdir(t);
900                 free(t);
901
902                 if (r < 0)
903                         if (errno != ENOENT)
904                                 return -errno;
905         }
906
907         return 0;
908 }
909 #endif // 0
910
911 char hexchar(int x) {
912         static const char table[16] = "0123456789abcdef";
913
914         return table[x & 15];
915 }
916
917 int unhexchar(char c) {
918
919         if (c >= '0' && c <= '9')
920                 return c - '0';
921
922         if (c >= 'a' && c <= 'f')
923                 return c - 'a' + 10;
924
925         if (c >= 'A' && c <= 'F')
926                 return c - 'A' + 10;
927
928         return -EINVAL;
929 }
930
931 char *hexmem(const void *p, size_t l) {
932         char *r, *z;
933         const uint8_t *x;
934
935         z = r = malloc(l * 2 + 1);
936         if (!r)
937                 return NULL;
938
939         for (x = p; x < (const uint8_t*) p + l; x++) {
940                 *(z++) = hexchar(*x >> 4);
941                 *(z++) = hexchar(*x & 15);
942         }
943
944         *z = 0;
945         return r;
946 }
947
948 int unhexmem(const char *p, size_t l, void **mem, size_t *len) {
949         _cleanup_free_ uint8_t *r = NULL;
950         uint8_t *z;
951         const char *x;
952
953         assert(mem);
954         assert(len);
955         assert(p);
956
957         z = r = malloc((l + 1) / 2 + 1);
958         if (!r)
959                 return -ENOMEM;
960
961         for (x = p; x < p + l; x += 2) {
962                 int a, b;
963
964                 a = unhexchar(x[0]);
965                 if (a < 0)
966                         return a;
967                 else if (x+1 < p + l) {
968                         b = unhexchar(x[1]);
969                         if (b < 0)
970                                 return b;
971                 } else
972                         b = 0;
973
974                 *(z++) = (uint8_t) a << 4 | (uint8_t) b;
975         }
976
977         *z = 0;
978
979         *mem = r;
980         r = NULL;
981         *len = (l + 1) / 2;
982
983         return 0;
984 }
985
986 /* https://tools.ietf.org/html/rfc4648#section-6
987  * Notice that base32hex differs from base32 in the alphabet it uses.
988  * The distinction is that the base32hex representation preserves the
989  * order of the underlying data when compared as bytestrings, this is
990  * useful when representing NSEC3 hashes, as one can then verify the
991  * order of hashes directly from their representation. */
992 char base32hexchar(int x) {
993         static const char table[32] = "0123456789"
994                                       "ABCDEFGHIJKLMNOPQRSTUV";
995
996         return table[x & 31];
997 }
998
999 int unbase32hexchar(char c) {
1000         unsigned offset;
1001
1002         if (c >= '0' && c <= '9')
1003                 return c - '0';
1004
1005         offset = '9' - '0' + 1;
1006
1007         if (c >= 'A' && c <= 'V')
1008                 return c - 'A' + offset;
1009
1010         return -EINVAL;
1011 }
1012
1013 char *base32hexmem(const void *p, size_t l, bool padding) {
1014         char *r, *z;
1015         const uint8_t *x;
1016         size_t len;
1017
1018         if (padding)
1019                 /* five input bytes makes eight output bytes, padding is added so we must round up */
1020                 len = 8 * (l + 4) / 5;
1021         else {
1022                 /* same, but round down as there is no padding */
1023                 len = 8 * l / 5;
1024
1025                 switch (l % 5) {
1026                 case 4:
1027                         len += 7;
1028                         break;
1029                 case 3:
1030                         len += 5;
1031                         break;
1032                 case 2:
1033                         len += 4;
1034                         break;
1035                 case 1:
1036                         len += 2;
1037                         break;
1038                 }
1039         }
1040
1041         z = r = malloc(len + 1);
1042         if (!r)
1043                 return NULL;
1044
1045         for (x = p; x < (const uint8_t*) p + (l / 5) * 5; x += 5) {
1046                 /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ
1047                    x[3] == QQQQQQQQ; x[4] == WWWWWWWW */
1048                 *(z++) = base32hexchar(x[0] >> 3);                    /* 000XXXXX */
1049                 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6);  /* 000XXXYY */
1050                 *(z++) = base32hexchar((x[1] & 63) >> 1);             /* 000YYYYY */
1051                 *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4);  /* 000YZZZZ */
1052                 *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */
1053                 *(z++) = base32hexchar((x[3] & 127) >> 2);            /* 000QQQQQ */
1054                 *(z++) = base32hexchar((x[3] & 3) << 3 | x[4] >> 5);  /* 000QQWWW */
1055                 *(z++) = base32hexchar((x[4] & 31));                  /* 000WWWWW */
1056         }
1057
1058         switch (l % 5) {
1059         case 4:
1060                 *(z++) = base32hexchar(x[0] >> 3);                    /* 000XXXXX */
1061                 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6);  /* 000XXXYY */
1062                 *(z++) = base32hexchar((x[1] & 63) >> 1);             /* 000YYYYY */
1063                 *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4);   /* 000YZZZZ */
1064                 *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */
1065                 *(z++) = base32hexchar((x[3] & 127) >> 2);            /* 000QQQQQ */
1066                 *(z++) = base32hexchar((x[3] & 3) << 3);              /* 000QQ000 */
1067                 if (padding)
1068                         *(z++) = '=';
1069
1070                 break;
1071
1072         case 3:
1073                 *(z++) = base32hexchar(x[0] >> 3);                   /* 000XXXXX */
1074                 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
1075                 *(z++) = base32hexchar((x[1] & 63) >> 1);            /* 000YYYYY */
1076                 *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
1077                 *(z++) = base32hexchar((x[2] & 15) << 1);            /* 000ZZZZ0 */
1078                 if (padding) {
1079                         *(z++) = '=';
1080                         *(z++) = '=';
1081                         *(z++) = '=';
1082                 }
1083
1084                 break;
1085
1086         case 2:
1087                 *(z++) = base32hexchar(x[0] >> 3);                   /* 000XXXXX */
1088                 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
1089                 *(z++) = base32hexchar((x[1] & 63) >> 1);            /* 000YYYYY */
1090                 *(z++) = base32hexchar((x[1] & 1) << 4);             /* 000Y0000 */
1091                 if (padding) {
1092                         *(z++) = '=';
1093                         *(z++) = '=';
1094                         *(z++) = '=';
1095                         *(z++) = '=';
1096                 }
1097
1098                 break;
1099
1100         case 1:
1101                 *(z++) = base32hexchar(x[0] >> 3);       /* 000XXXXX */
1102                 *(z++) = base32hexchar((x[0] & 7) << 2); /* 000XXX00 */
1103                 if (padding) {
1104                         *(z++) = '=';
1105                         *(z++) = '=';
1106                         *(z++) = '=';
1107                         *(z++) = '=';
1108                         *(z++) = '=';
1109                         *(z++) = '=';
1110                 }
1111
1112                 break;
1113         }
1114
1115         *z = 0;
1116         return r;
1117 }
1118
1119 int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_len) {
1120         _cleanup_free_ uint8_t *r = NULL;
1121         int a, b, c, d, e, f, g, h;
1122         uint8_t *z;
1123         const char *x;
1124         size_t len;
1125         unsigned pad = 0;
1126
1127         assert(p);
1128
1129         /* padding ensures any base32hex input has input divisible by 8 */
1130         if (padding && l % 8 != 0)
1131                 return -EINVAL;
1132
1133         if (padding) {
1134                 /* strip the padding */
1135                 while (l > 0 && p[l - 1] == '=' && pad < 7) {
1136                         pad ++;
1137                         l --;
1138                 }
1139         }
1140
1141         /* a group of eight input bytes needs five output bytes, in case of
1142            padding we need to add some extra bytes */
1143         len = (l / 8) * 5;
1144
1145         switch (l % 8) {
1146         case 7:
1147                 len += 4;
1148                 break;
1149         case 5:
1150                 len += 3;
1151                 break;
1152         case 4:
1153                 len += 2;
1154                 break;
1155         case 2:
1156                 len += 1;
1157                 break;
1158         case 0:
1159                 break;
1160         default:
1161                 return -EINVAL;
1162         }
1163
1164         z = r = malloc(len + 1);
1165         if (!r)
1166                 return -ENOMEM;
1167
1168         for (x = p; x < p + (l / 8) * 8; x += 8) {
1169                 /* a == 000XXXXX; b == 000YYYYY; c == 000ZZZZZ; d == 000WWWWW
1170                    e == 000SSSSS; f == 000QQQQQ; g == 000VVVVV; h == 000RRRRR */
1171                 a = unbase32hexchar(x[0]);
1172                 if (a < 0)
1173                         return -EINVAL;
1174
1175                 b = unbase32hexchar(x[1]);
1176                 if (b < 0)
1177                         return -EINVAL;
1178
1179                 c = unbase32hexchar(x[2]);
1180                 if (c < 0)
1181                         return -EINVAL;
1182
1183                 d = unbase32hexchar(x[3]);
1184                 if (d < 0)
1185                         return -EINVAL;
1186
1187                 e = unbase32hexchar(x[4]);
1188                 if (e < 0)
1189                         return -EINVAL;
1190
1191                 f = unbase32hexchar(x[5]);
1192                 if (f < 0)
1193                         return -EINVAL;
1194
1195                 g = unbase32hexchar(x[6]);
1196                 if (g < 0)
1197                         return -EINVAL;
1198
1199                 h = unbase32hexchar(x[7]);
1200                 if (h < 0)
1201                         return -EINVAL;
1202
1203                 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2;                    /* XXXXXYYY */
1204                 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
1205                 *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1;                    /* WWWWSSSS */
1206                 *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */
1207                 *(z++) = (uint8_t) g << 5 | (uint8_t) h;                         /* VVVRRRRR */
1208         }
1209
1210         switch (l % 8) {
1211         case 7:
1212                 a = unbase32hexchar(x[0]);
1213                 if (a < 0)
1214                         return -EINVAL;
1215
1216                 b = unbase32hexchar(x[1]);
1217                 if (b < 0)
1218                         return -EINVAL;
1219
1220                 c = unbase32hexchar(x[2]);
1221                 if (c < 0)
1222                         return -EINVAL;
1223
1224                 d = unbase32hexchar(x[3]);
1225                 if (d < 0)
1226                         return -EINVAL;
1227
1228                 e = unbase32hexchar(x[4]);
1229                 if (e < 0)
1230                         return -EINVAL;
1231
1232                 f = unbase32hexchar(x[5]);
1233                 if (f < 0)
1234                         return -EINVAL;
1235
1236                 g = unbase32hexchar(x[6]);
1237                 if (g < 0)
1238                         return -EINVAL;
1239
1240                 /* g == 000VV000 */
1241                 if (g & 7)
1242                         return -EINVAL;
1243
1244                 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2;                    /* XXXXXYYY */
1245                 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
1246                 *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1;                    /* WWWWSSSS */
1247                 *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */
1248
1249                 break;
1250         case 5:
1251                 a = unbase32hexchar(x[0]);
1252                 if (a < 0)
1253                         return -EINVAL;
1254
1255                 b = unbase32hexchar(x[1]);
1256                 if (b < 0)
1257                         return -EINVAL;
1258
1259                 c = unbase32hexchar(x[2]);
1260                 if (c < 0)
1261                         return -EINVAL;
1262
1263                 d = unbase32hexchar(x[3]);
1264                 if (d < 0)
1265                         return -EINVAL;
1266
1267                 e = unbase32hexchar(x[4]);
1268                 if (e < 0)
1269                         return -EINVAL;
1270
1271                 /* e == 000SSSS0 */
1272                 if (e & 1)
1273                         return -EINVAL;
1274
1275                 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2;                    /* XXXXXYYY */
1276                 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
1277                 *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1;                    /* WWWWSSSS */
1278
1279                 break;
1280         case 4:
1281                 a = unbase32hexchar(x[0]);
1282                 if (a < 0)
1283                         return -EINVAL;
1284
1285                 b = unbase32hexchar(x[1]);
1286                 if (b < 0)
1287                         return -EINVAL;
1288
1289                 c = unbase32hexchar(x[2]);
1290                 if (c < 0)
1291                         return -EINVAL;
1292
1293                 d = unbase32hexchar(x[3]);
1294                 if (d < 0)
1295                         return -EINVAL;
1296
1297                 /* d == 000W0000 */
1298                 if (d & 15)
1299                         return -EINVAL;
1300
1301                 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2;                    /* XXXXXYYY */
1302                 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
1303
1304                 break;
1305         case 2:
1306                 a = unbase32hexchar(x[0]);
1307                 if (a < 0)
1308                         return -EINVAL;
1309
1310                 b = unbase32hexchar(x[1]);
1311                 if (b < 0)
1312                         return -EINVAL;
1313
1314                 /* b == 000YYY00 */
1315                 if (b & 3)
1316                         return -EINVAL;
1317
1318                 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
1319
1320                 break;
1321         case 0:
1322                 break;
1323         default:
1324                 return -EINVAL;
1325         }
1326
1327         *z = 0;
1328
1329         *mem = r;
1330         r = NULL;
1331         *_len = len;
1332
1333         return 0;
1334 }
1335
1336 /* https://tools.ietf.org/html/rfc4648#section-4 */
1337 char base64char(int x) {
1338         static const char table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1339                                       "abcdefghijklmnopqrstuvwxyz"
1340                                       "0123456789+/";
1341         return table[x & 63];
1342 }
1343
1344 int unbase64char(char c) {
1345         unsigned offset;
1346
1347         if (c >= 'A' && c <= 'Z')
1348                 return c - 'A';
1349
1350         offset = 'Z' - 'A' + 1;
1351
1352         if (c >= 'a' && c <= 'z')
1353                 return c - 'a' + offset;
1354
1355         offset += 'z' - 'a' + 1;
1356
1357         if (c >= '0' && c <= '9')
1358                 return c - '0' + offset;
1359
1360         offset += '9' - '0' + 1;
1361
1362         if (c == '+')
1363                 return offset;
1364
1365         offset ++;
1366
1367         if (c == '/')
1368                 return offset;
1369
1370         return -EINVAL;
1371 }
1372
1373 char *base64mem(const void *p, size_t l) {
1374         char *r, *z;
1375         const uint8_t *x;
1376
1377         /* three input bytes makes four output bytes, padding is added so we must round up */
1378         z = r = malloc(4 * (l + 2) / 3 + 1);
1379         if (!r)
1380                 return NULL;
1381
1382         for (x = p; x < (const uint8_t*) p + (l / 3) * 3; x += 3) {
1383                 /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ */
1384                 *(z++) = base64char(x[0] >> 2);                    /* 00XXXXXX */
1385                 *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4);  /* 00XXYYYY */
1386                 *(z++) = base64char((x[1] & 15) << 2 | x[2] >> 6); /* 00YYYYZZ */
1387                 *(z++) = base64char(x[2] & 63);                    /* 00ZZZZZZ */
1388         }
1389
1390         switch (l % 3) {
1391         case 2:
1392                 *(z++) = base64char(x[0] >> 2);                   /* 00XXXXXX */
1393                 *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */
1394                 *(z++) = base64char((x[1] & 15) << 2);            /* 00YYYY00 */
1395                 *(z++) = '=';
1396
1397                 break;
1398         case 1:
1399                 *(z++) = base64char(x[0] >> 2);        /* 00XXXXXX */
1400                 *(z++) = base64char((x[0] & 3) << 4);  /* 00XX0000 */
1401                 *(z++) = '=';
1402                 *(z++) = '=';
1403
1404                 break;
1405         }
1406
1407         *z = 0;
1408         return r;
1409 }
1410
1411 int unbase64mem(const char *p, size_t l, void **mem, size_t *_len) {
1412         _cleanup_free_ uint8_t *r = NULL;
1413         int a, b, c, d;
1414         uint8_t *z;
1415         const char *x;
1416         size_t len;
1417
1418         assert(p);
1419
1420         /* padding ensures any base63 input has input divisible by 4 */
1421         if (l % 4 != 0)
1422                 return -EINVAL;
1423
1424         /* strip the padding */
1425         if (l > 0 && p[l - 1] == '=')
1426                 l --;
1427         if (l > 0 && p[l - 1] == '=')
1428                 l --;
1429
1430         /* a group of four input bytes needs three output bytes, in case of
1431            padding we need to add two or three extra bytes */
1432         len = (l / 4) * 3 + (l % 4 ? (l % 4) - 1 : 0);
1433
1434         z = r = malloc(len + 1);
1435         if (!r)
1436                 return -ENOMEM;
1437
1438         for (x = p; x < p + (l / 4) * 4; x += 4) {
1439                 /* a == 00XXXXXX; b == 00YYYYYY; c == 00ZZZZZZ; d == 00WWWWWW */
1440                 a = unbase64char(x[0]);
1441                 if (a < 0)
1442                         return -EINVAL;
1443
1444                 b = unbase64char(x[1]);
1445                 if (b < 0)
1446                         return -EINVAL;
1447
1448                 c = unbase64char(x[2]);
1449                 if (c < 0)
1450                         return -EINVAL;
1451
1452                 d = unbase64char(x[3]);
1453                 if (d < 0)
1454                         return -EINVAL;
1455
1456                 *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
1457                 *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
1458                 *(z++) = (uint8_t) c << 6 | (uint8_t) d;      /* ZZWWWWWW */
1459         }
1460
1461         switch (l % 4) {
1462         case 3:
1463                 a = unbase64char(x[0]);
1464                 if (a < 0)
1465                         return -EINVAL;
1466
1467                 b = unbase64char(x[1]);
1468                 if (b < 0)
1469                         return -EINVAL;
1470
1471                 c = unbase64char(x[2]);
1472                 if (c < 0)
1473                         return -EINVAL;
1474
1475                 /* c == 00ZZZZ00 */
1476                 if (c & 3)
1477                         return -EINVAL;
1478
1479                 *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
1480                 *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
1481
1482                 break;
1483         case 2:
1484                 a = unbase64char(x[0]);
1485                 if (a < 0)
1486                         return -EINVAL;
1487
1488                 b = unbase64char(x[1]);
1489                 if (b < 0)
1490                         return -EINVAL;
1491
1492                 /* b == 00YY0000 */
1493                 if (b & 15)
1494                         return -EINVAL;
1495
1496                 *(z++) = (uint8_t) a << 2 | (uint8_t) (b >> 4); /* XXXXXXYY */
1497
1498                 break;
1499         case 0:
1500
1501                 break;
1502         default:
1503                 return -EINVAL;
1504         }
1505
1506         *z = 0;
1507
1508         *mem = r;
1509         r = NULL;
1510         *_len = len;
1511
1512         return 0;
1513 }
1514
1515 char octchar(int x) {
1516         return '0' + (x & 7);
1517 }
1518
1519 int unoctchar(char c) {
1520
1521         if (c >= '0' && c <= '7')
1522                 return c - '0';
1523
1524         return -EINVAL;
1525 }
1526
1527 char decchar(int x) {
1528         return '0' + (x % 10);
1529 }
1530
1531 int undecchar(char c) {
1532
1533         if (c >= '0' && c <= '9')
1534                 return c - '0';
1535
1536         return -EINVAL;
1537 }
1538
1539 char *cescape(const char *s) {
1540         char *r, *t;
1541         const char *f;
1542
1543         assert(s);
1544
1545         /* Does C style string escaping. May be reversed with
1546          * cunescape(). */
1547
1548         r = new(char, strlen(s)*4 + 1);
1549         if (!r)
1550                 return NULL;
1551
1552         for (f = s, t = r; *f; f++)
1553                 t += cescape_char(*f, t);
1554
1555         *t = 0;
1556
1557         return r;
1558 }
1559
1560 static int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode) {
1561         int r = 1;
1562
1563         assert(p);
1564         assert(*p);
1565         assert(ret);
1566
1567         /* Unescapes C style. Returns the unescaped character in ret,
1568          * unless we encountered a \u sequence in which case the full
1569          * unicode character is returned in ret_unicode, instead. */
1570
1571         if (length != (size_t) -1 && length < 1)
1572                 return -EINVAL;
1573
1574         switch (p[0]) {
1575
1576         case 'a':
1577                 *ret = '\a';
1578                 break;
1579         case 'b':
1580                 *ret = '\b';
1581                 break;
1582         case 'f':
1583                 *ret = '\f';
1584                 break;
1585         case 'n':
1586                 *ret = '\n';
1587                 break;
1588         case 'r':
1589                 *ret = '\r';
1590                 break;
1591         case 't':
1592                 *ret = '\t';
1593                 break;
1594         case 'v':
1595                 *ret = '\v';
1596                 break;
1597         case '\\':
1598                 *ret = '\\';
1599                 break;
1600         case '"':
1601                 *ret = '"';
1602                 break;
1603         case '\'':
1604                 *ret = '\'';
1605                 break;
1606
1607         case 's':
1608                 /* This is an extension of the XDG syntax files */
1609                 *ret = ' ';
1610                 break;
1611
1612         case 'x': {
1613                 /* hexadecimal encoding */
1614                 int a, b;
1615
1616                 if (length != (size_t) -1 && length < 3)
1617                         return -EINVAL;
1618
1619                 a = unhexchar(p[1]);
1620                 if (a < 0)
1621                         return -EINVAL;
1622
1623                 b = unhexchar(p[2]);
1624                 if (b < 0)
1625                         return -EINVAL;
1626
1627                 /* Don't allow NUL bytes */
1628                 if (a == 0 && b == 0)
1629                         return -EINVAL;
1630
1631                 *ret = (char) ((a << 4U) | b);
1632                 r = 3;
1633                 break;
1634         }
1635
1636         case 'u': {
1637                 /* C++11 style 16bit unicode */
1638
1639                 int a[4];
1640                 unsigned i;
1641                 uint32_t c;
1642
1643                 if (length != (size_t) -1 && length < 5)
1644                         return -EINVAL;
1645
1646                 for (i = 0; i < 4; i++) {
1647                         a[i] = unhexchar(p[1 + i]);
1648                         if (a[i] < 0)
1649                                 return a[i];
1650                 }
1651
1652                 c = ((uint32_t) a[0] << 12U) | ((uint32_t) a[1] << 8U) | ((uint32_t) a[2] << 4U) | (uint32_t) a[3];
1653
1654                 /* Don't allow 0 chars */
1655                 if (c == 0)
1656                         return -EINVAL;
1657
1658                 if (c < 128)
1659                         *ret = c;
1660                 else {
1661                         if (!ret_unicode)
1662                                 return -EINVAL;
1663
1664                         *ret = 0;
1665                         *ret_unicode = c;
1666                 }
1667
1668                 r = 5;
1669                 break;
1670         }
1671
1672         case 'U': {
1673                 /* C++11 style 32bit unicode */
1674
1675                 int a[8];
1676                 unsigned i;
1677                 uint32_t c;
1678
1679                 if (length != (size_t) -1 && length < 9)
1680                         return -EINVAL;
1681
1682                 for (i = 0; i < 8; i++) {
1683                         a[i] = unhexchar(p[1 + i]);
1684                         if (a[i] < 0)
1685                                 return a[i];
1686                 }
1687
1688                 c = ((uint32_t) a[0] << 28U) | ((uint32_t) a[1] << 24U) | ((uint32_t) a[2] << 20U) | ((uint32_t) a[3] << 16U) |
1689                     ((uint32_t) a[4] << 12U) | ((uint32_t) a[5] <<  8U) | ((uint32_t) a[6] <<  4U) |  (uint32_t) a[7];
1690
1691                 /* Don't allow 0 chars */
1692                 if (c == 0)
1693                         return -EINVAL;
1694
1695                 /* Don't allow invalid code points */
1696                 if (!unichar_is_valid(c))
1697                         return -EINVAL;
1698
1699                 if (c < 128)
1700                         *ret = c;
1701                 else {
1702                         if (!ret_unicode)
1703                                 return -EINVAL;
1704
1705                         *ret = 0;
1706                         *ret_unicode = c;
1707                 }
1708
1709                 r = 9;
1710                 break;
1711         }
1712
1713         case '0':
1714         case '1':
1715         case '2':
1716         case '3':
1717         case '4':
1718         case '5':
1719         case '6':
1720         case '7': {
1721                 /* octal encoding */
1722                 int a, b, c;
1723                 uint32_t m;
1724
1725                 if (length != (size_t) -1 && length < 3)
1726                         return -EINVAL;
1727
1728                 a = unoctchar(p[0]);
1729                 if (a < 0)
1730                         return -EINVAL;
1731
1732                 b = unoctchar(p[1]);
1733                 if (b < 0)
1734                         return -EINVAL;
1735
1736                 c = unoctchar(p[2]);
1737                 if (c < 0)
1738                         return -EINVAL;
1739
1740                 /* don't allow NUL bytes */
1741                 if (a == 0 && b == 0 && c == 0)
1742                         return -EINVAL;
1743
1744                 /* Don't allow bytes above 255 */
1745                 m = ((uint32_t) a << 6U) | ((uint32_t) b << 3U) | (uint32_t) c;
1746                 if (m > 255)
1747                         return -EINVAL;
1748
1749                 *ret = m;
1750                 r = 3;
1751                 break;
1752         }
1753
1754         default:
1755                 return -EINVAL;
1756         }
1757
1758         return r;
1759 }
1760
1761 int cunescape_length_with_prefix(const char *s, size_t length, const char *prefix, UnescapeFlags flags, char **ret) {
1762         char *r, *t;
1763         const char *f;
1764         size_t pl;
1765
1766         assert(s);
1767         assert(ret);
1768
1769         /* Undoes C style string escaping, and optionally prefixes it. */
1770
1771         pl = prefix ? strlen(prefix) : 0;
1772
1773         r = new(char, pl+length+1);
1774         if (!r)
1775                 return -ENOMEM;
1776
1777         if (prefix)
1778                 memcpy(r, prefix, pl);
1779
1780         for (f = s, t = r + pl; f < s + length; f++) {
1781                 size_t remaining;
1782                 uint32_t u;
1783                 char c;
1784                 int k;
1785
1786                 remaining = s + length - f;
1787                 assert(remaining > 0);
1788
1789                 if (*f != '\\') {
1790                         /* A literal literal, copy verbatim */
1791                         *(t++) = *f;
1792                         continue;
1793                 }
1794
1795                 if (remaining == 1) {
1796                         if (flags & UNESCAPE_RELAX) {
1797                                 /* A trailing backslash, copy verbatim */
1798                                 *(t++) = *f;
1799                                 continue;
1800                         }
1801
1802                         free(r);
1803                         return -EINVAL;
1804                 }
1805
1806                 k = cunescape_one(f + 1, remaining - 1, &c, &u);
1807                 if (k < 0) {
1808                         if (flags & UNESCAPE_RELAX) {
1809                                 /* Invalid escape code, let's take it literal then */
1810                                 *(t++) = '\\';
1811                                 continue;
1812                         }
1813
1814                         free(r);
1815                         return k;
1816                 }
1817
1818                 if (c != 0)
1819                         /* Non-Unicode? Let's encode this directly */
1820                         *(t++) = c;
1821                 else
1822                         /* Unicode? Then let's encode this in UTF-8 */
1823                         t += utf8_encode_unichar(t, u);
1824
1825                 f += k;
1826         }
1827
1828         *t = 0;
1829
1830         *ret = r;
1831         return t - r;
1832 }
1833
1834 int cunescape_length(const char *s, size_t length, UnescapeFlags flags, char **ret) {
1835         return cunescape_length_with_prefix(s, length, NULL, flags, ret);
1836 }
1837
1838 int cunescape(const char *s, UnescapeFlags flags, char **ret) {
1839         return cunescape_length(s, strlen(s), flags, ret);
1840 }
1841
1842 char *xescape(const char *s, const char *bad) {
1843         char *r, *t;
1844         const char *f;
1845
1846         /* Escapes all chars in bad, in addition to \ and all special
1847          * chars, in \xFF style escaping. May be reversed with
1848          * cunescape(). */
1849
1850         r = new(char, strlen(s) * 4 + 1);
1851         if (!r)
1852                 return NULL;
1853
1854         for (f = s, t = r; *f; f++) {
1855
1856                 if ((*f < ' ') || (*f >= 127) ||
1857                     (*f == '\\') || strchr(bad, *f)) {
1858                         *(t++) = '\\';
1859                         *(t++) = 'x';
1860                         *(t++) = hexchar(*f >> 4);
1861                         *(t++) = hexchar(*f);
1862                 } else
1863                         *(t++) = *f;
1864         }
1865
1866         *t = 0;
1867
1868         return r;
1869 }
1870
1871 /// UNNEEDED by elogind
1872 #if 0
1873 char *ascii_strlower(char *t) {
1874         char *p;
1875
1876         assert(t);
1877
1878         for (p = t; *p; p++)
1879                 if (*p >= 'A' && *p <= 'Z')
1880                         *p = *p - 'A' + 'a';
1881
1882         return t;
1883 }
1884 #endif // 0
1885
1886 _pure_ static bool hidden_file_allow_backup(const char *filename) {
1887         assert(filename);
1888
1889         return
1890                 filename[0] == '.' ||
1891                 streq(filename, "lost+found") ||
1892                 streq(filename, "aquota.user") ||
1893                 streq(filename, "aquota.group") ||
1894                 endswith(filename, ".rpmnew") ||
1895                 endswith(filename, ".rpmsave") ||
1896                 endswith(filename, ".rpmorig") ||
1897                 endswith(filename, ".dpkg-old") ||
1898                 endswith(filename, ".dpkg-new") ||
1899                 endswith(filename, ".dpkg-tmp") ||
1900                 endswith(filename, ".dpkg-dist") ||
1901                 endswith(filename, ".dpkg-bak") ||
1902                 endswith(filename, ".dpkg-backup") ||
1903                 endswith(filename, ".dpkg-remove") ||
1904                 endswith(filename, ".swp");
1905 }
1906
1907 bool hidden_file(const char *filename) {
1908         assert(filename);
1909
1910         if (endswith(filename, "~"))
1911                 return true;
1912
1913         return hidden_file_allow_backup(filename);
1914 }
1915
1916 int fd_nonblock(int fd, bool nonblock) {
1917         int flags, nflags;
1918
1919         assert(fd >= 0);
1920
1921         flags = fcntl(fd, F_GETFL, 0);
1922         if (flags < 0)
1923                 return -errno;
1924
1925         if (nonblock)
1926                 nflags = flags | O_NONBLOCK;
1927         else
1928                 nflags = flags & ~O_NONBLOCK;
1929
1930         if (nflags == flags)
1931                 return 0;
1932
1933         if (fcntl(fd, F_SETFL, nflags) < 0)
1934                 return -errno;
1935
1936         return 0;
1937 }
1938
1939 int fd_cloexec(int fd, bool cloexec) {
1940         int flags, nflags;
1941
1942         assert(fd >= 0);
1943
1944         flags = fcntl(fd, F_GETFD, 0);
1945         if (flags < 0)
1946                 return -errno;
1947
1948         if (cloexec)
1949                 nflags = flags | FD_CLOEXEC;
1950         else
1951                 nflags = flags & ~FD_CLOEXEC;
1952
1953         if (nflags == flags)
1954                 return 0;
1955
1956         if (fcntl(fd, F_SETFD, nflags) < 0)
1957                 return -errno;
1958
1959         return 0;
1960 }
1961
1962 _pure_ static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
1963         unsigned i;
1964
1965         assert(n_fdset == 0 || fdset);
1966
1967         for (i = 0; i < n_fdset; i++)
1968                 if (fdset[i] == fd)
1969                         return true;
1970
1971         return false;
1972 }
1973
1974 int close_all_fds(const int except[], unsigned n_except) {
1975         _cleanup_closedir_ DIR *d = NULL;
1976         struct dirent *de;
1977         int r = 0;
1978
1979         assert(n_except == 0 || except);
1980
1981         d = opendir("/proc/self/fd");
1982         if (!d) {
1983                 int fd;
1984                 struct rlimit rl;
1985
1986                 /* When /proc isn't available (for example in chroots)
1987                  * the fallback is brute forcing through the fd
1988                  * table */
1989
1990                 assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0);
1991                 for (fd = 3; fd < (int) rl.rlim_max; fd ++) {
1992
1993                         if (fd_in_set(fd, except, n_except))
1994                                 continue;
1995
1996                         if (close_nointr(fd) < 0)
1997                                 if (errno != EBADF && r == 0)
1998                                         r = -errno;
1999                 }
2000
2001                 return r;
2002         }
2003
2004         while ((de = readdir(d))) {
2005                 int fd = -1;
2006
2007                 if (hidden_file(de->d_name))
2008                         continue;
2009
2010                 if (safe_atoi(de->d_name, &fd) < 0)
2011                         /* Let's better ignore this, just in case */
2012                         continue;
2013
2014                 if (fd < 3)
2015                         continue;
2016
2017                 if (fd == dirfd(d))
2018                         continue;
2019
2020                 if (fd_in_set(fd, except, n_except))
2021                         continue;
2022
2023                 if (close_nointr(fd) < 0) {
2024                         /* Valgrind has its own FD and doesn't want to have it closed */
2025                         if (errno != EBADF && r == 0)
2026                                 r = -errno;
2027                 }
2028         }
2029
2030         return r;
2031 }
2032
2033 bool chars_intersect(const char *a, const char *b) {
2034         const char *p;
2035
2036         /* Returns true if any of the chars in a are in b. */
2037         for (p = a; *p; p++)
2038                 if (strchr(b, *p))
2039                         return true;
2040
2041         return false;
2042 }
2043
2044 /// UNNEEDED by elogind
2045 #if 0
2046 bool fstype_is_network(const char *fstype) {
2047         static const char table[] =
2048                 "afs\0"
2049                 "cifs\0"
2050                 "smbfs\0"
2051                 "sshfs\0"
2052                 "ncpfs\0"
2053                 "ncp\0"
2054                 "nfs\0"
2055                 "nfs4\0"
2056                 "gfs\0"
2057                 "gfs2\0"
2058                 "glusterfs\0";
2059
2060         const char *x;
2061
2062         x = startswith(fstype, "fuse.");
2063         if (x)
2064                 fstype = x;
2065
2066         return nulstr_contains(table, fstype);
2067 }
2068 #endif // 0
2069
2070 int flush_fd(int fd) {
2071         struct pollfd pollfd = {
2072                 .fd = fd,
2073                 .events = POLLIN,
2074         };
2075
2076         for (;;) {
2077                 char buf[LINE_MAX];
2078                 ssize_t l;
2079                 int r;
2080
2081                 r = poll(&pollfd, 1, 0);
2082                 if (r < 0) {
2083                         if (errno == EINTR)
2084                                 continue;
2085
2086                         return -errno;
2087
2088                 } else if (r == 0)
2089                         return 0;
2090
2091                 l = read(fd, buf, sizeof(buf));
2092                 if (l < 0) {
2093
2094                         if (errno == EINTR)
2095                                 continue;
2096
2097                         if (errno == EAGAIN)
2098                                 return 0;
2099
2100                         return -errno;
2101                 } else if (l == 0)
2102                         return 0;
2103         }
2104 }
2105
2106 void safe_close_pair(int p[]) {
2107         assert(p);
2108
2109         if (p[0] == p[1]) {
2110                 /* Special case pairs which use the same fd in both
2111                  * directions... */
2112                 p[0] = p[1] = safe_close(p[0]);
2113                 return;
2114         }
2115
2116         p[0] = safe_close(p[0]);
2117         p[1] = safe_close(p[1]);
2118 }
2119
2120 ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) {
2121         uint8_t *p = buf;
2122         ssize_t n = 0;
2123
2124         assert(fd >= 0);
2125         assert(buf);
2126
2127         while (nbytes > 0) {
2128                 ssize_t k;
2129
2130                 k = read(fd, p, nbytes);
2131                 if (k < 0) {
2132                         if (errno == EINTR)
2133                                 continue;
2134
2135                         if (errno == EAGAIN && do_poll) {
2136
2137                                 /* We knowingly ignore any return value here,
2138                                  * and expect that any error/EOF is reported
2139                                  * via read() */
2140
2141                                 fd_wait_for_event(fd, POLLIN, USEC_INFINITY);
2142                                 continue;
2143                         }
2144
2145                         return n > 0 ? n : -errno;
2146                 }
2147
2148                 if (k == 0)
2149                         return n;
2150
2151                 p += k;
2152                 nbytes -= k;
2153                 n += k;
2154         }
2155
2156         return n;
2157 }
2158
2159 int loop_read_exact(int fd, void *buf, size_t nbytes, bool do_poll) {
2160         ssize_t n;
2161
2162         n = loop_read(fd, buf, nbytes, do_poll);
2163         if (n < 0)
2164                 return n;
2165         if ((size_t) n != nbytes)
2166                 return -EIO;
2167         return 0;
2168 }
2169
2170 int loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
2171         const uint8_t *p = buf;
2172
2173         assert(fd >= 0);
2174         assert(buf);
2175
2176         errno = 0;
2177
2178         do {
2179                 ssize_t k;
2180
2181                 k = write(fd, p, nbytes);
2182                 if (k < 0) {
2183                         if (errno == EINTR)
2184                                 continue;
2185
2186                         if (errno == EAGAIN && do_poll) {
2187                                 /* We knowingly ignore any return value here,
2188                                  * and expect that any error/EOF is reported
2189                                  * via write() */
2190
2191                                 fd_wait_for_event(fd, POLLOUT, USEC_INFINITY);
2192                                 continue;
2193                         }
2194
2195                         return -errno;
2196                 }
2197
2198                 if (nbytes > 0 && k == 0) /* Can't really happen */
2199                         return -EIO;
2200
2201                 p += k;
2202                 nbytes -= k;
2203         } while (nbytes > 0);
2204
2205         return 0;
2206 }
2207
2208 int parse_size(const char *t, off_t base, off_t *size) {
2209
2210         /* Soo, sometimes we want to parse IEC binary suffixes, and
2211          * sometimes SI decimal suffixes. This function can parse
2212          * both. Which one is the right way depends on the
2213          * context. Wikipedia suggests that SI is customary for
2214          * hardware metrics and network speeds, while IEC is
2215          * customary for most data sizes used by software and volatile
2216          * (RAM) memory. Hence be careful which one you pick!
2217          *
2218          * In either case we use just K, M, G as suffix, and not Ki,
2219          * Mi, Gi or so (as IEC would suggest). That's because that's
2220          * frickin' ugly. But this means you really need to make sure
2221          * to document which base you are parsing when you use this
2222          * call. */
2223
2224         struct table {
2225                 const char *suffix;
2226                 unsigned long long factor;
2227         };
2228
2229         static const struct table iec[] = {
2230                 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
2231                 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
2232                 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
2233                 { "G", 1024ULL*1024ULL*1024ULL },
2234                 { "M", 1024ULL*1024ULL },
2235                 { "K", 1024ULL },
2236                 { "B", 1 },
2237                 { "", 1 },
2238         };
2239
2240         static const struct table si[] = {
2241                 { "E", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
2242                 { "P", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
2243                 { "T", 1000ULL*1000ULL*1000ULL*1000ULL },
2244                 { "G", 1000ULL*1000ULL*1000ULL },
2245                 { "M", 1000ULL*1000ULL },
2246                 { "K", 1000ULL },
2247                 { "B", 1 },
2248                 { "", 1 },
2249         };
2250
2251         const struct table *table;
2252         const char *p;
2253         unsigned long long r = 0;
2254         unsigned n_entries, start_pos = 0;
2255
2256         assert(t);
2257         assert(base == 1000 || base == 1024);
2258         assert(size);
2259
2260         if (base == 1000) {
2261                 table = si;
2262                 n_entries = ELEMENTSOF(si);
2263         } else {
2264                 table = iec;
2265                 n_entries = ELEMENTSOF(iec);
2266         }
2267
2268         p = t;
2269         do {
2270                 long long l;
2271                 unsigned long long l2;
2272                 double frac = 0;
2273                 char *e;
2274                 unsigned i;
2275
2276                 errno = 0;
2277                 l = strtoll(p, &e, 10);
2278
2279                 if (errno > 0)
2280                         return -errno;
2281
2282                 if (l < 0)
2283                         return -ERANGE;
2284
2285                 if (e == p)
2286                         return -EINVAL;
2287
2288                 if (*e == '.') {
2289                         e++;
2290                         if (*e >= '0' && *e <= '9') {
2291                                 char *e2;
2292
2293                                 /* strotoull itself would accept space/+/- */
2294                                 l2 = strtoull(e, &e2, 10);
2295
2296                                 if (errno == ERANGE)
2297                                         return -errno;
2298
2299                                 /* Ignore failure. E.g. 10.M is valid */
2300                                 frac = l2;
2301                                 for (; e < e2; e++)
2302                                         frac /= 10;
2303                         }
2304                 }
2305
2306                 e += strspn(e, WHITESPACE);
2307
2308                 for (i = start_pos; i < n_entries; i++)
2309                         if (startswith(e, table[i].suffix)) {
2310                                 unsigned long long tmp;
2311                                 if ((unsigned long long) l + (frac > 0) > ULLONG_MAX / table[i].factor)
2312                                         return -ERANGE;
2313                                 tmp = l * table[i].factor + (unsigned long long) (frac * table[i].factor);
2314                                 if (tmp > ULLONG_MAX - r)
2315                                         return -ERANGE;
2316
2317                                 r += tmp;
2318                                 if ((unsigned long long) (off_t) r != r)
2319                                         return -ERANGE;
2320
2321                                 p = e + strlen(table[i].suffix);
2322
2323                                 start_pos = i + 1;
2324                                 break;
2325                         }
2326
2327                 if (i >= n_entries)
2328                         return -EINVAL;
2329
2330         } while (*p);
2331
2332         *size = r;
2333
2334         return 0;
2335 }
2336
2337 bool is_device_path(const char *path) {
2338
2339         /* Returns true on paths that refer to a device, either in
2340          * sysfs or in /dev */
2341
2342         return
2343                 path_startswith(path, "/dev/") ||
2344                 path_startswith(path, "/sys/");
2345 }
2346
2347 /// UNNEEDED by elogind
2348 #if 0
2349 int dir_is_empty(const char *path) {
2350         _cleanup_closedir_ DIR *d;
2351
2352         d = opendir(path);
2353         if (!d)
2354                 return -errno;
2355
2356         for (;;) {
2357                 struct dirent *de;
2358
2359                 errno = 0;
2360                 de = readdir(d);
2361                 if (!de && errno != 0)
2362                         return -errno;
2363
2364                 if (!de)
2365                         return 1;
2366
2367                 if (!hidden_file(de->d_name))
2368                         return 0;
2369         }
2370 }
2371
2372 char* dirname_malloc(const char *path) {
2373         char *d, *dir, *dir2;
2374
2375         d = strdup(path);
2376         if (!d)
2377                 return NULL;
2378         dir = dirname(d);
2379         assert(dir);
2380
2381         if (dir != d) {
2382                 dir2 = strdup(dir);
2383                 free(d);
2384                 return dir2;
2385         }
2386
2387         return dir;
2388 }
2389
2390 void rename_process(const char name[8]) {
2391         assert(name);
2392
2393         /* This is a like a poor man's setproctitle(). It changes the
2394          * comm field, argv[0], and also the glibc's internally used
2395          * name of the process. For the first one a limit of 16 chars
2396          * applies, to the second one usually one of 10 (i.e. length
2397          * of "/sbin/init"), to the third one one of 7 (i.e. length of
2398          * "systemd"). If you pass a longer string it will be
2399          * truncated */
2400
2401         prctl(PR_SET_NAME, name);
2402
2403         if (program_invocation_name)
2404                 strncpy(program_invocation_name, name, strlen(program_invocation_name));
2405
2406         if (saved_argc > 0) {
2407                 int i;
2408
2409                 if (saved_argv[0])
2410                         strncpy(saved_argv[0], name, strlen(saved_argv[0]));
2411
2412                 for (i = 1; i < saved_argc; i++) {
2413                         if (!saved_argv[i])
2414                                 break;
2415
2416                         memzero(saved_argv[i], strlen(saved_argv[i]));
2417                 }
2418         }
2419 }
2420 #endif // 0
2421
2422 char *lookup_uid(uid_t uid) {
2423         long bufsize;
2424         char *name;
2425         _cleanup_free_ char *buf = NULL;
2426         struct passwd pwbuf, *pw = NULL;
2427
2428         /* Shortcut things to avoid NSS lookups */
2429         if (uid == 0)
2430                 return strdup("root");
2431
2432         bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
2433         if (bufsize <= 0)
2434                 bufsize = 4096;
2435
2436         buf = malloc(bufsize);
2437         if (!buf)
2438                 return NULL;
2439
2440         if (getpwuid_r(uid, &pwbuf, buf, bufsize, &pw) == 0 && pw)
2441                 return strdup(pw->pw_name);
2442
2443         if (asprintf(&name, UID_FMT, uid) < 0)
2444                 return NULL;
2445
2446         return name;
2447 }
2448
2449 /// UNNEEDED by elogind
2450 #if 0
2451 char* getlogname_malloc(void) {
2452         uid_t uid;
2453         struct stat st;
2454
2455         if (isatty(STDIN_FILENO) && fstat(STDIN_FILENO, &st) >= 0)
2456                 uid = st.st_uid;
2457         else
2458                 uid = getuid();
2459
2460         return lookup_uid(uid);
2461 }
2462
2463 char *getusername_malloc(void) {
2464         const char *e;
2465
2466         e = getenv("USER");
2467         if (e)
2468                 return strdup(e);
2469
2470         return lookup_uid(getuid());
2471 }
2472 #endif // 0
2473
2474 bool is_temporary_fs(const struct statfs *s) {
2475         assert(s);
2476
2477         return F_TYPE_EQUAL(s->f_type, TMPFS_MAGIC) ||
2478                F_TYPE_EQUAL(s->f_type, RAMFS_MAGIC);
2479 }
2480
2481 int fd_is_temporary_fs(int fd) {
2482         struct statfs s;
2483
2484         if (fstatfs(fd, &s) < 0)
2485                 return -errno;
2486
2487         return is_temporary_fs(&s);
2488 }
2489
2490 int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
2491         assert(path);
2492
2493         /* Under the assumption that we are running privileged we
2494          * first change the access mode and only then hand out
2495          * ownership to avoid a window where access is too open. */
2496
2497         if (mode != MODE_INVALID)
2498                 if (chmod(path, mode) < 0)
2499                         return -errno;
2500
2501         if (uid != UID_INVALID || gid != GID_INVALID)
2502                 if (chown(path, uid, gid) < 0)
2503                         return -errno;
2504
2505         return 0;
2506 }
2507
2508 /// UNNEEDED by elogind
2509 #if 0
2510 int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid) {
2511         assert(fd >= 0);
2512
2513         /* Under the assumption that we are running privileged we
2514          * first change the access mode and only then hand out
2515          * ownership to avoid a window where access is too open. */
2516
2517         if (mode != MODE_INVALID)
2518                 if (fchmod(fd, mode) < 0)
2519                         return -errno;
2520
2521         if (uid != UID_INVALID || gid != GID_INVALID)
2522                 if (fchown(fd, uid, gid) < 0)
2523                         return -errno;
2524
2525         return 0;
2526 }
2527
2528 cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
2529         cpu_set_t *r;
2530         unsigned n = 1024;
2531
2532         /* Allocates the cpuset in the right size */
2533
2534         for (;;) {
2535                 if (!(r = CPU_ALLOC(n)))
2536                         return NULL;
2537
2538                 if (sched_getaffinity(0, CPU_ALLOC_SIZE(n), r) >= 0) {
2539                         CPU_ZERO_S(CPU_ALLOC_SIZE(n), r);
2540
2541                         if (ncpus)
2542                                 *ncpus = n;
2543
2544                         return r;
2545                 }
2546
2547                 CPU_FREE(r);
2548
2549                 if (errno != EINVAL)
2550                         return NULL;
2551
2552                 n *= 2;
2553         }
2554 }
2555 #endif // 0
2556
2557 int files_same(const char *filea, const char *fileb) {
2558         struct stat a, b;
2559
2560         if (stat(filea, &a) < 0)
2561                 return -errno;
2562
2563         if (stat(fileb, &b) < 0)
2564                 return -errno;
2565
2566         return a.st_dev == b.st_dev &&
2567                a.st_ino == b.st_ino;
2568 }
2569
2570 /// UNNEEDED by elogind
2571 #if 0
2572 int running_in_chroot(void) {
2573         int ret;
2574
2575         ret = files_same("/proc/1/root", "/");
2576         if (ret < 0)
2577                 return ret;
2578
2579         return ret == 0;
2580 }
2581 #endif // 0
2582
2583 static char *ascii_ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
2584         size_t x;
2585         char *r;
2586
2587         assert(s);
2588         assert(percent <= 100);
2589         assert(new_length >= 3);
2590
2591         if (old_length <= 3 || old_length <= new_length)
2592                 return strndup(s, old_length);
2593
2594         r = new0(char, new_length+1);
2595         if (!r)
2596                 return NULL;
2597
2598         x = (new_length * percent) / 100;
2599
2600         if (x > new_length - 3)
2601                 x = new_length - 3;
2602
2603         memcpy(r, s, x);
2604         r[x] = '.';
2605         r[x+1] = '.';
2606         r[x+2] = '.';
2607         memcpy(r + x + 3,
2608                s + old_length - (new_length - x - 3),
2609                new_length - x - 3);
2610
2611         return r;
2612 }
2613
2614 char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
2615         size_t x;
2616         char *e;
2617         const char *i, *j;
2618         unsigned k, len, len2;
2619
2620         assert(s);
2621         assert(percent <= 100);
2622         assert(new_length >= 3);
2623
2624         /* if no multibyte characters use ascii_ellipsize_mem for speed */
2625         if (ascii_is_valid(s))
2626                 return ascii_ellipsize_mem(s, old_length, new_length, percent);
2627
2628         if (old_length <= 3 || old_length <= new_length)
2629                 return strndup(s, old_length);
2630
2631         x = (new_length * percent) / 100;
2632
2633         if (x > new_length - 3)
2634                 x = new_length - 3;
2635
2636         k = 0;
2637         for (i = s; k < x && i < s + old_length; i = utf8_next_char(i)) {
2638                 int c;
2639
2640                 c = utf8_encoded_to_unichar(i);
2641                 if (c < 0)
2642                         return NULL;
2643                 k += unichar_iswide(c) ? 2 : 1;
2644         }
2645
2646         if (k > x) /* last character was wide and went over quota */
2647                 x ++;
2648
2649         for (j = s + old_length; k < new_length && j > i; ) {
2650                 int c;
2651
2652                 j = utf8_prev_char(j);
2653                 c = utf8_encoded_to_unichar(j);
2654                 if (c < 0)
2655                         return NULL;
2656                 k += unichar_iswide(c) ? 2 : 1;
2657         }
2658         assert(i <= j);
2659
2660         /* we don't actually need to ellipsize */
2661         if (i == j)
2662                 return memdup(s, old_length + 1);
2663
2664         /* make space for ellipsis */
2665         j = utf8_next_char(j);
2666
2667         len = i - s;
2668         len2 = s + old_length - j;
2669         e = new(char, len + 3 + len2 + 1);
2670         if (!e)
2671                 return NULL;
2672
2673         /*
2674         printf("old_length=%zu new_length=%zu x=%zu len=%u len2=%u k=%u\n",
2675                old_length, new_length, x, len, len2, k);
2676         */
2677
2678         memcpy(e, s, len);
2679         e[len]   = 0xe2; /* tri-dot ellipsis: … */
2680         e[len + 1] = 0x80;
2681         e[len + 2] = 0xa6;
2682
2683         memcpy(e + len + 3, j, len2 + 1);
2684
2685         return e;
2686 }
2687
2688 char *ellipsize(const char *s, size_t length, unsigned percent) {
2689         return ellipsize_mem(s, strlen(s), length, percent);
2690 }
2691
2692 int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode) {
2693         _cleanup_close_ int fd;
2694         int r;
2695
2696         assert(path);
2697
2698         if (parents)
2699                 mkdir_parents(path, 0755);
2700
2701         fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, mode > 0 ? mode : 0644);
2702         if (fd < 0)
2703                 return -errno;
2704
2705         if (mode > 0) {
2706                 r = fchmod(fd, mode);
2707                 if (r < 0)
2708                         return -errno;
2709         }
2710
2711         if (uid != UID_INVALID || gid != GID_INVALID) {
2712                 r = fchown(fd, uid, gid);
2713                 if (r < 0)
2714                         return -errno;
2715         }
2716
2717         if (stamp != USEC_INFINITY) {
2718                 struct timespec ts[2];
2719
2720                 timespec_store(&ts[0], stamp);
2721                 ts[1] = ts[0];
2722                 r = futimens(fd, ts);
2723         } else
2724                 r = futimens(fd, NULL);
2725         if (r < 0)
2726                 return -errno;
2727
2728         return 0;
2729 }
2730
2731 int touch(const char *path) {
2732         return touch_file(path, false, USEC_INFINITY, UID_INVALID, GID_INVALID, 0);
2733 }
2734
2735 /// UNNEEDED by elogind
2736 #if 0
2737 static char *unquote(const char *s, const char* quotes) {
2738         size_t l;
2739         assert(s);
2740
2741         /* This is rather stupid, simply removes the heading and
2742          * trailing quotes if there is one. Doesn't care about
2743          * escaping or anything.
2744          *
2745          * DON'T USE THIS FOR NEW CODE ANYMORE!*/
2746
2747         l = strlen(s);
2748         if (l < 2)
2749                 return strdup(s);
2750
2751         if (strchr(quotes, s[0]) && s[l-1] == s[0])
2752                 return strndup(s+1, l-2);
2753
2754         return strdup(s);
2755 }
2756 #endif // 0
2757
2758 noreturn void freeze(void) {
2759
2760         /* Make sure nobody waits for us on a socket anymore */
2761         close_all_fds(NULL, 0);
2762
2763         sync();
2764
2765         for (;;)
2766                 pause();
2767 }
2768
2769 bool null_or_empty(struct stat *st) {
2770         assert(st);
2771
2772         if (S_ISREG(st->st_mode) && st->st_size <= 0)
2773                 return true;
2774
2775         if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
2776                 return true;
2777
2778         return false;
2779 }
2780
2781 int null_or_empty_path(const char *fn) {
2782         struct stat st;
2783
2784         assert(fn);
2785
2786         if (stat(fn, &st) < 0)
2787                 return -errno;
2788
2789         return null_or_empty(&st);
2790 }
2791
2792 /// UNNEEDED by elogind
2793 #if 0
2794 int null_or_empty_fd(int fd) {
2795         struct stat st;
2796
2797         assert(fd >= 0);
2798
2799         if (fstat(fd, &st) < 0)
2800                 return -errno;
2801
2802         return null_or_empty(&st);
2803 }
2804 #endif // 0
2805
2806 DIR *xopendirat(int fd, const char *name, int flags) {
2807         int nfd;
2808         DIR *d;
2809
2810         assert(!(flags & O_CREAT));
2811
2812         nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags, 0);
2813         if (nfd < 0)
2814                 return NULL;
2815
2816         d = fdopendir(nfd);
2817         if (!d) {
2818                 safe_close(nfd);
2819                 return NULL;
2820         }
2821
2822         return d;
2823 }
2824
2825 /// UNNEEDED by elogind
2826 #if 0
2827 static char *tag_to_udev_node(const char *tagvalue, const char *by) {
2828         _cleanup_free_ char *t = NULL, *u = NULL;
2829         size_t enc_len;
2830
2831         u = unquote(tagvalue, QUOTES);
2832         if (!u)
2833                 return NULL;
2834
2835         enc_len = strlen(u) * 4 + 1;
2836         t = new(char, enc_len);
2837         if (!t)
2838                 return NULL;
2839
2840         if (encode_devnode_name(u, t, enc_len) < 0)
2841                 return NULL;
2842
2843         return strjoin("/dev/disk/by-", by, "/", t, NULL);
2844 }
2845
2846 char *fstab_node_to_udev_node(const char *p) {
2847         assert(p);
2848
2849         if (startswith(p, "LABEL="))
2850                 return tag_to_udev_node(p+6, "label");
2851
2852         if (startswith(p, "UUID="))
2853                 return tag_to_udev_node(p+5, "uuid");
2854
2855         if (startswith(p, "PARTUUID="))
2856                 return tag_to_udev_node(p+9, "partuuid");
2857
2858         if (startswith(p, "PARTLABEL="))
2859                 return tag_to_udev_node(p+10, "partlabel");
2860
2861         return strdup(p);
2862 }
2863 #endif // 0
2864
2865 bool dirent_is_file(const struct dirent *de) {
2866         assert(de);
2867
2868         if (hidden_file(de->d_name))
2869                 return false;
2870
2871         if (de->d_type != DT_REG &&
2872             de->d_type != DT_LNK &&
2873             de->d_type != DT_UNKNOWN)
2874                 return false;
2875
2876         return true;
2877 }
2878
2879 bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
2880         assert(de);
2881
2882         if (de->d_type != DT_REG &&
2883             de->d_type != DT_LNK &&
2884             de->d_type != DT_UNKNOWN)
2885                 return false;
2886
2887         if (hidden_file_allow_backup(de->d_name))
2888                 return false;
2889
2890         return endswith(de->d_name, suffix);
2891 }
2892
2893 /// UNNEEDED by elogind
2894 #if 0
2895 static int do_execute(char **directories, usec_t timeout, char *argv[]) {
2896         _cleanup_hashmap_free_free_ Hashmap *pids = NULL;
2897         _cleanup_set_free_free_ Set *seen = NULL;
2898         char **directory;
2899
2900         /* We fork this all off from a child process so that we can
2901          * somewhat cleanly make use of SIGALRM to set a time limit */
2902
2903         (void) reset_all_signal_handlers();
2904         (void) reset_signal_mask();
2905
2906         assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
2907
2908         pids = hashmap_new(NULL);
2909         if (!pids)
2910                 return log_oom();
2911
2912         seen = set_new(&string_hash_ops);
2913         if (!seen)
2914                 return log_oom();
2915
2916         STRV_FOREACH(directory, directories) {
2917                 _cleanup_closedir_ DIR *d;
2918                 struct dirent *de;
2919
2920                 d = opendir(*directory);
2921                 if (!d) {
2922                         if (errno == ENOENT)
2923                                 continue;
2924
2925                         return log_error_errno(errno, "Failed to open directory %s: %m", *directory);
2926                 }
2927
2928                 FOREACH_DIRENT(de, d, break) {
2929                         _cleanup_free_ char *path = NULL;
2930                         pid_t pid;
2931                         int r;
2932
2933                         if (!dirent_is_file(de))
2934                                 continue;
2935
2936                         if (set_contains(seen, de->d_name)) {
2937                                 log_debug("%1$s/%2$s skipped (%2$s was already seen).", *directory, de->d_name);
2938                                 continue;
2939                         }
2940
2941                         r = set_put_strdup(seen, de->d_name);
2942                         if (r < 0)
2943                                 return log_oom();
2944
2945                         path = strjoin(*directory, "/", de->d_name, NULL);
2946                         if (!path)
2947                                 return log_oom();
2948
2949                         if (null_or_empty_path(path)) {
2950                                 log_debug("%s is empty (a mask).", path);
2951                                 continue;
2952                         }
2953
2954                         pid = fork();
2955                         if (pid < 0) {
2956                                 log_error_errno(errno, "Failed to fork: %m");
2957                                 continue;
2958                         } else if (pid == 0) {
2959                                 char *_argv[2];
2960
2961                                 assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
2962
2963                                 if (!argv) {
2964                                         _argv[0] = path;
2965                                         _argv[1] = NULL;
2966                                         argv = _argv;
2967                                 } else
2968                                         argv[0] = path;
2969
2970                                 execv(path, argv);
2971                                 return log_error_errno(errno, "Failed to execute %s: %m", path);
2972                         }
2973
2974                         log_debug("Spawned %s as " PID_FMT ".", path, pid);
2975
2976                         r = hashmap_put(pids, UINT_TO_PTR(pid), path);
2977                         if (r < 0)
2978                                 return log_oom();
2979                         path = NULL;
2980                 }
2981         }
2982
2983         /* Abort execution of this process after the timout. We simply
2984          * rely on SIGALRM as default action terminating the process,
2985          * and turn on alarm(). */
2986
2987         if (timeout != USEC_INFINITY)
2988                 alarm((timeout + USEC_PER_SEC - 1) / USEC_PER_SEC);
2989
2990         while (!hashmap_isempty(pids)) {
2991                 _cleanup_free_ char *path = NULL;
2992                 pid_t pid;
2993
2994                 pid = PTR_TO_UINT(hashmap_first_key(pids));
2995                 assert(pid > 0);
2996
2997                 path = hashmap_remove(pids, UINT_TO_PTR(pid));
2998                 assert(path);
2999
3000                 wait_for_terminate_and_warn(path, pid, true);
3001         }
3002
3003         return 0;
3004 }
3005
3006 void execute_directories(const char* const* directories, usec_t timeout, char *argv[]) {
3007         pid_t executor_pid;
3008         int r;
3009         char *name;
3010         char **dirs = (char**) directories;
3011
3012         assert(!strv_isempty(dirs));
3013
3014         name = basename(dirs[0]);
3015         assert(!isempty(name));
3016
3017         /* Executes all binaries in the directories in parallel and waits
3018          * for them to finish. Optionally a timeout is applied. If a file
3019          * with the same name exists in more than one directory, the
3020          * earliest one wins. */
3021
3022         executor_pid = fork();
3023         if (executor_pid < 0) {
3024                 log_error_errno(errno, "Failed to fork: %m");
3025                 return;
3026
3027         } else if (executor_pid == 0) {
3028                 r = do_execute(dirs, timeout, argv);
3029                 _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
3030         }
3031
3032         wait_for_terminate_and_warn(name, executor_pid, true);
3033 }
3034 #endif // 0
3035
3036 bool nulstr_contains(const char*nulstr, const char *needle) {
3037         const char *i;
3038
3039         if (!nulstr)
3040                 return false;
3041
3042         NULSTR_FOREACH(i, nulstr)
3043                 if (streq(i, needle))
3044                         return true;
3045
3046         return false;
3047 }
3048
3049 /// UNNEEDED by elogind
3050 #if 0
3051 bool plymouth_running(void) {
3052         return access("/run/plymouth/pid", F_OK) >= 0;
3053 }
3054 #endif // 0
3055
3056 char* strshorten(char *s, size_t l) {
3057         assert(s);
3058
3059         if (l < strlen(s))
3060                 s[l] = 0;
3061
3062         return s;
3063 }
3064
3065 int pipe_eof(int fd) {
3066         struct pollfd pollfd = {
3067                 .fd = fd,
3068                 .events = POLLIN|POLLHUP,
3069         };
3070
3071         int r;
3072
3073         r = poll(&pollfd, 1, 0);
3074         if (r < 0)
3075                 return -errno;
3076
3077         if (r == 0)
3078                 return 0;
3079
3080         return pollfd.revents & POLLHUP;
3081 }
3082
3083 int fd_wait_for_event(int fd, int event, usec_t t) {
3084
3085         struct pollfd pollfd = {
3086                 .fd = fd,
3087                 .events = event,
3088         };
3089
3090         struct timespec ts;
3091         int r;
3092
3093         r = ppoll(&pollfd, 1, t == USEC_INFINITY ? NULL : timespec_store(&ts, t), NULL);
3094         if (r < 0)
3095                 return -errno;
3096
3097         if (r == 0)
3098                 return 0;
3099
3100         return pollfd.revents;
3101 }
3102
3103 int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
3104         FILE *f;
3105         char *t;
3106         int r, fd;
3107
3108         assert(path);
3109         assert(_f);
3110         assert(_temp_path);
3111
3112         r = tempfn_xxxxxx(path, NULL, &t);
3113         if (r < 0)
3114                 return r;
3115
3116         fd = mkostemp_safe(t, O_WRONLY|O_CLOEXEC);
3117         if (fd < 0) {
3118                 free(t);
3119                 return -errno;
3120         }
3121
3122         f = fdopen(fd, "we");
3123         if (!f) {
3124                 unlink_noerrno(t);
3125                 free(t);
3126                 safe_close(fd);
3127                 return -errno;
3128         }
3129
3130         *_f = f;
3131         *_temp_path = t;
3132
3133         return 0;
3134 }
3135
3136 /// UNNEEDED by elogind
3137 #if 0
3138 int symlink_atomic(const char *from, const char *to) {
3139         _cleanup_free_ char *t = NULL;
3140         int r;
3141
3142         assert(from);
3143         assert(to);
3144
3145         r = tempfn_random(to, NULL, &t);
3146         if (r < 0)
3147                 return r;
3148
3149         if (symlink(from, t) < 0)
3150                 return -errno;
3151
3152         if (rename(t, to) < 0) {
3153                 unlink_noerrno(t);
3154                 return -errno;
3155         }
3156
3157         return 0;
3158 }
3159
3160 int symlink_idempotent(const char *from, const char *to) {
3161         _cleanup_free_ char *p = NULL;
3162         int r;
3163
3164         assert(from);
3165         assert(to);
3166
3167         if (symlink(from, to) < 0) {
3168                 if (errno != EEXIST)
3169                         return -errno;
3170
3171                 r = readlink_malloc(to, &p);
3172                 if (r < 0)
3173                         return r;
3174
3175                 if (!streq(p, from))
3176                         return -EINVAL;
3177         }
3178
3179         return 0;
3180 }
3181
3182 int mknod_atomic(const char *path, mode_t mode, dev_t dev) {
3183         _cleanup_free_ char *t = NULL;
3184         int r;
3185
3186         assert(path);
3187
3188         r = tempfn_random(path, NULL, &t);
3189         if (r < 0)
3190                 return r;
3191
3192         if (mknod(t, mode, dev) < 0)
3193                 return -errno;
3194
3195         if (rename(t, path) < 0) {
3196                 unlink_noerrno(t);
3197                 return -errno;
3198         }
3199
3200         return 0;
3201 }
3202
3203 int mkfifo_atomic(const char *path, mode_t mode) {
3204         _cleanup_free_ char *t = NULL;
3205         int r;
3206
3207         assert(path);
3208
3209         r = tempfn_random(path, NULL, &t);
3210         if (r < 0)
3211                 return r;
3212
3213         if (mkfifo(t, mode) < 0)
3214                 return -errno;
3215
3216         if (rename(t, path) < 0) {
3217                 unlink_noerrno(t);
3218                 return -errno;
3219         }
3220
3221         return 0;
3222 }
3223 #endif // 0
3224
3225 bool display_is_local(const char *display) {
3226         assert(display);
3227
3228         return
3229                 display[0] == ':' &&
3230                 display[1] >= '0' &&
3231                 display[1] <= '9';
3232 }
3233
3234 int socket_from_display(const char *display, char **path) {
3235         size_t k;
3236         char *f, *c;
3237
3238         assert(display);
3239         assert(path);
3240
3241         if (!display_is_local(display))
3242                 return -EINVAL;
3243
3244         k = strspn(display+1, "0123456789");
3245
3246         f = new(char, strlen("/tmp/.X11-unix/X") + k + 1);
3247         if (!f)
3248                 return -ENOMEM;
3249
3250         c = stpcpy(f, "/tmp/.X11-unix/X");
3251         memcpy(c, display+1, k);
3252         c[k] = 0;
3253
3254         *path = f;
3255
3256         return 0;
3257 }
3258
3259 int get_user_creds(
3260                 const char **username,
3261                 uid_t *uid, gid_t *gid,
3262                 const char **home,
3263                 const char **shell) {
3264
3265         struct passwd *p;
3266         uid_t u;
3267
3268         assert(username);
3269         assert(*username);
3270
3271         /* We enforce some special rules for uid=0: in order to avoid
3272          * NSS lookups for root we hardcode its data. */
3273
3274         if (streq(*username, "root") || streq(*username, "0")) {
3275                 *username = "root";
3276
3277                 if (uid)
3278                         *uid = 0;
3279
3280                 if (gid)
3281                         *gid = 0;
3282
3283                 if (home)
3284                         *home = "/root";
3285
3286                 if (shell)
3287                         *shell = "/bin/sh";
3288
3289                 return 0;
3290         }
3291
3292         if (parse_uid(*username, &u) >= 0) {
3293                 errno = 0;
3294                 p = getpwuid(u);
3295
3296                 /* If there are multiple users with the same id, make
3297                  * sure to leave $USER to the configured value instead
3298                  * of the first occurrence in the database. However if
3299                  * the uid was configured by a numeric uid, then let's
3300                  * pick the real username from /etc/passwd. */
3301                 if (p)
3302                         *username = p->pw_name;
3303         } else {
3304                 errno = 0;
3305                 p = getpwnam(*username);
3306         }
3307
3308         if (!p)
3309                 return errno > 0 ? -errno : -ESRCH;
3310
3311         if (uid)
3312                 *uid = p->pw_uid;
3313
3314         if (gid)
3315                 *gid = p->pw_gid;
3316
3317         if (home)
3318                 *home = p->pw_dir;
3319
3320         if (shell)
3321                 *shell = p->pw_shell;
3322
3323         return 0;
3324 }
3325
3326 char* uid_to_name(uid_t uid) {
3327         struct passwd *p;
3328         char *r;
3329
3330         if (uid == 0)
3331                 return strdup("root");
3332
3333         p = getpwuid(uid);
3334         if (p)
3335                 return strdup(p->pw_name);
3336
3337         if (asprintf(&r, UID_FMT, uid) < 0)
3338                 return NULL;
3339
3340         return r;
3341 }
3342
3343 char* gid_to_name(gid_t gid) {
3344         struct group *p;
3345         char *r;
3346
3347         if (gid == 0)
3348                 return strdup("root");
3349
3350         p = getgrgid(gid);
3351         if (p)
3352                 return strdup(p->gr_name);
3353
3354         if (asprintf(&r, GID_FMT, gid) < 0)
3355                 return NULL;
3356
3357         return r;
3358 }
3359
3360 int get_group_creds(const char **groupname, gid_t *gid) {
3361         struct group *g;
3362         gid_t id;
3363
3364         assert(groupname);
3365
3366         /* We enforce some special rules for gid=0: in order to avoid
3367          * NSS lookups for root we hardcode its data. */
3368
3369         if (streq(*groupname, "root") || streq(*groupname, "0")) {
3370                 *groupname = "root";
3371
3372                 if (gid)
3373                         *gid = 0;
3374
3375                 return 0;
3376         }
3377
3378         if (parse_gid(*groupname, &id) >= 0) {
3379                 errno = 0;
3380                 g = getgrgid(id);
3381
3382                 if (g)
3383                         *groupname = g->gr_name;
3384         } else {
3385                 errno = 0;
3386                 g = getgrnam(*groupname);
3387         }
3388
3389         if (!g)
3390                 return errno > 0 ? -errno : -ESRCH;
3391
3392         if (gid)
3393                 *gid = g->gr_gid;
3394
3395         return 0;
3396 }
3397
3398 int in_gid(gid_t gid) {
3399         gid_t *gids;
3400         int ngroups_max, r, i;
3401
3402         if (getgid() == gid)
3403                 return 1;
3404
3405         if (getegid() == gid)
3406                 return 1;
3407
3408         ngroups_max = sysconf(_SC_NGROUPS_MAX);
3409         assert(ngroups_max > 0);
3410
3411         gids = alloca(sizeof(gid_t) * ngroups_max);
3412
3413         r = getgroups(ngroups_max, gids);
3414         if (r < 0)
3415                 return -errno;
3416
3417         for (i = 0; i < r; i++)
3418                 if (gids[i] == gid)
3419                         return 1;
3420
3421         return 0;
3422 }
3423
3424 /// UNNEEDED by elogind
3425 #if 0
3426 int in_group(const char *name) {
3427         int r;
3428         gid_t gid;
3429
3430         r = get_group_creds(&name, &gid);
3431         if (r < 0)
3432                 return r;
3433
3434         return in_gid(gid);
3435 }
3436
3437 int glob_exists(const char *path) {
3438         _cleanup_globfree_ glob_t g = {};
3439         int k;
3440
3441         assert(path);
3442
3443         errno = 0;
3444         k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
3445
3446         if (k == GLOB_NOMATCH)
3447                 return 0;
3448         else if (k == GLOB_NOSPACE)
3449                 return -ENOMEM;
3450         else if (k == 0)
3451                 return !strv_isempty(g.gl_pathv);
3452         else
3453                 return errno ? -errno : -EIO;
3454 }
3455
3456 int glob_extend(char ***strv, const char *path) {
3457         _cleanup_globfree_ glob_t g = {};
3458         int k;
3459         char **p;
3460
3461         errno = 0;
3462         k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
3463
3464         if (k == GLOB_NOMATCH)
3465                 return -ENOENT;
3466         else if (k == GLOB_NOSPACE)
3467                 return -ENOMEM;
3468         else if (k != 0 || strv_isempty(g.gl_pathv))
3469                 return errno ? -errno : -EIO;
3470
3471         STRV_FOREACH(p, g.gl_pathv) {
3472                 k = strv_extend(strv, *p);
3473                 if (k < 0)
3474                         break;
3475         }
3476
3477         return k;
3478 }
3479 #endif // 0
3480
3481 int dirent_ensure_type(DIR *d, struct dirent *de) {
3482         struct stat st;
3483
3484         assert(d);
3485         assert(de);
3486
3487         if (de->d_type != DT_UNKNOWN)
3488                 return 0;
3489
3490         if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
3491                 return -errno;
3492
3493         de->d_type =
3494                 S_ISREG(st.st_mode)  ? DT_REG  :
3495                 S_ISDIR(st.st_mode)  ? DT_DIR  :
3496                 S_ISLNK(st.st_mode)  ? DT_LNK  :
3497                 S_ISFIFO(st.st_mode) ? DT_FIFO :
3498                 S_ISSOCK(st.st_mode) ? DT_SOCK :
3499                 S_ISCHR(st.st_mode)  ? DT_CHR  :
3500                 S_ISBLK(st.st_mode)  ? DT_BLK  :
3501                                        DT_UNKNOWN;
3502
3503         return 0;
3504 }
3505
3506 int get_files_in_directory(const char *path, char ***list) {
3507         _cleanup_closedir_ DIR *d = NULL;
3508         size_t bufsize = 0, n = 0;
3509         _cleanup_strv_free_ char **l = NULL;
3510
3511         assert(path);
3512
3513         /* Returns all files in a directory in *list, and the number
3514          * of files as return value. If list is NULL returns only the
3515          * number. */
3516
3517         d = opendir(path);
3518         if (!d)
3519                 return -errno;
3520
3521         for (;;) {
3522                 struct dirent *de;
3523
3524                 errno = 0;
3525                 de = readdir(d);
3526                 if (!de && errno != 0)
3527                         return -errno;
3528                 if (!de)
3529                         break;
3530
3531                 dirent_ensure_type(d, de);
3532
3533                 if (!dirent_is_file(de))
3534                         continue;
3535
3536                 if (list) {
3537                         /* one extra slot is needed for the terminating NULL */
3538                         if (!GREEDY_REALLOC(l, bufsize, n + 2))
3539                                 return -ENOMEM;
3540
3541                         l[n] = strdup(de->d_name);
3542                         if (!l[n])
3543                                 return -ENOMEM;
3544
3545                         l[++n] = NULL;
3546                 } else
3547                         n++;
3548         }
3549
3550         if (list) {
3551                 *list = l;
3552                 l = NULL; /* avoid freeing */
3553         }
3554
3555         return n;
3556 }
3557
3558 char *strjoin(const char *x, ...) {
3559         va_list ap;
3560         size_t l;
3561         char *r, *p;
3562
3563         va_start(ap, x);
3564
3565         if (x) {
3566                 l = strlen(x);
3567
3568                 for (;;) {
3569                         const char *t;
3570                         size_t n;
3571
3572                         t = va_arg(ap, const char *);
3573                         if (!t)
3574                                 break;
3575
3576                         n = strlen(t);
3577                         if (n > ((size_t) -1) - l) {
3578                                 va_end(ap);
3579                                 return NULL;
3580                         }
3581
3582                         l += n;
3583                 }
3584         } else
3585                 l = 0;
3586
3587         va_end(ap);
3588
3589         r = new(char, l+1);
3590         if (!r)
3591                 return NULL;
3592
3593         if (x) {
3594                 p = stpcpy(r, x);
3595
3596                 va_start(ap, x);
3597
3598                 for (;;) {
3599                         const char *t;
3600
3601                         t = va_arg(ap, const char *);
3602                         if (!t)
3603                                 break;
3604
3605                         p = stpcpy(p, t);
3606                 }
3607
3608                 va_end(ap);
3609         } else
3610                 r[0] = 0;
3611
3612         return r;
3613 }
3614
3615 bool is_main_thread(void) {
3616         static thread_local int cached = 0;
3617
3618         if (_unlikely_(cached == 0))
3619                 cached = getpid() == gettid() ? 1 : -1;
3620
3621         return cached > 0;
3622 }
3623
3624 /// UNNEEDED by elogind
3625 #if 0
3626 int block_get_whole_disk(dev_t d, dev_t *ret) {
3627         char *p, *s;
3628         int r;
3629         unsigned n, m;
3630
3631         assert(ret);
3632
3633         /* If it has a queue this is good enough for us */
3634         if (asprintf(&p, "/sys/dev/block/%u:%u/queue", major(d), minor(d)) < 0)
3635                 return -ENOMEM;
3636
3637         r = access(p, F_OK);
3638         free(p);
3639
3640         if (r >= 0) {
3641                 *ret = d;
3642                 return 0;
3643         }
3644
3645         /* If it is a partition find the originating device */
3646         if (asprintf(&p, "/sys/dev/block/%u:%u/partition", major(d), minor(d)) < 0)
3647                 return -ENOMEM;
3648
3649         r = access(p, F_OK);
3650         free(p);
3651
3652         if (r < 0)
3653                 return -ENOENT;
3654
3655         /* Get parent dev_t */
3656         if (asprintf(&p, "/sys/dev/block/%u:%u/../dev", major(d), minor(d)) < 0)
3657                 return -ENOMEM;
3658
3659         r = read_one_line_file(p, &s);
3660         free(p);
3661
3662         if (r < 0)
3663                 return r;
3664
3665         r = sscanf(s, "%u:%u", &m, &n);
3666         free(s);
3667
3668         if (r != 2)
3669                 return -EINVAL;
3670
3671         /* Only return this if it is really good enough for us. */
3672         if (asprintf(&p, "/sys/dev/block/%u:%u/queue", m, n) < 0)
3673                 return -ENOMEM;
3674
3675         r = access(p, F_OK);
3676         free(p);
3677
3678         if (r >= 0) {
3679                 *ret = makedev(m, n);
3680                 return 0;
3681         }
3682
3683         return -ENOENT;
3684 }
3685 #endif // 0
3686
3687 static const char *const ioprio_class_table[] = {
3688         [IOPRIO_CLASS_NONE] = "none",
3689         [IOPRIO_CLASS_RT] = "realtime",
3690         [IOPRIO_CLASS_BE] = "best-effort",
3691         [IOPRIO_CLASS_IDLE] = "idle"
3692 };
3693
3694 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX);
3695
3696 static const char *const sigchld_code_table[] = {
3697         [CLD_EXITED] = "exited",
3698         [CLD_KILLED] = "killed",
3699         [CLD_DUMPED] = "dumped",
3700         [CLD_TRAPPED] = "trapped",
3701         [CLD_STOPPED] = "stopped",
3702         [CLD_CONTINUED] = "continued",
3703 };
3704
3705 DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
3706
3707 static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = {
3708         [LOG_FAC(LOG_KERN)] = "kern",
3709         [LOG_FAC(LOG_USER)] = "user",
3710         [LOG_FAC(LOG_MAIL)] = "mail",
3711         [LOG_FAC(LOG_DAEMON)] = "daemon",
3712         [LOG_FAC(LOG_AUTH)] = "auth",
3713         [LOG_FAC(LOG_SYSLOG)] = "syslog",
3714         [LOG_FAC(LOG_LPR)] = "lpr",
3715         [LOG_FAC(LOG_NEWS)] = "news",
3716         [LOG_FAC(LOG_UUCP)] = "uucp",
3717         [LOG_FAC(LOG_CRON)] = "cron",
3718         [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
3719         [LOG_FAC(LOG_FTP)] = "ftp",
3720         [LOG_FAC(LOG_LOCAL0)] = "local0",
3721         [LOG_FAC(LOG_LOCAL1)] = "local1",
3722         [LOG_FAC(LOG_LOCAL2)] = "local2",
3723         [LOG_FAC(LOG_LOCAL3)] = "local3",
3724         [LOG_FAC(LOG_LOCAL4)] = "local4",
3725         [LOG_FAC(LOG_LOCAL5)] = "local5",
3726         [LOG_FAC(LOG_LOCAL6)] = "local6",
3727         [LOG_FAC(LOG_LOCAL7)] = "local7"
3728 };
3729
3730 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_facility_unshifted, int, LOG_FAC(~0));
3731
3732 static const char *const log_level_table[] = {
3733         [LOG_EMERG] = "emerg",
3734         [LOG_ALERT] = "alert",
3735         [LOG_CRIT] = "crit",
3736         [LOG_ERR] = "err",
3737         [LOG_WARNING] = "warning",
3738         [LOG_NOTICE] = "notice",
3739         [LOG_INFO] = "info",
3740         [LOG_DEBUG] = "debug"
3741 };
3742
3743 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_level, int, LOG_DEBUG);
3744
3745 static const char* const sched_policy_table[] = {
3746         [SCHED_OTHER] = "other",
3747         [SCHED_BATCH] = "batch",
3748         [SCHED_IDLE] = "idle",
3749         [SCHED_FIFO] = "fifo",
3750         [SCHED_RR] = "rr"
3751 };
3752
3753 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX);
3754
3755 static const char* const rlimit_table[_RLIMIT_MAX] = {
3756         [RLIMIT_CPU] = "LimitCPU",
3757         [RLIMIT_FSIZE] = "LimitFSIZE",
3758         [RLIMIT_DATA] = "LimitDATA",
3759         [RLIMIT_STACK] = "LimitSTACK",
3760         [RLIMIT_CORE] = "LimitCORE",
3761         [RLIMIT_RSS] = "LimitRSS",
3762         [RLIMIT_NOFILE] = "LimitNOFILE",
3763         [RLIMIT_AS] = "LimitAS",
3764         [RLIMIT_NPROC] = "LimitNPROC",
3765         [RLIMIT_MEMLOCK] = "LimitMEMLOCK",
3766         [RLIMIT_LOCKS] = "LimitLOCKS",
3767         [RLIMIT_SIGPENDING] = "LimitSIGPENDING",
3768         [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE",
3769         [RLIMIT_NICE] = "LimitNICE",
3770         [RLIMIT_RTPRIO] = "LimitRTPRIO",
3771         [RLIMIT_RTTIME] = "LimitRTTIME"
3772 };
3773
3774 DEFINE_STRING_TABLE_LOOKUP(rlimit, int);
3775
3776 static const char* const ip_tos_table[] = {
3777         [IPTOS_LOWDELAY] = "low-delay",
3778         [IPTOS_THROUGHPUT] = "throughput",
3779         [IPTOS_RELIABILITY] = "reliability",
3780         [IPTOS_LOWCOST] = "low-cost",
3781 };
3782
3783 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
3784
3785 bool kexec_loaded(void) {
3786        bool loaded = false;
3787        char *s;
3788
3789        if (read_one_line_file("/sys/kernel/kexec_loaded", &s) >= 0) {
3790                if (s[0] == '1')
3791                        loaded = true;
3792                free(s);
3793        }
3794        return loaded;
3795 }
3796
3797 /// UNNEEDED by elogind
3798 #if 0
3799 int prot_from_flags(int flags) {
3800
3801         switch (flags & O_ACCMODE) {
3802
3803         case O_RDONLY:
3804                 return PROT_READ;
3805
3806         case O_WRONLY:
3807                 return PROT_WRITE;
3808
3809         case O_RDWR:
3810                 return PROT_READ|PROT_WRITE;
3811
3812         default:
3813                 return -EINVAL;
3814         }
3815 }
3816
3817 char *format_bytes(char *buf, size_t l, off_t t) {
3818         unsigned i;
3819
3820         static const struct {
3821                 const char *suffix;
3822                 off_t factor;
3823         } table[] = {
3824                 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
3825                 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
3826                 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
3827                 { "G", 1024ULL*1024ULL*1024ULL },
3828                 { "M", 1024ULL*1024ULL },
3829                 { "K", 1024ULL },
3830         };
3831
3832         if (t == (off_t) -1)
3833                 return NULL;
3834
3835         for (i = 0; i < ELEMENTSOF(table); i++) {
3836
3837                 if (t >= table[i].factor) {
3838                         snprintf(buf, l,
3839                                  "%llu.%llu%s",
3840                                  (unsigned long long) (t / table[i].factor),
3841                                  (unsigned long long) (((t*10ULL) / table[i].factor) % 10ULL),
3842                                  table[i].suffix);
3843
3844                         goto finish;
3845                 }
3846         }
3847
3848         snprintf(buf, l, "%lluB", (unsigned long long) t);
3849
3850 finish:
3851         buf[l-1] = 0;
3852         return buf;
3853
3854 }
3855 #endif // 0
3856
3857 void* memdup(const void *p, size_t l) {
3858         void *r;
3859
3860         assert(p);
3861
3862         r = malloc(l);
3863         if (!r)
3864                 return NULL;
3865
3866         memcpy(r, p, l);
3867         return r;
3868 }
3869
3870 int fd_inc_sndbuf(int fd, size_t n) {
3871         int r, value;
3872         socklen_t l = sizeof(value);
3873
3874         r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
3875         if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
3876                 return 0;
3877
3878         /* If we have the privileges we will ignore the kernel limit. */
3879
3880         value = (int) n;
3881         if (setsockopt(fd, SOL_SOCKET, SO_SNDBUFFORCE, &value, sizeof(value)) < 0)
3882                 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value)) < 0)
3883                         return -errno;
3884
3885         return 1;
3886 }
3887
3888 int fd_inc_rcvbuf(int fd, size_t n) {
3889         int r, value;
3890         socklen_t l = sizeof(value);
3891
3892         r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
3893         if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
3894                 return 0;
3895
3896         /* If we have the privileges we will ignore the kernel limit. */
3897
3898         value = (int) n;
3899         if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value)) < 0)
3900                 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) < 0)
3901                         return -errno;
3902         return 1;
3903 }
3904
3905 int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
3906         bool stdout_is_tty, stderr_is_tty;
3907         pid_t parent_pid, agent_pid;
3908         sigset_t ss, saved_ss;
3909         unsigned n, i;
3910         va_list ap;
3911         char **l;
3912
3913         assert(pid);
3914         assert(path);
3915
3916         /* Spawns a temporary TTY agent, making sure it goes away when
3917          * we go away */
3918
3919         parent_pid = getpid();
3920
3921         /* First we temporarily block all signals, so that the new
3922          * child has them blocked initially. This way, we can be sure
3923          * that SIGTERMs are not lost we might send to the agent. */
3924         assert_se(sigfillset(&ss) >= 0);
3925         assert_se(sigprocmask(SIG_SETMASK, &ss, &saved_ss) >= 0);
3926
3927         agent_pid = fork();
3928         if (agent_pid < 0) {
3929                 assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0);
3930                 return -errno;
3931         }
3932
3933         if (agent_pid != 0) {
3934                 assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0);
3935                 *pid = agent_pid;
3936                 return 0;
3937         }
3938
3939         /* In the child:
3940          *
3941          * Make sure the agent goes away when the parent dies */
3942         if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
3943                 _exit(EXIT_FAILURE);
3944
3945         /* Make sure we actually can kill the agent, if we need to, in
3946          * case somebody invoked us from a shell script that trapped
3947          * SIGTERM or so... */
3948         (void) reset_all_signal_handlers();
3949         (void) reset_signal_mask();
3950
3951         /* Check whether our parent died before we were able
3952          * to set the death signal and unblock the signals */
3953         if (getppid() != parent_pid)
3954                 _exit(EXIT_SUCCESS);
3955
3956         /* Don't leak fds to the agent */
3957         close_all_fds(except, n_except);
3958
3959         stdout_is_tty = isatty(STDOUT_FILENO);
3960         stderr_is_tty = isatty(STDERR_FILENO);
3961
3962         if (!stdout_is_tty || !stderr_is_tty) {
3963                 int fd;
3964
3965                 /* Detach from stdout/stderr. and reopen
3966                  * /dev/tty for them. This is important to
3967                  * ensure that when systemctl is started via
3968                  * popen() or a similar call that expects to
3969                  * read EOF we actually do generate EOF and
3970                  * not delay this indefinitely by because we
3971                  * keep an unused copy of stdin around. */
3972                 fd = open("/dev/tty", O_WRONLY);
3973                 if (fd < 0) {
3974                         log_error_errno(errno, "Failed to open /dev/tty: %m");
3975                         _exit(EXIT_FAILURE);
3976                 }
3977
3978                 if (!stdout_is_tty)
3979                         dup2(fd, STDOUT_FILENO);
3980
3981                 if (!stderr_is_tty)
3982                         dup2(fd, STDERR_FILENO);
3983
3984                 if (fd > 2)
3985                         close(fd);
3986         }
3987
3988         /* Count arguments */
3989         va_start(ap, path);
3990         for (n = 0; va_arg(ap, char*); n++)
3991                 ;
3992         va_end(ap);
3993
3994         /* Allocate strv */
3995         l = alloca(sizeof(char *) * (n + 1));
3996
3997         /* Fill in arguments */
3998         va_start(ap, path);
3999         for (i = 0; i <= n; i++)
4000                 l[i] = va_arg(ap, char*);
4001         va_end(ap);
4002
4003         execv(path, l);
4004         _exit(EXIT_FAILURE);
4005 }
4006
4007 /// UNNEEDED by elogind
4008 #if 0
4009 int setrlimit_closest(int resource, const struct rlimit *rlim) {
4010         struct rlimit highest, fixed;
4011
4012         assert(rlim);
4013
4014         if (setrlimit(resource, rlim) >= 0)
4015                 return 0;
4016
4017         if (errno != EPERM)
4018                 return -errno;
4019
4020         /* So we failed to set the desired setrlimit, then let's try
4021          * to get as close as we can */
4022         assert_se(getrlimit(resource, &highest) == 0);
4023
4024         fixed.rlim_cur = MIN(rlim->rlim_cur, highest.rlim_max);
4025         fixed.rlim_max = MIN(rlim->rlim_max, highest.rlim_max);
4026
4027         if (setrlimit(resource, &fixed) < 0)
4028                 return -errno;
4029
4030         return 0;
4031 }
4032
4033 bool http_etag_is_valid(const char *etag) {
4034         if (isempty(etag))
4035                 return false;
4036
4037         if (!endswith(etag, "\""))
4038                 return false;
4039
4040         if (!startswith(etag, "\"") && !startswith(etag, "W/\""))
4041                 return false;
4042
4043         return true;
4044 }
4045 #endif // 0
4046
4047 bool http_url_is_valid(const char *url) {
4048         const char *p;
4049
4050         if (isempty(url))
4051                 return false;
4052
4053         p = startswith(url, "http://");
4054         if (!p)
4055                 p = startswith(url, "https://");
4056         if (!p)
4057                 return false;
4058
4059         if (isempty(p))
4060                 return false;
4061
4062         return ascii_is_valid(p);
4063 }
4064
4065 bool documentation_url_is_valid(const char *url) {
4066         const char *p;
4067
4068         if (isempty(url))
4069                 return false;
4070
4071         if (http_url_is_valid(url))
4072                 return true;
4073
4074         p = startswith(url, "file:/");
4075         if (!p)
4076                 p = startswith(url, "info:");
4077         if (!p)
4078                 p = startswith(url, "man:");
4079
4080         if (isempty(p))
4081                 return false;
4082
4083         return ascii_is_valid(p);
4084 }
4085
4086 bool in_initrd(void) {
4087         static int saved = -1;
4088         struct statfs s;
4089
4090         if (saved >= 0)
4091                 return saved;
4092
4093         /* We make two checks here:
4094          *
4095          * 1. the flag file /etc/initrd-release must exist
4096          * 2. the root file system must be a memory file system
4097          *
4098          * The second check is extra paranoia, since misdetecting an
4099          * initrd can have bad bad consequences due the initrd
4100          * emptying when transititioning to the main systemd.
4101          */
4102
4103         saved = access("/etc/initrd-release", F_OK) >= 0 &&
4104                 statfs("/", &s) >= 0 &&
4105                 is_temporary_fs(&s);
4106
4107         return saved;
4108 }
4109
4110 int get_home_dir(char **_h) {
4111         struct passwd *p;
4112         const char *e;
4113         char *h;
4114         uid_t u;
4115
4116         assert(_h);
4117
4118         /* Take the user specified one */
4119         e = secure_getenv("HOME");
4120         if (e && path_is_absolute(e)) {
4121                 h = strdup(e);
4122                 if (!h)
4123                         return -ENOMEM;
4124
4125                 *_h = h;
4126                 return 0;
4127         }
4128
4129         /* Hardcode home directory for root to avoid NSS */
4130         u = getuid();
4131         if (u == 0) {
4132                 h = strdup("/root");
4133                 if (!h)
4134                         return -ENOMEM;
4135
4136                 *_h = h;
4137                 return 0;
4138         }
4139
4140         /* Check the database... */
4141         errno = 0;
4142         p = getpwuid(u);
4143         if (!p)
4144                 return errno > 0 ? -errno : -ESRCH;
4145
4146         if (!path_is_absolute(p->pw_dir))
4147                 return -EINVAL;
4148
4149         h = strdup(p->pw_dir);
4150         if (!h)
4151                 return -ENOMEM;
4152
4153         *_h = h;
4154         return 0;
4155 }
4156
4157 /// UNNEEDED by elogind
4158 #if 0
4159 int get_shell(char **_s) {
4160         struct passwd *p;
4161         const char *e;
4162         char *s;
4163         uid_t u;
4164
4165         assert(_s);
4166
4167         /* Take the user specified one */
4168         e = getenv("SHELL");
4169         if (e) {
4170                 s = strdup(e);
4171                 if (!s)
4172                         return -ENOMEM;
4173
4174                 *_s = s;
4175                 return 0;
4176         }
4177
4178         /* Hardcode home directory for root to avoid NSS */
4179         u = getuid();
4180         if (u == 0) {
4181                 s = strdup("/bin/sh");
4182                 if (!s)
4183                         return -ENOMEM;
4184
4185                 *_s = s;
4186                 return 0;
4187         }
4188
4189         /* Check the database... */
4190         errno = 0;
4191         p = getpwuid(u);
4192         if (!p)
4193                 return errno > 0 ? -errno : -ESRCH;
4194
4195         if (!path_is_absolute(p->pw_shell))
4196                 return -EINVAL;
4197
4198         s = strdup(p->pw_shell);
4199         if (!s)
4200                 return -ENOMEM;
4201
4202         *_s = s;
4203         return 0;
4204 }
4205 #endif // 0
4206
4207 bool filename_is_valid(const char *p) {
4208
4209         if (isempty(p))
4210                 return false;
4211
4212         if (strchr(p, '/'))
4213                 return false;
4214
4215         if (streq(p, "."))
4216                 return false;
4217
4218         if (streq(p, ".."))
4219                 return false;
4220
4221         if (strlen(p) > FILENAME_MAX)
4222                 return false;
4223
4224         return true;
4225 }
4226
4227 bool string_is_safe(const char *p) {
4228         const char *t;
4229
4230         if (!p)
4231                 return false;
4232
4233         for (t = p; *t; t++) {
4234                 if (*t > 0 && *t < ' ')
4235                         return false;
4236
4237                 if (strchr("\\\"\'\x7f", *t))
4238                         return false;
4239         }
4240
4241         return true;
4242 }
4243
4244 /**
4245  * Check if a string contains control characters. If 'ok' is non-NULL
4246  * it may be a string containing additional CCs to be considered OK.
4247  */
4248 bool string_has_cc(const char *p, const char *ok) {
4249         const char *t;
4250
4251         assert(p);
4252
4253         for (t = p; *t; t++) {
4254                 if (ok && strchr(ok, *t))
4255                         continue;
4256
4257                 if (*t > 0 && *t < ' ')
4258                         return true;
4259
4260                 if (*t == 127)
4261                         return true;
4262         }
4263
4264         return false;
4265 }
4266
4267 bool path_is_safe(const char *p) {
4268
4269         if (isempty(p))
4270                 return false;
4271
4272         if (streq(p, "..") || startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../"))
4273                 return false;
4274
4275         if (strlen(p)+1 > PATH_MAX)
4276                 return false;
4277
4278         /* The following two checks are not really dangerous, but hey, they still are confusing */
4279         if (streq(p, ".") || startswith(p, "./") || endswith(p, "/.") || strstr(p, "/./"))
4280                 return false;
4281
4282         if (strstr(p, "//"))
4283                 return false;
4284
4285         return true;
4286 }
4287
4288 /// UNNEEDED by elogind
4289 #if 0
4290 /* hey glibc, APIs with callbacks without a user pointer are so useless */
4291 void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
4292                  int (*compar) (const void *, const void *, void *), void *arg) {
4293         size_t l, u, idx;
4294         const void *p;
4295         int comparison;
4296
4297         l = 0;
4298         u = nmemb;
4299         while (l < u) {
4300                 idx = (l + u) / 2;
4301                 p = (void *)(((const char *) base) + (idx * size));
4302                 comparison = compar(key, p, arg);
4303                 if (comparison < 0)
4304                         u = idx;
4305                 else if (comparison > 0)
4306                         l = idx + 1;
4307                 else
4308                         return (void *)p;
4309         }
4310         return NULL;
4311 }
4312
4313 void init_gettext(void) {
4314         setlocale(LC_ALL, "");
4315         textdomain(GETTEXT_PACKAGE);
4316 }
4317 #endif // 0
4318
4319 bool is_locale_utf8(void) {
4320         const char *set;
4321         static int cached_answer = -1;
4322
4323         if (cached_answer >= 0)
4324                 goto out;
4325
4326         if (!setlocale(LC_ALL, "")) {
4327                 cached_answer = true;
4328                 goto out;
4329         }
4330
4331         set = nl_langinfo(CODESET);
4332         if (!set) {
4333                 cached_answer = true;
4334                 goto out;
4335         }
4336
4337         if (streq(set, "UTF-8")) {
4338                 cached_answer = true;
4339                 goto out;
4340         }
4341
4342         /* For LC_CTYPE=="C" return true, because CTYPE is effectly
4343          * unset and everything can do to UTF-8 nowadays. */
4344         set = setlocale(LC_CTYPE, NULL);
4345         if (!set) {
4346                 cached_answer = true;
4347                 goto out;
4348         }
4349
4350         /* Check result, but ignore the result if C was set
4351          * explicitly. */
4352         cached_answer =
4353                 STR_IN_SET(set, "C", "POSIX") &&
4354                 !getenv("LC_ALL") &&
4355                 !getenv("LC_CTYPE") &&
4356                 !getenv("LANG");
4357
4358 out:
4359         return (bool) cached_answer;
4360 }
4361
4362 const char *draw_special_char(DrawSpecialChar ch) {
4363         static const char *draw_table[2][_DRAW_SPECIAL_CHAR_MAX] = {
4364
4365                 /* UTF-8 */ {
4366                         [DRAW_TREE_VERTICAL]      = "\342\224\202 ",            /* │  */
4367                         [DRAW_TREE_BRANCH]        = "\342\224\234\342\224\200", /* ├─ */
4368                         [DRAW_TREE_RIGHT]         = "\342\224\224\342\224\200", /* └─ */
4369                         [DRAW_TREE_SPACE]         = "  ",                       /*    */
4370                         [DRAW_TRIANGULAR_BULLET]  = "\342\200\243",             /* ‣ */
4371                         [DRAW_BLACK_CIRCLE]       = "\342\227\217",             /* ● */
4372                         [DRAW_ARROW]              = "\342\206\222",             /* → */
4373                         [DRAW_DASH]               = "\342\200\223",             /* – */
4374                 },
4375
4376                 /* ASCII fallback */ {
4377                         [DRAW_TREE_VERTICAL]      = "| ",
4378                         [DRAW_TREE_BRANCH]        = "|-",
4379                         [DRAW_TREE_RIGHT]         = "`-",
4380                         [DRAW_TREE_SPACE]         = "  ",
4381                         [DRAW_TRIANGULAR_BULLET]  = ">",
4382                         [DRAW_BLACK_CIRCLE]       = "*",
4383                         [DRAW_ARROW]              = "->",
4384                         [DRAW_DASH]               = "-",
4385                 }
4386         };
4387
4388         return draw_table[!is_locale_utf8()][ch];
4389 }
4390
4391 /// UNNEEDED by elogind
4392 #if 0
4393 char *strreplace(const char *text, const char *old_string, const char *new_string) {
4394         const char *f;
4395         char *t, *r;
4396         size_t l, old_len, new_len;
4397
4398         assert(text);
4399         assert(old_string);
4400         assert(new_string);
4401
4402         old_len = strlen(old_string);
4403         new_len = strlen(new_string);
4404
4405         l = strlen(text);
4406         r = new(char, l+1);
4407         if (!r)
4408                 return NULL;
4409
4410         f = text;
4411         t = r;
4412         while (*f) {
4413                 char *a;
4414                 size_t d, nl;
4415
4416                 if (!startswith(f, old_string)) {
4417                         *(t++) = *(f++);
4418                         continue;
4419                 }
4420
4421                 d = t - r;
4422                 nl = l - old_len + new_len;
4423                 a = realloc(r, nl + 1);
4424                 if (!a)
4425                         goto oom;
4426
4427                 l = nl;
4428                 r = a;
4429                 t = r + d;
4430
4431                 t = stpcpy(t, new_string);
4432                 f += old_len;
4433         }
4434
4435         *t = 0;
4436         return r;
4437
4438 oom:
4439         free(r);
4440         return NULL;
4441 }
4442
4443 char *strip_tab_ansi(char **ibuf, size_t *_isz) {
4444         const char *i, *begin = NULL;
4445         enum {
4446                 STATE_OTHER,
4447                 STATE_ESCAPE,
4448                 STATE_BRACKET
4449         } state = STATE_OTHER;
4450         char *obuf = NULL;
4451         size_t osz = 0, isz;
4452         FILE *f;
4453
4454         assert(ibuf);
4455         assert(*ibuf);
4456
4457         /* Strips ANSI color and replaces TABs by 8 spaces */
4458
4459         isz = _isz ? *_isz : strlen(*ibuf);
4460
4461         f = open_memstream(&obuf, &osz);
4462         if (!f)
4463                 return NULL;
4464
4465         for (i = *ibuf; i < *ibuf + isz + 1; i++) {
4466
4467                 switch (state) {
4468
4469                 case STATE_OTHER:
4470                         if (i >= *ibuf + isz) /* EOT */
4471                                 break;
4472                         else if (*i == '\x1B')
4473                                 state = STATE_ESCAPE;
4474                         else if (*i == '\t')
4475                                 fputs("        ", f);
4476                         else
4477                                 fputc(*i, f);
4478                         break;
4479
4480                 case STATE_ESCAPE:
4481                         if (i >= *ibuf + isz) { /* EOT */
4482                                 fputc('\x1B', f);
4483                                 break;
4484                         } else if (*i == '[') {
4485                                 state = STATE_BRACKET;
4486                                 begin = i + 1;
4487                         } else {
4488                                 fputc('\x1B', f);
4489                                 fputc(*i, f);
4490                                 state = STATE_OTHER;
4491                         }
4492
4493                         break;
4494
4495                 case STATE_BRACKET:
4496
4497                         if (i >= *ibuf + isz || /* EOT */
4498                             (!(*i >= '0' && *i <= '9') && *i != ';' && *i != 'm')) {
4499                                 fputc('\x1B', f);
4500                                 fputc('[', f);
4501                                 state = STATE_OTHER;
4502                                 i = begin-1;
4503                         } else if (*i == 'm')
4504                                 state = STATE_OTHER;
4505                         break;
4506                 }
4507         }
4508
4509         if (ferror(f)) {
4510                 fclose(f);
4511                 free(obuf);
4512                 return NULL;
4513         }
4514
4515         fclose(f);
4516
4517         free(*ibuf);
4518         *ibuf = obuf;
4519
4520         if (_isz)
4521                 *_isz = osz;
4522
4523         return obuf;
4524 }
4525
4526 int on_ac_power(void) {
4527         bool found_offline = false, found_online = false;
4528         _cleanup_closedir_ DIR *d = NULL;
4529
4530         d = opendir("/sys/class/power_supply");
4531         if (!d)
4532                 return errno == ENOENT ? true : -errno;
4533
4534         for (;;) {
4535                 struct dirent *de;
4536                 _cleanup_close_ int fd = -1, device = -1;
4537                 char contents[6];
4538                 ssize_t n;
4539
4540                 errno = 0;
4541                 de = readdir(d);
4542                 if (!de && errno != 0)
4543                         return -errno;
4544
4545                 if (!de)
4546                         break;
4547
4548                 if (hidden_file(de->d_name))
4549                         continue;
4550
4551                 device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY);
4552                 if (device < 0) {
4553                         if (errno == ENOENT || errno == ENOTDIR)
4554                                 continue;
4555
4556                         return -errno;
4557                 }
4558
4559                 fd = openat(device, "type", O_RDONLY|O_CLOEXEC|O_NOCTTY);
4560                 if (fd < 0) {
4561                         if (errno == ENOENT)
4562                                 continue;
4563
4564                         return -errno;
4565                 }
4566
4567                 n = read(fd, contents, sizeof(contents));
4568                 if (n < 0)
4569                         return -errno;
4570
4571                 if (n != 6 || memcmp(contents, "Mains\n", 6))
4572                         continue;
4573
4574                 safe_close(fd);
4575                 fd = openat(device, "online", O_RDONLY|O_CLOEXEC|O_NOCTTY);
4576                 if (fd < 0) {
4577                         if (errno == ENOENT)
4578                                 continue;
4579
4580                         return -errno;
4581                 }
4582
4583                 n = read(fd, contents, sizeof(contents));
4584                 if (n < 0)
4585                         return -errno;
4586
4587                 if (n != 2 || contents[1] != '\n')
4588                         return -EIO;
4589
4590                 if (contents[0] == '1') {
4591                         found_online = true;
4592                         break;
4593                 } else if (contents[0] == '0')
4594                         found_offline = true;
4595                 else
4596                         return -EIO;
4597         }
4598
4599         return found_online || !found_offline;
4600 }
4601 #endif // 0
4602
4603 static int search_and_fopen_internal(const char *path, const char *mode, const char *root, char **search, FILE **_f) {
4604         char **i;
4605
4606         assert(path);
4607         assert(mode);
4608         assert(_f);
4609
4610         if (!path_strv_resolve_uniq(search, root))
4611                 return -ENOMEM;
4612
4613         STRV_FOREACH(i, search) {
4614                 _cleanup_free_ char *p = NULL;
4615                 FILE *f;
4616
4617                 if (root)
4618                         p = strjoin(root, *i, "/", path, NULL);
4619                 else
4620                         p = strjoin(*i, "/", path, NULL);
4621                 if (!p)
4622                         return -ENOMEM;
4623
4624                 f = fopen(p, mode);
4625                 if (f) {
4626                         *_f = f;
4627                         return 0;
4628                 }
4629
4630                 if (errno != ENOENT)
4631                         return -errno;
4632         }
4633
4634         return -ENOENT;
4635 }
4636
4637 int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f) {
4638         _cleanup_strv_free_ char **copy = NULL;
4639
4640         assert(path);
4641         assert(mode);
4642         assert(_f);
4643
4644         if (path_is_absolute(path)) {
4645                 FILE *f;
4646
4647                 f = fopen(path, mode);
4648                 if (f) {
4649                         *_f = f;
4650                         return 0;
4651                 }
4652
4653                 return -errno;
4654         }
4655
4656         copy = strv_copy((char**) search);
4657         if (!copy)
4658                 return -ENOMEM;
4659
4660         return search_and_fopen_internal(path, mode, root, copy, _f);
4661 }
4662
4663 /// UNNEEDED by elogind
4664 #if 0
4665 int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f) {
4666         _cleanup_strv_free_ char **s = NULL;
4667
4668         if (path_is_absolute(path)) {
4669                 FILE *f;
4670
4671                 f = fopen(path, mode);
4672                 if (f) {
4673                         *_f = f;
4674                         return 0;
4675                 }
4676
4677                 return -errno;
4678         }
4679
4680         s = strv_split_nulstr(search);
4681         if (!s)
4682                 return -ENOMEM;
4683
4684         return search_and_fopen_internal(path, mode, root, s, _f);
4685 }
4686 #endif // 0
4687
4688 char *strextend(char **x, ...) {
4689         va_list ap;
4690         size_t f, l;
4691         char *r, *p;
4692
4693         assert(x);
4694
4695         l = f = *x ? strlen(*x) : 0;
4696
4697         va_start(ap, x);
4698         for (;;) {
4699                 const char *t;
4700                 size_t n;
4701
4702                 t = va_arg(ap, const char *);
4703                 if (!t)
4704                         break;
4705
4706                 n = strlen(t);
4707                 if (n > ((size_t) -1) - l) {
4708                         va_end(ap);
4709                         return NULL;
4710                 }
4711
4712                 l += n;
4713         }
4714         va_end(ap);
4715
4716         r = realloc(*x, l+1);
4717         if (!r)
4718                 return NULL;
4719
4720         p = r + f;
4721
4722         va_start(ap, x);
4723         for (;;) {
4724                 const char *t;
4725
4726                 t = va_arg(ap, const char *);
4727                 if (!t)
4728                         break;
4729
4730                 p = stpcpy(p, t);
4731         }
4732         va_end(ap);
4733
4734         *p = 0;
4735         *x = r;
4736
4737         return r + l;
4738 }
4739
4740 char *strrep(const char *s, unsigned n) {
4741         size_t l;
4742         char *r, *p;
4743         unsigned i;
4744
4745         assert(s);
4746
4747         l = strlen(s);
4748         p = r = malloc(l * n + 1);
4749         if (!r)
4750                 return NULL;
4751
4752         for (i = 0; i < n; i++)
4753                 p = stpcpy(p, s);
4754
4755         *p = 0;
4756         return r;
4757 }
4758
4759 void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) {
4760         size_t a, newalloc;
4761         void *q;
4762
4763         assert(p);
4764         assert(allocated);
4765
4766         if (*allocated >= need)
4767                 return *p;
4768
4769         newalloc = MAX(need * 2, 64u / size);
4770         a = newalloc * size;
4771
4772         /* check for overflows */
4773         if (a < size * need)
4774                 return NULL;
4775
4776         q = realloc(*p, a);
4777         if (!q)
4778                 return NULL;
4779
4780         *p = q;
4781         *allocated = newalloc;
4782         return q;
4783 }
4784
4785 void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size) {
4786         size_t prev;
4787         uint8_t *q;
4788
4789         assert(p);
4790         assert(allocated);
4791
4792         prev = *allocated;
4793
4794         q = greedy_realloc(p, allocated, need, size);
4795         if (!q)
4796                 return NULL;
4797
4798         if (*allocated > prev)
4799                 memzero(q + prev * size, (*allocated - prev) * size);
4800
4801         return q;
4802 }
4803
4804 bool id128_is_valid(const char *s) {
4805         size_t i, l;
4806
4807         l = strlen(s);
4808         if (l == 32) {
4809
4810                 /* Simple formatted 128bit hex string */
4811
4812                 for (i = 0; i < l; i++) {
4813                         char c = s[i];
4814
4815                         if (!(c >= '0' && c <= '9') &&
4816                             !(c >= 'a' && c <= 'z') &&
4817                             !(c >= 'A' && c <= 'Z'))
4818                                 return false;
4819                 }
4820
4821         } else if (l == 36) {
4822
4823                 /* Formatted UUID */
4824
4825                 for (i = 0; i < l; i++) {
4826                         char c = s[i];
4827
4828                         if ((i == 8 || i == 13 || i == 18 || i == 23)) {
4829                                 if (c != '-')
4830                                         return false;
4831                         } else {
4832                                 if (!(c >= '0' && c <= '9') &&
4833                                     !(c >= 'a' && c <= 'z') &&
4834                                     !(c >= 'A' && c <= 'Z'))
4835                                         return false;
4836                         }
4837                 }
4838
4839         } else
4840                 return false;
4841
4842         return true;
4843 }
4844
4845 /// UNNEEDED by elogind
4846 #if 0
4847 int split_pair(const char *s, const char *sep, char **l, char **r) {
4848         char *x, *a, *b;
4849
4850         assert(s);
4851         assert(sep);
4852         assert(l);
4853         assert(r);
4854
4855         if (isempty(sep))
4856                 return -EINVAL;
4857
4858         x = strstr(s, sep);
4859         if (!x)
4860                 return -EINVAL;
4861
4862         a = strndup(s, x - s);
4863         if (!a)
4864                 return -ENOMEM;
4865
4866         b = strdup(x + strlen(sep));
4867         if (!b) {
4868                 free(a);
4869                 return -ENOMEM;
4870         }
4871
4872         *l = a;
4873         *r = b;
4874
4875         return 0;
4876 }
4877
4878 int shall_restore_state(void) {
4879         _cleanup_free_ char *value = NULL;
4880         int r;
4881
4882         r = get_proc_cmdline_key("systemd.restore_state=", &value);
4883         if (r < 0)
4884                 return r;
4885         if (r == 0)
4886                 return true;
4887
4888         return parse_boolean(value) != 0;
4889 }
4890 #endif // 0
4891
4892 int proc_cmdline(char **ret) {
4893         assert(ret);
4894
4895         if (detect_container(NULL) > 0)
4896                 return get_process_cmdline(1, 0, false, ret);
4897         else
4898                 return read_one_line_file("/proc/cmdline", ret);
4899 }
4900
4901 int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) {
4902         _cleanup_free_ char *line = NULL;
4903         const char *p;
4904         int r;
4905
4906         assert(parse_item);
4907
4908         r = proc_cmdline(&line);
4909         if (r < 0)
4910                 return r;
4911
4912         p = line;
4913         for (;;) {
4914                 _cleanup_free_ char *word = NULL;
4915                 char *value = NULL;
4916
4917                 r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX);
4918                 if (r < 0)
4919                         return r;
4920                 if (r == 0)
4921                         break;
4922
4923                 /* Filter out arguments that are intended only for the
4924                  * initrd */
4925                 if (!in_initrd() && startswith(word, "rd."))
4926                         continue;
4927
4928                 value = strchr(word, '=');
4929                 if (value)
4930                         *(value++) = 0;
4931
4932                 r = parse_item(word, value);
4933                 if (r < 0)
4934                         return r;
4935         }
4936
4937         return 0;
4938 }
4939
4940 int get_proc_cmdline_key(const char *key, char **value) {
4941         _cleanup_free_ char *line = NULL, *ret = NULL;
4942         bool found = false;
4943         const char *p;
4944         int r;
4945
4946         assert(key);
4947
4948         r = proc_cmdline(&line);
4949         if (r < 0)
4950                 return r;
4951
4952         p = line;
4953         for (;;) {
4954                 _cleanup_free_ char *word = NULL;
4955                 const char *e;
4956
4957                 r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX);
4958                 if (r < 0)
4959                         return r;
4960                 if (r == 0)
4961                         break;
4962
4963                 /* Filter out arguments that are intended only for the
4964                  * initrd */
4965                 if (!in_initrd() && startswith(word, "rd."))
4966                         continue;
4967
4968                 if (value) {
4969                         e = startswith(word, key);
4970                         if (!e)
4971                                 continue;
4972
4973                         r = free_and_strdup(&ret, e);
4974                         if (r < 0)
4975                                 return r;
4976
4977                         found = true;
4978                 } else {
4979                         if (streq(word, key))
4980                                 found = true;
4981                 }
4982         }
4983
4984         if (value) {
4985                 *value = ret;
4986                 ret = NULL;
4987         }
4988
4989         return found;
4990
4991 }
4992
4993 int container_get_leader(const char *machine, pid_t *pid) {
4994         _cleanup_free_ char *s = NULL, *class = NULL;
4995         const char *p;
4996         pid_t leader;
4997         int r;
4998
4999         assert(machine);
5000         assert(pid);
5001
5002         if (!machine_name_is_valid(machine))
5003                 return -EINVAL;
5004
5005         p = strjoina("/run/systemd/machines/", machine);
5006         r = parse_env_file(p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL);
5007         if (r == -ENOENT)
5008                 return -EHOSTDOWN;
5009         if (r < 0)
5010                 return r;
5011         if (!s)
5012                 return -EIO;
5013
5014         if (!streq_ptr(class, "container"))
5015                 return -EIO;
5016
5017         r = parse_pid(s, &leader);
5018         if (r < 0)
5019                 return r;
5020         if (leader <= 1)
5021                 return -EIO;
5022
5023         *pid = leader;
5024         return 0;
5025 }
5026
5027 int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd) {
5028         _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, netnsfd = -1, usernsfd = -1;
5029         int rfd = -1;
5030
5031         assert(pid >= 0);
5032
5033         if (mntns_fd) {
5034                 const char *mntns;
5035
5036                 mntns = procfs_file_alloca(pid, "ns/mnt");
5037                 mntnsfd = open(mntns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
5038                 if (mntnsfd < 0)
5039                         return -errno;
5040         }
5041
5042         if (pidns_fd) {
5043                 const char *pidns;
5044
5045                 pidns = procfs_file_alloca(pid, "ns/pid");
5046                 pidnsfd = open(pidns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
5047                 if (pidnsfd < 0)
5048                         return -errno;
5049         }
5050
5051         if (netns_fd) {
5052                 const char *netns;
5053
5054                 netns = procfs_file_alloca(pid, "ns/net");
5055                 netnsfd = open(netns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
5056                 if (netnsfd < 0)
5057                         return -errno;
5058         }
5059
5060         if (userns_fd) {
5061                 const char *userns;
5062
5063                 userns = procfs_file_alloca(pid, "ns/user");
5064                 usernsfd = open(userns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
5065                 if (usernsfd < 0 && errno != ENOENT)
5066                         return -errno;
5067         }
5068
5069         if (root_fd) {
5070                 const char *root;
5071
5072                 root = procfs_file_alloca(pid, "root");
5073                 rfd = open(root, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
5074                 if (rfd < 0)
5075                         return -errno;
5076         }
5077
5078         if (pidns_fd)
5079                 *pidns_fd = pidnsfd;
5080
5081         if (mntns_fd)
5082                 *mntns_fd = mntnsfd;
5083
5084         if (netns_fd)
5085                 *netns_fd = netnsfd;
5086
5087         if (userns_fd)
5088                 *userns_fd = usernsfd;
5089
5090         if (root_fd)
5091                 *root_fd = rfd;
5092
5093         pidnsfd = mntnsfd = netnsfd = usernsfd = -1;
5094
5095         return 0;
5096 }
5097
5098 int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd) {
5099         if (userns_fd >= 0) {
5100                 /* Can't setns to your own userns, since then you could
5101                  * escalate from non-root to root in your own namespace, so
5102                  * check if namespaces equal before attempting to enter. */
5103                 _cleanup_free_ char *userns_fd_path = NULL;
5104                 int r;
5105                 if (asprintf(&userns_fd_path, "/proc/self/fd/%d", userns_fd) < 0)
5106                         return -ENOMEM;
5107
5108                 r = files_same(userns_fd_path, "/proc/self/ns/user");
5109                 if (r < 0)
5110                         return r;
5111                 if (r)
5112                         userns_fd = -1;
5113         }
5114
5115         if (pidns_fd >= 0)
5116                 if (setns(pidns_fd, CLONE_NEWPID) < 0)
5117                         return -errno;
5118
5119         if (mntns_fd >= 0)
5120                 if (setns(mntns_fd, CLONE_NEWNS) < 0)
5121                         return -errno;
5122
5123         if (netns_fd >= 0)
5124                 if (setns(netns_fd, CLONE_NEWNET) < 0)
5125                         return -errno;
5126
5127         if (userns_fd >= 0)
5128                 if (setns(userns_fd, CLONE_NEWUSER) < 0)
5129                         return -errno;
5130
5131         if (root_fd >= 0) {
5132                 if (fchdir(root_fd) < 0)
5133                         return -errno;
5134
5135                 if (chroot(".") < 0)
5136                         return -errno;
5137         }
5138
5139         return reset_uid_gid();
5140 }
5141
5142 int getpeercred(int fd, struct ucred *ucred) {
5143         socklen_t n = sizeof(struct ucred);
5144         struct ucred u;
5145         int r;
5146
5147         assert(fd >= 0);
5148         assert(ucred);
5149
5150         r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &u, &n);
5151         if (r < 0)
5152                 return -errno;
5153
5154         if (n != sizeof(struct ucred))
5155                 return -EIO;
5156
5157         /* Check if the data is actually useful and not suppressed due
5158          * to namespacing issues */
5159         if (u.pid <= 0)
5160                 return -ENODATA;
5161         if (u.uid == UID_INVALID)
5162                 return -ENODATA;
5163         if (u.gid == GID_INVALID)
5164                 return -ENODATA;
5165
5166         *ucred = u;
5167         return 0;
5168 }
5169
5170 int getpeersec(int fd, char **ret) {
5171         socklen_t n = 64;
5172         char *s;
5173         int r;
5174
5175         assert(fd >= 0);
5176         assert(ret);
5177
5178         s = new0(char, n);
5179         if (!s)
5180                 return -ENOMEM;
5181
5182         r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
5183         if (r < 0) {
5184                 free(s);
5185
5186                 if (errno != ERANGE)
5187                         return -errno;
5188
5189                 s = new0(char, n);
5190                 if (!s)
5191                         return -ENOMEM;
5192
5193                 r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
5194                 if (r < 0) {
5195                         free(s);
5196                         return -errno;
5197                 }
5198         }
5199
5200         if (isempty(s)) {
5201                 free(s);
5202                 return -EOPNOTSUPP;
5203         }
5204
5205         *ret = s;
5206         return 0;
5207 }
5208
5209 /* This is much like like mkostemp() but is subject to umask(). */
5210 int mkostemp_safe(char *pattern, int flags) {
5211         _cleanup_umask_ mode_t u;
5212         int fd;
5213
5214         assert(pattern);
5215
5216         u = umask(077);
5217
5218         fd = mkostemp(pattern, flags);
5219         if (fd < 0)
5220                 return -errno;
5221
5222         return fd;
5223 }
5224
5225 /// UNNEEDED by elogind
5226 #if 0
5227 int open_tmpfile(const char *path, int flags) {
5228         char *p;
5229         int fd;
5230
5231         assert(path);
5232
5233 #ifdef O_TMPFILE
5234         /* Try O_TMPFILE first, if it is supported */
5235         fd = open(path, flags|O_TMPFILE|O_EXCL, S_IRUSR|S_IWUSR);
5236         if (fd >= 0)
5237                 return fd;
5238 #endif
5239
5240         /* Fall back to unguessable name + unlinking */
5241         p = strjoina(path, "/systemd-tmp-XXXXXX");
5242
5243         fd = mkostemp_safe(p, flags);
5244         if (fd < 0)
5245                 return fd;
5246
5247         unlink(p);
5248         return fd;
5249 }
5250 #endif // 0
5251
5252 int fd_warn_permissions(const char *path, int fd) {
5253         struct stat st;
5254
5255         if (fstat(fd, &st) < 0)
5256                 return -errno;
5257
5258         if (st.st_mode & 0111)
5259                 log_warning("Configuration file %s is marked executable. Please remove executable permission bits. Proceeding anyway.", path);
5260
5261         if (st.st_mode & 0002)
5262                 log_warning("Configuration file %s is marked world-writable. Please remove world writability permission bits. Proceeding anyway.", path);
5263
5264         if (getpid() == 1 && (st.st_mode & 0044) != 0044)
5265                 log_warning("Configuration file %s is marked world-inaccessible. This has no effect as configuration data is accessible via APIs without restrictions. Proceeding anyway.", path);
5266
5267         return 0;
5268 }
5269
5270 /// UNNEEDED by elogind
5271 #if 0
5272 unsigned long personality_from_string(const char *p) {
5273
5274         /* Parse a personality specifier. We introduce our own
5275          * identifiers that indicate specific ABIs, rather than just
5276          * hints regarding the register size, since we want to keep
5277          * things open for multiple locally supported ABIs for the
5278          * same register size. We try to reuse the ABI identifiers
5279          * used by libseccomp. */
5280
5281 #if defined(__x86_64__)
5282
5283         if (streq(p, "x86"))
5284                 return PER_LINUX32;
5285
5286         if (streq(p, "x86-64"))
5287                 return PER_LINUX;
5288
5289 #elif defined(__i386__)
5290
5291         if (streq(p, "x86"))
5292                 return PER_LINUX;
5293 #endif
5294
5295         return PERSONALITY_INVALID;
5296 }
5297
5298 const char* personality_to_string(unsigned long p) {
5299
5300 #if defined(__x86_64__)
5301
5302         if (p == PER_LINUX32)
5303                 return "x86";
5304
5305         if (p == PER_LINUX)
5306                 return "x86-64";
5307
5308 #elif defined(__i386__)
5309
5310         if (p == PER_LINUX)
5311                 return "x86";
5312 #endif
5313
5314         return NULL;
5315 }
5316 #endif // 0
5317
5318 uint64_t physical_memory(void) {
5319         long mem;
5320
5321         /* We return this as uint64_t in case we are running as 32bit
5322          * process on a 64bit kernel with huge amounts of memory */
5323
5324         mem = sysconf(_SC_PHYS_PAGES);
5325         assert(mem > 0);
5326
5327         return (uint64_t) mem * (uint64_t) page_size();
5328 }
5329
5330 /// UNNEEDED by elogind
5331 #if 0
5332 void hexdump(FILE *f, const void *p, size_t s) {
5333         const uint8_t *b = p;
5334         unsigned n = 0;
5335
5336         assert(s == 0 || b);
5337
5338         while (s > 0) {
5339                 size_t i;
5340
5341                 fprintf(f, "%04x  ", n);
5342
5343                 for (i = 0; i < 16; i++) {
5344
5345                         if (i >= s)
5346                                 fputs("   ", f);
5347                         else
5348                                 fprintf(f, "%02x ", b[i]);
5349
5350                         if (i == 7)
5351                                 fputc(' ', f);
5352                 }
5353
5354                 fputc(' ', f);
5355
5356                 for (i = 0; i < 16; i++) {
5357
5358                         if (i >= s)
5359                                 fputc(' ', f);
5360                         else
5361                                 fputc(isprint(b[i]) ? (char) b[i] : '.', f);
5362                 }
5363
5364                 fputc('\n', f);
5365
5366                 if (s < 16)
5367                         break;
5368
5369                 n += 16;
5370                 b += 16;
5371                 s -= 16;
5372         }
5373 }
5374
5375 int update_reboot_param_file(const char *param) {
5376         int r = 0;
5377
5378         if (param) {
5379
5380                 r = write_string_file(REBOOT_PARAM_FILE, param, WRITE_STRING_FILE_CREATE);
5381                 if (r < 0)
5382                         log_error("Failed to write reboot param to "
5383                                   REBOOT_PARAM_FILE": %s", strerror(-r));
5384         } else
5385                 unlink(REBOOT_PARAM_FILE);
5386
5387         return r;
5388 }
5389
5390 int umount_recursive(const char *prefix, int flags) {
5391         bool again;
5392         int n = 0, r;
5393
5394         /* Try to umount everything recursively below a
5395          * directory. Also, take care of stacked mounts, and keep
5396          * unmounting them until they are gone. */
5397
5398         do {
5399                 _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
5400
5401                 again = false;
5402                 r = 0;
5403
5404                 proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
5405                 if (!proc_self_mountinfo)
5406                         return -errno;
5407
5408                 for (;;) {
5409                         _cleanup_free_ char *path = NULL, *p = NULL;
5410                         int k;
5411
5412                         k = fscanf(proc_self_mountinfo,
5413                                    "%*s "       /* (1) mount id */
5414                                    "%*s "       /* (2) parent id */
5415                                    "%*s "       /* (3) major:minor */
5416                                    "%*s "       /* (4) root */
5417                                    "%ms "       /* (5) mount point */
5418                                    "%*s"        /* (6) mount options */
5419                                    "%*[^-]"     /* (7) optional fields */
5420                                    "- "         /* (8) separator */
5421                                    "%*s "       /* (9) file system type */
5422                                    "%*s"        /* (10) mount source */
5423                                    "%*s"        /* (11) mount options 2 */
5424                                    "%*[^\n]",   /* some rubbish at the end */
5425                                    &path);
5426                         if (k != 1) {
5427                                 if (k == EOF)
5428                                         break;
5429
5430                                 continue;
5431                         }
5432
5433                         r = cunescape(path, UNESCAPE_RELAX, &p);
5434                         if (r < 0)
5435                                 return r;
5436
5437                         if (!path_startswith(p, prefix))
5438                                 continue;
5439
5440                         if (umount2(p, flags) < 0) {
5441                                 r = -errno;
5442                                 continue;
5443                         }
5444
5445                         again = true;
5446                         n++;
5447
5448                         break;
5449                 }
5450
5451         } while (again);
5452
5453         return r ? r : n;
5454 }
5455
5456 static int get_mount_flags(const char *path, unsigned long *flags) {
5457         struct statvfs buf;
5458
5459         if (statvfs(path, &buf) < 0)
5460                 return -errno;
5461         *flags = buf.f_flag;
5462         return 0;
5463 }
5464
5465 int bind_remount_recursive(const char *prefix, bool ro) {
5466         _cleanup_set_free_free_ Set *done = NULL;
5467         _cleanup_free_ char *cleaned = NULL;
5468         int r;
5469
5470         /* Recursively remount a directory (and all its submounts)
5471          * read-only or read-write. If the directory is already
5472          * mounted, we reuse the mount and simply mark it
5473          * MS_BIND|MS_RDONLY (or remove the MS_RDONLY for read-write
5474          * operation). If it isn't we first make it one. Afterwards we
5475          * apply MS_BIND|MS_RDONLY (or remove MS_RDONLY) to all
5476          * submounts we can access, too. When mounts are stacked on
5477          * the same mount point we only care for each individual
5478          * "top-level" mount on each point, as we cannot
5479          * influence/access the underlying mounts anyway. We do not
5480          * have any effect on future submounts that might get
5481          * propagated, they migt be writable. This includes future
5482          * submounts that have been triggered via autofs. */
5483
5484         cleaned = strdup(prefix);
5485         if (!cleaned)
5486                 return -ENOMEM;
5487
5488         path_kill_slashes(cleaned);
5489
5490         done = set_new(&string_hash_ops);
5491         if (!done)
5492                 return -ENOMEM;
5493
5494         for (;;) {
5495                 _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
5496                 _cleanup_set_free_free_ Set *todo = NULL;
5497                 bool top_autofs = false;
5498                 char *x;
5499                 unsigned long orig_flags;
5500
5501                 todo = set_new(&string_hash_ops);
5502                 if (!todo)
5503                         return -ENOMEM;
5504
5505                 proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
5506                 if (!proc_self_mountinfo)
5507                         return -errno;
5508
5509                 for (;;) {
5510                         _cleanup_free_ char *path = NULL, *p = NULL, *type = NULL;
5511                         int k;
5512
5513                         k = fscanf(proc_self_mountinfo,
5514                                    "%*s "       /* (1) mount id */
5515                                    "%*s "       /* (2) parent id */
5516                                    "%*s "       /* (3) major:minor */
5517                                    "%*s "       /* (4) root */
5518                                    "%ms "       /* (5) mount point */
5519                                    "%*s"        /* (6) mount options (superblock) */
5520                                    "%*[^-]"     /* (7) optional fields */
5521                                    "- "         /* (8) separator */
5522                                    "%ms "       /* (9) file system type */
5523                                    "%*s"        /* (10) mount source */
5524                                    "%*s"        /* (11) mount options (bind mount) */
5525                                    "%*[^\n]",   /* some rubbish at the end */
5526                                    &path,
5527                                    &type);
5528                         if (k != 2) {
5529                                 if (k == EOF)
5530                                         break;
5531
5532                                 continue;
5533                         }
5534
5535                         r = cunescape(path, UNESCAPE_RELAX, &p);
5536                         if (r < 0)
5537                                 return r;
5538
5539                         /* Let's ignore autofs mounts.  If they aren't
5540                          * triggered yet, we want to avoid triggering
5541                          * them, as we don't make any guarantees for
5542                          * future submounts anyway.  If they are
5543                          * already triggered, then we will find
5544                          * another entry for this. */
5545                         if (streq(type, "autofs")) {
5546                                 top_autofs = top_autofs || path_equal(cleaned, p);
5547                                 continue;
5548                         }
5549
5550                         if (path_startswith(p, cleaned) &&
5551                             !set_contains(done, p)) {
5552
5553                                 r = set_consume(todo, p);
5554                                 p = NULL;
5555
5556                                 if (r == -EEXIST)
5557                                         continue;
5558                                 if (r < 0)
5559                                         return r;
5560                         }
5561                 }
5562
5563                 /* If we have no submounts to process anymore and if
5564                  * the root is either already done, or an autofs, we
5565                  * are done */
5566                 if (set_isempty(todo) &&
5567                     (top_autofs || set_contains(done, cleaned)))
5568                         return 0;
5569
5570                 if (!set_contains(done, cleaned) &&
5571                     !set_contains(todo, cleaned)) {
5572                         /* The prefix directory itself is not yet a
5573                          * mount, make it one. */
5574                         if (mount(cleaned, cleaned, NULL, MS_BIND|MS_REC, NULL) < 0)
5575                                 return -errno;
5576
5577                         orig_flags = 0;
5578                         (void) get_mount_flags(cleaned, &orig_flags);
5579                         orig_flags &= ~MS_RDONLY;
5580
5581                         if (mount(NULL, prefix, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0)
5582                                 return -errno;
5583
5584                         x = strdup(cleaned);
5585                         if (!x)
5586                                 return -ENOMEM;
5587
5588                         r = set_consume(done, x);
5589                         if (r < 0)
5590                                 return r;
5591                 }
5592
5593                 while ((x = set_steal_first(todo))) {
5594
5595                         r = set_consume(done, x);
5596                         if (r == -EEXIST || r == 0)
5597                                 continue;
5598                         if (r < 0)
5599                                 return r;
5600
5601                         /* Try to reuse the original flag set, but
5602                          * don't care for errors, in case of
5603                          * obstructed mounts */
5604                         orig_flags = 0;
5605                         (void) get_mount_flags(x, &orig_flags);
5606                         orig_flags &= ~MS_RDONLY;
5607
5608                         if (mount(NULL, x, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0) {
5609
5610                                 /* Deal with mount points that are
5611                                  * obstructed by a later mount */
5612
5613                                 if (errno != ENOENT)
5614                                         return -errno;
5615                         }
5616
5617                 }
5618         }
5619 }
5620 #endif // 0
5621
5622 int fflush_and_check(FILE *f) {
5623         assert(f);
5624
5625         errno = 0;
5626         fflush(f);
5627
5628         if (ferror(f))
5629                 return errno ? -errno : -EIO;
5630
5631         return 0;
5632 }
5633
5634 int tempfn_xxxxxx(const char *p, const char *extra, char **ret) {
5635         const char *fn;
5636         char *t;
5637
5638         assert(p);
5639         assert(ret);
5640
5641         /*
5642          * Turns this:
5643          *         /foo/bar/waldo
5644          *
5645          * Into this:
5646          *         /foo/bar/.#<extra>waldoXXXXXX
5647          */
5648
5649         fn = basename(p);
5650         if (!filename_is_valid(fn))
5651                 return -EINVAL;
5652
5653         if (extra == NULL)
5654                 extra = "";
5655
5656         t = new(char, strlen(p) + 2 + strlen(extra) + 6 + 1);
5657         if (!t)
5658                 return -ENOMEM;
5659
5660         strcpy(stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), extra), fn), "XXXXXX");
5661
5662         *ret = path_kill_slashes(t);
5663         return 0;
5664 }
5665
5666 int tempfn_random(const char *p, const char *extra, char **ret) {
5667         const char *fn;
5668         char *t, *x;
5669         uint64_t u;
5670         unsigned i;
5671
5672         assert(p);
5673         assert(ret);
5674
5675         /*
5676          * Turns this:
5677          *         /foo/bar/waldo
5678          *
5679          * Into this:
5680          *         /foo/bar/.#<extra>waldobaa2a261115984a9
5681          */
5682
5683         fn = basename(p);
5684         if (!filename_is_valid(fn))
5685                 return -EINVAL;
5686
5687         if (!extra)
5688                 extra = "";
5689
5690         t = new(char, strlen(p) + 2 + strlen(extra) + 16 + 1);
5691         if (!t)
5692                 return -ENOMEM;
5693
5694         x = stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), extra), fn);
5695
5696         u = random_u64();
5697         for (i = 0; i < 16; i++) {
5698                 *(x++) = hexchar(u & 0xF);
5699                 u >>= 4;
5700         }
5701
5702         *x = 0;
5703
5704         *ret = path_kill_slashes(t);
5705         return 0;
5706 }
5707
5708 /// UNNEEDED by elogind
5709 #if 0
5710 int tempfn_random_child(const char *p, const char *extra, char **ret) {
5711         char *t, *x;
5712         uint64_t u;
5713         unsigned i;
5714
5715         assert(p);
5716         assert(ret);
5717
5718         /* Turns this:
5719          *         /foo/bar/waldo
5720          * Into this:
5721          *         /foo/bar/waldo/.#<extra>3c2b6219aa75d7d0
5722          */
5723
5724         if (!extra)
5725                 extra = "";
5726
5727         t = new(char, strlen(p) + 3 + strlen(extra) + 16 + 1);
5728         if (!t)
5729                 return -ENOMEM;
5730
5731         x = stpcpy(stpcpy(stpcpy(t, p), "/.#"), extra);
5732
5733         u = random_u64();
5734         for (i = 0; i < 16; i++) {
5735                 *(x++) = hexchar(u & 0xF);
5736                 u >>= 4;
5737         }
5738
5739         *x = 0;
5740
5741         *ret = path_kill_slashes(t);
5742         return 0;
5743 }
5744
5745 int take_password_lock(const char *root) {
5746
5747         struct flock flock = {
5748                 .l_type = F_WRLCK,
5749                 .l_whence = SEEK_SET,
5750                 .l_start = 0,
5751                 .l_len = 0,
5752         };
5753
5754         const char *path;
5755         int fd, r;
5756
5757         /* This is roughly the same as lckpwdf(), but not as awful. We
5758          * don't want to use alarm() and signals, hence we implement
5759          * our own trivial version of this.
5760          *
5761          * Note that shadow-utils also takes per-database locks in
5762          * addition to lckpwdf(). However, we don't given that they
5763          * are redundant as they they invoke lckpwdf() first and keep
5764          * it during everything they do. The per-database locks are
5765          * awfully racy, and thus we just won't do them. */
5766
5767         if (root)
5768                 path = strjoina(root, "/etc/.pwd.lock");
5769         else
5770                 path = "/etc/.pwd.lock";
5771
5772         fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0600);
5773         if (fd < 0)
5774                 return -errno;
5775
5776         r = fcntl(fd, F_SETLKW, &flock);
5777         if (r < 0) {
5778                 safe_close(fd);
5779                 return -errno;
5780         }
5781
5782         return fd;
5783 }
5784
5785 int is_symlink(const char *path) {
5786         struct stat info;
5787
5788         if (lstat(path, &info) < 0)
5789                 return -errno;
5790
5791         return !!S_ISLNK(info.st_mode);
5792 }
5793 #endif // 0
5794
5795 int is_dir(const char* path, bool follow) {
5796         struct stat st;
5797         int r;
5798
5799         if (follow)
5800                 r = stat(path, &st);
5801         else
5802                 r = lstat(path, &st);
5803         if (r < 0)
5804                 return -errno;
5805
5806         return !!S_ISDIR(st.st_mode);
5807 }
5808
5809 /// UNNEEDED by elogind
5810 #if 0
5811 int is_device_node(const char *path) {
5812         struct stat info;
5813
5814         if (lstat(path, &info) < 0)
5815                 return -errno;
5816
5817         return !!(S_ISBLK(info.st_mode) || S_ISCHR(info.st_mode));
5818 }
5819 #endif // 0
5820
5821 int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags) {
5822         _cleanup_free_ char *s = NULL;
5823         size_t allocated = 0, sz = 0;
5824         int r;
5825
5826         enum {
5827                 START,
5828                 VALUE,
5829                 VALUE_ESCAPE,
5830                 SINGLE_QUOTE,
5831                 SINGLE_QUOTE_ESCAPE,
5832                 DOUBLE_QUOTE,
5833                 DOUBLE_QUOTE_ESCAPE,
5834                 SEPARATOR,
5835         } state = START;
5836
5837         assert(p);
5838         assert(ret);
5839
5840         if (!separators)
5841                 separators = WHITESPACE;
5842
5843         /* Bail early if called after last value or with no input */
5844         if (!*p)
5845                 goto finish_force_terminate;
5846
5847         /* Parses the first word of a string, and returns it in
5848          * *ret. Removes all quotes in the process. When parsing fails
5849          * (because of an uneven number of quotes or similar), leaves
5850          * the pointer *p at the first invalid character. */
5851
5852         for (;;) {
5853                 char c = **p;
5854
5855                 switch (state) {
5856
5857                 case START:
5858                         if (flags & EXTRACT_DONT_COALESCE_SEPARATORS)
5859                                 if (!GREEDY_REALLOC(s, allocated, sz+1))
5860                                         return -ENOMEM;
5861
5862                         if (c == 0)
5863                                 goto finish_force_terminate;
5864                         else if (strchr(separators, c)) {
5865                                 if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) {
5866                                         (*p) ++;
5867                                         goto finish_force_next;
5868                                 }
5869                                 break;
5870                         }
5871
5872                         /* We found a non-blank character, so we will always
5873                          * want to return a string (even if it is empty),
5874                          * allocate it here. */
5875                         if (!GREEDY_REALLOC(s, allocated, sz+1))
5876                                 return -ENOMEM;
5877
5878                         state = VALUE;
5879                         /* fallthrough */
5880
5881                 case VALUE:
5882                         if (c == 0)
5883                                 goto finish_force_terminate;
5884                         else if (c == '\'' && (flags & EXTRACT_QUOTES))
5885                                 state = SINGLE_QUOTE;
5886                         else if (c == '\\')
5887                                 state = VALUE_ESCAPE;
5888                         else if (c == '\"' && (flags & EXTRACT_QUOTES))
5889                                 state = DOUBLE_QUOTE;
5890                         else if (strchr(separators, c)) {
5891                                 if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) {
5892                                         (*p) ++;
5893                                         goto finish_force_next;
5894                                 }
5895                                 state = SEPARATOR;
5896                         } else {
5897                                 if (!GREEDY_REALLOC(s, allocated, sz+2))
5898                                         return -ENOMEM;
5899
5900                                 s[sz++] = c;
5901                         }
5902
5903                         break;
5904
5905                 case SINGLE_QUOTE:
5906                         if (c == 0) {
5907                                 if (flags & EXTRACT_RELAX)
5908                                         goto finish_force_terminate;
5909                                 return -EINVAL;
5910                         } else if (c == '\'')
5911                                 state = VALUE;
5912                         else if (c == '\\')
5913                                 state = SINGLE_QUOTE_ESCAPE;
5914                         else {
5915                                 if (!GREEDY_REALLOC(s, allocated, sz+2))
5916                                         return -ENOMEM;
5917
5918                                 s[sz++] = c;
5919                         }
5920
5921                         break;
5922
5923                 case DOUBLE_QUOTE:
5924                         if (c == 0)
5925                                 return -EINVAL;
5926                         else if (c == '\"')
5927                                 state = VALUE;
5928                         else if (c == '\\')
5929                                 state = DOUBLE_QUOTE_ESCAPE;
5930                         else {
5931                                 if (!GREEDY_REALLOC(s, allocated, sz+2))
5932                                         return -ENOMEM;
5933
5934                                 s[sz++] = c;
5935                         }
5936
5937                         break;
5938
5939                 case SINGLE_QUOTE_ESCAPE:
5940                 case DOUBLE_QUOTE_ESCAPE:
5941                 case VALUE_ESCAPE:
5942                         if (!GREEDY_REALLOC(s, allocated, sz+7))
5943                                 return -ENOMEM;
5944
5945                         if (c == 0) {
5946                                 if ((flags & EXTRACT_CUNESCAPE_RELAX) &&
5947                                     (state == VALUE_ESCAPE || flags & EXTRACT_RELAX)) {
5948                                         /* If we find an unquoted trailing backslash and we're in
5949                                          * EXTRACT_CUNESCAPE_RELAX mode, keep it verbatim in the
5950                                          * output.
5951                                          *
5952                                          * Unbalanced quotes will only be allowed in EXTRACT_RELAX
5953                                          * mode, EXTRACT_CUNESCAPE_RELAX mode does not allow them.
5954                                          */
5955                                         s[sz++] = '\\';
5956                                         goto finish_force_terminate;
5957                                 }
5958                                 if (flags & EXTRACT_RELAX)
5959                                         goto finish_force_terminate;
5960                                 return -EINVAL;
5961                         }
5962
5963                         if (flags & EXTRACT_CUNESCAPE) {
5964                                 uint32_t u;
5965
5966                                 r = cunescape_one(*p, (size_t) -1, &c, &u);
5967                                 if (r < 0) {
5968                                         if (flags & EXTRACT_CUNESCAPE_RELAX) {
5969                                                 s[sz++] = '\\';
5970                                                 s[sz++] = c;
5971                                                 goto end_escape;
5972                                         }
5973                                         return -EINVAL;
5974                                 }
5975
5976                                 (*p) += r - 1;
5977
5978                                 if (c != 0)
5979                                         s[sz++] = c; /* normal explicit char */
5980                                 else
5981                                         sz += utf8_encode_unichar(s + sz, u); /* unicode chars we'll encode as utf8 */
5982                         } else
5983                                 s[sz++] = c;
5984
5985 end_escape:
5986                         state = (state == SINGLE_QUOTE_ESCAPE) ? SINGLE_QUOTE :
5987                                 (state == DOUBLE_QUOTE_ESCAPE) ? DOUBLE_QUOTE :
5988                                 VALUE;
5989                         break;
5990
5991                 case SEPARATOR:
5992                         if (c == 0)
5993                                 goto finish_force_terminate;
5994                         if (!strchr(separators, c))
5995                                 goto finish;
5996                         break;
5997                 }
5998
5999                 (*p) ++;
6000         }
6001
6002 finish_force_terminate:
6003         *p = NULL;
6004 finish:
6005         if (!s) {
6006                 *p = NULL;
6007                 *ret = NULL;
6008                 return 0;
6009         }
6010
6011 finish_force_next:
6012         s[sz] = 0;
6013         *ret = s;
6014         s = NULL;
6015
6016         return 1;
6017 }
6018
6019 /// UNNEEDED by elogind
6020 #if 0
6021 int extract_first_word_and_warn(
6022                 const char **p,
6023                 char **ret,
6024                 const char *separators,
6025                 ExtractFlags flags,
6026                 const char *unit,
6027                 const char *filename,
6028                 unsigned line,
6029                 const char *rvalue) {
6030         /* Try to unquote it, if it fails, warn about it and try again but this
6031          * time using EXTRACT_CUNESCAPE_RELAX to keep the backslashes verbatim
6032          * in invalid escape sequences. */
6033         const char *save;
6034         int r;
6035
6036         save = *p;
6037         r = extract_first_word(p, ret, separators, flags);
6038         if (r < 0 && !(flags&EXTRACT_CUNESCAPE_RELAX)) {
6039                 /* Retry it with EXTRACT_CUNESCAPE_RELAX. */
6040                 *p = save;
6041                 r = extract_first_word(p, ret, separators, flags|EXTRACT_CUNESCAPE_RELAX);
6042                 if (r < 0)
6043                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
6044                                    "Unbalanced quoting in command line, ignoring: \"%s\"", rvalue);
6045                 else
6046                         log_syntax(unit, LOG_WARNING, filename, line, EINVAL,
6047                                    "Invalid escape sequences in command line: \"%s\"", rvalue);
6048         }
6049         return r;
6050 }
6051
6052 int extract_many_words(const char **p, const char *separators, ExtractFlags flags, ...) {
6053         va_list ap;
6054         char **l;
6055         int n = 0, i, c, r;
6056
6057         /* Parses a number of words from a string, stripping any
6058          * quotes if necessary. */
6059
6060         assert(p);
6061
6062         /* Count how many words are expected */
6063         va_start(ap, flags);
6064         for (;;) {
6065                 if (!va_arg(ap, char **))
6066                         break;
6067                 n++;
6068         }
6069         va_end(ap);
6070
6071         if (n <= 0)
6072                 return 0;
6073
6074         /* Read all words into a temporary array */
6075         l = newa0(char*, n);
6076         for (c = 0; c < n; c++) {
6077
6078                 r = extract_first_word(p, &l[c], separators, flags);
6079                 if (r < 0) {
6080                         int j;
6081
6082                         for (j = 0; j < c; j++)
6083                                 free(l[j]);
6084
6085                         return r;
6086                 }
6087
6088                 if (r == 0)
6089                         break;
6090         }
6091
6092         /* If we managed to parse all words, return them in the passed
6093          * in parameters */
6094         va_start(ap, flags);
6095         for (i = 0; i < n; i++) {
6096                 char **v;
6097
6098                 v = va_arg(ap, char **);
6099                 assert(v);
6100
6101                 *v = l[i];
6102         }
6103         va_end(ap);
6104
6105         return c;
6106 }
6107 #endif // 0
6108
6109 int free_and_strdup(char **p, const char *s) {
6110         char *t;
6111
6112         assert(p);
6113
6114         /* Replaces a string pointer with an strdup()ed new string,
6115          * possibly freeing the old one. */
6116
6117         if (streq_ptr(*p, s))
6118                 return 0;
6119
6120         if (s) {
6121                 t = strdup(s);
6122                 if (!t)
6123                         return -ENOMEM;
6124         } else
6125                 t = NULL;
6126
6127         free(*p);
6128         *p = t;
6129
6130         return 1;
6131 }
6132
6133 /// UNNEEDED by elogind
6134 #if 0
6135 int ptsname_malloc(int fd, char **ret) {
6136         size_t l = 100;
6137
6138         assert(fd >= 0);
6139         assert(ret);
6140
6141         for (;;) {
6142                 char *c;
6143
6144                 c = new(char, l);
6145                 if (!c)
6146                         return -ENOMEM;
6147
6148                 if (ptsname_r(fd, c, l) == 0) {
6149                         *ret = c;
6150                         return 0;
6151                 }
6152                 if (errno != ERANGE) {
6153                         free(c);
6154                         return -errno;
6155                 }
6156
6157                 free(c);
6158                 l *= 2;
6159         }
6160 }
6161
6162 int openpt_in_namespace(pid_t pid, int flags) {
6163         _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
6164         _cleanup_close_pair_ int pair[2] = { -1, -1 };
6165         union {
6166                 struct cmsghdr cmsghdr;
6167                 uint8_t buf[CMSG_SPACE(sizeof(int))];
6168         } control = {};
6169         struct msghdr mh = {
6170                 .msg_control = &control,
6171                 .msg_controllen = sizeof(control),
6172         };
6173         struct cmsghdr *cmsg;
6174         siginfo_t si;
6175         pid_t child;
6176         int r;
6177
6178         assert(pid > 0);
6179
6180         r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd);
6181         if (r < 0)
6182                 return r;
6183
6184         if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
6185                 return -errno;
6186
6187         child = fork();
6188         if (child < 0)
6189                 return -errno;
6190
6191         if (child == 0) {
6192                 int master;
6193
6194                 pair[0] = safe_close(pair[0]);
6195
6196                 r = namespace_enter(pidnsfd, mntnsfd, -1, usernsfd, rootfd);
6197                 if (r < 0)
6198                         _exit(EXIT_FAILURE);
6199
6200                 master = posix_openpt(flags);
6201                 if (master < 0)
6202                         _exit(EXIT_FAILURE);
6203
6204                 if (unlockpt(master) < 0)
6205                         _exit(EXIT_FAILURE);
6206
6207                 cmsg = CMSG_FIRSTHDR(&mh);
6208                 cmsg->cmsg_level = SOL_SOCKET;
6209                 cmsg->cmsg_type = SCM_RIGHTS;
6210                 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
6211                 memcpy(CMSG_DATA(cmsg), &master, sizeof(int));
6212
6213                 mh.msg_controllen = cmsg->cmsg_len;
6214
6215                 if (sendmsg(pair[1], &mh, MSG_NOSIGNAL) < 0)
6216                         _exit(EXIT_FAILURE);
6217
6218                 _exit(EXIT_SUCCESS);
6219         }
6220
6221         pair[1] = safe_close(pair[1]);
6222
6223         r = wait_for_terminate(child, &si);
6224         if (r < 0)
6225                 return r;
6226         if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
6227                 return -EIO;
6228
6229         if (recvmsg(pair[0], &mh, MSG_NOSIGNAL|MSG_CMSG_CLOEXEC) < 0)
6230                 return -errno;
6231
6232         CMSG_FOREACH(cmsg, &mh)
6233                 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
6234                         int *fds;
6235                         unsigned n_fds;
6236
6237                         fds = (int*) CMSG_DATA(cmsg);
6238                         n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
6239
6240                         if (n_fds != 1) {
6241                                 close_many(fds, n_fds);
6242                                 return -EIO;
6243                         }
6244
6245                         return fds[0];
6246                 }
6247
6248         return -EIO;
6249 }
6250 #endif // 0
6251
6252 ssize_t fgetxattrat_fake(int dirfd, const char *filename, const char *attribute, void *value, size_t size, int flags) {
6253         _cleanup_close_ int fd = -1;
6254         ssize_t l;
6255
6256         /* The kernel doesn't have a fgetxattrat() command, hence let's emulate one */
6257
6258         fd = openat(dirfd, filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOATIME|(flags & AT_SYMLINK_NOFOLLOW ? O_NOFOLLOW : 0));
6259         if (fd < 0)
6260                 return -errno;
6261
6262         l = fgetxattr(fd, attribute, value, size);
6263         if (l < 0)
6264                 return -errno;
6265
6266         return l;
6267 }
6268
6269 static int parse_crtime(le64_t le, usec_t *usec) {
6270         uint64_t u;
6271
6272         assert(usec);
6273
6274         u = le64toh(le);
6275         if (u == 0 || u == (uint64_t) -1)
6276                 return -EIO;
6277
6278         *usec = (usec_t) u;
6279         return 0;
6280 }
6281
6282 int fd_getcrtime(int fd, usec_t *usec) {
6283         le64_t le;
6284         ssize_t n;
6285
6286         assert(fd >= 0);
6287         assert(usec);
6288
6289         /* Until Linux gets a real concept of birthtime/creation time,
6290          * let's fake one with xattrs */
6291
6292         n = fgetxattr(fd, "user.crtime_usec", &le, sizeof(le));
6293         if (n < 0)
6294                 return -errno;
6295         if (n != sizeof(le))
6296                 return -EIO;
6297
6298         return parse_crtime(le, usec);
6299 }
6300
6301 /// UNNEEDED by elogind
6302 #if 0
6303 int fd_getcrtime_at(int dirfd, const char *name, usec_t *usec, int flags) {
6304         le64_t le;
6305         ssize_t n;
6306
6307         n = fgetxattrat_fake(dirfd, name, "user.crtime_usec", &le, sizeof(le), flags);
6308         if (n < 0)
6309                 return -errno;
6310         if (n != sizeof(le))
6311                 return -EIO;
6312
6313         return parse_crtime(le, usec);
6314 }
6315
6316 int path_getcrtime(const char *p, usec_t *usec) {
6317         le64_t le;
6318         ssize_t n;
6319
6320         assert(p);
6321         assert(usec);
6322
6323         n = getxattr(p, "user.crtime_usec", &le, sizeof(le));
6324         if (n < 0)
6325                 return -errno;
6326         if (n != sizeof(le))
6327                 return -EIO;
6328
6329         return parse_crtime(le, usec);
6330 }
6331
6332 int fd_setcrtime(int fd, usec_t usec) {
6333         le64_t le;
6334
6335         assert(fd >= 0);
6336
6337         if (usec <= 0)
6338                 usec = now(CLOCK_REALTIME);
6339
6340         le = htole64((uint64_t) usec);
6341         if (fsetxattr(fd, "user.crtime_usec", &le, sizeof(le), 0) < 0)
6342                 return -errno;
6343
6344         return 0;
6345 }
6346
6347 int same_fd(int a, int b) {
6348         struct stat sta, stb;
6349         pid_t pid;
6350         int r, fa, fb;
6351
6352         assert(a >= 0);
6353         assert(b >= 0);
6354
6355         /* Compares two file descriptors. Note that semantics are
6356          * quite different depending on whether we have kcmp() or we
6357          * don't. If we have kcmp() this will only return true for
6358          * dup()ed file descriptors, but not otherwise. If we don't
6359          * have kcmp() this will also return true for two fds of the same
6360          * file, created by separate open() calls. Since we use this
6361          * call mostly for filtering out duplicates in the fd store
6362          * this difference hopefully doesn't matter too much. */
6363
6364         if (a == b)
6365                 return true;
6366
6367         /* Try to use kcmp() if we have it. */
6368         pid = getpid();
6369         r = kcmp(pid, pid, KCMP_FILE, a, b);
6370         if (r == 0)
6371                 return true;
6372         if (r > 0)
6373                 return false;
6374         if (errno != ENOSYS)
6375                 return -errno;
6376
6377         /* We don't have kcmp(), use fstat() instead. */
6378         if (fstat(a, &sta) < 0)
6379                 return -errno;
6380
6381         if (fstat(b, &stb) < 0)
6382                 return -errno;
6383
6384         if ((sta.st_mode & S_IFMT) != (stb.st_mode & S_IFMT))
6385                 return false;
6386
6387         /* We consider all device fds different, since two device fds
6388          * might refer to quite different device contexts even though
6389          * they share the same inode and backing dev_t. */
6390
6391         if (S_ISCHR(sta.st_mode) || S_ISBLK(sta.st_mode))
6392                 return false;
6393
6394         if (sta.st_dev != stb.st_dev || sta.st_ino != stb.st_ino)
6395                 return false;
6396
6397         /* The fds refer to the same inode on disk, let's also check
6398          * if they have the same fd flags. This is useful to
6399          * distinguish the read and write side of a pipe created with
6400          * pipe(). */
6401         fa = fcntl(a, F_GETFL);
6402         if (fa < 0)
6403                 return -errno;
6404
6405         fb = fcntl(b, F_GETFL);
6406         if (fb < 0)
6407                 return -errno;
6408
6409         return fa == fb;
6410 }
6411 #endif // 0
6412
6413 int chattr_fd(int fd, unsigned value, unsigned mask) {
6414         unsigned old_attr, new_attr;
6415         struct stat st;
6416
6417         assert(fd >= 0);
6418
6419         if (fstat(fd, &st) < 0)
6420                 return -errno;
6421
6422         /* Explicitly check whether this is a regular file or
6423          * directory. If it is anything else (such as a device node or
6424          * fifo), then the ioctl will not hit the file systems but
6425          * possibly drivers, where the ioctl might have different
6426          * effects. Notably, DRM is using the same ioctl() number. */
6427
6428         if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode))
6429                 return -ENOTTY;
6430
6431         if (mask == 0)
6432                 return 0;
6433
6434         if (ioctl(fd, FS_IOC_GETFLAGS, &old_attr) < 0)
6435                 return -errno;
6436
6437         new_attr = (old_attr & ~mask) | (value & mask);
6438         if (new_attr == old_attr)
6439                 return 0;
6440
6441         if (ioctl(fd, FS_IOC_SETFLAGS, &new_attr) < 0)
6442                 return -errno;
6443
6444         return 1;
6445 }
6446
6447 /// UNNEEDED by elogind
6448 #if 0
6449 int chattr_path(const char *p, unsigned value, unsigned mask) {
6450         _cleanup_close_ int fd = -1;
6451
6452         assert(p);
6453
6454         if (mask == 0)
6455                 return 0;
6456
6457         fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
6458         if (fd < 0)
6459                 return -errno;
6460
6461         return chattr_fd(fd, value, mask);
6462 }
6463 #endif // 0
6464
6465 int read_attr_fd(int fd, unsigned *ret) {
6466         struct stat st;
6467
6468         assert(fd >= 0);
6469
6470         if (fstat(fd, &st) < 0)
6471                 return -errno;
6472
6473         if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode))
6474                 return -ENOTTY;
6475
6476         if (ioctl(fd, FS_IOC_GETFLAGS, ret) < 0)
6477                 return -errno;
6478
6479         return 0;
6480 }
6481
6482 /// UNNEEDED by elogind
6483 #if 0
6484 int read_attr_path(const char *p, unsigned *ret) {
6485         _cleanup_close_ int fd = -1;
6486
6487         assert(p);
6488         assert(ret);
6489
6490         fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
6491         if (fd < 0)
6492                 return -errno;
6493
6494         return read_attr_fd(fd, ret);
6495 }
6496
6497 static size_t nul_length(const uint8_t *p, size_t sz) {
6498         size_t n = 0;
6499
6500         while (sz > 0) {
6501                 if (*p != 0)
6502                         break;
6503
6504                 n++;
6505                 p++;
6506                 sz--;
6507         }
6508
6509         return n;
6510 }
6511
6512 ssize_t sparse_write(int fd, const void *p, size_t sz, size_t run_length) {
6513         const uint8_t *q, *w, *e;
6514         ssize_t l;
6515
6516         q = w = p;
6517         e = q + sz;
6518         while (q < e) {
6519                 size_t n;
6520
6521                 n = nul_length(q, e - q);
6522
6523                 /* If there are more than the specified run length of
6524                  * NUL bytes, or if this is the beginning or the end
6525                  * of the buffer, then seek instead of write */
6526                 if ((n > run_length) ||
6527                     (n > 0 && q == p) ||
6528                     (n > 0 && q + n >= e)) {
6529                         if (q > w) {
6530                                 l = write(fd, w, q - w);
6531                                 if (l < 0)
6532                                         return -errno;
6533                                 if (l != q -w)
6534                                         return -EIO;
6535                         }
6536
6537                         if (lseek(fd, n, SEEK_CUR) == (off_t) -1)
6538                                 return -errno;
6539
6540                         q += n;
6541                         w = q;
6542                 } else if (n > 0)
6543                         q += n;
6544                 else
6545                         q ++;
6546         }
6547
6548         if (q > w) {
6549                 l = write(fd, w, q - w);
6550                 if (l < 0)
6551                         return -errno;
6552                 if (l != q - w)
6553                         return -EIO;
6554         }
6555
6556         return q - (const uint8_t*) p;
6557 }
6558 #endif // 0
6559
6560 void sigkill_wait(pid_t *pid) {
6561         if (!pid)
6562                 return;
6563         if (*pid <= 1)
6564                 return;
6565
6566         if (kill(*pid, SIGKILL) > 0)
6567                 (void) wait_for_terminate(*pid, NULL);
6568 }
6569
6570 /// UNNEEDED by elogind
6571 #if 0
6572 int syslog_parse_priority(const char **p, int *priority, bool with_facility) {
6573         int a = 0, b = 0, c = 0;
6574         int k;
6575
6576         assert(p);
6577         assert(*p);
6578         assert(priority);
6579
6580         if ((*p)[0] != '<')
6581                 return 0;
6582
6583         if (!strchr(*p, '>'))
6584                 return 0;
6585
6586         if ((*p)[2] == '>') {
6587                 c = undecchar((*p)[1]);
6588                 k = 3;
6589         } else if ((*p)[3] == '>') {
6590                 b = undecchar((*p)[1]);
6591                 c = undecchar((*p)[2]);
6592                 k = 4;
6593         } else if ((*p)[4] == '>') {
6594                 a = undecchar((*p)[1]);
6595                 b = undecchar((*p)[2]);
6596                 c = undecchar((*p)[3]);
6597                 k = 5;
6598         } else
6599                 return 0;
6600
6601         if (a < 0 || b < 0 || c < 0 ||
6602             (!with_facility && (a || b || c > 7)))
6603                 return 0;
6604
6605         if (with_facility)
6606                 *priority = a*100 + b*10 + c;
6607         else
6608                 *priority = (*priority & LOG_FACMASK) | c;
6609
6610         *p += k;
6611         return 1;
6612 }
6613 #endif // 0
6614
6615 ssize_t string_table_lookup(const char * const *table, size_t len, const char *key) {
6616         size_t i;
6617
6618         if (!key)
6619                 return -1;
6620
6621         for (i = 0; i < len; ++i)
6622                 if (streq_ptr(table[i], key))
6623                         return (ssize_t)i;
6624
6625         return -1;
6626 }
6627
6628 /// UNNEEDED by elogind
6629 #if 0
6630 void cmsg_close_all(struct msghdr *mh) {
6631         struct cmsghdr *cmsg;
6632
6633         assert(mh);
6634
6635         CMSG_FOREACH(cmsg, mh)
6636                 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
6637                         close_many((int*) CMSG_DATA(cmsg), (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int));
6638 }
6639
6640 int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) {
6641         struct stat buf;
6642         int ret;
6643
6644         ret = renameat2(olddirfd, oldpath, newdirfd, newpath, RENAME_NOREPLACE);
6645         if (ret >= 0)
6646                 return 0;
6647
6648         /* renameat2() exists since Linux 3.15, btrfs added support for it later.
6649          * If it is not implemented, fallback to another method. */
6650         if (!IN_SET(errno, EINVAL, ENOSYS))
6651                 return -errno;
6652
6653         /* The link()/unlink() fallback does not work on directories. But
6654          * renameat() without RENAME_NOREPLACE gives the same semantics on
6655          * directories, except when newpath is an *empty* directory. This is
6656          * good enough. */
6657         ret = fstatat(olddirfd, oldpath, &buf, AT_SYMLINK_NOFOLLOW);
6658         if (ret >= 0 && S_ISDIR(buf.st_mode)) {
6659                 ret = renameat(olddirfd, oldpath, newdirfd, newpath);
6660                 return ret >= 0 ? 0 : -errno;
6661         }
6662
6663         /* If it is not a directory, use the link()/unlink() fallback. */
6664         ret = linkat(olddirfd, oldpath, newdirfd, newpath, 0);
6665         if (ret < 0)
6666                 return -errno;
6667
6668         ret = unlinkat(olddirfd, oldpath, 0);
6669         if (ret < 0) {
6670                 /* backup errno before the following unlinkat() alters it */
6671                 ret = errno;
6672                 (void) unlinkat(newdirfd, newpath, 0);
6673                 errno = ret;
6674                 return -errno;
6675         }
6676
6677         return 0;
6678 }
6679 #endif // 0
6680
6681 static char *strcpy_backslash_escaped(char *t, const char *s, const char *bad) {
6682         assert(bad);
6683
6684         for (; *s; s++) {
6685                 if (*s == '\\' || strchr(bad, *s))
6686                         *(t++) = '\\';
6687
6688                 *(t++) = *s;
6689         }
6690
6691         return t;
6692 }
6693
6694 char *shell_escape(const char *s, const char *bad) {
6695         char *r, *t;
6696
6697         r = new(char, strlen(s)*2+1);
6698         if (!r)
6699                 return NULL;
6700
6701         t = strcpy_backslash_escaped(r, s, bad);
6702         *t = 0;
6703
6704         return r;
6705 }
6706
6707 char *shell_maybe_quote(const char *s) {
6708         const char *p;
6709         char *r, *t;
6710
6711         assert(s);
6712
6713         /* Encloses a string in double quotes if necessary to make it
6714          * OK as shell string. */
6715
6716         for (p = s; *p; p++)
6717                 if (*p <= ' ' ||
6718                     *p >= 127 ||
6719                     strchr(SHELL_NEED_QUOTES, *p))
6720                         break;
6721
6722         if (!*p)
6723                 return strdup(s);
6724
6725         r = new(char, 1+strlen(s)*2+1+1);
6726         if (!r)
6727                 return NULL;
6728
6729         t = r;
6730         *(t++) = '"';
6731         t = mempcpy(t, s, p - s);
6732
6733         t = strcpy_backslash_escaped(t, p, SHELL_NEED_ESCAPE);
6734
6735         *(t++)= '"';
6736         *t = 0;
6737
6738         return r;
6739 }
6740
6741 int parse_mode(const char *s, mode_t *ret) {
6742         char *x;
6743         long l;
6744
6745         assert(s);
6746         assert(ret);
6747
6748         errno = 0;
6749         l = strtol(s, &x, 8);
6750         if (errno != 0)
6751                 return -errno;
6752
6753         if (!x || x == s || *x)
6754                 return -EINVAL;
6755         if (l < 0 || l  > 07777)
6756                 return -ERANGE;
6757
6758         *ret = (mode_t) l;
6759         return 0;
6760 }
6761
6762 /// UNNEEDED by elogind
6763 #if 0
6764 int mount_move_root(const char *path) {
6765         assert(path);
6766
6767         if (chdir(path) < 0)
6768                 return -errno;
6769
6770         if (mount(path, "/", NULL, MS_MOVE, NULL) < 0)
6771                 return -errno;
6772
6773         if (chroot(".") < 0)
6774                 return -errno;
6775
6776         if (chdir("/") < 0)
6777                 return -errno;
6778
6779         return 0;
6780 }
6781 #endif // 0
6782
6783 int reset_uid_gid(void) {
6784
6785         if (setgroups(0, NULL) < 0)
6786                 return -errno;
6787
6788         if (setresgid(0, 0, 0) < 0)
6789                 return -errno;
6790
6791         if (setresuid(0, 0, 0) < 0)
6792                 return -errno;
6793
6794         return 0;
6795 }
6796
6797 int getxattr_malloc(const char *path, const char *name, char **value, bool allow_symlink) {
6798         char *v;
6799         size_t l;
6800         ssize_t n;
6801
6802         assert(path);
6803         assert(name);
6804         assert(value);
6805
6806         for (l = 100; ; l = (size_t) n + 1) {
6807                 v = new0(char, l);
6808                 if (!v)
6809                         return -ENOMEM;
6810
6811                 if (allow_symlink)
6812                         n = lgetxattr(path, name, v, l);
6813                 else
6814                         n = getxattr(path, name, v, l);
6815
6816                 if (n >= 0 && (size_t) n < l) {
6817                         *value = v;
6818                         return n;
6819                 }
6820
6821                 free(v);
6822
6823                 if (n < 0 && errno != ERANGE)
6824                         return -errno;
6825
6826                 if (allow_symlink)
6827                         n = lgetxattr(path, name, NULL, 0);
6828                 else
6829                         n = getxattr(path, name, NULL, 0);
6830                 if (n < 0)
6831                         return -errno;
6832         }
6833 }
6834
6835 int fgetxattr_malloc(int fd, const char *name, char **value) {
6836         char *v;
6837         size_t l;
6838         ssize_t n;
6839
6840         assert(fd >= 0);
6841         assert(name);
6842         assert(value);
6843
6844         for (l = 100; ; l = (size_t) n + 1) {
6845                 v = new0(char, l);
6846                 if (!v)
6847                         return -ENOMEM;
6848
6849                 n = fgetxattr(fd, name, v, l);
6850
6851                 if (n >= 0 && (size_t) n < l) {
6852                         *value = v;
6853                         return n;
6854                 }
6855
6856                 free(v);
6857
6858                 if (n < 0 && errno != ERANGE)
6859                         return -errno;
6860
6861                 n = fgetxattr(fd, name, NULL, 0);
6862                 if (n < 0)
6863                         return -errno;
6864         }
6865 }