1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
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.
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.
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/>.
22 // #include <string.h>
23 // #include <unistd.h>
25 // #include <stdlib.h>
26 // #include <signal.h>
27 // #include <libintl.h>
29 // #include <syslog.h>
31 // #include <sys/resource.h>
32 // #include <linux/sched.h>
33 // #include <sys/types.h>
34 // #include <sys/stat.h>
36 // #include <dirent.h>
37 // #include <sys/ioctl.h>
38 // #include <stdarg.h>
41 #include <sys/prctl.h>
42 // #include <sys/utsname.h>
44 #include <netinet/ip.h>
45 // #include <sys/wait.h>
46 // #include <sys/time.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>
55 // #include <locale.h>
56 // #include <sys/personality.h>
57 #include <sys/xattr.h>
58 // #include <sys/statvfs.h>
59 // #include <sys/file.h>
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>
68 #ifdef HAVE_SYS_AUXV_H
76 // #include "missing.h"
80 #include "path-util.h"
81 // #include "exit-status.h"
82 // #include "hashmap.h"
83 // #include "env-util.h"
85 // #include "device-nodes.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"
98 /* Put this test here for a lack of better place */
99 assert_cc(EAGAIN == EWOULDBLOCK);
102 char **saved_argv = NULL;
104 size_t page_size(void) {
105 static thread_local size_t pgsz = 0;
108 if (_likely_(pgsz > 0))
111 r = sysconf(_SC_PAGESIZE);
118 bool streq_ptr(const char *a, const char *b) {
120 /* Like streq(), but tries to make sense of NULL pointers */
131 char* endswith(const char *s, const char *postfix) {
138 pl = strlen(postfix);
141 return (char*) s + sl;
146 if (memcmp(s + sl - pl, postfix, pl) != 0)
149 return (char*) s + sl - pl;
152 char* endswith_no_case(const char *s, const char *postfix) {
159 pl = strlen(postfix);
162 return (char*) s + sl;
167 if (strcasecmp(s + sl - pl, postfix) != 0)
170 return (char*) s + sl - pl;
173 char* first_word(const char *s, const char *word) {
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. */
193 if (memcmp(s, word, wl) != 0)
200 if (!strchr(WHITESPACE, *p))
203 p += strspn(p, WHITESPACE);
207 size_t cescape_char(char c, char *buf) {
208 char * buf_old = buf;
254 /* For special chars we prefer octal over
255 * hexadecimal encoding, simply because glib's
256 * g_strescape() does the same */
257 if ((c < ' ') || (c >= 127)) {
259 *(buf++) = octchar((unsigned char) c >> 6);
260 *(buf++) = octchar((unsigned char) c >> 3);
261 *(buf++) = octchar((unsigned char) c);
267 return buf - buf_old;
270 int close_nointr(int fd) {
277 * Just ignore EINTR; a retry loop is the wrong thing to do on
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
291 int safe_close(int fd) {
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:
298 * fd = safe_close(fd);
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... */
309 assert_se(close_nointr(fd) != -EBADF);
315 void close_many(const int fds[], unsigned n_fd) {
318 assert(fds || n_fd <= 0);
320 for (i = 0; i < n_fd; i++)
324 int unlink_noerrno(const char *path) {
335 int parse_boolean(const char *v) {
338 if (streq(v, "1") || strcaseeq(v, "yes") || strcaseeq(v, "y") || strcaseeq(v, "true") || strcaseeq(v, "t") || strcaseeq(v, "on"))
340 else if (streq(v, "0") || strcaseeq(v, "no") || strcaseeq(v, "n") || strcaseeq(v, "false") || strcaseeq(v, "f") || strcaseeq(v, "off"))
346 int parse_pid(const char *s, pid_t* ret_pid) {
347 unsigned long ul = 0;
354 r = safe_atolu(s, &ul);
360 if ((unsigned long) pid != ul)
370 int parse_uid(const char *s, uid_t* ret_uid) {
371 unsigned long ul = 0;
377 r = safe_atolu(s, &ul);
383 if ((unsigned long) uid != ul)
386 /* Some libc APIs use UID_INVALID as special placeholder */
387 if (uid == (uid_t) 0xFFFFFFFF)
390 /* A long time ago UIDs where 16bit, hence explicitly avoid the 16bit -1 too */
391 if (uid == (uid_t) 0xFFFF)
400 int safe_atou(const char *s, unsigned *ret_u) {
408 l = strtoul(s, &x, 0);
410 if (!x || x == s || *x || errno)
411 return errno > 0 ? -errno : -EINVAL;
413 if ((unsigned long) (unsigned) l != l)
416 *ret_u = (unsigned) l;
420 int safe_atoi(const char *s, int *ret_i) {
428 l = strtol(s, &x, 0);
430 if (!x || x == s || *x || errno)
431 return errno > 0 ? -errno : -EINVAL;
433 if ((long) (int) l != l)
440 int safe_atou8(const char *s, uint8_t *ret) {
448 l = strtoul(s, &x, 0);
450 if (!x || x == s || *x || errno)
451 return errno > 0 ? -errno : -EINVAL;
453 if ((unsigned long) (uint8_t) l != l)
460 int safe_atou16(const char *s, uint16_t *ret) {
468 l = strtoul(s, &x, 0);
470 if (!x || x == s || *x || errno)
471 return errno > 0 ? -errno : -EINVAL;
473 if ((unsigned long) (uint16_t) l != l)
480 int safe_atoi16(const char *s, int16_t *ret) {
488 l = strtol(s, &x, 0);
490 if (!x || x == s || *x || errno)
491 return errno > 0 ? -errno : -EINVAL;
493 if ((long) (int16_t) l != l)
500 int safe_atollu(const char *s, long long unsigned *ret_llu) {
502 unsigned long long l;
508 l = strtoull(s, &x, 0);
510 if (!x || x == s || *x || errno)
511 return errno ? -errno : -EINVAL;
517 int safe_atolli(const char *s, long long int *ret_lli) {
525 l = strtoll(s, &x, 0);
527 if (!x || x == s || *x || errno)
528 return errno ? -errno : -EINVAL;
534 int safe_atod(const char *s, double *ret_d) {
542 loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0);
543 if (loc == (locale_t) 0)
547 d = strtod_l(s, &x, loc);
549 if (!x || x == s || *x || errno) {
551 return errno ? -errno : -EINVAL;
559 static size_t strcspn_escaped(const char *s, const char *reject) {
560 bool escaped = false;
563 for (n=0; s[n]; n++) {
566 else if (s[n] == '\\')
568 else if (strchr(reject, s[n]))
572 /* if s ends in \, return index of previous char */
576 /* Split a string into words. */
577 const char* split(const char **state, size_t *l, const char *separator, bool quoted) {
583 assert(**state == '\0');
587 current += strspn(current, separator);
593 if (quoted && strchr("\'\"", *current)) {
594 char quotechars[2] = {*current, '\0'};
596 *l = strcspn_escaped(current + 1, quotechars);
597 if (current[*l + 1] == '\0' || current[*l + 1] != quotechars[0] ||
598 (current[*l + 2] && !strchr(separator, current[*l + 2]))) {
599 /* right quote missing or garbage at the end */
603 *state = current++ + *l + 2;
605 *l = strcspn_escaped(current, separator);
606 if (current[*l] && !strchr(separator, current[*l])) {
607 /* unfinished escape */
611 *state = current + *l;
613 *l = strcspn(current, separator);
614 *state = current + *l;
620 int fchmod_umask(int fd, mode_t m) {
625 r = fchmod(fd, m & (~u)) < 0 ? -errno : 0;
631 char *truncate_nl(char *s) {
634 s[strcspn(s, NEWLINE)] = 0;
638 char *strnappend(const char *s, const char *suffix, size_t b) {
646 return strndup(suffix, b);
655 if (b > ((size_t) -1) - a)
658 r = new(char, a+b+1);
663 memcpy(r+a, suffix, b);
669 char *strappend(const char *s, const char *suffix) {
670 return strnappend(s, suffix, suffix ? strlen(suffix) : 0);
673 int readlinkat_malloc(int fd, const char *p, char **ret) {
688 n = readlinkat(fd, p, c, l-1);
695 if ((size_t) n < l-1) {
706 int readlink_malloc(const char *p, char **ret) {
707 return readlinkat_malloc(AT_FDCWD, p, ret);
710 /// UNNEEDED by elogind
712 int readlink_value(const char *p, char **ret) {
713 _cleanup_free_ char *link = NULL;
717 r = readlink_malloc(p, &link);
721 value = basename(link);
725 value = strdup(value);
735 int readlink_and_make_absolute(const char *p, char **r) {
736 _cleanup_free_ char *target = NULL;
743 j = readlink_malloc(p, &target);
747 k = file_in_same_dir(p, target);
755 /// UNNEEDED by elogind
757 int readlink_and_canonicalize(const char *p, char **r) {
764 j = readlink_and_make_absolute(p, &t);
768 s = canonicalize_file_name(t);
775 path_kill_slashes(*r);
781 char *strstrip(char *s) {
784 /* Drops trailing whitespace. Modifies the string in
785 * place. Returns pointer to first non-space character */
787 s += strspn(s, WHITESPACE);
789 for (e = strchr(s, 0); e > s; e --)
790 if (!strchr(WHITESPACE, e[-1]))
798 /// UNNEEDED by elogind
800 char *delete_chars(char *s, const char *bad) {
803 /* Drops all whitespace, regardless where in the string */
805 for (f = s, t = s; *f; f++) {
818 char *file_in_same_dir(const char *path, const char *filename) {
825 /* This removes the last component of path and appends
826 * filename, unless the latter is absolute anyway or the
829 if (path_is_absolute(filename))
830 return strdup(filename);
832 e = strrchr(path, '/');
834 return strdup(filename);
836 k = strlen(filename);
837 ret = new(char, (e + 1 - path) + k + 1);
841 memcpy(mempcpy(ret, path, e + 1 - path), filename, k + 1);
845 /// UNNEEDED by elogind
847 int rmdir_parents(const char *path, const char *stop) {
856 /* Skip trailing slashes */
857 while (l > 0 && path[l-1] == '/')
863 /* Skip last component */
864 while (l > 0 && path[l-1] != '/')
867 /* Skip trailing slashes */
868 while (l > 0 && path[l-1] == '/')
874 if (!(t = strndup(path, l)))
877 if (path_startswith(stop, t)) {
894 char hexchar(int x) {
895 static const char table[16] = "0123456789abcdef";
897 return table[x & 15];
900 int unhexchar(char c) {
902 if (c >= '0' && c <= '9')
905 if (c >= 'a' && c <= 'f')
908 if (c >= 'A' && c <= 'F')
914 char *hexmem(const void *p, size_t l) {
918 z = r = malloc(l * 2 + 1);
922 for (x = p; x < (const uint8_t*) p + l; x++) {
923 *(z++) = hexchar(*x >> 4);
924 *(z++) = hexchar(*x & 15);
931 void *unhexmem(const char *p, size_t l) {
937 z = r = malloc((l + 1) / 2 + 1);
941 for (x = p; x < p + l; x += 2) {
950 *(z++) = (uint8_t) a << 4 | (uint8_t) b;
957 char octchar(int x) {
958 return '0' + (x & 7);
961 int unoctchar(char c) {
963 if (c >= '0' && c <= '7')
969 char decchar(int x) {
970 return '0' + (x % 10);
973 int undecchar(char c) {
975 if (c >= '0' && c <= '9')
981 char *cescape(const char *s) {
987 /* Does C style string escaping. May be reversed with
990 r = new(char, strlen(s)*4 + 1);
994 for (f = s, t = r; *f; f++)
995 t += cescape_char(*f, t);
1002 static int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode) {
1009 /* Unescapes C style. Returns the unescaped character in ret,
1010 * unless we encountered a \u sequence in which case the full
1011 * unicode character is returned in ret_unicode, instead. */
1013 if (length != (size_t) -1 && length < 1)
1050 /* This is an extension of the XDG syntax files */
1055 /* hexadecimal encoding */
1058 if (length != (size_t) -1 && length < 3)
1061 a = unhexchar(p[1]);
1065 b = unhexchar(p[2]);
1069 /* Don't allow NUL bytes */
1070 if (a == 0 && b == 0)
1073 *ret = (char) ((a << 4U) | b);
1079 /* C++11 style 16bit unicode */
1085 if (length != (size_t) -1 && length < 5)
1088 for (i = 0; i < 4; i++) {
1089 a[i] = unhexchar(p[1 + i]);
1094 c = ((uint32_t) a[0] << 12U) | ((uint32_t) a[1] << 8U) | ((uint32_t) a[2] << 4U) | (uint32_t) a[3];
1096 /* Don't allow 0 chars */
1115 /* C++11 style 32bit unicode */
1121 if (length != (size_t) -1 && length < 9)
1124 for (i = 0; i < 8; i++) {
1125 a[i] = unhexchar(p[1 + i]);
1130 c = ((uint32_t) a[0] << 28U) | ((uint32_t) a[1] << 24U) | ((uint32_t) a[2] << 20U) | ((uint32_t) a[3] << 16U) |
1131 ((uint32_t) a[4] << 12U) | ((uint32_t) a[5] << 8U) | ((uint32_t) a[6] << 4U) | (uint32_t) a[7];
1133 /* Don't allow 0 chars */
1137 /* Don't allow invalid code points */
1138 if (!unichar_is_valid(c))
1163 /* octal encoding */
1167 if (length != (size_t) -1 && length < 3)
1170 a = unoctchar(p[0]);
1174 b = unoctchar(p[1]);
1178 c = unoctchar(p[2]);
1182 /* don't allow NUL bytes */
1183 if (a == 0 && b == 0 && c == 0)
1186 /* Don't allow bytes above 255 */
1187 m = ((uint32_t) a << 6U) | ((uint32_t) b << 3U) | (uint32_t) c;
1203 int cunescape_length_with_prefix(const char *s, size_t length, const char *prefix, UnescapeFlags flags, char **ret) {
1211 /* Undoes C style string escaping, and optionally prefixes it. */
1213 pl = prefix ? strlen(prefix) : 0;
1215 r = new(char, pl+length+1);
1220 memcpy(r, prefix, pl);
1222 for (f = s, t = r + pl; f < s + length; f++) {
1228 remaining = s + length - f;
1229 assert(remaining > 0);
1232 /* A literal literal, copy verbatim */
1237 if (remaining == 1) {
1238 if (flags & UNESCAPE_RELAX) {
1239 /* A trailing backslash, copy verbatim */
1248 k = cunescape_one(f + 1, remaining - 1, &c, &u);
1250 if (flags & UNESCAPE_RELAX) {
1251 /* Invalid escape code, let's take it literal then */
1261 /* Non-Unicode? Let's encode this directly */
1264 /* Unicode? Then let's encode this in UTF-8 */
1265 t += utf8_encode_unichar(t, u);
1276 int cunescape_length(const char *s, size_t length, UnescapeFlags flags, char **ret) {
1277 return cunescape_length_with_prefix(s, length, NULL, flags, ret);
1280 int cunescape(const char *s, UnescapeFlags flags, char **ret) {
1281 return cunescape_length(s, strlen(s), flags, ret);
1284 char *xescape(const char *s, const char *bad) {
1288 /* Escapes all chars in bad, in addition to \ and all special
1289 * chars, in \xFF style escaping. May be reversed with
1292 r = new(char, strlen(s) * 4 + 1);
1296 for (f = s, t = r; *f; f++) {
1298 if ((*f < ' ') || (*f >= 127) ||
1299 (*f == '\\') || strchr(bad, *f)) {
1302 *(t++) = hexchar(*f >> 4);
1303 *(t++) = hexchar(*f);
1313 /// UNNEEDED by elogind
1315 char *ascii_strlower(char *t) {
1320 for (p = t; *p; p++)
1321 if (*p >= 'A' && *p <= 'Z')
1322 *p = *p - 'A' + 'a';
1328 _pure_ static bool hidden_file_allow_backup(const char *filename) {
1332 filename[0] == '.' ||
1333 streq(filename, "lost+found") ||
1334 streq(filename, "aquota.user") ||
1335 streq(filename, "aquota.group") ||
1336 endswith(filename, ".rpmnew") ||
1337 endswith(filename, ".rpmsave") ||
1338 endswith(filename, ".rpmorig") ||
1339 endswith(filename, ".dpkg-old") ||
1340 endswith(filename, ".dpkg-new") ||
1341 endswith(filename, ".dpkg-tmp") ||
1342 endswith(filename, ".dpkg-dist") ||
1343 endswith(filename, ".dpkg-bak") ||
1344 endswith(filename, ".dpkg-backup") ||
1345 endswith(filename, ".dpkg-remove") ||
1346 endswith(filename, ".swp");
1349 bool hidden_file(const char *filename) {
1352 if (endswith(filename, "~"))
1355 return hidden_file_allow_backup(filename);
1358 int fd_nonblock(int fd, bool nonblock) {
1363 flags = fcntl(fd, F_GETFL, 0);
1368 nflags = flags | O_NONBLOCK;
1370 nflags = flags & ~O_NONBLOCK;
1372 if (nflags == flags)
1375 if (fcntl(fd, F_SETFL, nflags) < 0)
1381 int fd_cloexec(int fd, bool cloexec) {
1386 flags = fcntl(fd, F_GETFD, 0);
1391 nflags = flags | FD_CLOEXEC;
1393 nflags = flags & ~FD_CLOEXEC;
1395 if (nflags == flags)
1398 if (fcntl(fd, F_SETFD, nflags) < 0)
1404 _pure_ static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
1407 assert(n_fdset == 0 || fdset);
1409 for (i = 0; i < n_fdset; i++)
1416 int close_all_fds(const int except[], unsigned n_except) {
1417 _cleanup_closedir_ DIR *d = NULL;
1421 assert(n_except == 0 || except);
1423 d = opendir("/proc/self/fd");
1428 /* When /proc isn't available (for example in chroots)
1429 * the fallback is brute forcing through the fd
1432 assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0);
1433 for (fd = 3; fd < (int) rl.rlim_max; fd ++) {
1435 if (fd_in_set(fd, except, n_except))
1438 if (close_nointr(fd) < 0)
1439 if (errno != EBADF && r == 0)
1446 while ((de = readdir(d))) {
1449 if (hidden_file(de->d_name))
1452 if (safe_atoi(de->d_name, &fd) < 0)
1453 /* Let's better ignore this, just in case */
1462 if (fd_in_set(fd, except, n_except))
1465 if (close_nointr(fd) < 0) {
1466 /* Valgrind has its own FD and doesn't want to have it closed */
1467 if (errno != EBADF && r == 0)
1475 bool chars_intersect(const char *a, const char *b) {
1478 /* Returns true if any of the chars in a are in b. */
1479 for (p = a; *p; p++)
1486 /// UNNEEDED by elogind
1488 bool fstype_is_network(const char *fstype) {
1489 static const char table[] =
1504 x = startswith(fstype, "fuse.");
1508 return nulstr_contains(table, fstype);
1512 int flush_fd(int fd) {
1513 struct pollfd pollfd = {
1523 r = poll(&pollfd, 1, 0);
1533 l = read(fd, buf, sizeof(buf));
1539 if (errno == EAGAIN)
1548 void safe_close_pair(int p[]) {
1552 /* Special case pairs which use the same fd in both
1554 p[0] = p[1] = safe_close(p[0]);
1558 p[0] = safe_close(p[0]);
1559 p[1] = safe_close(p[1]);
1562 ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) {
1569 while (nbytes > 0) {
1572 k = read(fd, p, nbytes);
1577 if (errno == EAGAIN && do_poll) {
1579 /* We knowingly ignore any return value here,
1580 * and expect that any error/EOF is reported
1583 fd_wait_for_event(fd, POLLIN, USEC_INFINITY);
1587 return n > 0 ? n : -errno;
1601 int loop_read_exact(int fd, void *buf, size_t nbytes, bool do_poll) {
1604 n = loop_read(fd, buf, nbytes, do_poll);
1607 if ((size_t) n != nbytes)
1612 int loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
1613 const uint8_t *p = buf;
1623 k = write(fd, p, nbytes);
1628 if (errno == EAGAIN && do_poll) {
1629 /* We knowingly ignore any return value here,
1630 * and expect that any error/EOF is reported
1633 fd_wait_for_event(fd, POLLOUT, USEC_INFINITY);
1640 if (nbytes > 0 && k == 0) /* Can't really happen */
1645 } while (nbytes > 0);
1650 int parse_size(const char *t, off_t base, off_t *size) {
1652 /* Soo, sometimes we want to parse IEC binary suffixes, and
1653 * sometimes SI decimal suffixes. This function can parse
1654 * both. Which one is the right way depends on the
1655 * context. Wikipedia suggests that SI is customary for
1656 * hardware metrics and network speeds, while IEC is
1657 * customary for most data sizes used by software and volatile
1658 * (RAM) memory. Hence be careful which one you pick!
1660 * In either case we use just K, M, G as suffix, and not Ki,
1661 * Mi, Gi or so (as IEC would suggest). That's because that's
1662 * frickin' ugly. But this means you really need to make sure
1663 * to document which base you are parsing when you use this
1668 unsigned long long factor;
1671 static const struct table iec[] = {
1672 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
1673 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
1674 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
1675 { "G", 1024ULL*1024ULL*1024ULL },
1676 { "M", 1024ULL*1024ULL },
1682 static const struct table si[] = {
1683 { "E", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
1684 { "P", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
1685 { "T", 1000ULL*1000ULL*1000ULL*1000ULL },
1686 { "G", 1000ULL*1000ULL*1000ULL },
1687 { "M", 1000ULL*1000ULL },
1693 const struct table *table;
1695 unsigned long long r = 0;
1696 unsigned n_entries, start_pos = 0;
1699 assert(base == 1000 || base == 1024);
1704 n_entries = ELEMENTSOF(si);
1707 n_entries = ELEMENTSOF(iec);
1713 unsigned long long l2;
1719 l = strtoll(p, &e, 10);
1732 if (*e >= '0' && *e <= '9') {
1735 /* strotoull itself would accept space/+/- */
1736 l2 = strtoull(e, &e2, 10);
1738 if (errno == ERANGE)
1741 /* Ignore failure. E.g. 10.M is valid */
1748 e += strspn(e, WHITESPACE);
1750 for (i = start_pos; i < n_entries; i++)
1751 if (startswith(e, table[i].suffix)) {
1752 unsigned long long tmp;
1753 if ((unsigned long long) l + (frac > 0) > ULLONG_MAX / table[i].factor)
1755 tmp = l * table[i].factor + (unsigned long long) (frac * table[i].factor);
1756 if (tmp > ULLONG_MAX - r)
1760 if ((unsigned long long) (off_t) r != r)
1763 p = e + strlen(table[i].suffix);
1779 bool is_device_path(const char *path) {
1781 /* Returns true on paths that refer to a device, either in
1782 * sysfs or in /dev */
1785 path_startswith(path, "/dev/") ||
1786 path_startswith(path, "/sys/");
1789 /// UNNEEDED by elogind
1791 int dir_is_empty(const char *path) {
1792 _cleanup_closedir_ DIR *d;
1803 if (!de && errno != 0)
1809 if (!hidden_file(de->d_name))
1814 char* dirname_malloc(const char *path) {
1815 char *d, *dir, *dir2;
1832 void rename_process(const char name[8]) {
1835 /* This is a like a poor man's setproctitle(). It changes the
1836 * comm field, argv[0], and also the glibc's internally used
1837 * name of the process. For the first one a limit of 16 chars
1838 * applies, to the second one usually one of 10 (i.e. length
1839 * of "/sbin/init"), to the third one one of 7 (i.e. length of
1840 * "systemd"). If you pass a longer string it will be
1843 prctl(PR_SET_NAME, name);
1845 if (program_invocation_name)
1846 strncpy(program_invocation_name, name, strlen(program_invocation_name));
1848 if (saved_argc > 0) {
1852 strncpy(saved_argv[0], name, strlen(saved_argv[0]));
1854 for (i = 1; i < saved_argc; i++) {
1858 memzero(saved_argv[i], strlen(saved_argv[i]));
1864 char *lookup_uid(uid_t uid) {
1867 _cleanup_free_ char *buf = NULL;
1868 struct passwd pwbuf, *pw = NULL;
1870 /* Shortcut things to avoid NSS lookups */
1872 return strdup("root");
1874 bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
1878 buf = malloc(bufsize);
1882 if (getpwuid_r(uid, &pwbuf, buf, bufsize, &pw) == 0 && pw)
1883 return strdup(pw->pw_name);
1885 if (asprintf(&name, UID_FMT, uid) < 0)
1891 /// UNNEEDED by elogind
1893 char* getlogname_malloc(void) {
1897 if (isatty(STDIN_FILENO) && fstat(STDIN_FILENO, &st) >= 0)
1902 return lookup_uid(uid);
1905 char *getusername_malloc(void) {
1912 return lookup_uid(getuid());
1916 bool is_temporary_fs(const struct statfs *s) {
1919 return F_TYPE_EQUAL(s->f_type, TMPFS_MAGIC) ||
1920 F_TYPE_EQUAL(s->f_type, RAMFS_MAGIC);
1923 int fd_is_temporary_fs(int fd) {
1926 if (fstatfs(fd, &s) < 0)
1929 return is_temporary_fs(&s);
1932 int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
1935 /* Under the assumption that we are running privileged we
1936 * first change the access mode and only then hand out
1937 * ownership to avoid a window where access is too open. */
1939 if (mode != MODE_INVALID)
1940 if (chmod(path, mode) < 0)
1943 if (uid != UID_INVALID || gid != GID_INVALID)
1944 if (chown(path, uid, gid) < 0)
1950 /// UNNEEDED by elogind
1952 int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid) {
1955 /* Under the assumption that we are running privileged we
1956 * first change the access mode and only then hand out
1957 * ownership to avoid a window where access is too open. */
1959 if (mode != MODE_INVALID)
1960 if (fchmod(fd, mode) < 0)
1963 if (uid != UID_INVALID || gid != GID_INVALID)
1964 if (fchown(fd, uid, gid) < 0)
1970 cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
1974 /* Allocates the cpuset in the right size */
1977 if (!(r = CPU_ALLOC(n)))
1980 if (sched_getaffinity(0, CPU_ALLOC_SIZE(n), r) >= 0) {
1981 CPU_ZERO_S(CPU_ALLOC_SIZE(n), r);
1991 if (errno != EINVAL)
1999 int files_same(const char *filea, const char *fileb) {
2002 if (stat(filea, &a) < 0)
2005 if (stat(fileb, &b) < 0)
2008 return a.st_dev == b.st_dev &&
2009 a.st_ino == b.st_ino;
2012 /// UNNEEDED by elogind
2014 int running_in_chroot(void) {
2017 ret = files_same("/proc/1/root", "/");
2025 static char *ascii_ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
2030 assert(percent <= 100);
2031 assert(new_length >= 3);
2033 if (old_length <= 3 || old_length <= new_length)
2034 return strndup(s, old_length);
2036 r = new0(char, new_length+1);
2040 x = (new_length * percent) / 100;
2042 if (x > new_length - 3)
2050 s + old_length - (new_length - x - 3),
2051 new_length - x - 3);
2056 char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
2060 unsigned k, len, len2;
2063 assert(percent <= 100);
2064 assert(new_length >= 3);
2066 /* if no multibyte characters use ascii_ellipsize_mem for speed */
2067 if (ascii_is_valid(s))
2068 return ascii_ellipsize_mem(s, old_length, new_length, percent);
2070 if (old_length <= 3 || old_length <= new_length)
2071 return strndup(s, old_length);
2073 x = (new_length * percent) / 100;
2075 if (x > new_length - 3)
2079 for (i = s; k < x && i < s + old_length; i = utf8_next_char(i)) {
2082 c = utf8_encoded_to_unichar(i);
2085 k += unichar_iswide(c) ? 2 : 1;
2088 if (k > x) /* last character was wide and went over quota */
2091 for (j = s + old_length; k < new_length && j > i; ) {
2094 j = utf8_prev_char(j);
2095 c = utf8_encoded_to_unichar(j);
2098 k += unichar_iswide(c) ? 2 : 1;
2102 /* we don't actually need to ellipsize */
2104 return memdup(s, old_length + 1);
2106 /* make space for ellipsis */
2107 j = utf8_next_char(j);
2110 len2 = s + old_length - j;
2111 e = new(char, len + 3 + len2 + 1);
2116 printf("old_length=%zu new_length=%zu x=%zu len=%u len2=%u k=%u\n",
2117 old_length, new_length, x, len, len2, k);
2121 e[len] = 0xe2; /* tri-dot ellipsis: … */
2125 memcpy(e + len + 3, j, len2 + 1);
2130 char *ellipsize(const char *s, size_t length, unsigned percent) {
2131 return ellipsize_mem(s, strlen(s), length, percent);
2134 int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode) {
2135 _cleanup_close_ int fd;
2141 mkdir_parents(path, 0755);
2143 fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, mode > 0 ? mode : 0644);
2148 r = fchmod(fd, mode);
2153 if (uid != UID_INVALID || gid != GID_INVALID) {
2154 r = fchown(fd, uid, gid);
2159 if (stamp != USEC_INFINITY) {
2160 struct timespec ts[2];
2162 timespec_store(&ts[0], stamp);
2164 r = futimens(fd, ts);
2166 r = futimens(fd, NULL);
2173 int touch(const char *path) {
2174 return touch_file(path, false, USEC_INFINITY, UID_INVALID, GID_INVALID, 0);
2177 /// UNNEEDED by elogind
2179 static char *unquote(const char *s, const char* quotes) {
2183 /* This is rather stupid, simply removes the heading and
2184 * trailing quotes if there is one. Doesn't care about
2185 * escaping or anything.
2187 * DON'T USE THIS FOR NEW CODE ANYMORE!*/
2193 if (strchr(quotes, s[0]) && s[l-1] == s[0])
2194 return strndup(s+1, l-2);
2200 noreturn void freeze(void) {
2202 /* Make sure nobody waits for us on a socket anymore */
2203 close_all_fds(NULL, 0);
2211 bool null_or_empty(struct stat *st) {
2214 if (S_ISREG(st->st_mode) && st->st_size <= 0)
2217 if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
2223 int null_or_empty_path(const char *fn) {
2228 if (stat(fn, &st) < 0)
2231 return null_or_empty(&st);
2234 /// UNNEEDED by elogind
2236 int null_or_empty_fd(int fd) {
2241 if (fstat(fd, &st) < 0)
2244 return null_or_empty(&st);
2248 DIR *xopendirat(int fd, const char *name, int flags) {
2252 assert(!(flags & O_CREAT));
2254 nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags, 0);
2267 /// UNNEEDED by elogind
2269 static char *tag_to_udev_node(const char *tagvalue, const char *by) {
2270 _cleanup_free_ char *t = NULL, *u = NULL;
2273 u = unquote(tagvalue, QUOTES);
2277 enc_len = strlen(u) * 4 + 1;
2278 t = new(char, enc_len);
2282 if (encode_devnode_name(u, t, enc_len) < 0)
2285 return strjoin("/dev/disk/by-", by, "/", t, NULL);
2288 char *fstab_node_to_udev_node(const char *p) {
2291 if (startswith(p, "LABEL="))
2292 return tag_to_udev_node(p+6, "label");
2294 if (startswith(p, "UUID="))
2295 return tag_to_udev_node(p+5, "uuid");
2297 if (startswith(p, "PARTUUID="))
2298 return tag_to_udev_node(p+9, "partuuid");
2300 if (startswith(p, "PARTLABEL="))
2301 return tag_to_udev_node(p+10, "partlabel");
2307 bool dirent_is_file(const struct dirent *de) {
2310 if (hidden_file(de->d_name))
2313 if (de->d_type != DT_REG &&
2314 de->d_type != DT_LNK &&
2315 de->d_type != DT_UNKNOWN)
2321 bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
2324 if (de->d_type != DT_REG &&
2325 de->d_type != DT_LNK &&
2326 de->d_type != DT_UNKNOWN)
2329 if (hidden_file_allow_backup(de->d_name))
2332 return endswith(de->d_name, suffix);
2335 /// UNNEEDED by elogind
2337 static int do_execute(char **directories, usec_t timeout, char *argv[]) {
2338 _cleanup_hashmap_free_free_ Hashmap *pids = NULL;
2339 _cleanup_set_free_free_ Set *seen = NULL;
2342 /* We fork this all off from a child process so that we can
2343 * somewhat cleanly make use of SIGALRM to set a time limit */
2345 (void) reset_all_signal_handlers();
2346 (void) reset_signal_mask();
2348 assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
2350 pids = hashmap_new(NULL);
2354 seen = set_new(&string_hash_ops);
2358 STRV_FOREACH(directory, directories) {
2359 _cleanup_closedir_ DIR *d;
2362 d = opendir(*directory);
2364 if (errno == ENOENT)
2367 return log_error_errno(errno, "Failed to open directory %s: %m", *directory);
2370 FOREACH_DIRENT(de, d, break) {
2371 _cleanup_free_ char *path = NULL;
2375 if (!dirent_is_file(de))
2378 if (set_contains(seen, de->d_name)) {
2379 log_debug("%1$s/%2$s skipped (%2$s was already seen).", *directory, de->d_name);
2383 r = set_put_strdup(seen, de->d_name);
2387 path = strjoin(*directory, "/", de->d_name, NULL);
2391 if (null_or_empty_path(path)) {
2392 log_debug("%s is empty (a mask).", path);
2398 log_error_errno(errno, "Failed to fork: %m");
2400 } else if (pid == 0) {
2403 assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
2413 return log_error_errno(errno, "Failed to execute %s: %m", path);
2416 log_debug("Spawned %s as " PID_FMT ".", path, pid);
2418 r = hashmap_put(pids, UINT_TO_PTR(pid), path);
2425 /* Abort execution of this process after the timout. We simply
2426 * rely on SIGALRM as default action terminating the process,
2427 * and turn on alarm(). */
2429 if (timeout != USEC_INFINITY)
2430 alarm((timeout + USEC_PER_SEC - 1) / USEC_PER_SEC);
2432 while (!hashmap_isempty(pids)) {
2433 _cleanup_free_ char *path = NULL;
2436 pid = PTR_TO_UINT(hashmap_first_key(pids));
2439 path = hashmap_remove(pids, UINT_TO_PTR(pid));
2442 wait_for_terminate_and_warn(path, pid, true);
2448 void execute_directories(const char* const* directories, usec_t timeout, char *argv[]) {
2452 char **dirs = (char**) directories;
2454 assert(!strv_isempty(dirs));
2456 name = basename(dirs[0]);
2457 assert(!isempty(name));
2459 /* Executes all binaries in the directories in parallel and waits
2460 * for them to finish. Optionally a timeout is applied. If a file
2461 * with the same name exists in more than one directory, the
2462 * earliest one wins. */
2464 executor_pid = fork();
2465 if (executor_pid < 0) {
2466 log_error_errno(errno, "Failed to fork: %m");
2469 } else if (executor_pid == 0) {
2470 r = do_execute(dirs, timeout, argv);
2471 _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
2474 wait_for_terminate_and_warn(name, executor_pid, true);
2478 bool nulstr_contains(const char*nulstr, const char *needle) {
2484 NULSTR_FOREACH(i, nulstr)
2485 if (streq(i, needle))
2491 /// UNNEEDED by elogind
2493 bool plymouth_running(void) {
2494 return access("/run/plymouth/pid", F_OK) >= 0;
2498 char* strshorten(char *s, size_t l) {
2507 bool machine_name_is_valid(const char *s) {
2509 if (!hostname_is_valid(s))
2512 /* Machine names should be useful hostnames, but also be
2513 * useful in unit names, hence we enforce a stricter length
2522 int pipe_eof(int fd) {
2523 struct pollfd pollfd = {
2525 .events = POLLIN|POLLHUP,
2530 r = poll(&pollfd, 1, 0);
2537 return pollfd.revents & POLLHUP;
2540 int fd_wait_for_event(int fd, int event, usec_t t) {
2542 struct pollfd pollfd = {
2550 r = ppoll(&pollfd, 1, t == USEC_INFINITY ? NULL : timespec_store(&ts, t), NULL);
2557 return pollfd.revents;
2560 int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
2569 r = tempfn_xxxxxx(path, NULL, &t);
2573 fd = mkostemp_safe(t, O_WRONLY|O_CLOEXEC);
2579 f = fdopen(fd, "we");
2592 /// UNNEEDED by elogind
2594 int symlink_atomic(const char *from, const char *to) {
2595 _cleanup_free_ char *t = NULL;
2601 r = tempfn_random(to, NULL, &t);
2605 if (symlink(from, t) < 0)
2608 if (rename(t, to) < 0) {
2616 int symlink_idempotent(const char *from, const char *to) {
2617 _cleanup_free_ char *p = NULL;
2623 if (symlink(from, to) < 0) {
2624 if (errno != EEXIST)
2627 r = readlink_malloc(to, &p);
2631 if (!streq(p, from))
2638 int mknod_atomic(const char *path, mode_t mode, dev_t dev) {
2639 _cleanup_free_ char *t = NULL;
2644 r = tempfn_random(path, NULL, &t);
2648 if (mknod(t, mode, dev) < 0)
2651 if (rename(t, path) < 0) {
2659 int mkfifo_atomic(const char *path, mode_t mode) {
2660 _cleanup_free_ char *t = NULL;
2665 r = tempfn_random(path, NULL, &t);
2669 if (mkfifo(t, mode) < 0)
2672 if (rename(t, path) < 0) {
2681 bool display_is_local(const char *display) {
2685 display[0] == ':' &&
2686 display[1] >= '0' &&
2690 int socket_from_display(const char *display, char **path) {
2697 if (!display_is_local(display))
2700 k = strspn(display+1, "0123456789");
2702 f = new(char, strlen("/tmp/.X11-unix/X") + k + 1);
2706 c = stpcpy(f, "/tmp/.X11-unix/X");
2707 memcpy(c, display+1, k);
2716 const char **username,
2717 uid_t *uid, gid_t *gid,
2719 const char **shell) {
2727 /* We enforce some special rules for uid=0: in order to avoid
2728 * NSS lookups for root we hardcode its data. */
2730 if (streq(*username, "root") || streq(*username, "0")) {
2748 if (parse_uid(*username, &u) >= 0) {
2752 /* If there are multiple users with the same id, make
2753 * sure to leave $USER to the configured value instead
2754 * of the first occurrence in the database. However if
2755 * the uid was configured by a numeric uid, then let's
2756 * pick the real username from /etc/passwd. */
2758 *username = p->pw_name;
2761 p = getpwnam(*username);
2765 return errno > 0 ? -errno : -ESRCH;
2777 *shell = p->pw_shell;
2782 char* uid_to_name(uid_t uid) {
2787 return strdup("root");
2791 return strdup(p->pw_name);
2793 if (asprintf(&r, UID_FMT, uid) < 0)
2799 char* gid_to_name(gid_t gid) {
2804 return strdup("root");
2808 return strdup(p->gr_name);
2810 if (asprintf(&r, GID_FMT, gid) < 0)
2816 int get_group_creds(const char **groupname, gid_t *gid) {
2822 /* We enforce some special rules for gid=0: in order to avoid
2823 * NSS lookups for root we hardcode its data. */
2825 if (streq(*groupname, "root") || streq(*groupname, "0")) {
2826 *groupname = "root";
2834 if (parse_gid(*groupname, &id) >= 0) {
2839 *groupname = g->gr_name;
2842 g = getgrnam(*groupname);
2846 return errno > 0 ? -errno : -ESRCH;
2854 int in_gid(gid_t gid) {
2856 int ngroups_max, r, i;
2858 if (getgid() == gid)
2861 if (getegid() == gid)
2864 ngroups_max = sysconf(_SC_NGROUPS_MAX);
2865 assert(ngroups_max > 0);
2867 gids = alloca(sizeof(gid_t) * ngroups_max);
2869 r = getgroups(ngroups_max, gids);
2873 for (i = 0; i < r; i++)
2880 /// UNNEEDED by elogind
2882 int in_group(const char *name) {
2886 r = get_group_creds(&name, &gid);
2893 int glob_exists(const char *path) {
2894 _cleanup_globfree_ glob_t g = {};
2900 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
2902 if (k == GLOB_NOMATCH)
2904 else if (k == GLOB_NOSPACE)
2907 return !strv_isempty(g.gl_pathv);
2909 return errno ? -errno : -EIO;
2912 int glob_extend(char ***strv, const char *path) {
2913 _cleanup_globfree_ glob_t g = {};
2918 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
2920 if (k == GLOB_NOMATCH)
2922 else if (k == GLOB_NOSPACE)
2924 else if (k != 0 || strv_isempty(g.gl_pathv))
2925 return errno ? -errno : -EIO;
2927 STRV_FOREACH(p, g.gl_pathv) {
2928 k = strv_extend(strv, *p);
2937 int dirent_ensure_type(DIR *d, struct dirent *de) {
2943 if (de->d_type != DT_UNKNOWN)
2946 if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
2950 S_ISREG(st.st_mode) ? DT_REG :
2951 S_ISDIR(st.st_mode) ? DT_DIR :
2952 S_ISLNK(st.st_mode) ? DT_LNK :
2953 S_ISFIFO(st.st_mode) ? DT_FIFO :
2954 S_ISSOCK(st.st_mode) ? DT_SOCK :
2955 S_ISCHR(st.st_mode) ? DT_CHR :
2956 S_ISBLK(st.st_mode) ? DT_BLK :
2962 int get_files_in_directory(const char *path, char ***list) {
2963 _cleanup_closedir_ DIR *d = NULL;
2964 size_t bufsize = 0, n = 0;
2965 _cleanup_strv_free_ char **l = NULL;
2969 /* Returns all files in a directory in *list, and the number
2970 * of files as return value. If list is NULL returns only the
2982 if (!de && errno != 0)
2987 dirent_ensure_type(d, de);
2989 if (!dirent_is_file(de))
2993 /* one extra slot is needed for the terminating NULL */
2994 if (!GREEDY_REALLOC(l, bufsize, n + 2))
2997 l[n] = strdup(de->d_name);
3008 l = NULL; /* avoid freeing */
3014 char *strjoin(const char *x, ...) {
3028 t = va_arg(ap, const char *);
3033 if (n > ((size_t) -1) - l) {
3057 t = va_arg(ap, const char *);
3071 bool is_main_thread(void) {
3072 static thread_local int cached = 0;
3074 if (_unlikely_(cached == 0))
3075 cached = getpid() == gettid() ? 1 : -1;
3080 /// UNNEEDED by elogind
3082 int block_get_whole_disk(dev_t d, dev_t *ret) {
3089 /* If it has a queue this is good enough for us */
3090 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", major(d), minor(d)) < 0)
3093 r = access(p, F_OK);
3101 /* If it is a partition find the originating device */
3102 if (asprintf(&p, "/sys/dev/block/%u:%u/partition", major(d), minor(d)) < 0)
3105 r = access(p, F_OK);
3111 /* Get parent dev_t */
3112 if (asprintf(&p, "/sys/dev/block/%u:%u/../dev", major(d), minor(d)) < 0)
3115 r = read_one_line_file(p, &s);
3121 r = sscanf(s, "%u:%u", &m, &n);
3127 /* Only return this if it is really good enough for us. */
3128 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", m, n) < 0)
3131 r = access(p, F_OK);
3135 *ret = makedev(m, n);
3143 static const char *const ioprio_class_table[] = {
3144 [IOPRIO_CLASS_NONE] = "none",
3145 [IOPRIO_CLASS_RT] = "realtime",
3146 [IOPRIO_CLASS_BE] = "best-effort",
3147 [IOPRIO_CLASS_IDLE] = "idle"
3150 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX);
3152 static const char *const sigchld_code_table[] = {
3153 [CLD_EXITED] = "exited",
3154 [CLD_KILLED] = "killed",
3155 [CLD_DUMPED] = "dumped",
3156 [CLD_TRAPPED] = "trapped",
3157 [CLD_STOPPED] = "stopped",
3158 [CLD_CONTINUED] = "continued",
3161 DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
3163 static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = {
3164 [LOG_FAC(LOG_KERN)] = "kern",
3165 [LOG_FAC(LOG_USER)] = "user",
3166 [LOG_FAC(LOG_MAIL)] = "mail",
3167 [LOG_FAC(LOG_DAEMON)] = "daemon",
3168 [LOG_FAC(LOG_AUTH)] = "auth",
3169 [LOG_FAC(LOG_SYSLOG)] = "syslog",
3170 [LOG_FAC(LOG_LPR)] = "lpr",
3171 [LOG_FAC(LOG_NEWS)] = "news",
3172 [LOG_FAC(LOG_UUCP)] = "uucp",
3173 [LOG_FAC(LOG_CRON)] = "cron",
3174 [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
3175 [LOG_FAC(LOG_FTP)] = "ftp",
3176 [LOG_FAC(LOG_LOCAL0)] = "local0",
3177 [LOG_FAC(LOG_LOCAL1)] = "local1",
3178 [LOG_FAC(LOG_LOCAL2)] = "local2",
3179 [LOG_FAC(LOG_LOCAL3)] = "local3",
3180 [LOG_FAC(LOG_LOCAL4)] = "local4",
3181 [LOG_FAC(LOG_LOCAL5)] = "local5",
3182 [LOG_FAC(LOG_LOCAL6)] = "local6",
3183 [LOG_FAC(LOG_LOCAL7)] = "local7"
3186 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_facility_unshifted, int, LOG_FAC(~0));
3188 static const char *const log_level_table[] = {
3189 [LOG_EMERG] = "emerg",
3190 [LOG_ALERT] = "alert",
3191 [LOG_CRIT] = "crit",
3193 [LOG_WARNING] = "warning",
3194 [LOG_NOTICE] = "notice",
3195 [LOG_INFO] = "info",
3196 [LOG_DEBUG] = "debug"
3199 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_level, int, LOG_DEBUG);
3201 static const char* const sched_policy_table[] = {
3202 [SCHED_OTHER] = "other",
3203 [SCHED_BATCH] = "batch",
3204 [SCHED_IDLE] = "idle",
3205 [SCHED_FIFO] = "fifo",
3209 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX);
3211 static const char* const rlimit_table[_RLIMIT_MAX] = {
3212 [RLIMIT_CPU] = "LimitCPU",
3213 [RLIMIT_FSIZE] = "LimitFSIZE",
3214 [RLIMIT_DATA] = "LimitDATA",
3215 [RLIMIT_STACK] = "LimitSTACK",
3216 [RLIMIT_CORE] = "LimitCORE",
3217 [RLIMIT_RSS] = "LimitRSS",
3218 [RLIMIT_NOFILE] = "LimitNOFILE",
3219 [RLIMIT_AS] = "LimitAS",
3220 [RLIMIT_NPROC] = "LimitNPROC",
3221 [RLIMIT_MEMLOCK] = "LimitMEMLOCK",
3222 [RLIMIT_LOCKS] = "LimitLOCKS",
3223 [RLIMIT_SIGPENDING] = "LimitSIGPENDING",
3224 [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE",
3225 [RLIMIT_NICE] = "LimitNICE",
3226 [RLIMIT_RTPRIO] = "LimitRTPRIO",
3227 [RLIMIT_RTTIME] = "LimitRTTIME"
3230 DEFINE_STRING_TABLE_LOOKUP(rlimit, int);
3232 static const char* const ip_tos_table[] = {
3233 [IPTOS_LOWDELAY] = "low-delay",
3234 [IPTOS_THROUGHPUT] = "throughput",
3235 [IPTOS_RELIABILITY] = "reliability",
3236 [IPTOS_LOWCOST] = "low-cost",
3239 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
3241 bool kexec_loaded(void) {
3242 bool loaded = false;
3245 if (read_one_line_file("/sys/kernel/kexec_loaded", &s) >= 0) {
3253 /// UNNEEDED by elogind
3255 int prot_from_flags(int flags) {
3257 switch (flags & O_ACCMODE) {
3266 return PROT_READ|PROT_WRITE;
3273 char *format_bytes(char *buf, size_t l, off_t t) {
3276 static const struct {
3280 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
3281 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
3282 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
3283 { "G", 1024ULL*1024ULL*1024ULL },
3284 { "M", 1024ULL*1024ULL },
3288 if (t == (off_t) -1)
3291 for (i = 0; i < ELEMENTSOF(table); i++) {
3293 if (t >= table[i].factor) {
3296 (unsigned long long) (t / table[i].factor),
3297 (unsigned long long) (((t*10ULL) / table[i].factor) % 10ULL),
3304 snprintf(buf, l, "%lluB", (unsigned long long) t);
3313 void* memdup(const void *p, size_t l) {
3326 int fd_inc_sndbuf(int fd, size_t n) {
3328 socklen_t l = sizeof(value);
3330 r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
3331 if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
3334 /* If we have the privileges we will ignore the kernel limit. */
3337 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUFFORCE, &value, sizeof(value)) < 0)
3338 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value)) < 0)
3344 int fd_inc_rcvbuf(int fd, size_t n) {
3346 socklen_t l = sizeof(value);
3348 r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
3349 if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
3352 /* If we have the privileges we will ignore the kernel limit. */
3355 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value)) < 0)
3356 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) < 0)
3361 int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
3362 bool stdout_is_tty, stderr_is_tty;
3363 pid_t parent_pid, agent_pid;
3364 sigset_t ss, saved_ss;
3372 /* Spawns a temporary TTY agent, making sure it goes away when
3375 parent_pid = getpid();
3377 /* First we temporarily block all signals, so that the new
3378 * child has them blocked initially. This way, we can be sure
3379 * that SIGTERMs are not lost we might send to the agent. */
3380 assert_se(sigfillset(&ss) >= 0);
3381 assert_se(sigprocmask(SIG_SETMASK, &ss, &saved_ss) >= 0);
3384 if (agent_pid < 0) {
3385 assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0);
3389 if (agent_pid != 0) {
3390 assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0);
3397 * Make sure the agent goes away when the parent dies */
3398 if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
3399 _exit(EXIT_FAILURE);
3401 /* Make sure we actually can kill the agent, if we need to, in
3402 * case somebody invoked us from a shell script that trapped
3403 * SIGTERM or so... */
3404 (void) reset_all_signal_handlers();
3405 (void) reset_signal_mask();
3407 /* Check whether our parent died before we were able
3408 * to set the death signal and unblock the signals */
3409 if (getppid() != parent_pid)
3410 _exit(EXIT_SUCCESS);
3412 /* Don't leak fds to the agent */
3413 close_all_fds(except, n_except);
3415 stdout_is_tty = isatty(STDOUT_FILENO);
3416 stderr_is_tty = isatty(STDERR_FILENO);
3418 if (!stdout_is_tty || !stderr_is_tty) {
3421 /* Detach from stdout/stderr. and reopen
3422 * /dev/tty for them. This is important to
3423 * ensure that when systemctl is started via
3424 * popen() or a similar call that expects to
3425 * read EOF we actually do generate EOF and
3426 * not delay this indefinitely by because we
3427 * keep an unused copy of stdin around. */
3428 fd = open("/dev/tty", O_WRONLY);
3430 log_error_errno(errno, "Failed to open /dev/tty: %m");
3431 _exit(EXIT_FAILURE);
3435 dup2(fd, STDOUT_FILENO);
3438 dup2(fd, STDERR_FILENO);
3444 /* Count arguments */
3446 for (n = 0; va_arg(ap, char*); n++)
3451 l = alloca(sizeof(char *) * (n + 1));
3453 /* Fill in arguments */
3455 for (i = 0; i <= n; i++)
3456 l[i] = va_arg(ap, char*);
3460 _exit(EXIT_FAILURE);
3463 /// UNNEEDED by elogind
3465 int setrlimit_closest(int resource, const struct rlimit *rlim) {
3466 struct rlimit highest, fixed;
3470 if (setrlimit(resource, rlim) >= 0)
3476 /* So we failed to set the desired setrlimit, then let's try
3477 * to get as close as we can */
3478 assert_se(getrlimit(resource, &highest) == 0);
3480 fixed.rlim_cur = MIN(rlim->rlim_cur, highest.rlim_max);
3481 fixed.rlim_max = MIN(rlim->rlim_max, highest.rlim_max);
3483 if (setrlimit(resource, &fixed) < 0)
3489 bool http_etag_is_valid(const char *etag) {
3493 if (!endswith(etag, "\""))
3496 if (!startswith(etag, "\"") && !startswith(etag, "W/\""))
3503 bool http_url_is_valid(const char *url) {
3509 p = startswith(url, "http://");
3511 p = startswith(url, "https://");
3518 return ascii_is_valid(p);
3521 bool documentation_url_is_valid(const char *url) {
3527 if (http_url_is_valid(url))
3530 p = startswith(url, "file:/");
3532 p = startswith(url, "info:");
3534 p = startswith(url, "man:");
3539 return ascii_is_valid(p);
3542 bool in_initrd(void) {
3543 static int saved = -1;
3549 /* We make two checks here:
3551 * 1. the flag file /etc/initrd-release must exist
3552 * 2. the root file system must be a memory file system
3554 * The second check is extra paranoia, since misdetecting an
3555 * initrd can have bad bad consequences due the initrd
3556 * emptying when transititioning to the main systemd.
3559 saved = access("/etc/initrd-release", F_OK) >= 0 &&
3560 statfs("/", &s) >= 0 &&
3561 is_temporary_fs(&s);
3566 int get_home_dir(char **_h) {
3574 /* Take the user specified one */
3575 e = secure_getenv("HOME");
3576 if (e && path_is_absolute(e)) {
3585 /* Hardcode home directory for root to avoid NSS */
3588 h = strdup("/root");
3596 /* Check the database... */
3600 return errno > 0 ? -errno : -ESRCH;
3602 if (!path_is_absolute(p->pw_dir))
3605 h = strdup(p->pw_dir);
3613 /// UNNEEDED by elogind
3615 int get_shell(char **_s) {
3623 /* Take the user specified one */
3624 e = getenv("SHELL");
3634 /* Hardcode home directory for root to avoid NSS */
3637 s = strdup("/bin/sh");
3645 /* Check the database... */
3649 return errno > 0 ? -errno : -ESRCH;
3651 if (!path_is_absolute(p->pw_shell))
3654 s = strdup(p->pw_shell);
3663 bool filename_is_valid(const char *p) {
3677 if (strlen(p) > FILENAME_MAX)
3683 bool string_is_safe(const char *p) {
3689 for (t = p; *t; t++) {
3690 if (*t > 0 && *t < ' ')
3693 if (strchr("\\\"\'\0x7f", *t))
3701 * Check if a string contains control characters. If 'ok' is non-NULL
3702 * it may be a string containing additional CCs to be considered OK.
3704 bool string_has_cc(const char *p, const char *ok) {
3709 for (t = p; *t; t++) {
3710 if (ok && strchr(ok, *t))
3713 if (*t > 0 && *t < ' ')
3723 bool path_is_safe(const char *p) {
3728 if (streq(p, "..") || startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../"))
3731 if (strlen(p)+1 > PATH_MAX)
3734 /* The following two checks are not really dangerous, but hey, they still are confusing */
3735 if (streq(p, ".") || startswith(p, "./") || endswith(p, "/.") || strstr(p, "/./"))
3738 if (strstr(p, "//"))
3744 /// UNNEEDED by elogind
3746 /* hey glibc, APIs with callbacks without a user pointer are so useless */
3747 void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
3748 int (*compar) (const void *, const void *, void *), void *arg) {
3757 p = (void *)(((const char *) base) + (idx * size));
3758 comparison = compar(key, p, arg);
3761 else if (comparison > 0)
3769 void init_gettext(void) {
3770 setlocale(LC_ALL, "");
3771 textdomain(GETTEXT_PACKAGE);
3775 bool is_locale_utf8(void) {
3777 static int cached_answer = -1;
3779 if (cached_answer >= 0)
3782 if (!setlocale(LC_ALL, "")) {
3783 cached_answer = true;
3787 set = nl_langinfo(CODESET);
3789 cached_answer = true;
3793 if (streq(set, "UTF-8")) {
3794 cached_answer = true;
3798 /* For LC_CTYPE=="C" return true, because CTYPE is effectly
3799 * unset and everything can do to UTF-8 nowadays. */
3800 set = setlocale(LC_CTYPE, NULL);
3802 cached_answer = true;
3806 /* Check result, but ignore the result if C was set
3810 !getenv("LC_ALL") &&
3811 !getenv("LC_CTYPE") &&
3815 return (bool) cached_answer;
3818 const char *draw_special_char(DrawSpecialChar ch) {
3819 static const char *draw_table[2][_DRAW_SPECIAL_CHAR_MAX] = {
3822 [DRAW_TREE_VERTICAL] = "\342\224\202 ", /* │ */
3823 [DRAW_TREE_BRANCH] = "\342\224\234\342\224\200", /* ├─ */
3824 [DRAW_TREE_RIGHT] = "\342\224\224\342\224\200", /* └─ */
3825 [DRAW_TREE_SPACE] = " ", /* */
3826 [DRAW_TRIANGULAR_BULLET] = "\342\200\243", /* ‣ */
3827 [DRAW_BLACK_CIRCLE] = "\342\227\217", /* ● */
3828 [DRAW_ARROW] = "\342\206\222", /* → */
3829 [DRAW_DASH] = "\342\200\223", /* – */
3832 /* ASCII fallback */ {
3833 [DRAW_TREE_VERTICAL] = "| ",
3834 [DRAW_TREE_BRANCH] = "|-",
3835 [DRAW_TREE_RIGHT] = "`-",
3836 [DRAW_TREE_SPACE] = " ",
3837 [DRAW_TRIANGULAR_BULLET] = ">",
3838 [DRAW_BLACK_CIRCLE] = "*",
3839 [DRAW_ARROW] = "->",
3844 return draw_table[!is_locale_utf8()][ch];
3847 /// UNNEEDED by elogind
3849 char *strreplace(const char *text, const char *old_string, const char *new_string) {
3852 size_t l, old_len, new_len;
3858 old_len = strlen(old_string);
3859 new_len = strlen(new_string);
3872 if (!startswith(f, old_string)) {
3878 nl = l - old_len + new_len;
3879 a = realloc(r, nl + 1);
3887 t = stpcpy(t, new_string);
3899 char *strip_tab_ansi(char **ibuf, size_t *_isz) {
3900 const char *i, *begin = NULL;
3905 } state = STATE_OTHER;
3907 size_t osz = 0, isz;
3913 /* Strips ANSI color and replaces TABs by 8 spaces */
3915 isz = _isz ? *_isz : strlen(*ibuf);
3917 f = open_memstream(&obuf, &osz);
3921 for (i = *ibuf; i < *ibuf + isz + 1; i++) {
3926 if (i >= *ibuf + isz) /* EOT */
3928 else if (*i == '\x1B')
3929 state = STATE_ESCAPE;
3930 else if (*i == '\t')
3937 if (i >= *ibuf + isz) { /* EOT */
3940 } else if (*i == '[') {
3941 state = STATE_BRACKET;
3946 state = STATE_OTHER;
3953 if (i >= *ibuf + isz || /* EOT */
3954 (!(*i >= '0' && *i <= '9') && *i != ';' && *i != 'm')) {
3957 state = STATE_OTHER;
3959 } else if (*i == 'm')
3960 state = STATE_OTHER;
3982 int on_ac_power(void) {
3983 bool found_offline = false, found_online = false;
3984 _cleanup_closedir_ DIR *d = NULL;
3986 d = opendir("/sys/class/power_supply");
3988 return errno == ENOENT ? true : -errno;
3992 _cleanup_close_ int fd = -1, device = -1;
3998 if (!de && errno != 0)
4004 if (hidden_file(de->d_name))
4007 device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY);
4009 if (errno == ENOENT || errno == ENOTDIR)
4015 fd = openat(device, "type", O_RDONLY|O_CLOEXEC|O_NOCTTY);
4017 if (errno == ENOENT)
4023 n = read(fd, contents, sizeof(contents));
4027 if (n != 6 || memcmp(contents, "Mains\n", 6))
4031 fd = openat(device, "online", O_RDONLY|O_CLOEXEC|O_NOCTTY);
4033 if (errno == ENOENT)
4039 n = read(fd, contents, sizeof(contents));
4043 if (n != 2 || contents[1] != '\n')
4046 if (contents[0] == '1') {
4047 found_online = true;
4049 } else if (contents[0] == '0')
4050 found_offline = true;
4055 return found_online || !found_offline;
4059 static int search_and_fopen_internal(const char *path, const char *mode, const char *root, char **search, FILE **_f) {
4066 if (!path_strv_resolve_uniq(search, root))
4069 STRV_FOREACH(i, search) {
4070 _cleanup_free_ char *p = NULL;
4074 p = strjoin(root, *i, "/", path, NULL);
4076 p = strjoin(*i, "/", path, NULL);
4086 if (errno != ENOENT)
4093 int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f) {
4094 _cleanup_strv_free_ char **copy = NULL;
4100 if (path_is_absolute(path)) {
4103 f = fopen(path, mode);
4112 copy = strv_copy((char**) search);
4116 return search_and_fopen_internal(path, mode, root, copy, _f);
4119 /// UNNEEDED by elogind
4121 int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f) {
4122 _cleanup_strv_free_ char **s = NULL;
4124 if (path_is_absolute(path)) {
4127 f = fopen(path, mode);
4136 s = strv_split_nulstr(search);
4140 return search_and_fopen_internal(path, mode, root, s, _f);
4144 char *strextend(char **x, ...) {
4151 l = f = *x ? strlen(*x) : 0;
4158 t = va_arg(ap, const char *);
4163 if (n > ((size_t) -1) - l) {
4172 r = realloc(*x, l+1);
4182 t = va_arg(ap, const char *);
4196 char *strrep(const char *s, unsigned n) {
4204 p = r = malloc(l * n + 1);
4208 for (i = 0; i < n; i++)
4215 void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) {
4222 if (*allocated >= need)
4225 newalloc = MAX(need * 2, 64u / size);
4226 a = newalloc * size;
4228 /* check for overflows */
4229 if (a < size * need)
4237 *allocated = newalloc;
4241 void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size) {
4250 q = greedy_realloc(p, allocated, need, size);
4254 if (*allocated > prev)
4255 memzero(q + prev * size, (*allocated - prev) * size);
4260 bool id128_is_valid(const char *s) {
4266 /* Simple formatted 128bit hex string */
4268 for (i = 0; i < l; i++) {
4271 if (!(c >= '0' && c <= '9') &&
4272 !(c >= 'a' && c <= 'z') &&
4273 !(c >= 'A' && c <= 'Z'))
4277 } else if (l == 36) {
4279 /* Formatted UUID */
4281 for (i = 0; i < l; i++) {
4284 if ((i == 8 || i == 13 || i == 18 || i == 23)) {
4288 if (!(c >= '0' && c <= '9') &&
4289 !(c >= 'a' && c <= 'z') &&
4290 !(c >= 'A' && c <= 'Z'))
4301 /// UNNEEDED by elogind
4303 int split_pair(const char *s, const char *sep, char **l, char **r) {
4318 a = strndup(s, x - s);
4322 b = strdup(x + strlen(sep));
4334 int shall_restore_state(void) {
4335 _cleanup_free_ char *value = NULL;
4338 r = get_proc_cmdline_key("systemd.restore_state=", &value);
4344 return parse_boolean(value) != 0;
4348 int proc_cmdline(char **ret) {
4351 if (detect_container(NULL) > 0)
4352 return get_process_cmdline(1, 0, false, ret);
4354 return read_one_line_file("/proc/cmdline", ret);
4357 int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) {
4358 _cleanup_free_ char *line = NULL;
4364 r = proc_cmdline(&line);
4370 _cleanup_free_ char *word = NULL;
4373 r = unquote_first_word(&p, &word, UNQUOTE_RELAX);
4379 /* Filter out arguments that are intended only for the
4381 if (!in_initrd() && startswith(word, "rd."))
4384 value = strchr(word, '=');
4388 r = parse_item(word, value);
4396 int get_proc_cmdline_key(const char *key, char **value) {
4397 _cleanup_free_ char *line = NULL, *ret = NULL;
4404 r = proc_cmdline(&line);
4410 _cleanup_free_ char *word = NULL;
4413 r = unquote_first_word(&p, &word, UNQUOTE_RELAX);
4419 /* Filter out arguments that are intended only for the
4421 if (!in_initrd() && startswith(word, "rd."))
4425 e = startswith(word, key);
4429 r = free_and_strdup(&ret, e);
4435 if (streq(word, key))
4449 /// UNNEEDED by elogind
4451 int container_get_leader(const char *machine, pid_t *pid) {
4452 _cleanup_free_ char *s = NULL, *class = NULL;
4460 p = strjoina("/run/systemd/machines/", machine);
4461 r = parse_env_file(p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL);
4469 if (!streq_ptr(class, "container"))
4472 r = parse_pid(s, &leader);
4483 int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *root_fd) {
4484 _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, netnsfd = -1;
4492 mntns = procfs_file_alloca(pid, "ns/mnt");
4493 mntnsfd = open(mntns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
4501 pidns = procfs_file_alloca(pid, "ns/pid");
4502 pidnsfd = open(pidns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
4510 netns = procfs_file_alloca(pid, "ns/net");
4511 netnsfd = open(netns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
4519 root = procfs_file_alloca(pid, "root");
4520 rfd = open(root, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
4526 *pidns_fd = pidnsfd;
4529 *mntns_fd = mntnsfd;
4532 *netns_fd = netnsfd;
4537 pidnsfd = mntnsfd = netnsfd = -1;
4542 int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int root_fd) {
4545 if (setns(pidns_fd, CLONE_NEWPID) < 0)
4549 if (setns(mntns_fd, CLONE_NEWNS) < 0)
4553 if (setns(netns_fd, CLONE_NEWNET) < 0)
4557 if (fchdir(root_fd) < 0)
4560 if (chroot(".") < 0)
4564 return reset_uid_gid();
4567 int getpeercred(int fd, struct ucred *ucred) {
4568 socklen_t n = sizeof(struct ucred);
4575 r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &u, &n);
4579 if (n != sizeof(struct ucred))
4582 /* Check if the data is actually useful and not suppressed due
4583 * to namespacing issues */
4586 if (u.uid == UID_INVALID)
4588 if (u.gid == GID_INVALID)
4595 int getpeersec(int fd, char **ret) {
4607 r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
4611 if (errno != ERANGE)
4618 r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
4634 /* This is much like like mkostemp() but is subject to umask(). */
4635 int mkostemp_safe(char *pattern, int flags) {
4636 _cleanup_umask_ mode_t u;
4643 fd = mkostemp(pattern, flags);
4650 /// UNNEEDED by elogind
4652 int open_tmpfile(const char *path, int flags) {
4659 /* Try O_TMPFILE first, if it is supported */
4660 fd = open(path, flags|O_TMPFILE|O_EXCL, S_IRUSR|S_IWUSR);
4665 /* Fall back to unguessable name + unlinking */
4666 p = strjoina(path, "/systemd-tmp-XXXXXX");
4668 fd = mkostemp_safe(p, flags);
4677 int fd_warn_permissions(const char *path, int fd) {
4680 if (fstat(fd, &st) < 0)
4683 if (st.st_mode & 0111)
4684 log_warning("Configuration file %s is marked executable. Please remove executable permission bits. Proceeding anyway.", path);
4686 if (st.st_mode & 0002)
4687 log_warning("Configuration file %s is marked world-writable. Please remove world writability permission bits. Proceeding anyway.", path);
4689 if (getpid() == 1 && (st.st_mode & 0044) != 0044)
4690 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);
4695 /// UNNEEDED by elogind
4697 unsigned long personality_from_string(const char *p) {
4699 /* Parse a personality specifier. We introduce our own
4700 * identifiers that indicate specific ABIs, rather than just
4701 * hints regarding the register size, since we want to keep
4702 * things open for multiple locally supported ABIs for the
4703 * same register size. We try to reuse the ABI identifiers
4704 * used by libseccomp. */
4706 #if defined(__x86_64__)
4708 if (streq(p, "x86"))
4711 if (streq(p, "x86-64"))
4714 #elif defined(__i386__)
4716 if (streq(p, "x86"))
4720 return PERSONALITY_INVALID;
4724 /// UNNEEDED by elogind
4726 const char* personality_to_string(unsigned long p) {
4728 #if defined(__x86_64__)
4730 if (p == PER_LINUX32)
4736 #elif defined(__i386__)
4746 uint64_t physical_memory(void) {
4749 /* We return this as uint64_t in case we are running as 32bit
4750 * process on a 64bit kernel with huge amounts of memory */
4752 mem = sysconf(_SC_PHYS_PAGES);
4755 return (uint64_t) mem * (uint64_t) page_size();
4758 /// UNNEEDED by elogind
4760 void hexdump(FILE *f, const void *p, size_t s) {
4761 const uint8_t *b = p;
4764 assert(s == 0 || b);
4769 fprintf(f, "%04x ", n);
4771 for (i = 0; i < 16; i++) {
4776 fprintf(f, "%02x ", b[i]);
4784 for (i = 0; i < 16; i++) {
4789 fputc(isprint(b[i]) ? (char) b[i] : '.', f);
4803 int update_reboot_param_file(const char *param) {
4808 r = write_string_file(REBOOT_PARAM_FILE, param, WRITE_STRING_FILE_CREATE);
4810 log_error("Failed to write reboot param to "
4811 REBOOT_PARAM_FILE": %s", strerror(-r));
4813 unlink(REBOOT_PARAM_FILE);
4818 int umount_recursive(const char *prefix, int flags) {
4822 /* Try to umount everything recursively below a
4823 * directory. Also, take care of stacked mounts, and keep
4824 * unmounting them until they are gone. */
4827 _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
4832 proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
4833 if (!proc_self_mountinfo)
4837 _cleanup_free_ char *path = NULL, *p = NULL;
4840 k = fscanf(proc_self_mountinfo,
4841 "%*s " /* (1) mount id */
4842 "%*s " /* (2) parent id */
4843 "%*s " /* (3) major:minor */
4844 "%*s " /* (4) root */
4845 "%ms " /* (5) mount point */
4846 "%*s" /* (6) mount options */
4847 "%*[^-]" /* (7) optional fields */
4848 "- " /* (8) separator */
4849 "%*s " /* (9) file system type */
4850 "%*s" /* (10) mount source */
4851 "%*s" /* (11) mount options 2 */
4852 "%*[^\n]", /* some rubbish at the end */
4861 r = cunescape(path, UNESCAPE_RELAX, &p);
4865 if (!path_startswith(p, prefix))
4868 if (umount2(p, flags) < 0) {
4884 static int get_mount_flags(const char *path, unsigned long *flags) {
4887 if (statvfs(path, &buf) < 0)
4889 *flags = buf.f_flag;
4893 int bind_remount_recursive(const char *prefix, bool ro) {
4894 _cleanup_set_free_free_ Set *done = NULL;
4895 _cleanup_free_ char *cleaned = NULL;
4898 /* Recursively remount a directory (and all its submounts)
4899 * read-only or read-write. If the directory is already
4900 * mounted, we reuse the mount and simply mark it
4901 * MS_BIND|MS_RDONLY (or remove the MS_RDONLY for read-write
4902 * operation). If it isn't we first make it one. Afterwards we
4903 * apply MS_BIND|MS_RDONLY (or remove MS_RDONLY) to all
4904 * submounts we can access, too. When mounts are stacked on
4905 * the same mount point we only care for each individual
4906 * "top-level" mount on each point, as we cannot
4907 * influence/access the underlying mounts anyway. We do not
4908 * have any effect on future submounts that might get
4909 * propagated, they migt be writable. This includes future
4910 * submounts that have been triggered via autofs. */
4912 cleaned = strdup(prefix);
4916 path_kill_slashes(cleaned);
4918 done = set_new(&string_hash_ops);
4923 _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
4924 _cleanup_set_free_free_ Set *todo = NULL;
4925 bool top_autofs = false;
4927 unsigned long orig_flags;
4929 todo = set_new(&string_hash_ops);
4933 proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
4934 if (!proc_self_mountinfo)
4938 _cleanup_free_ char *path = NULL, *p = NULL, *type = NULL;
4941 k = fscanf(proc_self_mountinfo,
4942 "%*s " /* (1) mount id */
4943 "%*s " /* (2) parent id */
4944 "%*s " /* (3) major:minor */
4945 "%*s " /* (4) root */
4946 "%ms " /* (5) mount point */
4947 "%*s" /* (6) mount options (superblock) */
4948 "%*[^-]" /* (7) optional fields */
4949 "- " /* (8) separator */
4950 "%ms " /* (9) file system type */
4951 "%*s" /* (10) mount source */
4952 "%*s" /* (11) mount options (bind mount) */
4953 "%*[^\n]", /* some rubbish at the end */
4963 r = cunescape(path, UNESCAPE_RELAX, &p);
4967 /* Let's ignore autofs mounts. If they aren't
4968 * triggered yet, we want to avoid triggering
4969 * them, as we don't make any guarantees for
4970 * future submounts anyway. If they are
4971 * already triggered, then we will find
4972 * another entry for this. */
4973 if (streq(type, "autofs")) {
4974 top_autofs = top_autofs || path_equal(cleaned, p);
4978 if (path_startswith(p, cleaned) &&
4979 !set_contains(done, p)) {
4981 r = set_consume(todo, p);
4991 /* If we have no submounts to process anymore and if
4992 * the root is either already done, or an autofs, we
4994 if (set_isempty(todo) &&
4995 (top_autofs || set_contains(done, cleaned)))
4998 if (!set_contains(done, cleaned) &&
4999 !set_contains(todo, cleaned)) {
5000 /* The prefix directory itself is not yet a
5001 * mount, make it one. */
5002 if (mount(cleaned, cleaned, NULL, MS_BIND|MS_REC, NULL) < 0)
5006 (void) get_mount_flags(cleaned, &orig_flags);
5007 orig_flags &= ~MS_RDONLY;
5009 if (mount(NULL, prefix, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0)
5012 x = strdup(cleaned);
5016 r = set_consume(done, x);
5021 while ((x = set_steal_first(todo))) {
5023 r = set_consume(done, x);
5024 if (r == -EEXIST || r == 0)
5029 /* Try to reuse the original flag set, but
5030 * don't care for errors, in case of
5031 * obstructed mounts */
5033 (void) get_mount_flags(x, &orig_flags);
5034 orig_flags &= ~MS_RDONLY;
5036 if (mount(NULL, x, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0) {
5038 /* Deal with mount points that are
5039 * obstructed by a later mount */
5041 if (errno != ENOENT)
5050 int fflush_and_check(FILE *f) {
5057 return errno ? -errno : -EIO;
5062 int tempfn_xxxxxx(const char *p, const char *extra, char **ret) {
5074 * /foo/bar/.#<extra>waldoXXXXXX
5078 if (!filename_is_valid(fn))
5084 t = new(char, strlen(p) + 2 + strlen(extra) + 6 + 1);
5088 strcpy(stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), extra), fn), "XXXXXX");
5090 *ret = path_kill_slashes(t);
5094 int tempfn_random(const char *p, const char *extra, char **ret) {
5108 * /foo/bar/.#<extra>waldobaa2a261115984a9
5112 if (!filename_is_valid(fn))
5118 t = new(char, strlen(p) + 2 + strlen(extra) + 16 + 1);
5122 x = stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), extra), fn);
5125 for (i = 0; i < 16; i++) {
5126 *(x++) = hexchar(u & 0xF);
5132 *ret = path_kill_slashes(t);
5136 /// UNNEEDED by elogind
5138 int tempfn_random_child(const char *p, const char *extra, char **ret) {
5149 * /foo/bar/waldo/.#<extra>3c2b6219aa75d7d0
5155 t = new(char, strlen(p) + 3 + strlen(extra) + 16 + 1);
5159 x = stpcpy(stpcpy(stpcpy(t, p), "/.#"), extra);
5162 for (i = 0; i < 16; i++) {
5163 *(x++) = hexchar(u & 0xF);
5169 *ret = path_kill_slashes(t);
5173 int take_password_lock(const char *root) {
5175 struct flock flock = {
5177 .l_whence = SEEK_SET,
5185 /* This is roughly the same as lckpwdf(), but not as awful. We
5186 * don't want to use alarm() and signals, hence we implement
5187 * our own trivial version of this.
5189 * Note that shadow-utils also takes per-database locks in
5190 * addition to lckpwdf(). However, we don't given that they
5191 * are redundant as they they invoke lckpwdf() first and keep
5192 * it during everything they do. The per-database locks are
5193 * awfully racy, and thus we just won't do them. */
5196 path = strjoina(root, "/etc/.pwd.lock");
5198 path = "/etc/.pwd.lock";
5200 fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0600);
5204 r = fcntl(fd, F_SETLKW, &flock);
5213 int is_symlink(const char *path) {
5216 if (lstat(path, &info) < 0)
5219 return !!S_ISLNK(info.st_mode);
5223 int is_dir(const char* path, bool follow) {
5228 r = stat(path, &st);
5230 r = lstat(path, &st);
5234 return !!S_ISDIR(st.st_mode);
5237 /// UNNEEDED by elogind
5239 int is_device_node(const char *path) {
5242 if (lstat(path, &info) < 0)
5245 return !!(S_ISBLK(info.st_mode) || S_ISCHR(info.st_mode));
5249 int unquote_first_word(const char **p, char **ret, UnquoteFlags flags) {
5250 _cleanup_free_ char *s = NULL;
5251 size_t allocated = 0, sz = 0;
5259 SINGLE_QUOTE_ESCAPE,
5261 DOUBLE_QUOTE_ESCAPE,
5269 /* Parses the first word of a string, and returns it in
5270 * *ret. Removes all quotes in the process. When parsing fails
5271 * (because of an uneven number of quotes or similar), leaves
5272 * the pointer *p at the first invalid character. */
5282 else if (strchr(WHITESPACE, c))
5292 state = SINGLE_QUOTE;
5294 state = VALUE_ESCAPE;
5296 state = DOUBLE_QUOTE;
5297 else if (strchr(WHITESPACE, c))
5300 if (!GREEDY_REALLOC(s, allocated, sz+2))
5310 if (flags & UNQUOTE_RELAX)
5313 } else if (c == '\'')
5316 state = SINGLE_QUOTE_ESCAPE;
5318 if (!GREEDY_REALLOC(s, allocated, sz+2))
5332 state = DOUBLE_QUOTE_ESCAPE;
5334 if (!GREEDY_REALLOC(s, allocated, sz+2))
5342 case SINGLE_QUOTE_ESCAPE:
5343 case DOUBLE_QUOTE_ESCAPE:
5345 if (!GREEDY_REALLOC(s, allocated, sz+7))
5349 if ((flags & UNQUOTE_CUNESCAPE_RELAX) &&
5350 (state == VALUE_ESCAPE || flags & UNQUOTE_RELAX)) {
5351 /* If we find an unquoted trailing backslash and we're in
5352 * UNQUOTE_CUNESCAPE_RELAX mode, keep it verbatim in the
5355 * Unbalanced quotes will only be allowed in UNQUOTE_RELAX
5356 * mode, UNQUOTE_CUNESCAP_RELAX mode does not allow them.
5361 if (flags & UNQUOTE_RELAX)
5366 if (flags & UNQUOTE_CUNESCAPE) {
5369 r = cunescape_one(*p, (size_t) -1, &c, &u);
5371 if (flags & UNQUOTE_CUNESCAPE_RELAX) {
5382 s[sz++] = c; /* normal explicit char */
5384 sz += utf8_encode_unichar(s + sz, u); /* unicode chars we'll encode as utf8 */
5389 state = (state == SINGLE_QUOTE_ESCAPE) ? SINGLE_QUOTE :
5390 (state == DOUBLE_QUOTE_ESCAPE) ? DOUBLE_QUOTE :
5397 if (!strchr(WHITESPACE, c))
5419 /// UNNEEDED by elogind
5421 int unquote_first_word_and_warn(
5426 const char *filename,
5428 const char *rvalue) {
5429 /* Try to unquote it, if it fails, warn about it and try again but this
5430 * time using UNQUOTE_CUNESCAPE_RELAX to keep the backslashes verbatim
5431 * in invalid escape sequences. */
5436 r = unquote_first_word(p, ret, flags);
5437 if (r < 0 && !(flags&UNQUOTE_CUNESCAPE_RELAX)) {
5438 /* Retry it with UNQUOTE_CUNESCAPE_RELAX. */
5440 r = unquote_first_word(p, ret, flags|UNQUOTE_CUNESCAPE_RELAX);
5442 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
5443 "Unbalanced quoting in command line, ignoring: \"%s\"", rvalue);
5445 log_syntax(unit, LOG_WARNING, filename, line, EINVAL,
5446 "Invalid escape sequences in command line: \"%s\"", rvalue);
5451 int unquote_many_words(const char **p, UnquoteFlags flags, ...) {
5456 /* Parses a number of words from a string, stripping any
5457 * quotes if necessary. */
5461 /* Count how many words are expected */
5462 va_start(ap, flags);
5464 if (!va_arg(ap, char **))
5473 /* Read all words into a temporary array */
5474 l = newa0(char*, n);
5475 for (c = 0; c < n; c++) {
5477 r = unquote_first_word(p, &l[c], flags);
5481 for (j = 0; j < c; j++)
5491 /* If we managed to parse all words, return them in the passed
5493 va_start(ap, flags);
5494 for (i = 0; i < n; i++) {
5497 v = va_arg(ap, char **);
5508 int free_and_strdup(char **p, const char *s) {
5513 /* Replaces a string pointer with an strdup()ed new string,
5514 * possibly freeing the old one. */
5516 if (streq_ptr(*p, s))
5532 /// UNNEEDED by elogind
5534 int ptsname_malloc(int fd, char **ret) {
5547 if (ptsname_r(fd, c, l) == 0) {
5551 if (errno != ERANGE) {
5561 int openpt_in_namespace(pid_t pid, int flags) {
5562 _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, rootfd = -1;
5563 _cleanup_close_pair_ int pair[2] = { -1, -1 };
5565 struct cmsghdr cmsghdr;
5566 uint8_t buf[CMSG_SPACE(sizeof(int))];
5568 struct msghdr mh = {
5569 .msg_control = &control,
5570 .msg_controllen = sizeof(control),
5572 struct cmsghdr *cmsg;
5579 r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &rootfd);
5583 if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
5593 pair[0] = safe_close(pair[0]);
5595 r = namespace_enter(pidnsfd, mntnsfd, -1, rootfd);
5597 _exit(EXIT_FAILURE);
5599 master = posix_openpt(flags);
5601 _exit(EXIT_FAILURE);
5603 cmsg = CMSG_FIRSTHDR(&mh);
5604 cmsg->cmsg_level = SOL_SOCKET;
5605 cmsg->cmsg_type = SCM_RIGHTS;
5606 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
5607 memcpy(CMSG_DATA(cmsg), &master, sizeof(int));
5609 mh.msg_controllen = cmsg->cmsg_len;
5611 if (sendmsg(pair[1], &mh, MSG_NOSIGNAL) < 0)
5612 _exit(EXIT_FAILURE);
5614 _exit(EXIT_SUCCESS);
5617 pair[1] = safe_close(pair[1]);
5619 r = wait_for_terminate(child, &si);
5622 if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
5625 if (recvmsg(pair[0], &mh, MSG_NOSIGNAL|MSG_CMSG_CLOEXEC) < 0)
5628 CMSG_FOREACH(cmsg, &mh)
5629 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
5633 fds = (int*) CMSG_DATA(cmsg);
5634 n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
5637 close_many(fds, n_fds);
5648 ssize_t fgetxattrat_fake(int dirfd, const char *filename, const char *attribute, void *value, size_t size, int flags) {
5649 _cleanup_close_ int fd = -1;
5652 /* The kernel doesn't have a fgetxattrat() command, hence let's emulate one */
5654 fd = openat(dirfd, filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOATIME|(flags & AT_SYMLINK_NOFOLLOW ? O_NOFOLLOW : 0));
5658 l = fgetxattr(fd, attribute, value, size);
5665 static int parse_crtime(le64_t le, usec_t *usec) {
5671 if (u == 0 || u == (uint64_t) -1)
5678 int fd_getcrtime(int fd, usec_t *usec) {
5685 /* Until Linux gets a real concept of birthtime/creation time,
5686 * let's fake one with xattrs */
5688 n = fgetxattr(fd, "user.crtime_usec", &le, sizeof(le));
5691 if (n != sizeof(le))
5694 return parse_crtime(le, usec);
5697 /// UNNEEDED by elogind
5699 int fd_getcrtime_at(int dirfd, const char *name, usec_t *usec, int flags) {
5703 n = fgetxattrat_fake(dirfd, name, "user.crtime_usec", &le, sizeof(le), flags);
5706 if (n != sizeof(le))
5709 return parse_crtime(le, usec);
5712 int path_getcrtime(const char *p, usec_t *usec) {
5719 n = getxattr(p, "user.crtime_usec", &le, sizeof(le));
5722 if (n != sizeof(le))
5725 return parse_crtime(le, usec);
5728 int fd_setcrtime(int fd, usec_t usec) {
5734 usec = now(CLOCK_REALTIME);
5736 le = htole64((uint64_t) usec);
5737 if (fsetxattr(fd, "user.crtime_usec", &le, sizeof(le), 0) < 0)
5743 int same_fd(int a, int b) {
5744 struct stat sta, stb;
5751 /* Compares two file descriptors. Note that semantics are
5752 * quite different depending on whether we have kcmp() or we
5753 * don't. If we have kcmp() this will only return true for
5754 * dup()ed file descriptors, but not otherwise. If we don't
5755 * have kcmp() this will also return true for two fds of the same
5756 * file, created by separate open() calls. Since we use this
5757 * call mostly for filtering out duplicates in the fd store
5758 * this difference hopefully doesn't matter too much. */
5763 /* Try to use kcmp() if we have it. */
5765 r = kcmp(pid, pid, KCMP_FILE, a, b);
5770 if (errno != ENOSYS)
5773 /* We don't have kcmp(), use fstat() instead. */
5774 if (fstat(a, &sta) < 0)
5777 if (fstat(b, &stb) < 0)
5780 if ((sta.st_mode & S_IFMT) != (stb.st_mode & S_IFMT))
5783 /* We consider all device fds different, since two device fds
5784 * might refer to quite different device contexts even though
5785 * they share the same inode and backing dev_t. */
5787 if (S_ISCHR(sta.st_mode) || S_ISBLK(sta.st_mode))
5790 if (sta.st_dev != stb.st_dev || sta.st_ino != stb.st_ino)
5793 /* The fds refer to the same inode on disk, let's also check
5794 * if they have the same fd flags. This is useful to
5795 * distinguish the read and write side of a pipe created with
5797 fa = fcntl(a, F_GETFL);
5801 fb = fcntl(b, F_GETFL);
5809 int chattr_fd(int fd, unsigned value, unsigned mask) {
5810 unsigned old_attr, new_attr;
5815 if (fstat(fd, &st) < 0)
5818 /* Explicitly check whether this is a regular file or
5819 * directory. If it is anything else (such as a device node or
5820 * fifo), then the ioctl will not hit the file systems but
5821 * possibly drivers, where the ioctl might have different
5822 * effects. Notably, DRM is using the same ioctl() number. */
5824 if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode))
5830 if (ioctl(fd, FS_IOC_GETFLAGS, &old_attr) < 0)
5833 new_attr = (old_attr & ~mask) | (value & mask);
5834 if (new_attr == old_attr)
5837 if (ioctl(fd, FS_IOC_SETFLAGS, &new_attr) < 0)
5843 /// UNNEEDED by elogind
5845 int chattr_path(const char *p, unsigned value, unsigned mask) {
5846 _cleanup_close_ int fd = -1;
5853 fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
5857 return chattr_fd(fd, value, mask);
5861 int read_attr_fd(int fd, unsigned *ret) {
5866 if (fstat(fd, &st) < 0)
5869 if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode))
5872 if (ioctl(fd, FS_IOC_GETFLAGS, ret) < 0)
5878 /// UNNEEDED by elogind
5880 int read_attr_path(const char *p, unsigned *ret) {
5881 _cleanup_close_ int fd = -1;
5886 fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
5890 return read_attr_fd(fd, ret);
5893 static size_t nul_length(const uint8_t *p, size_t sz) {
5908 ssize_t sparse_write(int fd, const void *p, size_t sz, size_t run_length) {
5909 const uint8_t *q, *w, *e;
5917 n = nul_length(q, e - q);
5919 /* If there are more than the specified run length of
5920 * NUL bytes, or if this is the beginning or the end
5921 * of the buffer, then seek instead of write */
5922 if ((n > run_length) ||
5923 (n > 0 && q == p) ||
5924 (n > 0 && q + n >= e)) {
5926 l = write(fd, w, q - w);
5933 if (lseek(fd, n, SEEK_CUR) == (off_t) -1)
5945 l = write(fd, w, q - w);
5952 return q - (const uint8_t*) p;
5956 void sigkill_wait(pid_t *pid) {
5962 if (kill(*pid, SIGKILL) > 0)
5963 (void) wait_for_terminate(*pid, NULL);
5966 /// UNNEEDED by elogind
5968 int syslog_parse_priority(const char **p, int *priority, bool with_facility) {
5969 int a = 0, b = 0, c = 0;
5979 if (!strchr(*p, '>'))
5982 if ((*p)[2] == '>') {
5983 c = undecchar((*p)[1]);
5985 } else if ((*p)[3] == '>') {
5986 b = undecchar((*p)[1]);
5987 c = undecchar((*p)[2]);
5989 } else if ((*p)[4] == '>') {
5990 a = undecchar((*p)[1]);
5991 b = undecchar((*p)[2]);
5992 c = undecchar((*p)[3]);
5997 if (a < 0 || b < 0 || c < 0 ||
5998 (!with_facility && (a || b || c > 7)))
6002 *priority = a*100 + b*10 + c;
6004 *priority = (*priority & LOG_FACMASK) | c;
6011 ssize_t string_table_lookup(const char * const *table, size_t len, const char *key) {
6017 for (i = 0; i < len; ++i)
6018 if (streq_ptr(table[i], key))
6024 /// UNNEEDED by elogind
6026 void cmsg_close_all(struct msghdr *mh) {
6027 struct cmsghdr *cmsg;
6031 CMSG_FOREACH(cmsg, mh)
6032 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
6033 close_many((int*) CMSG_DATA(cmsg), (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int));
6036 int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) {
6040 ret = renameat2(olddirfd, oldpath, newdirfd, newpath, RENAME_NOREPLACE);
6044 /* Even though renameat2() exists since Linux 3.15, btrfs added
6045 * support for it later. If it is not implemented, fallback to another
6047 if (errno != EINVAL)
6050 /* The link()/unlink() fallback does not work on directories. But
6051 * renameat() without RENAME_NOREPLACE gives the same semantics on
6052 * directories, except when newpath is an *empty* directory. This is
6054 ret = fstatat(olddirfd, oldpath, &buf, AT_SYMLINK_NOFOLLOW);
6055 if (ret >= 0 && S_ISDIR(buf.st_mode)) {
6056 ret = renameat(olddirfd, oldpath, newdirfd, newpath);
6057 return ret >= 0 ? 0 : -errno;
6060 /* If it is not a directory, use the link()/unlink() fallback. */
6061 ret = linkat(olddirfd, oldpath, newdirfd, newpath, 0);
6065 ret = unlinkat(olddirfd, oldpath, 0);
6067 /* backup errno before the following unlinkat() alters it */
6069 (void) unlinkat(newdirfd, newpath, 0);
6078 char *shell_maybe_quote(const char *s) {
6084 /* Encloses a string in double quotes if necessary to make it
6085 * OK as shell string. */
6087 for (p = s; *p; p++)
6090 strchr(SHELL_NEED_QUOTES, *p))
6096 r = new(char, 1+strlen(s)*2+1+1);
6102 t = mempcpy(t, s, p - s);
6106 if (strchr(SHELL_NEED_ESCAPE, *p))
6118 int parse_mode(const char *s, mode_t *ret) {
6126 l = strtol(s, &x, 8);
6130 if (!x || x == s || *x)
6132 if (l < 0 || l > 07777)
6139 /// UNNEEDED by elogind
6141 int mount_move_root(const char *path) {
6144 if (chdir(path) < 0)
6147 if (mount(path, "/", NULL, MS_MOVE, NULL) < 0)
6150 if (chroot(".") < 0)
6160 int reset_uid_gid(void) {
6162 if (setgroups(0, NULL) < 0)
6165 if (setresgid(0, 0, 0) < 0)
6168 if (setresuid(0, 0, 0) < 0)