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