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