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