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