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