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