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