]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/util.c
treewide: auto-convert the simple cases to log_*_errno()
[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)
0a1beeb6 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
LP
3797 r = wait_for_terminate(pid, &status);
3798 if (r < 0) {
0a1beeb6 3799 log_warning_errno(-r, "Failed to wait for %s: %m", name);
97c4a07d
LP
3800 return r;
3801 }
3802
3803 if (status.si_code == CLD_EXITED) {
3804 if (status.si_status != 0) {
3805 log_warning("%s failed with error code %i.", name, status.si_status);
0a27cf3f 3806 return status.si_status;
97c4a07d
LP
3807 }
3808
3809 log_debug("%s succeeded.", name);
3810 return 0;
3811
3812 } else if (status.si_code == CLD_KILLED ||
3813 status.si_code == CLD_DUMPED) {
3814
3815 log_warning("%s terminated by signal %s.", name, signal_to_string(status.si_status));
3816 return -EPROTO;
3817 }
3818
3819 log_warning("%s failed due to unknown reason.", name);
3820 return -EPROTO;
97c4a07d
LP
3821}
3822
919ce0b7 3823noreturn void freeze(void) {
720ce21d
LP
3824
3825 /* Make sure nobody waits for us on a socket anymore */
3826 close_all_fds(NULL, 0);
3827
c29597a1
LP
3828 sync();
3829
3c14d26c
LP
3830 for (;;)
3831 pause();
3832}
3833
00dc5d76
LP
3834bool null_or_empty(struct stat *st) {
3835 assert(st);
3836
3837 if (S_ISREG(st->st_mode) && st->st_size <= 0)
3838 return true;
3839
c8f26f42 3840 if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
00dc5d76
LP
3841 return true;
3842
3843 return false;
3844}
3845
83096483
LP
3846int null_or_empty_path(const char *fn) {
3847 struct stat st;
3848
3849 assert(fn);
3850
3851 if (stat(fn, &st) < 0)
3852 return -errno;
3853
3854 return null_or_empty(&st);
3855}
3856
ed88bcfb
ZJS
3857int null_or_empty_fd(int fd) {
3858 struct stat st;
3859
3860 assert(fd >= 0);
3861
3862 if (fstat(fd, &st) < 0)
3863 return -errno;
3864
3865 return null_or_empty(&st);
3866}
3867
a247755d 3868DIR *xopendirat(int fd, const char *name, int flags) {
c4731d11
LP
3869 int nfd;
3870 DIR *d;
3871
dd94c17e
LP
3872 assert(!(flags & O_CREAT));
3873
3874 nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags, 0);
73836c5c 3875 if (nfd < 0)
c4731d11
LP
3876 return NULL;
3877
73836c5c
LP
3878 d = fdopendir(nfd);
3879 if (!d) {
03e334a1 3880 safe_close(nfd);
c4731d11
LP
3881 return NULL;
3882 }
3883
3884 return d;
3b63d2d3
LP
3885}
3886
8a0867d6
LP
3887int signal_from_string_try_harder(const char *s) {
3888 int signo;
3889 assert(s);
3890
73836c5c
LP
3891 signo = signal_from_string(s);
3892 if (signo <= 0)
8a0867d6
LP
3893 if (startswith(s, "SIG"))
3894 return signal_from_string(s+3);
3895
3896 return signo;
3897}
3898
383182b5 3899static char *tag_to_udev_node(const char *tagvalue, const char *by) {
22f5f628 3900 _cleanup_free_ char *t = NULL, *u = NULL;
22f5f628 3901 size_t enc_len;
e23a0ce8 3902
383182b5 3903 u = unquote(tagvalue, "\"\'");
6db615c1 3904 if (!u)
383182b5 3905 return NULL;
e23a0ce8 3906
1d5989fd 3907 enc_len = strlen(u) * 4 + 1;
22f5f628 3908 t = new(char, enc_len);
6db615c1 3909 if (!t)
383182b5 3910 return NULL;
e23a0ce8 3911
8f6ce71f 3912 if (encode_devnode_name(u, t, enc_len) < 0)
22f5f628 3913 return NULL;
e23a0ce8 3914
6db615c1 3915 return strjoin("/dev/disk/by-", by, "/", t, NULL);
383182b5 3916}
e23a0ce8 3917
383182b5 3918char *fstab_node_to_udev_node(const char *p) {
faa368e3
LP
3919 assert(p);
3920
383182b5
DR
3921 if (startswith(p, "LABEL="))
3922 return tag_to_udev_node(p+6, "label");
e23a0ce8 3923
383182b5
DR
3924 if (startswith(p, "UUID="))
3925 return tag_to_udev_node(p+5, "uuid");
e23a0ce8 3926
84cc2abf
DR
3927 if (startswith(p, "PARTUUID="))
3928 return tag_to_udev_node(p+9, "partuuid");
3929
3930 if (startswith(p, "PARTLABEL="))
3931 return tag_to_udev_node(p+10, "partlabel");
3932
e23a0ce8
LP
3933 return strdup(p);
3934}
3935
f212ac12
LP
3936bool tty_is_vc(const char *tty) {
3937 assert(tty);
3938
98a28fef
LP
3939 return vtnr_from_tty(tty) >= 0;
3940}
3941
d1122ad5
LP
3942bool tty_is_console(const char *tty) {
3943 assert(tty);
3944
3945 if (startswith(tty, "/dev/"))
3946 tty += 5;
3947
3948 return streq(tty, "console");
3949}
3950
98a28fef
LP
3951int vtnr_from_tty(const char *tty) {
3952 int i, r;
3953
3954 assert(tty);
3955
3956 if (startswith(tty, "/dev/"))
3957 tty += 5;
3958
3959 if (!startswith(tty, "tty") )
3960 return -EINVAL;
3961
3962 if (tty[3] < '0' || tty[3] > '9')
3963 return -EINVAL;
3964
3965 r = safe_atoi(tty+3, &i);
3966 if (r < 0)
3967 return r;
3968
3969 if (i < 0 || i > 63)
3970 return -EINVAL;
3971
3972 return i;
f212ac12
LP
3973}
3974
21baf21a
MS
3975char *resolve_dev_console(char **active) {
3976 char *tty;
3977
3978 /* Resolve where /dev/console is pointing to, if /sys is actually ours
3979 * (i.e. not read-only-mounted which is a sign for container setups) */
3980
3981 if (path_is_read_only_fs("/sys") > 0)
3982 return NULL;
3983
3984 if (read_one_line_file("/sys/class/tty/console/active", active) < 0)
3985 return NULL;
3986
3987 /* If multiple log outputs are configured the last one is what
3988 * /dev/console points to */
3989 tty = strrchr(*active, ' ');
3990 if (tty)
3991 tty++;
3992 else
3993 tty = *active;
3994
8aa5429a
OB
3995 if (streq(tty, "tty0")) {
3996 char *tmp;
3997
3998 /* Get the active VC (e.g. tty1) */
3999 if (read_one_line_file("/sys/class/tty/tty0/active", &tmp) >= 0) {
4000 free(*active);
4001 tty = *active = tmp;
4002 }
4003 }
4004
21baf21a
MS
4005 return tty;
4006}
4007
3043935f 4008bool tty_is_vc_resolve(const char *tty) {
9588bc32 4009 _cleanup_free_ char *active = NULL;
3030ccd7 4010
e3aa71c3
LP
4011 assert(tty);
4012
4013 if (startswith(tty, "/dev/"))
4014 tty += 5;
4015
21baf21a
MS
4016 if (streq(tty, "console")) {
4017 tty = resolve_dev_console(&active);
4018 if (!tty)
4019 return false;
4020 }
3030ccd7 4021
9588bc32 4022 return tty_is_vc(tty);
3043935f
LP
4023}
4024
4025const char *default_term_for_tty(const char *tty) {
4026 assert(tty);
4027
acda6a05 4028 return tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt102";
e3aa71c3
LP
4029}
4030
87d2c1ff 4031bool dirent_is_file(const struct dirent *de) {
fb19a739
LP
4032 assert(de);
4033
4034 if (ignore_file(de->d_name))
4035 return false;
4036
4037 if (de->d_type != DT_REG &&
4038 de->d_type != DT_LNK &&
4039 de->d_type != DT_UNKNOWN)
4040 return false;
4041
4042 return true;
4043}
4044
87d2c1ff
LP
4045bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
4046 assert(de);
4047
a228a22f
LP
4048 if (de->d_type != DT_REG &&
4049 de->d_type != DT_LNK &&
4050 de->d_type != DT_UNKNOWN)
4051 return false;
4052
4053 if (ignore_file_allow_backup(de->d_name))
87d2c1ff
LP
4054 return false;
4055
4056 return endswith(de->d_name, suffix);
4057}
4058
e2680723 4059void execute_directory(const char *directory, DIR *d, usec_t timeout, char *argv[]) {
aa62a893
LP
4060 pid_t executor_pid;
4061 int r;
83cc030f
LP
4062
4063 assert(directory);
4064
aa62a893
LP
4065 /* Executes all binaries in a directory in parallel and waits
4066 * for them to finish. Optionally a timeout is applied. */
83cc030f 4067
aa62a893
LP
4068 executor_pid = fork();
4069 if (executor_pid < 0) {
4070 log_error("Failed to fork: %m");
4071 return;
83cc030f 4072
aa62a893
LP
4073 } else if (executor_pid == 0) {
4074 _cleanup_hashmap_free_free_ Hashmap *pids = NULL;
4075 _cleanup_closedir_ DIR *_d = NULL;
4076 struct dirent *de;
83cc030f 4077
aa62a893
LP
4078 /* We fork this all off from a child process so that
4079 * we can somewhat cleanly make use of SIGALRM to set
4080 * a time limit */
83cc030f 4081
aa62a893 4082 reset_all_signal_handlers();
1b6d7fa7 4083 reset_signal_mask();
83cc030f 4084
aa62a893 4085 assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
83cc030f 4086
aa62a893
LP
4087 if (!d) {
4088 d = _d = opendir(directory);
4089 if (!d) {
4090 if (errno == ENOENT)
4091 _exit(EXIT_SUCCESS);
83cc030f 4092
aa62a893
LP
4093 log_error("Failed to enumerate directory %s: %m", directory);
4094 _exit(EXIT_FAILURE);
4095 }
83cc030f
LP
4096 }
4097
d5099efc 4098 pids = hashmap_new(NULL);
aa62a893
LP
4099 if (!pids) {
4100 log_oom();
4101 _exit(EXIT_FAILURE);
83cc030f
LP
4102 }
4103
aa62a893
LP
4104 FOREACH_DIRENT(de, d, break) {
4105 _cleanup_free_ char *path = NULL;
4106 pid_t pid;
83cc030f 4107
aa62a893
LP
4108 if (!dirent_is_file(de))
4109 continue;
83cc030f 4110
418b9be5
LP
4111 path = strjoin(directory, "/", de->d_name, NULL);
4112 if (!path) {
aa62a893
LP
4113 log_oom();
4114 _exit(EXIT_FAILURE);
4115 }
83cc030f 4116
aa62a893
LP
4117 pid = fork();
4118 if (pid < 0) {
4119 log_error("Failed to fork: %m");
4120 continue;
4121 } else if (pid == 0) {
4122 char *_argv[2];
83cc030f 4123
aa62a893 4124 assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
83cc030f 4125
aa62a893
LP
4126 if (!argv) {
4127 _argv[0] = path;
4128 _argv[1] = NULL;
4129 argv = _argv;
4130 } else
4131 argv[0] = path;
83cc030f 4132
aa62a893
LP
4133 execv(path, argv);
4134 log_error("Failed to execute %s: %m", path);
4135 _exit(EXIT_FAILURE);
4136 }
83cc030f 4137
aa62a893 4138 log_debug("Spawned %s as " PID_FMT ".", path, pid);
83cc030f 4139
aa62a893
LP
4140 r = hashmap_put(pids, UINT_TO_PTR(pid), path);
4141 if (r < 0) {
4142 log_oom();
4143 _exit(EXIT_FAILURE);
4144 }
4145
4146 path = NULL;
83cc030f
LP
4147 }
4148
aa62a893
LP
4149 /* Abort execution of this process after the
4150 * timout. We simply rely on SIGALRM as default action
4151 * terminating the process, and turn on alarm(). */
4152
3a43da28 4153 if (timeout != USEC_INFINITY)
aa62a893
LP
4154 alarm((timeout + USEC_PER_SEC - 1) / USEC_PER_SEC);
4155
4156 while (!hashmap_isempty(pids)) {
4157 _cleanup_free_ char *path = NULL;
4158 pid_t pid;
4159
4160 pid = PTR_TO_UINT(hashmap_first_key(pids));
4161 assert(pid > 0);
83cc030f 4162
aa62a893
LP
4163 path = hashmap_remove(pids, UINT_TO_PTR(pid));
4164 assert(path);
4165
4166 wait_for_terminate_and_warn(path, pid);
83cc030f 4167 }
83cc030f 4168
aa62a893
LP
4169 _exit(EXIT_SUCCESS);
4170 }
83cc030f 4171
aa62a893 4172 wait_for_terminate_and_warn(directory, executor_pid);
83cc030f
LP
4173}
4174
430c18ed
LP
4175int kill_and_sigcont(pid_t pid, int sig) {
4176 int r;
4177
4178 r = kill(pid, sig) < 0 ? -errno : 0;
4179
4180 if (r >= 0)
4181 kill(pid, SIGCONT);
4182
4183 return r;
4184}
4185
05feefe0
LP
4186bool nulstr_contains(const char*nulstr, const char *needle) {
4187 const char *i;
4188
4189 if (!nulstr)
4190 return false;
4191
4192 NULSTR_FOREACH(i, nulstr)
4193 if (streq(i, needle))
4194 return true;
4195
4196 return false;
4197}
4198
6faa1114 4199bool plymouth_running(void) {
9408a2d2 4200 return access("/run/plymouth/pid", F_OK) >= 0;
6faa1114
LP
4201}
4202
9beb3f4d
LP
4203char* strshorten(char *s, size_t l) {
4204 assert(s);
4205
4206 if (l < strlen(s))
4207 s[l] = 0;
4208
4209 return s;
4210}
4211
4212static bool hostname_valid_char(char c) {
4213 return
4214 (c >= 'a' && c <= 'z') ||
4215 (c >= 'A' && c <= 'Z') ||
4216 (c >= '0' && c <= '9') ||
4217 c == '-' ||
4218 c == '_' ||
4219 c == '.';
4220}
4221
4222bool hostname_is_valid(const char *s) {
4223 const char *p;
aa3c5cf8 4224 bool dot;
9beb3f4d
LP
4225
4226 if (isempty(s))
4227 return false;
4228
aa3c5cf8
LP
4229 for (p = s, dot = true; *p; p++) {
4230 if (*p == '.') {
4231 if (dot)
4232 return false;
4233
4234 dot = true;
4235 } else {
4236 if (!hostname_valid_char(*p))
4237 return false;
4238
4239 dot = false;
4240 }
4241 }
4242
4243 if (dot)
4244 return false;
9beb3f4d
LP
4245
4246 if (p-s > HOST_NAME_MAX)
4247 return false;
4248
4249 return true;
4250}
4251
e724b063 4252char* hostname_cleanup(char *s, bool lowercase) {
9beb3f4d 4253 char *p, *d;
cec4ead9
LP
4254 bool dot;
4255
4256 for (p = s, d = s, dot = true; *p; p++) {
4257 if (*p == '.') {
e724b063 4258 if (dot)
cec4ead9 4259 continue;
9beb3f4d 4260
e724b063 4261 *(d++) = '.';
cec4ead9 4262 dot = true;
e724b063
LP
4263 } else if (hostname_valid_char(*p)) {
4264 *(d++) = lowercase ? tolower(*p) : *p;
cec4ead9 4265 dot = false;
e724b063 4266 }
cec4ead9 4267
cec4ead9 4268 }
9beb3f4d 4269
e724b063
LP
4270 if (dot && d > s)
4271 d[-1] = 0;
4272 else
4273 *d = 0;
4274
9beb3f4d 4275 strshorten(s, HOST_NAME_MAX);
cec4ead9 4276
9beb3f4d
LP
4277 return s;
4278}
4279
7f0d207d
LP
4280bool machine_name_is_valid(const char *s) {
4281
4282 if (!hostname_is_valid(s))
4283 return false;
4284
4285 /* Machine names should be useful hostnames, but also be
4286 * useful in unit names, hence we enforce a stricter length
4287 * limitation. */
4288
4289 if (strlen(s) > 64)
4290 return false;
4291
4292 return true;
4293}
4294
1325aa42 4295int pipe_eof(int fd) {
b92bea5d
ZJS
4296 struct pollfd pollfd = {
4297 .fd = fd,
4298 .events = POLLIN|POLLHUP,
4299 };
1325aa42 4300
d37a91e8
LP
4301 int r;
4302
1325aa42
LP
4303 r = poll(&pollfd, 1, 0);
4304 if (r < 0)
4305 return -errno;
4306
4307 if (r == 0)
4308 return 0;
4309
4310 return pollfd.revents & POLLHUP;
4311}
4312
8f2d43a0 4313int fd_wait_for_event(int fd, int event, usec_t t) {
968d3d24 4314
b92bea5d
ZJS
4315 struct pollfd pollfd = {
4316 .fd = fd,
4317 .events = event,
4318 };
df50185b 4319
968d3d24
LP
4320 struct timespec ts;
4321 int r;
4322
3a43da28 4323 r = ppoll(&pollfd, 1, t == USEC_INFINITY ? NULL : timespec_store(&ts, t), NULL);
df50185b
LP
4324 if (r < 0)
4325 return -errno;
4326
4327 if (r == 0)
4328 return 0;
4329
4330 return pollfd.revents;
4331}
4332
5a3ab509
LP
4333int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
4334 FILE *f;
4335 char *t;
5a3ab509
LP
4336 int fd;
4337
4338 assert(path);
4339 assert(_f);
4340 assert(_temp_path);
4341
2e78fa79 4342 t = tempfn_xxxxxx(path);
5a3ab509
LP
4343 if (!t)
4344 return -ENOMEM;
4345
2d5bdf5b 4346 fd = mkostemp_safe(t, O_WRONLY|O_CLOEXEC);
5a3ab509
LP
4347 if (fd < 0) {
4348 free(t);
4349 return -errno;
4350 }
4351
4352 f = fdopen(fd, "we");
4353 if (!f) {
4354 unlink(t);
4355 free(t);
4356 return -errno;
4357 }
4358
4359 *_f = f;
4360 *_temp_path = t;
4361
4362 return 0;
4363}
4364
6ea832a2 4365int terminal_vhangup_fd(int fd) {
5a3ab509
LP
4366 assert(fd >= 0);
4367
6ea832a2
LP
4368 if (ioctl(fd, TIOCVHANGUP) < 0)
4369 return -errno;
4370
4371 return 0;
4372}
4373
4374int terminal_vhangup(const char *name) {
03e334a1 4375 _cleanup_close_ int fd;
6ea832a2
LP
4376
4377 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
4378 if (fd < 0)
4379 return fd;
4380
03e334a1 4381 return terminal_vhangup_fd(fd);
6ea832a2
LP
4382}
4383
4384int vt_disallocate(const char *name) {
4385 int fd, r;
4386 unsigned u;
6ea832a2
LP
4387
4388 /* Deallocate the VT if possible. If not possible
4389 * (i.e. because it is the active one), at least clear it
4390 * entirely (including the scrollback buffer) */
4391
b83bc4e9
LP
4392 if (!startswith(name, "/dev/"))
4393 return -EINVAL;
4394
4395 if (!tty_is_vc(name)) {
4396 /* So this is not a VT. I guess we cannot deallocate
4397 * it then. But let's at least clear the screen */
4398
4399 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
4400 if (fd < 0)
4401 return fd;
4402
8585357a
LP
4403 loop_write(fd,
4404 "\033[r" /* clear scrolling region */
4405 "\033[H" /* move home */
4406 "\033[2J", /* clear screen */
4407 10, false);
03e334a1 4408 safe_close(fd);
b83bc4e9
LP
4409
4410 return 0;
4411 }
6ea832a2
LP
4412
4413 if (!startswith(name, "/dev/tty"))
4414 return -EINVAL;
4415
4416 r = safe_atou(name+8, &u);
4417 if (r < 0)
4418 return r;
4419
4420 if (u <= 0)
b83bc4e9 4421 return -EINVAL;
6ea832a2 4422
b83bc4e9 4423 /* Try to deallocate */
6ea832a2
LP
4424 fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
4425 if (fd < 0)
4426 return fd;
4427
4428 r = ioctl(fd, VT_DISALLOCATE, u);
03e334a1 4429 safe_close(fd);
6ea832a2 4430
b83bc4e9
LP
4431 if (r >= 0)
4432 return 0;
6ea832a2 4433
b83bc4e9 4434 if (errno != EBUSY)
6ea832a2 4435 return -errno;
6ea832a2 4436
b83bc4e9
LP
4437 /* Couldn't deallocate, so let's clear it fully with
4438 * scrollback */
4439 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
6ea832a2 4440 if (fd < 0)
b83bc4e9 4441 return fd;
6ea832a2 4442
8585357a
LP
4443 loop_write(fd,
4444 "\033[r" /* clear scrolling region */
4445 "\033[H" /* move home */
4446 "\033[3J", /* clear screen including scrollback, requires Linux 2.6.40 */
4447 10, false);
03e334a1 4448 safe_close(fd);
6ea832a2 4449
b83bc4e9 4450 return 0;
6ea832a2
LP
4451}
4452
424a19f8 4453int symlink_atomic(const char *from, const char *to) {
2e78fa79 4454 _cleanup_free_ char *t = NULL;
34ca941c
LP
4455
4456 assert(from);
4457 assert(to);
4458
2e78fa79 4459 t = tempfn_random(to);
34ca941c
LP
4460 if (!t)
4461 return -ENOMEM;
4462
424a19f8
LP
4463 if (symlink(from, t) < 0)
4464 return -errno;
34ca941c
LP
4465
4466 if (rename(t, to) < 0) {
2e78fa79
LP
4467 unlink_noerrno(t);
4468 return -errno;
34ca941c
LP
4469 }
4470
424a19f8 4471 return 0;
34ca941c
LP
4472}
4473
1554afae
LP
4474int mknod_atomic(const char *path, mode_t mode, dev_t dev) {
4475 _cleanup_free_ char *t = NULL;
4476
4477 assert(path);
4478
4479 t = tempfn_random(path);
4480 if (!t)
4481 return -ENOMEM;
4482
4483 if (mknod(t, mode, dev) < 0)
4484 return -errno;
4485
4486 if (rename(t, path) < 0) {
4487 unlink_noerrno(t);
4488 return -errno;
4489 }
4490
4491 return 0;
4492}
4493
4494int mkfifo_atomic(const char *path, mode_t mode) {
4495 _cleanup_free_ char *t = NULL;
4496
4497 assert(path);
4498
4499 t = tempfn_random(path);
4500 if (!t)
4501 return -ENOMEM;
4502
4503 if (mkfifo(t, mode) < 0)
4504 return -errno;
4505
4506 if (rename(t, path) < 0) {
4507 unlink_noerrno(t);
4508 return -errno;
4509 }
4510
4511 return 0;
4512}
4513
4d6d6518
LP
4514bool display_is_local(const char *display) {
4515 assert(display);
4516
4517 return
4518 display[0] == ':' &&
4519 display[1] >= '0' &&
4520 display[1] <= '9';
4521}
4522
4523int socket_from_display(const char *display, char **path) {
4524 size_t k;
4525 char *f, *c;
4526
4527 assert(display);
4528 assert(path);
4529
4530 if (!display_is_local(display))
4531 return -EINVAL;
4532
4533 k = strspn(display+1, "0123456789");
4534
f8294e41 4535 f = new(char, strlen("/tmp/.X11-unix/X") + k + 1);
4d6d6518
LP
4536 if (!f)
4537 return -ENOMEM;
4538
4539 c = stpcpy(f, "/tmp/.X11-unix/X");
4540 memcpy(c, display+1, k);
4541 c[k] = 0;
4542
4543 *path = f;
4544
4545 return 0;
4546}
4547
d05c5031
LP
4548int get_user_creds(
4549 const char **username,
4550 uid_t *uid, gid_t *gid,
4551 const char **home,
4552 const char **shell) {
4553
1cccf435 4554 struct passwd *p;
ddd88763 4555 uid_t u;
1cccf435
MV
4556
4557 assert(username);
4558 assert(*username);
1cccf435
MV
4559
4560 /* We enforce some special rules for uid=0: in order to avoid
4561 * NSS lookups for root we hardcode its data. */
4562
4563 if (streq(*username, "root") || streq(*username, "0")) {
4564 *username = "root";
4b67834e
LP
4565
4566 if (uid)
4567 *uid = 0;
4568
4569 if (gid)
4570 *gid = 0;
4571
4572 if (home)
4573 *home = "/root";
d05c5031
LP
4574
4575 if (shell)
4576 *shell = "/bin/sh";
4577
1cccf435
MV
4578 return 0;
4579 }
4580
ddd88763 4581 if (parse_uid(*username, &u) >= 0) {
1cccf435 4582 errno = 0;
ddd88763 4583 p = getpwuid(u);
1cccf435
MV
4584
4585 /* If there are multiple users with the same id, make
4586 * sure to leave $USER to the configured value instead
4587 * of the first occurrence in the database. However if
4588 * the uid was configured by a numeric uid, then let's
4589 * pick the real username from /etc/passwd. */
4590 if (p)
4591 *username = p->pw_name;
4592 } else {
4593 errno = 0;
4594 p = getpwnam(*username);
4595 }
4596
4597 if (!p)
8333c77e 4598 return errno > 0 ? -errno : -ESRCH;
1cccf435 4599
4b67834e
LP
4600 if (uid)
4601 *uid = p->pw_uid;
4602
4603 if (gid)
4604 *gid = p->pw_gid;
4605
4606 if (home)
4607 *home = p->pw_dir;
4608
d05c5031
LP
4609 if (shell)
4610 *shell = p->pw_shell;
4611
4b67834e
LP
4612 return 0;
4613}
4614
59164be4
LP
4615char* uid_to_name(uid_t uid) {
4616 struct passwd *p;
4617 char *r;
4618
4619 if (uid == 0)
4620 return strdup("root");
4621
4622 p = getpwuid(uid);
4623 if (p)
4624 return strdup(p->pw_name);
4625
de0671ee 4626 if (asprintf(&r, UID_FMT, uid) < 0)
59164be4
LP
4627 return NULL;
4628
4629 return r;
4630}
4631
4468addc
LP
4632char* gid_to_name(gid_t gid) {
4633 struct group *p;
4634 char *r;
4635
4636 if (gid == 0)
4637 return strdup("root");
4638
4639 p = getgrgid(gid);
4640 if (p)
4641 return strdup(p->gr_name);
4642
de0671ee 4643 if (asprintf(&r, GID_FMT, gid) < 0)
4468addc
LP
4644 return NULL;
4645
4646 return r;
4647}
4648
4b67834e
LP
4649int get_group_creds(const char **groupname, gid_t *gid) {
4650 struct group *g;
4651 gid_t id;
4652
4653 assert(groupname);
4654
4655 /* We enforce some special rules for gid=0: in order to avoid
4656 * NSS lookups for root we hardcode its data. */
4657
4658 if (streq(*groupname, "root") || streq(*groupname, "0")) {
4659 *groupname = "root";
4660
4661 if (gid)
4662 *gid = 0;
4663
4664 return 0;
4665 }
4666
4667 if (parse_gid(*groupname, &id) >= 0) {
4668 errno = 0;
4669 g = getgrgid(id);
4670
4671 if (g)
4672 *groupname = g->gr_name;
4673 } else {
4674 errno = 0;
4675 g = getgrnam(*groupname);
4676 }
4677
4678 if (!g)
8333c77e 4679 return errno > 0 ? -errno : -ESRCH;
4b67834e
LP
4680
4681 if (gid)
4682 *gid = g->gr_gid;
4683
1cccf435
MV
4684 return 0;
4685}
4686
4468addc
LP
4687int in_gid(gid_t gid) {
4688 gid_t *gids;
43673799
LP
4689 int ngroups_max, r, i;
4690
43673799
LP
4691 if (getgid() == gid)
4692 return 1;
4693
4694 if (getegid() == gid)
4695 return 1;
4696
4697 ngroups_max = sysconf(_SC_NGROUPS_MAX);
4698 assert(ngroups_max > 0);
4699
4700 gids = alloca(sizeof(gid_t) * ngroups_max);
4701
4702 r = getgroups(ngroups_max, gids);
4703 if (r < 0)
4704 return -errno;
4705
4706 for (i = 0; i < r; i++)
4707 if (gids[i] == gid)
4708 return 1;
4709
4710 return 0;
4711}
4712
4468addc
LP
4713int in_group(const char *name) {
4714 int r;
4715 gid_t gid;
4716
4717 r = get_group_creds(&name, &gid);
4718 if (r < 0)
4719 return r;
4720
4721 return in_gid(gid);
4722}
4723
8092a428 4724int glob_exists(const char *path) {
7fd1b19b 4725 _cleanup_globfree_ glob_t g = {};
8d98da3f 4726 int k;
8092a428
LP
4727
4728 assert(path);
4729
8092a428
LP
4730 errno = 0;
4731 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
4732
4733 if (k == GLOB_NOMATCH)
8d98da3f 4734 return 0;
8092a428 4735 else if (k == GLOB_NOSPACE)
8d98da3f 4736 return -ENOMEM;
8092a428 4737 else if (k == 0)
8d98da3f 4738 return !strv_isempty(g.gl_pathv);
8092a428 4739 else
8d98da3f
ZJS
4740 return errno ? -errno : -EIO;
4741}
8092a428 4742
8d98da3f
ZJS
4743int glob_extend(char ***strv, const char *path) {
4744 _cleanup_globfree_ glob_t g = {};
4745 int k;
4746 char **p;
4747
4748 errno = 0;
a8ccacf5 4749 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
8d98da3f
ZJS
4750
4751 if (k == GLOB_NOMATCH)
4752 return -ENOENT;
4753 else if (k == GLOB_NOSPACE)
4754 return -ENOMEM;
4755 else if (k != 0 || strv_isempty(g.gl_pathv))
4756 return errno ? -errno : -EIO;
4757
4758 STRV_FOREACH(p, g.gl_pathv) {
4759 k = strv_extend(strv, *p);
4760 if (k < 0)
4761 break;
4762 }
4763
4764 return k;
8092a428
LP
4765}
4766
83096483
LP
4767int dirent_ensure_type(DIR *d, struct dirent *de) {
4768 struct stat st;
4769
4770 assert(d);
4771 assert(de);
4772
4773 if (de->d_type != DT_UNKNOWN)
4774 return 0;
4775
4776 if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
4777 return -errno;
4778
4779 de->d_type =
4780 S_ISREG(st.st_mode) ? DT_REG :
4781 S_ISDIR(st.st_mode) ? DT_DIR :
4782 S_ISLNK(st.st_mode) ? DT_LNK :
4783 S_ISFIFO(st.st_mode) ? DT_FIFO :
4784 S_ISSOCK(st.st_mode) ? DT_SOCK :
4785 S_ISCHR(st.st_mode) ? DT_CHR :
4786 S_ISBLK(st.st_mode) ? DT_BLK :
4787 DT_UNKNOWN;
4788
4789 return 0;
4790}
4791
034a2a52 4792int get_files_in_directory(const char *path, char ***list) {
893fa014
ZJS
4793 _cleanup_closedir_ DIR *d = NULL;
4794 size_t bufsize = 0, n = 0;
4795 _cleanup_strv_free_ char **l = NULL;
034a2a52
LP
4796
4797 assert(path);
d60ef526
LP
4798
4799 /* Returns all files in a directory in *list, and the number
4800 * of files as return value. If list is NULL returns only the
893fa014 4801 * number. */
034a2a52
LP
4802
4803 d = opendir(path);
8ea913b2
LP
4804 if (!d)
4805 return -errno;
4806
034a2a52 4807 for (;;) {
7d5e9c0f 4808 struct dirent *de;
034a2a52 4809
3fd11280
FW
4810 errno = 0;
4811 de = readdir(d);
4812 if (!de && errno != 0)
4813 return -errno;
034a2a52
LP
4814 if (!de)
4815 break;
4816
4817 dirent_ensure_type(d, de);
4818
4819 if (!dirent_is_file(de))
4820 continue;
4821
d60ef526 4822 if (list) {
893fa014
ZJS
4823 /* one extra slot is needed for the terminating NULL */
4824 if (!GREEDY_REALLOC(l, bufsize, n + 2))
4825 return -ENOMEM;
034a2a52 4826
893fa014
ZJS
4827 l[n] = strdup(de->d_name);
4828 if (!l[n])
4829 return -ENOMEM;
034a2a52 4830
893fa014 4831 l[++n] = NULL;
d60ef526 4832 } else
893fa014 4833 n++;
034a2a52
LP
4834 }
4835
893fa014
ZJS
4836 if (list) {
4837 *list = l;
4838 l = NULL; /* avoid freeing */
4839 }
034a2a52 4840
893fa014 4841 return n;
034a2a52
LP
4842}
4843
b7def684 4844char *strjoin(const char *x, ...) {
911a4828
LP
4845 va_list ap;
4846 size_t l;
4847 char *r, *p;
4848
4849 va_start(ap, x);
4850
4851 if (x) {
4852 l = strlen(x);
4853
4854 for (;;) {
4855 const char *t;
040f18ea 4856 size_t n;
911a4828
LP
4857
4858 t = va_arg(ap, const char *);
4859 if (!t)
4860 break;
4861
040f18ea 4862 n = strlen(t);
e98055de
LN
4863 if (n > ((size_t) -1) - l) {
4864 va_end(ap);
040f18ea 4865 return NULL;
e98055de 4866 }
040f18ea
LP
4867
4868 l += n;
911a4828
LP
4869 }
4870 } else
4871 l = 0;
4872
4873 va_end(ap);
4874
4875 r = new(char, l+1);
4876 if (!r)
4877 return NULL;
4878
4879 if (x) {
4880 p = stpcpy(r, x);
4881
4882 va_start(ap, x);
4883
4884 for (;;) {
4885 const char *t;
4886
4887 t = va_arg(ap, const char *);
4888 if (!t)
4889 break;
4890
4891 p = stpcpy(p, t);
4892 }
8ea913b2
LP
4893
4894 va_end(ap);
911a4828
LP
4895 } else
4896 r[0] = 0;
4897
4898 return r;
4899}
4900
b636465b 4901bool is_main_thread(void) {
ec202eae 4902 static thread_local int cached = 0;
b636465b
LP
4903
4904 if (_unlikely_(cached == 0))
4905 cached = getpid() == gettid() ? 1 : -1;
4906
4907 return cached > 0;
4908}
4909
94959f0f
LP
4910int block_get_whole_disk(dev_t d, dev_t *ret) {
4911 char *p, *s;
4912 int r;
4913 unsigned n, m;
4914
4915 assert(ret);
4916
4917 /* If it has a queue this is good enough for us */
4918 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", major(d), minor(d)) < 0)
4919 return -ENOMEM;
4920
4921 r = access(p, F_OK);
4922 free(p);
4923
4924 if (r >= 0) {
4925 *ret = d;
4926 return 0;
4927 }
4928
4929 /* If it is a partition find the originating device */
4930 if (asprintf(&p, "/sys/dev/block/%u:%u/partition", major(d), minor(d)) < 0)
4931 return -ENOMEM;
4932
4933 r = access(p, F_OK);
4934 free(p);
4935
4936 if (r < 0)
4937 return -ENOENT;
4938
4939 /* Get parent dev_t */
4940 if (asprintf(&p, "/sys/dev/block/%u:%u/../dev", major(d), minor(d)) < 0)
4941 return -ENOMEM;
4942
4943 r = read_one_line_file(p, &s);
4944 free(p);
4945
4946 if (r < 0)
4947 return r;
4948
4949 r = sscanf(s, "%u:%u", &m, &n);
4950 free(s);
4951
4952 if (r != 2)
4953 return -EINVAL;
4954
4955 /* Only return this if it is really good enough for us. */
4956 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", m, n) < 0)
4957 return -ENOMEM;
4958
4959 r = access(p, F_OK);
4960 free(p);
4961
4962 if (r >= 0) {
4963 *ret = makedev(m, n);
4964 return 0;
4965 }
4966
4967 return -ENOENT;
4968}
4969
f41607a6
LP
4970static const char *const ioprio_class_table[] = {
4971 [IOPRIO_CLASS_NONE] = "none",
4972 [IOPRIO_CLASS_RT] = "realtime",
4973 [IOPRIO_CLASS_BE] = "best-effort",
4974 [IOPRIO_CLASS_IDLE] = "idle"
4975};
4976
f8b69d1d 4977DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX);
f41607a6
LP
4978
4979static const char *const sigchld_code_table[] = {
4980 [CLD_EXITED] = "exited",
4981 [CLD_KILLED] = "killed",
4982 [CLD_DUMPED] = "dumped",
4983 [CLD_TRAPPED] = "trapped",
4984 [CLD_STOPPED] = "stopped",
4985 [CLD_CONTINUED] = "continued",
4986};
4987
4988DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
4989
4990static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = {
4991 [LOG_FAC(LOG_KERN)] = "kern",
4992 [LOG_FAC(LOG_USER)] = "user",
4993 [LOG_FAC(LOG_MAIL)] = "mail",
4994 [LOG_FAC(LOG_DAEMON)] = "daemon",
4995 [LOG_FAC(LOG_AUTH)] = "auth",
4996 [LOG_FAC(LOG_SYSLOG)] = "syslog",
4997 [LOG_FAC(LOG_LPR)] = "lpr",
4998 [LOG_FAC(LOG_NEWS)] = "news",
4999 [LOG_FAC(LOG_UUCP)] = "uucp",
5000 [LOG_FAC(LOG_CRON)] = "cron",
5001 [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
5002 [LOG_FAC(LOG_FTP)] = "ftp",
5003 [LOG_FAC(LOG_LOCAL0)] = "local0",
5004 [LOG_FAC(LOG_LOCAL1)] = "local1",
5005 [LOG_FAC(LOG_LOCAL2)] = "local2",
5006 [LOG_FAC(LOG_LOCAL3)] = "local3",
5007 [LOG_FAC(LOG_LOCAL4)] = "local4",
5008 [LOG_FAC(LOG_LOCAL5)] = "local5",
5009 [LOG_FAC(LOG_LOCAL6)] = "local6",
5010 [LOG_FAC(LOG_LOCAL7)] = "local7"
5011};
5012
f8b69d1d 5013DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_facility_unshifted, int, LOG_FAC(~0));
f41607a6
LP
5014
5015static const char *const log_level_table[] = {
5016 [LOG_EMERG] = "emerg",
5017 [LOG_ALERT] = "alert",
5018 [LOG_CRIT] = "crit",
5019 [LOG_ERR] = "err",
5020 [LOG_WARNING] = "warning",
5021 [LOG_NOTICE] = "notice",
5022 [LOG_INFO] = "info",
5023 [LOG_DEBUG] = "debug"
5024};
5025
f8b69d1d 5026DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_level, int, LOG_DEBUG);
f41607a6
LP
5027
5028static const char* const sched_policy_table[] = {
5029 [SCHED_OTHER] = "other",
5030 [SCHED_BATCH] = "batch",
5031 [SCHED_IDLE] = "idle",
5032 [SCHED_FIFO] = "fifo",
5033 [SCHED_RR] = "rr"
5034};
5035
f8b69d1d 5036DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX);
f41607a6 5037
517d56b1 5038static const char* const rlimit_table[_RLIMIT_MAX] = {
f41607a6
LP
5039 [RLIMIT_CPU] = "LimitCPU",
5040 [RLIMIT_FSIZE] = "LimitFSIZE",
5041 [RLIMIT_DATA] = "LimitDATA",
5042 [RLIMIT_STACK] = "LimitSTACK",
5043 [RLIMIT_CORE] = "LimitCORE",
5044 [RLIMIT_RSS] = "LimitRSS",
5045 [RLIMIT_NOFILE] = "LimitNOFILE",
5046 [RLIMIT_AS] = "LimitAS",
5047 [RLIMIT_NPROC] = "LimitNPROC",
5048 [RLIMIT_MEMLOCK] = "LimitMEMLOCK",
5049 [RLIMIT_LOCKS] = "LimitLOCKS",
5050 [RLIMIT_SIGPENDING] = "LimitSIGPENDING",
5051 [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE",
5052 [RLIMIT_NICE] = "LimitNICE",
5053 [RLIMIT_RTPRIO] = "LimitRTPRIO",
5054 [RLIMIT_RTTIME] = "LimitRTTIME"
5055};
5056
5057DEFINE_STRING_TABLE_LOOKUP(rlimit, int);
5058
5059static const char* const ip_tos_table[] = {
5060 [IPTOS_LOWDELAY] = "low-delay",
5061 [IPTOS_THROUGHPUT] = "throughput",
5062 [IPTOS_RELIABILITY] = "reliability",
5063 [IPTOS_LOWCOST] = "low-cost",
5064};
5065
f8b69d1d 5066DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
f41607a6 5067
4e240ab0 5068static const char *const __signal_table[] = {
f41607a6
LP
5069 [SIGHUP] = "HUP",
5070 [SIGINT] = "INT",
5071 [SIGQUIT] = "QUIT",
5072 [SIGILL] = "ILL",
5073 [SIGTRAP] = "TRAP",
5074 [SIGABRT] = "ABRT",
5075 [SIGBUS] = "BUS",
5076 [SIGFPE] = "FPE",
5077 [SIGKILL] = "KILL",
5078 [SIGUSR1] = "USR1",
5079 [SIGSEGV] = "SEGV",
5080 [SIGUSR2] = "USR2",
5081 [SIGPIPE] = "PIPE",
5082 [SIGALRM] = "ALRM",
5083 [SIGTERM] = "TERM",
5084#ifdef SIGSTKFLT
5085 [SIGSTKFLT] = "STKFLT", /* Linux on SPARC doesn't know SIGSTKFLT */
5086#endif
5087 [SIGCHLD] = "CHLD",
5088 [SIGCONT] = "CONT",
5089 [SIGSTOP] = "STOP",
5090 [SIGTSTP] = "TSTP",
5091 [SIGTTIN] = "TTIN",
5092 [SIGTTOU] = "TTOU",
5093 [SIGURG] = "URG",
5094 [SIGXCPU] = "XCPU",
5095 [SIGXFSZ] = "XFSZ",
5096 [SIGVTALRM] = "VTALRM",
5097 [SIGPROF] = "PROF",
5098 [SIGWINCH] = "WINCH",
5099 [SIGIO] = "IO",
5100 [SIGPWR] = "PWR",
5101 [SIGSYS] = "SYS"
5102};
5103
4e240ab0
MS
5104DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int);
5105
5106const char *signal_to_string(int signo) {
ec202eae 5107 static thread_local char buf[sizeof("RTMIN+")-1 + DECIMAL_STR_MAX(int) + 1];
4e240ab0
MS
5108 const char *name;
5109
5110 name = __signal_to_string(signo);
5111 if (name)
5112 return name;
5113
5114 if (signo >= SIGRTMIN && signo <= SIGRTMAX)
fa70beaa 5115 snprintf(buf, sizeof(buf), "RTMIN+%d", signo - SIGRTMIN);
4e240ab0 5116 else
fa70beaa
LP
5117 snprintf(buf, sizeof(buf), "%d", signo);
5118
4e240ab0
MS
5119 return buf;
5120}
5121
5122int signal_from_string(const char *s) {
5123 int signo;
5124 int offset = 0;
5125 unsigned u;
5126
040f18ea 5127 signo = __signal_from_string(s);
4e240ab0
MS
5128 if (signo > 0)
5129 return signo;
5130
5131 if (startswith(s, "RTMIN+")) {
5132 s += 6;
5133 offset = SIGRTMIN;
5134 }
5135 if (safe_atou(s, &u) >= 0) {
5136 signo = (int) u + offset;
5137 if (signo > 0 && signo < _NSIG)
5138 return signo;
5139 }
7e8185ef 5140 return -EINVAL;
4e240ab0 5141}
65457142
FC
5142
5143bool kexec_loaded(void) {
5144 bool loaded = false;
5145 char *s;
5146
5147 if (read_one_line_file("/sys/kernel/kexec_loaded", &s) >= 0) {
5148 if (s[0] == '1')
5149 loaded = true;
5150 free(s);
5151 }
5152 return loaded;
5153}
fb9de93d 5154
87d2c1ff
LP
5155int prot_from_flags(int flags) {
5156
5157 switch (flags & O_ACCMODE) {
5158
5159 case O_RDONLY:
5160 return PROT_READ;
5161
5162 case O_WRONLY:
5163 return PROT_WRITE;
5164
5165 case O_RDWR:
5166 return PROT_READ|PROT_WRITE;
5167
5168 default:
5169 return -EINVAL;
5170 }
7c99e0c1 5171}
689b9a22 5172
babfc091 5173char *format_bytes(char *buf, size_t l, off_t t) {
c0f99c21 5174 unsigned i;
babfc091
LP
5175
5176 static const struct {
5177 const char *suffix;
5178 off_t factor;
5179 } table[] = {
32895bb3
LP
5180 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
5181 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
babfc091
LP
5182 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
5183 { "G", 1024ULL*1024ULL*1024ULL },
5184 { "M", 1024ULL*1024ULL },
5185 { "K", 1024ULL },
5186 };
5187
5188 for (i = 0; i < ELEMENTSOF(table); i++) {
5189
5190 if (t >= table[i].factor) {
5191 snprintf(buf, l,
5192 "%llu.%llu%s",
5193 (unsigned long long) (t / table[i].factor),
5194 (unsigned long long) (((t*10ULL) / table[i].factor) % 10ULL),
5195 table[i].suffix);
5196
5197 goto finish;
5198 }
5199 }
5200
5201 snprintf(buf, l, "%lluB", (unsigned long long) t);
5202
5203finish:
5204 buf[l-1] = 0;
5205 return buf;
5206
5207}
55d7bfc1
LP
5208
5209void* memdup(const void *p, size_t l) {
5210 void *r;
5211
5212 assert(p);
5213
5214 r = malloc(l);
5215 if (!r)
5216 return NULL;
5217
5218 memcpy(r, p, l);
5219 return r;
5220}
bb99a35a
LP
5221
5222int fd_inc_sndbuf(int fd, size_t n) {
5223 int r, value;
5224 socklen_t l = sizeof(value);
5225
5226 r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
92d75ca4 5227 if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
bb99a35a
LP
5228 return 0;
5229
92d75ca4
LP
5230 /* If we have the privileges we will ignore the kernel limit. */
5231
bb99a35a 5232 value = (int) n;
92d75ca4
LP
5233 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUFFORCE, &value, sizeof(value)) < 0)
5234 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value)) < 0)
5235 return -errno;
bb99a35a
LP
5236
5237 return 1;
5238}
5239
5240int fd_inc_rcvbuf(int fd, size_t n) {
5241 int r, value;
5242 socklen_t l = sizeof(value);
5243
5244 r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
92d75ca4 5245 if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
bb99a35a
LP
5246 return 0;
5247
92d75ca4 5248 /* If we have the privileges we will ignore the kernel limit. */
bb99a35a 5249
92d75ca4
LP
5250 value = (int) n;
5251 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value)) < 0)
5252 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) < 0)
5253 return -errno;
bb99a35a
LP
5254 return 1;
5255}
6bb92a16 5256
9bdc770c 5257int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
6bb92a16 5258 bool stdout_is_tty, stderr_is_tty;
8a7c93d8
LP
5259 pid_t parent_pid, agent_pid;
5260 sigset_t ss, saved_ss;
6bb92a16
LP
5261 unsigned n, i;
5262 va_list ap;
5263 char **l;
5264
5265 assert(pid);
5266 assert(path);
5267
6bb92a16
LP
5268 /* Spawns a temporary TTY agent, making sure it goes away when
5269 * we go away */
5270
8a7c93d8
LP
5271 parent_pid = getpid();
5272
5273 /* First we temporarily block all signals, so that the new
5274 * child has them blocked initially. This way, we can be sure
5275 * that SIGTERMs are not lost we might send to the agent. */
5276 assert_se(sigfillset(&ss) >= 0);
5277 assert_se(sigprocmask(SIG_SETMASK, &ss, &saved_ss) >= 0);
5278
6bb92a16 5279 agent_pid = fork();
8a7c93d8
LP
5280 if (agent_pid < 0) {
5281 assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0);
6bb92a16 5282 return -errno;
8a7c93d8 5283 }
6bb92a16
LP
5284
5285 if (agent_pid != 0) {
8a7c93d8 5286 assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0);
6bb92a16
LP
5287 *pid = agent_pid;
5288 return 0;
5289 }
5290
5291 /* In the child:
5292 *
5293 * Make sure the agent goes away when the parent dies */
5294 if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
5295 _exit(EXIT_FAILURE);
5296
8a7c93d8
LP
5297 /* Make sure we actually can kill the agent, if we need to, in
5298 * case somebody invoked us from a shell script that trapped
5299 * SIGTERM or so... */
5300 reset_all_signal_handlers();
5301 reset_signal_mask();
5302
6bb92a16 5303 /* Check whether our parent died before we were able
8a7c93d8 5304 * to set the death signal and unblock the signals */
6bb92a16
LP
5305 if (getppid() != parent_pid)
5306 _exit(EXIT_SUCCESS);
5307
5308 /* Don't leak fds to the agent */
9bdc770c 5309 close_all_fds(except, n_except);
6bb92a16
LP
5310
5311 stdout_is_tty = isatty(STDOUT_FILENO);
5312 stderr_is_tty = isatty(STDERR_FILENO);
5313
5314 if (!stdout_is_tty || !stderr_is_tty) {
8a7c93d8
LP
5315 int fd;
5316
6bb92a16
LP
5317 /* Detach from stdout/stderr. and reopen
5318 * /dev/tty for them. This is important to
5319 * ensure that when systemctl is started via
5320 * popen() or a similar call that expects to
5321 * read EOF we actually do generate EOF and
5322 * not delay this indefinitely by because we
5323 * keep an unused copy of stdin around. */
5324 fd = open("/dev/tty", O_WRONLY);
5325 if (fd < 0) {
5326 log_error("Failed to open /dev/tty: %m");
5327 _exit(EXIT_FAILURE);
5328 }
5329
5330 if (!stdout_is_tty)
5331 dup2(fd, STDOUT_FILENO);
5332
5333 if (!stderr_is_tty)
5334 dup2(fd, STDERR_FILENO);
5335
5336 if (fd > 2)
5337 close(fd);
5338 }
5339
5340 /* Count arguments */
5341 va_start(ap, path);
5342 for (n = 0; va_arg(ap, char*); n++)
5343 ;
5344 va_end(ap);
5345
5346 /* Allocate strv */
5347 l = alloca(sizeof(char *) * (n + 1));
5348
5349 /* Fill in arguments */
5350 va_start(ap, path);
5351 for (i = 0; i <= n; i++)
5352 l[i] = va_arg(ap, char*);
5353 va_end(ap);
5354
5355 execv(path, l);
5356 _exit(EXIT_FAILURE);
5357}
68faf98c
LP
5358
5359int setrlimit_closest(int resource, const struct rlimit *rlim) {
5360 struct rlimit highest, fixed;
5361
5362 assert(rlim);
5363
5364 if (setrlimit(resource, rlim) >= 0)
5365 return 0;
5366
5367 if (errno != EPERM)
5368 return -errno;
5369
5370 /* So we failed to set the desired setrlimit, then let's try
5371 * to get as close as we can */
5372 assert_se(getrlimit(resource, &highest) == 0);
5373
5374 fixed.rlim_cur = MIN(rlim->rlim_cur, highest.rlim_max);
5375 fixed.rlim_max = MIN(rlim->rlim_max, highest.rlim_max);
5376
5377 if (setrlimit(resource, &fixed) < 0)
5378 return -errno;
5379
5380 return 0;
5381}
3d9a4122 5382
ab94af92 5383int getenv_for_pid(pid_t pid, const char *field, char **_value) {
49aa47c7
LP
5384 _cleanup_fclose_ FILE *f = NULL;
5385 char *value = NULL;
ab94af92 5386 int r;
ab94af92
LP
5387 bool done = false;
5388 size_t l;
49aa47c7 5389 const char *path;
ab94af92 5390
49aa47c7 5391 assert(pid >= 0);
ab94af92
LP
5392 assert(field);
5393 assert(_value);
5394
b68fa010 5395 path = procfs_file_alloca(pid, "environ");
ab94af92
LP
5396
5397 f = fopen(path, "re");
5398 if (!f)
5399 return -errno;
5400
5401 l = strlen(field);
5402 r = 0;
5403
5404 do {
5405 char line[LINE_MAX];
5406 unsigned i;
5407
5408 for (i = 0; i < sizeof(line)-1; i++) {
5409 int c;
5410
5411 c = getc(f);
5412 if (_unlikely_(c == EOF)) {
5413 done = true;
5414 break;
5415 } else if (c == 0)
5416 break;
5417
5418 line[i] = c;
5419 }
5420 line[i] = 0;
5421
5422 if (memcmp(line, field, l) == 0 && line[l] == '=') {
5423 value = strdup(line + l + 1);
49aa47c7
LP
5424 if (!value)
5425 return -ENOMEM;
ab94af92
LP
5426
5427 r = 1;
5428 break;
5429 }
5430
5431 } while (!done);
5432
49aa47c7 5433 *_value = value;
ab94af92
LP
5434 return r;
5435}
d889a206 5436
49dbfa7b
LP
5437bool is_valid_documentation_url(const char *url) {
5438 assert(url);
5439
5440 if (startswith(url, "http://") && url[7])
5441 return true;
5442
5443 if (startswith(url, "https://") && url[8])
5444 return true;
5445
5446 if (startswith(url, "file:") && url[5])
5447 return true;
5448
5449 if (startswith(url, "info:") && url[5])
5450 return true;
5451
5452 if (startswith(url, "man:") && url[4])
5453 return true;
5454
5455 return false;
5456}
9be346c9
HH
5457
5458bool in_initrd(void) {
73020ab2 5459 static int saved = -1;
825c6fe5 5460 struct statfs s;
8f33b5b8 5461
825c6fe5
LP
5462 if (saved >= 0)
5463 return saved;
5464
5465 /* We make two checks here:
5466 *
5467 * 1. the flag file /etc/initrd-release must exist
5468 * 2. the root file system must be a memory file system
5469 *
5470 * The second check is extra paranoia, since misdetecting an
5471 * initrd can have bad bad consequences due the initrd
5472 * emptying when transititioning to the main systemd.
5473 */
5474
5475 saved = access("/etc/initrd-release", F_OK) >= 0 &&
5476 statfs("/", &s) >= 0 &&
943aad8c 5477 is_temporary_fs(&s);
9be346c9 5478
8f33b5b8 5479 return saved;
9be346c9 5480}
069cfc85
LP
5481
5482void warn_melody(void) {
e67f47e5 5483 _cleanup_close_ int fd = -1;
069cfc85
LP
5484
5485 fd = open("/dev/console", O_WRONLY|O_CLOEXEC|O_NOCTTY);
5486 if (fd < 0)
5487 return;
5488
040f18ea 5489 /* Yeah, this is synchronous. Kinda sucks. But well... */
069cfc85
LP
5490
5491 ioctl(fd, KIOCSOUND, (int)(1193180/440));
5492 usleep(125*USEC_PER_MSEC);
5493
5494 ioctl(fd, KIOCSOUND, (int)(1193180/220));
5495 usleep(125*USEC_PER_MSEC);
5496
5497 ioctl(fd, KIOCSOUND, (int)(1193180/220));
5498 usleep(125*USEC_PER_MSEC);
5499
5500 ioctl(fd, KIOCSOUND, 0);
069cfc85 5501}
cd3bd60a
LP
5502
5503int make_console_stdio(void) {
5504 int fd, r;
5505
5506 /* Make /dev/console the controlling terminal and stdin/stdout/stderr */
5507
3a43da28 5508 fd = acquire_terminal("/dev/console", false, true, true, USEC_INFINITY);
cd3bd60a 5509 if (fd < 0) {
0a1beeb6 5510 log_error_errno(-fd, "Failed to acquire terminal: %m");
cd3bd60a
LP
5511 return fd;
5512 }
5513
5514 r = make_stdio(fd);
5515 if (r < 0) {
0a1beeb6 5516 log_error_errno(-r, "Failed to duplicate terminal fd: %m");
cd3bd60a
LP
5517 return r;
5518 }
5519
5520 return 0;
5521}
7c5f152a
LP
5522
5523int get_home_dir(char **_h) {
2cfbd749 5524 struct passwd *p;
7c5f152a 5525 const char *e;
2cfbd749 5526 char *h;
7c5f152a 5527 uid_t u;
7c5f152a
LP
5528
5529 assert(_h);
5530
5531 /* Take the user specified one */
9a00f57a
LP
5532 e = secure_getenv("HOME");
5533 if (e && path_is_absolute(e)) {
7c5f152a
LP
5534 h = strdup(e);
5535 if (!h)
5536 return -ENOMEM;
5537
5538 *_h = h;
5539 return 0;
5540 }
5541
5542 /* Hardcode home directory for root to avoid NSS */
5543 u = getuid();
5544 if (u == 0) {
5545 h = strdup("/root");
5546 if (!h)
5547 return -ENOMEM;
5548
5549 *_h = h;
5550 return 0;
5551 }
5552
5553 /* Check the database... */
5554 errno = 0;
5555 p = getpwuid(u);
5556 if (!p)
bcb161b0 5557 return errno > 0 ? -errno : -ESRCH;
7c5f152a
LP
5558
5559 if (!path_is_absolute(p->pw_dir))
5560 return -EINVAL;
5561
5562 h = strdup(p->pw_dir);
5563 if (!h)
5564 return -ENOMEM;
5565
5566 *_h = h;
5567 return 0;
5568}
5569
2cfbd749
LP
5570int get_shell(char **_s) {
5571 struct passwd *p;
5572 const char *e;
5573 char *s;
5574 uid_t u;
5575
5576 assert(_s);
5577
5578 /* Take the user specified one */
5579 e = getenv("SHELL");
5580 if (e) {
5581 s = strdup(e);
5582 if (!s)
5583 return -ENOMEM;
5584
5585 *_s = s;
5586 return 0;
5587 }
5588
5589 /* Hardcode home directory for root to avoid NSS */
5590 u = getuid();
5591 if (u == 0) {
5592 s = strdup("/bin/sh");
5593 if (!s)
5594 return -ENOMEM;
5595
5596 *_s = s;
5597 return 0;
5598 }
5599
5600 /* Check the database... */
5601 errno = 0;
5602 p = getpwuid(u);
5603 if (!p)
5604 return errno > 0 ? -errno : -ESRCH;
5605
5606 if (!path_is_absolute(p->pw_shell))
5607 return -EINVAL;
5608
5609 s = strdup(p->pw_shell);
5610 if (!s)
5611 return -ENOMEM;
5612
5613 *_s = s;
5614 return 0;
5615}
5616
0b507b17
LP
5617bool filename_is_safe(const char *p) {
5618
5619 if (isempty(p))
5620 return false;
5621
5622 if (strchr(p, '/'))
5623 return false;
5624
5625 if (streq(p, "."))
5626 return false;
5627
5628 if (streq(p, ".."))
5629 return false;
5630
5631 if (strlen(p) > FILENAME_MAX)
5632 return false;
5633
5634 return true;
5635}
5636
5637bool string_is_safe(const char *p) {
5638 const char *t;
5639
6294aa76
LP
5640 if (!p)
5641 return false;
0b507b17
LP
5642
5643 for (t = p; *t; t++) {
01539d6e 5644 if (*t > 0 && *t < ' ')
0b507b17
LP
5645 return false;
5646
6294aa76 5647 if (strchr("\\\"\'\0x7f", *t))
0b507b17
LP
5648 return false;
5649 }
5650
5651 return true;
5652}
cfbc22ab 5653
ac4c8d6d 5654/**
6294aa76
LP
5655 * Check if a string contains control characters. If 'ok' is non-NULL
5656 * it may be a string containing additional CCs to be considered OK.
ac4c8d6d 5657 */
6294aa76 5658bool string_has_cc(const char *p, const char *ok) {
4d1a6904
LP
5659 const char *t;
5660
5661 assert(p);
5662
3a8a9163 5663 for (t = p; *t; t++) {
6294aa76 5664 if (ok && strchr(ok, *t))
1cb1767a 5665 continue;
6294aa76
LP
5666
5667 if (*t > 0 && *t < ' ')
4d1a6904
LP
5668 return true;
5669
3a8a9163
LP
5670 if (*t == 127)
5671 return true;
5672 }
5673
4d1a6904
LP
5674 return false;
5675}
5676
e884315e
LP
5677bool path_is_safe(const char *p) {
5678
5679 if (isempty(p))
5680 return false;
5681
5682 if (streq(p, "..") || startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../"))
5683 return false;
5684
5685 if (strlen(p) > PATH_MAX)
5686 return false;
5687
5688 /* The following two checks are not really dangerous, but hey, they still are confusing */
5689 if (streq(p, ".") || startswith(p, "./") || endswith(p, "/.") || strstr(p, "/./"))
5690 return false;
5691
5692 if (strstr(p, "//"))
5693 return false;
5694
5695 return true;
5696}
5697
a9e12476
KS
5698/* hey glibc, APIs with callbacks without a user pointer are so useless */
5699void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
1c574591 5700 int (*compar) (const void *, const void *, void *), void *arg) {
a9e12476
KS
5701 size_t l, u, idx;
5702 const void *p;
5703 int comparison;
5704
5705 l = 0;
5706 u = nmemb;
5707 while (l < u) {
5708 idx = (l + u) / 2;
5709 p = (void *)(((const char *) base) + (idx * size));
5710 comparison = compar(key, p, arg);
5711 if (comparison < 0)
5712 u = idx;
5713 else if (comparison > 0)
5714 l = idx + 1;
5715 else
5716 return (void *)p;
5717 }
5718 return NULL;
5719}
09017585
MS
5720
5721bool is_locale_utf8(void) {
5722 const char *set;
5723 static int cached_answer = -1;
5724
5725 if (cached_answer >= 0)
5726 goto out;
5727
5728 if (!setlocale(LC_ALL, "")) {
5729 cached_answer = true;
5730 goto out;
5731 }
5732
5733 set = nl_langinfo(CODESET);
5734 if (!set) {
5735 cached_answer = true;
5736 goto out;
5737 }
5738
f168c273 5739 if (streq(set, "UTF-8")) {
fee79e01
HH
5740 cached_answer = true;
5741 goto out;
5742 }
5743
6cf2f1d9
HH
5744 /* For LC_CTYPE=="C" return true, because CTYPE is effectly
5745 * unset and everything can do to UTF-8 nowadays. */
fee79e01
HH
5746 set = setlocale(LC_CTYPE, NULL);
5747 if (!set) {
5748 cached_answer = true;
5749 goto out;
5750 }
5751
6cf2f1d9
HH
5752 /* Check result, but ignore the result if C was set
5753 * explicitly. */
5754 cached_answer =
5755 streq(set, "C") &&
5756 !getenv("LC_ALL") &&
5757 !getenv("LC_CTYPE") &&
5758 !getenv("LANG");
fee79e01 5759
09017585 5760out:
6cf2f1d9 5761 return (bool) cached_answer;
09017585 5762}
c339d977
MS
5763
5764const char *draw_special_char(DrawSpecialChar ch) {
5765 static const char *draw_table[2][_DRAW_SPECIAL_CHAR_MAX] = {
6b01f1d3 5766
c339d977 5767 /* UTF-8 */ {
6b01f1d3 5768 [DRAW_TREE_VERTICAL] = "\342\224\202 ", /* │ */
45a5ff0d
MS
5769 [DRAW_TREE_BRANCH] = "\342\224\234\342\224\200", /* ├─ */
5770 [DRAW_TREE_RIGHT] = "\342\224\224\342\224\200", /* └─ */
55c0b89c 5771 [DRAW_TREE_SPACE] = " ", /* */
6b01f1d3
LP
5772 [DRAW_TRIANGULAR_BULLET] = "\342\200\243", /* ‣ */
5773 [DRAW_BLACK_CIRCLE] = "\342\227\217", /* ● */
5774 [DRAW_ARROW] = "\342\206\222", /* → */
13f8b8cb 5775 [DRAW_DASH] = "\342\200\223", /* – */
c339d977 5776 },
6b01f1d3 5777
c339d977 5778 /* ASCII fallback */ {
6b01f1d3 5779 [DRAW_TREE_VERTICAL] = "| ",
45a5ff0d
MS
5780 [DRAW_TREE_BRANCH] = "|-",
5781 [DRAW_TREE_RIGHT] = "`-",
55c0b89c 5782 [DRAW_TREE_SPACE] = " ",
6b01f1d3
LP
5783 [DRAW_TRIANGULAR_BULLET] = ">",
5784 [DRAW_BLACK_CIRCLE] = "*",
5785 [DRAW_ARROW] = "->",
13f8b8cb 5786 [DRAW_DASH] = "-",
c339d977
MS
5787 }
5788 };
5789
5790 return draw_table[!is_locale_utf8()][ch];
5791}
409bc9c3
LP
5792
5793char *strreplace(const char *text, const char *old_string, const char *new_string) {
5794 const char *f;
5795 char *t, *r;
5796 size_t l, old_len, new_len;
5797
5798 assert(text);
5799 assert(old_string);
5800 assert(new_string);
5801
5802 old_len = strlen(old_string);
5803 new_len = strlen(new_string);
5804
5805 l = strlen(text);
5806 r = new(char, l+1);
5807 if (!r)
5808 return NULL;
5809
5810 f = text;
5811 t = r;
5812 while (*f) {
5813 char *a;
5814 size_t d, nl;
5815
5816 if (!startswith(f, old_string)) {
5817 *(t++) = *(f++);
5818 continue;
5819 }
5820
5821 d = t - r;
5822 nl = l - old_len + new_len;
5823 a = realloc(r, nl + 1);
5824 if (!a)
5825 goto oom;
5826
5827 l = nl;
5828 r = a;
5829 t = r + d;
5830
5831 t = stpcpy(t, new_string);
5832 f += old_len;
5833 }
5834
5835 *t = 0;
5836 return r;
5837
5838oom:
5839 free(r);
5840 return NULL;
5841}
e8bc0ea2
LP
5842
5843char *strip_tab_ansi(char **ibuf, size_t *_isz) {
660ddc72 5844 const char *i, *begin = NULL;
e8bc0ea2
LP
5845 enum {
5846 STATE_OTHER,
5847 STATE_ESCAPE,
5848 STATE_BRACKET
5849 } state = STATE_OTHER;
5850 char *obuf = NULL;
5851 size_t osz = 0, isz;
5852 FILE *f;
5853
5854 assert(ibuf);
5855 assert(*ibuf);
5856
5857 /* Strips ANSI color and replaces TABs by 8 spaces */
5858
5859 isz = _isz ? *_isz : strlen(*ibuf);
5860
5861 f = open_memstream(&obuf, &osz);
5862 if (!f)
5863 return NULL;
5864
5865 for (i = *ibuf; i < *ibuf + isz + 1; i++) {
5866
5867 switch (state) {
5868
5869 case STATE_OTHER:
5870 if (i >= *ibuf + isz) /* EOT */
5871 break;
5872 else if (*i == '\x1B')
5873 state = STATE_ESCAPE;
5874 else if (*i == '\t')
5875 fputs(" ", f);
5876 else
5877 fputc(*i, f);
5878 break;
5879
5880 case STATE_ESCAPE:
5881 if (i >= *ibuf + isz) { /* EOT */
5882 fputc('\x1B', f);
5883 break;
5884 } else if (*i == '[') {
5885 state = STATE_BRACKET;
5886 begin = i + 1;
5887 } else {
5888 fputc('\x1B', f);
5889 fputc(*i, f);
5890 state = STATE_OTHER;
5891 }
5892
5893 break;
5894
5895 case STATE_BRACKET:
5896
5897 if (i >= *ibuf + isz || /* EOT */
5898 (!(*i >= '0' && *i <= '9') && *i != ';' && *i != 'm')) {
5899 fputc('\x1B', f);
5900 fputc('[', f);
5901 state = STATE_OTHER;
5902 i = begin-1;
5903 } else if (*i == 'm')
5904 state = STATE_OTHER;
5905 break;
5906 }
5907 }
5908
5909 if (ferror(f)) {
5910 fclose(f);
5911 free(obuf);
5912 return NULL;
5913 }
5914
5915 fclose(f);
5916
5917 free(*ibuf);
5918 *ibuf = obuf;
5919
5920 if (_isz)
5921 *_isz = osz;
5922
5923 return obuf;
5924}
240dbaa4
LP
5925
5926int on_ac_power(void) {
5927 bool found_offline = false, found_online = false;
5928 _cleanup_closedir_ DIR *d = NULL;
5929
5930 d = opendir("/sys/class/power_supply");
5931 if (!d)
5932 return -errno;
5933
5934 for (;;) {
5935 struct dirent *de;
240dbaa4
LP
5936 _cleanup_close_ int fd = -1, device = -1;
5937 char contents[6];
5938 ssize_t n;
240dbaa4 5939
3fd11280
FW
5940 errno = 0;
5941 de = readdir(d);
5942 if (!de && errno != 0)
5943 return -errno;
240dbaa4
LP
5944
5945 if (!de)
5946 break;
5947
5948 if (ignore_file(de->d_name))
5949 continue;
5950
5951 device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY);
5952 if (device < 0) {
5953 if (errno == ENOENT || errno == ENOTDIR)
5954 continue;
5955
5956 return -errno;
5957 }
5958
5959 fd = openat(device, "type", O_RDONLY|O_CLOEXEC|O_NOCTTY);
5960 if (fd < 0) {
5961 if (errno == ENOENT)
5962 continue;
5963
5964 return -errno;
5965 }
5966
5967 n = read(fd, contents, sizeof(contents));
5968 if (n < 0)
5969 return -errno;
5970
5971 if (n != 6 || memcmp(contents, "Mains\n", 6))
5972 continue;
5973
03e334a1 5974 safe_close(fd);
240dbaa4
LP
5975 fd = openat(device, "online", O_RDONLY|O_CLOEXEC|O_NOCTTY);
5976 if (fd < 0) {
5977 if (errno == ENOENT)
5978 continue;
5979
5980 return -errno;
5981 }
5982
5983 n = read(fd, contents, sizeof(contents));
5984 if (n < 0)
5985 return -errno;
5986
5987 if (n != 2 || contents[1] != '\n')
5988 return -EIO;
5989
5990 if (contents[0] == '1') {
5991 found_online = true;
5992 break;
5993 } else if (contents[0] == '0')
5994 found_offline = true;
5995 else
5996 return -EIO;
5997 }
5998
5999 return found_online || !found_offline;
6000}
fabe5c0e 6001
4cf7ea55 6002static int search_and_fopen_internal(const char *path, const char *mode, const char *root, char **search, FILE **_f) {
fabe5c0e
LP
6003 char **i;
6004
6005 assert(path);
6006 assert(mode);
6007 assert(_f);
6008
7d8da2c9 6009 if (!path_strv_resolve_uniq(search, root))
fabe5c0e
LP
6010 return -ENOMEM;
6011
6012 STRV_FOREACH(i, search) {
6013 _cleanup_free_ char *p = NULL;
6014 FILE *f;
6015
375eadd9
MM
6016 if (root)
6017 p = strjoin(root, *i, "/", path, NULL);
6018 else
6019 p = strjoin(*i, "/", path, NULL);
fabe5c0e
LP
6020 if (!p)
6021 return -ENOMEM;
6022
6023 f = fopen(p, mode);
6024 if (f) {
6025 *_f = f;
6026 return 0;
6027 }
6028
6029 if (errno != ENOENT)
6030 return -errno;
6031 }
6032
6033 return -ENOENT;
6034}
6035
4cf7ea55 6036int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f) {
fabe5c0e
LP
6037 _cleanup_strv_free_ char **copy = NULL;
6038
6039 assert(path);
6040 assert(mode);
6041 assert(_f);
6042
6043 if (path_is_absolute(path)) {
6044 FILE *f;
6045
6046 f = fopen(path, mode);
6047 if (f) {
6048 *_f = f;
6049 return 0;
6050 }
6051
6052 return -errno;
6053 }
6054
6055 copy = strv_copy((char**) search);
6056 if (!copy)
6057 return -ENOMEM;
6058
4cf7ea55 6059 return search_and_fopen_internal(path, mode, root, copy, _f);
fabe5c0e
LP
6060}
6061
4cf7ea55 6062int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f) {
fabe5c0e
LP
6063 _cleanup_strv_free_ char **s = NULL;
6064
6065 if (path_is_absolute(path)) {
6066 FILE *f;
6067
6068 f = fopen(path, mode);
6069 if (f) {
6070 *_f = f;
6071 return 0;
6072 }
6073
6074 return -errno;
6075 }
6076
6077 s = strv_split_nulstr(search);
6078 if (!s)
6079 return -ENOMEM;
6080
4cf7ea55 6081 return search_and_fopen_internal(path, mode, root, s, _f);
fabe5c0e 6082}
c17ec25e 6083
66e35261
LP
6084char *strextend(char **x, ...) {
6085 va_list ap;
6086 size_t f, l;
6087 char *r, *p;
6088
6089 assert(x);
6090
6091 l = f = *x ? strlen(*x) : 0;
6092
6093 va_start(ap, x);
6094 for (;;) {
6095 const char *t;
6096 size_t n;
6097
6098 t = va_arg(ap, const char *);
6099 if (!t)
6100 break;
6101
6102 n = strlen(t);
6103 if (n > ((size_t) -1) - l) {
6104 va_end(ap);
6105 return NULL;
6106 }
6107
6108 l += n;
6109 }
6110 va_end(ap);
6111
6112 r = realloc(*x, l+1);
6113 if (!r)
6114 return NULL;
6115
6116 p = r + f;
6117
6118 va_start(ap, x);
6119 for (;;) {
6120 const char *t;
6121
6122 t = va_arg(ap, const char *);
6123 if (!t)
6124 break;
6125
6126 p = stpcpy(p, t);
6127 }
6128 va_end(ap);
6129
6130 *p = 0;
6131 *x = r;
6132
6133 return r + l;
6134}
9a17484d
LP
6135
6136char *strrep(const char *s, unsigned n) {
6137 size_t l;
6138 char *r, *p;
6139 unsigned i;
6140
6141 assert(s);
6142
6143 l = strlen(s);
6144 p = r = malloc(l * n + 1);
6145 if (!r)
6146 return NULL;
6147
6148 for (i = 0; i < n; i++)
6149 p = stpcpy(p, s);
6150
6151 *p = 0;
6152 return r;
6153}
392d5b37 6154
ca2d3784
ZJS
6155void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) {
6156 size_t a, newalloc;
392d5b37
LP
6157 void *q;
6158
98088803 6159 assert(p);
e93c33d4
SL
6160 assert(allocated);
6161
392d5b37
LP
6162 if (*allocated >= need)
6163 return *p;
6164
ca2d3784
ZJS
6165 newalloc = MAX(need * 2, 64u / size);
6166 a = newalloc * size;
98088803
LP
6167
6168 /* check for overflows */
ca2d3784 6169 if (a < size * need)
98088803
LP
6170 return NULL;
6171
392d5b37
LP
6172 q = realloc(*p, a);
6173 if (!q)
6174 return NULL;
6175
6176 *p = q;
ca2d3784 6177 *allocated = newalloc;
392d5b37
LP
6178 return q;
6179}
aa96c6cb 6180
ca2d3784 6181void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size) {
98088803 6182 size_t prev;
4545a231
DH
6183 uint8_t *q;
6184
98088803
LP
6185 assert(p);
6186 assert(allocated);
6187
6188 prev = *allocated;
6189
ca2d3784 6190 q = greedy_realloc(p, allocated, need, size);
4545a231
DH
6191 if (!q)
6192 return NULL;
6193
6194 if (*allocated > prev)
ca2d3784 6195 memzero(q + prev * size, (*allocated - prev) * size);
4545a231
DH
6196
6197 return q;
6198}
6199
aa96c6cb
LP
6200bool id128_is_valid(const char *s) {
6201 size_t i, l;
6202
6203 l = strlen(s);
6204 if (l == 32) {
6205
6206 /* Simple formatted 128bit hex string */
6207
6208 for (i = 0; i < l; i++) {
6209 char c = s[i];
6210
6211 if (!(c >= '0' && c <= '9') &&
6212 !(c >= 'a' && c <= 'z') &&
6213 !(c >= 'A' && c <= 'Z'))
6214 return false;
6215 }
6216
6217 } else if (l == 36) {
6218
6219 /* Formatted UUID */
6220
6221 for (i = 0; i < l; i++) {
6222 char c = s[i];
6223
6224 if ((i == 8 || i == 13 || i == 18 || i == 23)) {
6225 if (c != '-')
6226 return false;
6227 } else {
6228 if (!(c >= '0' && c <= '9') &&
6229 !(c >= 'a' && c <= 'z') &&
6230 !(c >= 'A' && c <= 'Z'))
6231 return false;
6232 }
6233 }
6234
6235 } else
6236 return false;
6237
6238 return true;
6239}
7085053a 6240
d4ac85c6
LP
6241int split_pair(const char *s, const char *sep, char **l, char **r) {
6242 char *x, *a, *b;
6243
6244 assert(s);
6245 assert(sep);
6246 assert(l);
6247 assert(r);
6248
6249 if (isempty(sep))
6250 return -EINVAL;
6251
6252 x = strstr(s, sep);
6253 if (!x)
6254 return -EINVAL;
6255
6256 a = strndup(s, x - s);
6257 if (!a)
6258 return -ENOMEM;
6259
6260 b = strdup(x + strlen(sep));
6261 if (!b) {
6262 free(a);
6263 return -ENOMEM;
6264 }
6265
6266 *l = a;
6267 *r = b;
6268
6269 return 0;
6270}
295edddf 6271
74df0fca 6272int shall_restore_state(void) {
1a299299 6273 _cleanup_free_ char *value = NULL;
74df0fca 6274 int r;
295edddf 6275
1a299299 6276 r = get_proc_cmdline_key("systemd.restore_state=", &value);
74df0fca
LP
6277 if (r < 0)
6278 return r;
1a299299
LP
6279 if (r == 0)
6280 return true;
295edddf 6281
1a299299 6282 return parse_boolean(value) != 0;
74df0fca
LP
6283}
6284
6285int proc_cmdline(char **ret) {
b5884878 6286 assert(ret);
295edddf 6287
b5884878
LP
6288 if (detect_container(NULL) > 0)
6289 return get_process_cmdline(1, 0, false, ret);
6290 else
6291 return read_one_line_file("/proc/cmdline", ret);
295edddf 6292}
bc9fd78c 6293
059cb385 6294int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) {
141a79f4 6295 _cleanup_free_ char *line = NULL;
f32d2db1 6296 const char *p;
141a79f4
ZJS
6297 int r;
6298
059cb385
LP
6299 assert(parse_item);
6300
141a79f4
ZJS
6301 r = proc_cmdline(&line);
6302 if (r < 0)
b5884878 6303 return r;
141a79f4 6304
f32d2db1
LP
6305 p = line;
6306 for (;;) {
6307 _cleanup_free_ char *word = NULL;
6308 char *value = NULL;
141a79f4 6309
f32d2db1
LP
6310 r = unquote_first_word(&p, &word, true);
6311 if (r < 0)
6312 return r;
6313 if (r == 0)
6314 break;
141a79f4 6315
059cb385
LP
6316 /* Filter out arguments that are intended only for the
6317 * initrd */
6318 if (!in_initrd() && startswith(word, "rd."))
6319 continue;
6320
6321 value = strchr(word, '=');
6322 if (value)
6323 *(value++) = 0;
6324
6325 r = parse_item(word, value);
6326 if (r < 0)
141a79f4 6327 return r;
141a79f4
ZJS
6328 }
6329
6330 return 0;
6331}
6332
1a299299
LP
6333int get_proc_cmdline_key(const char *key, char **value) {
6334 _cleanup_free_ char *line = NULL, *ret = NULL;
6335 bool found = false;
6336 const char *p;
6337 int r;
6338
6339 assert(key);
6340
6341 r = proc_cmdline(&line);
6342 if (r < 0)
6343 return r;
6344
6345 p = line;
6346 for (;;) {
6347 _cleanup_free_ char *word = NULL;
6348 const char *e;
6349
6350 r = unquote_first_word(&p, &word, true);
6351 if (r < 0)
6352 return r;
6353 if (r == 0)
6354 break;
6355
6356 /* Filter out arguments that are intended only for the
6357 * initrd */
6358 if (!in_initrd() && startswith(word, "rd."))
6359 continue;
6360
6361 if (value) {
6362 e = startswith(word, key);
6363 if (!e)
6364 continue;
6365
6366 r = free_and_strdup(&ret, e);
6367 if (r < 0)
6368 return r;
6369
6370 found = true;
6371 } else {
6372 if (streq(word, key))
6373 found = true;
6374 }
6375 }
6376
6377 if (value) {
6378 *value = ret;
6379 ret = NULL;
6380 }
6381
6382 return found;
6383
6384}
6385
bc9fd78c
LP
6386int container_get_leader(const char *machine, pid_t *pid) {
6387 _cleanup_free_ char *s = NULL, *class = NULL;
6388 const char *p;
6389 pid_t leader;
6390 int r;
6391
6392 assert(machine);
6393 assert(pid);
6394
6395 p = strappenda("/run/systemd/machines/", machine);
6396 r = parse_env_file(p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL);
6397 if (r == -ENOENT)
6398 return -EHOSTDOWN;
6399 if (r < 0)
6400 return r;
6401 if (!s)
6402 return -EIO;
6403
6404 if (!streq_ptr(class, "container"))
6405 return -EIO;
6406
6407 r = parse_pid(s, &leader);
6408 if (r < 0)
6409 return r;
6410 if (leader <= 1)
6411 return -EIO;
6412
6413 *pid = leader;
6414 return 0;
6415}
6416
878cd7e9
LP
6417int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *root_fd) {
6418 _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, netnsfd = -1;
359a06aa 6419 int rfd = -1;
bc9fd78c
LP
6420
6421 assert(pid >= 0);
bc9fd78c 6422
878cd7e9
LP
6423 if (mntns_fd) {
6424 const char *mntns;
a4475f57 6425
878cd7e9
LP
6426 mntns = procfs_file_alloca(pid, "ns/mnt");
6427 mntnsfd = open(mntns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
6428 if (mntnsfd < 0)
6429 return -errno;
6430 }
bc9fd78c 6431
878cd7e9
LP
6432 if (pidns_fd) {
6433 const char *pidns;
6434
6435 pidns = procfs_file_alloca(pid, "ns/pid");
6436 pidnsfd = open(pidns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
6437 if (pidnsfd < 0)
6438 return -errno;
6439 }
6440
6441 if (netns_fd) {
6442 const char *netns;
6443
6444 netns = procfs_file_alloca(pid, "ns/net");
6445 netnsfd = open(netns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
6446 if (netnsfd < 0)
6447 return -errno;
6448 }
6449
6450 if (root_fd) {
6451 const char *root;
6452
6453 root = procfs_file_alloca(pid, "root");
6454 rfd = open(root, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
6455 if (rfd < 0)
6456 return -errno;
6457 }
6458
6459 if (pidns_fd)
6460 *pidns_fd = pidnsfd;
bc9fd78c 6461
878cd7e9
LP
6462 if (mntns_fd)
6463 *mntns_fd = mntnsfd;
6464
6465 if (netns_fd)
6466 *netns_fd = netnsfd;
6467
6468 if (root_fd)
6469 *root_fd = rfd;
6470
6471 pidnsfd = mntnsfd = netnsfd = -1;
bc9fd78c
LP
6472
6473 return 0;
6474}
6475
878cd7e9 6476int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int root_fd) {
bc9fd78c 6477
878cd7e9
LP
6478 if (pidns_fd >= 0)
6479 if (setns(pidns_fd, CLONE_NEWPID) < 0)
6480 return -errno;
a4475f57 6481
878cd7e9
LP
6482 if (mntns_fd >= 0)
6483 if (setns(mntns_fd, CLONE_NEWNS) < 0)
6484 return -errno;
bc9fd78c 6485
878cd7e9
LP
6486 if (netns_fd >= 0)
6487 if (setns(netns_fd, CLONE_NEWNET) < 0)
6488 return -errno;
bc9fd78c 6489
878cd7e9
LP
6490 if (root_fd >= 0) {
6491 if (fchdir(root_fd) < 0)
6492 return -errno;
6493
6494 if (chroot(".") < 0)
6495 return -errno;
6496 }
bc9fd78c 6497
5e2b3214
LP
6498 if (setresgid(0, 0, 0) < 0)
6499 return -errno;
6500
878cd7e9
LP
6501 if (setgroups(0, NULL) < 0)
6502 return -errno;
6503
5e2b3214
LP
6504 if (setresuid(0, 0, 0) < 0)
6505 return -errno;
6506
bc9fd78c
LP
6507 return 0;
6508}
bf108e55 6509
9f5650ae
LP
6510bool pid_is_unwaited(pid_t pid) {
6511 /* Checks whether a PID is still valid at all, including a zombie */
6512
bf108e55
LP
6513 if (pid <= 0)
6514 return false;
6515
6516 if (kill(pid, 0) >= 0)
6517 return true;
6518
6519 return errno != ESRCH;
6520}
eff05270 6521
9f5650ae
LP
6522bool pid_is_alive(pid_t pid) {
6523 int r;
6524
6525 /* Checks whether a PID is still valid and not a zombie */
6526
6527 if (pid <= 0)
6528 return false;
6529
6530 r = get_process_state(pid);
6531 if (r == -ENOENT || r == 'Z')
6532 return false;
6533
6534 return true;
6535}
6536
eff05270
LP
6537int getpeercred(int fd, struct ucred *ucred) {
6538 socklen_t n = sizeof(struct ucred);
6539 struct ucred u;
6540 int r;
6541
6542 assert(fd >= 0);
6543 assert(ucred);
6544
6545 r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &u, &n);
6546 if (r < 0)
6547 return -errno;
6548
6549 if (n != sizeof(struct ucred))
6550 return -EIO;
6551
6552 /* Check if the data is actually useful and not suppressed due
6553 * to namespacing issues */
6554 if (u.pid <= 0)
6555 return -ENODATA;
62028d9c
LP
6556 if (u.uid == (uid_t) -1)
6557 return -ENODATA;
6558 if (u.gid == (gid_t) -1)
6559 return -ENODATA;
eff05270
LP
6560
6561 *ucred = u;
6562 return 0;
6563}
6564
6565int getpeersec(int fd, char **ret) {
6566 socklen_t n = 64;
6567 char *s;
6568 int r;
6569
6570 assert(fd >= 0);
6571 assert(ret);
6572
6573 s = new0(char, n);
6574 if (!s)
6575 return -ENOMEM;
6576
6577 r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
6578 if (r < 0) {
6579 free(s);
6580
6581 if (errno != ERANGE)
6582 return -errno;
6583
6584 s = new0(char, n);
6585 if (!s)
6586 return -ENOMEM;
6587
6588 r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
6589 if (r < 0) {
6590 free(s);
6591 return -errno;
6592 }
6593 }
6594
ae98841e
LP
6595 if (isempty(s)) {
6596 free(s);
6597 return -ENOTSUP;
6598 }
6599
eff05270
LP
6600 *ret = s;
6601 return 0;
6602}
8e33886e 6603
0f010ef2 6604/* This is much like like mkostemp() but is subject to umask(). */
65b3903f 6605int mkostemp_safe(char *pattern, int flags) {
2d5bdf5b 6606 _cleanup_umask_ mode_t u;
0f010ef2 6607 int fd;
65b3903f 6608
d37a91e8 6609 assert(pattern);
65b3903f 6610
2d5bdf5b
LP
6611 u = umask(077);
6612
0f010ef2
ZJS
6613 fd = mkostemp(pattern, flags);
6614 if (fd < 0)
6615 return -errno;
65b3903f 6616
0f010ef2 6617 return fd;
65b3903f
ZJS
6618}
6619
8e33886e 6620int open_tmpfile(const char *path, int flags) {
8e33886e 6621 char *p;
a6afc4ae
LP
6622 int fd;
6623
6624 assert(path);
8e33886e
ZJS
6625
6626#ifdef O_TMPFILE
7736202c
LP
6627 /* Try O_TMPFILE first, if it is supported */
6628 fd = open(path, flags|O_TMPFILE, S_IRUSR|S_IWUSR);
8e33886e
ZJS
6629 if (fd >= 0)
6630 return fd;
6631#endif
7736202c
LP
6632
6633 /* Fall back to unguessable name + unlinking */
8e33886e
ZJS
6634 p = strappenda(path, "/systemd-tmp-XXXXXX");
6635
a6afc4ae 6636 fd = mkostemp_safe(p, flags);
8e33886e 6637 if (fd < 0)
65b3903f 6638 return fd;
8e33886e
ZJS
6639
6640 unlink(p);
6641 return fd;
6642}
fdb9161c
LP
6643
6644int fd_warn_permissions(const char *path, int fd) {
6645 struct stat st;
6646
6647 if (fstat(fd, &st) < 0)
6648 return -errno;
6649
6650 if (st.st_mode & 0111)
6651 log_warning("Configuration file %s is marked executable. Please remove executable permission bits. Proceeding anyway.", path);
6652
6653 if (st.st_mode & 0002)
6654 log_warning("Configuration file %s is marked world-writable. Please remove world writability permission bits. Proceeding anyway.", path);
6655
6656 if (getpid() == 1 && (st.st_mode & 0044) != 0044)
6657 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);
6658
6659 return 0;
6660}
6afc95b7 6661
ac45f971 6662unsigned long personality_from_string(const char *p) {
6afc95b7
LP
6663
6664 /* Parse a personality specifier. We introduce our own
6665 * identifiers that indicate specific ABIs, rather than just
6666 * hints regarding the register size, since we want to keep
6667 * things open for multiple locally supported ABIs for the
6668 * same register size. We try to reuse the ABI identifiers
6669 * used by libseccomp. */
6670
6671#if defined(__x86_64__)
6672
6673 if (streq(p, "x86"))
6674 return PER_LINUX32;
6675
6676 if (streq(p, "x86-64"))
6677 return PER_LINUX;
6678
6679#elif defined(__i386__)
6680
6681 if (streq(p, "x86"))
6682 return PER_LINUX;
6683#endif
6684
6685 /* personality(7) documents that 0xffffffffUL is used for
6686 * querying the current personality, hence let's use that here
6687 * as error indicator. */
6688 return 0xffffffffUL;
6689}
ac45f971
LP
6690
6691const char* personality_to_string(unsigned long p) {
6692
6693#if defined(__x86_64__)
6694
6695 if (p == PER_LINUX32)
6696 return "x86";
6697
6698 if (p == PER_LINUX)
6699 return "x86-64";
6700
6701#elif defined(__i386__)
6702
6703 if (p == PER_LINUX)
6704 return "x86";
6705#endif
6706
6707 return NULL;
6708}
1c231f56
LP
6709
6710uint64_t physical_memory(void) {
6711 long mem;
6712
6713 /* We return this as uint64_t in case we are running as 32bit
6714 * process on a 64bit kernel with huge amounts of memory */
6715
6716 mem = sysconf(_SC_PHYS_PAGES);
6717 assert(mem > 0);
6718
6719 return (uint64_t) mem * (uint64_t) page_size();
6720}
6db615c1
LP
6721
6722char* mount_test_option(const char *haystack, const char *needle) {
6723
6724 struct mntent me = {
6725 .mnt_opts = (char*) haystack
6726 };
6727
6728 assert(needle);
6729
6730 /* Like glibc's hasmntopt(), but works on a string, not a
6731 * struct mntent */
6732
6733 if (!haystack)
6734 return NULL;
6735
6736 return hasmntopt(&me, needle);
6737}
29bfbcd6
LP
6738
6739void hexdump(FILE *f, const void *p, size_t s) {
6740 const uint8_t *b = p;
6741 unsigned n = 0;
6742
6743 assert(s == 0 || b);
6744
6745 while (s > 0) {
6746 size_t i;
6747
6748 fprintf(f, "%04x ", n);
6749
6750 for (i = 0; i < 16; i++) {
6751
6752 if (i >= s)
6753 fputs(" ", f);
6754 else
6755 fprintf(f, "%02x ", b[i]);
6756
6757 if (i == 7)
6758 fputc(' ', f);
6759 }
6760
6761 fputc(' ', f);
6762
6763 for (i = 0; i < 16; i++) {
6764
6765 if (i >= s)
6766 fputc(' ', f);
6767 else
6768 fputc(isprint(b[i]) ? (char) b[i] : '.', f);
6769 }
6770
6771 fputc('\n', f);
6772
6773 if (s < 16)
6774 break;
6775
6776 n += 16;
6777 b += 16;
6778 s -= 16;
6779 }
6780}
c5220a94 6781
966bff26 6782int update_reboot_param_file(const char *param) {
c5220a94
MO
6783 int r = 0;
6784
6785 if (param) {
6786
6787 r = write_string_file(REBOOT_PARAM_FILE, param);
6788 if (r < 0)
6789 log_error("Failed to write reboot param to "
6790 REBOOT_PARAM_FILE": %s", strerror(-r));
6791 } else
6792 unlink(REBOOT_PARAM_FILE);
6793
6794 return r;
6795}
6d313367
LP
6796
6797int umount_recursive(const char *prefix, int flags) {
6798 bool again;
6799 int n = 0, r;
6800
6801 /* Try to umount everything recursively below a
6802 * directory. Also, take care of stacked mounts, and keep
6803 * unmounting them until they are gone. */
6804
6805 do {
6806 _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
6807
6808 again = false;
6809 r = 0;
6810
6811 proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
6812 if (!proc_self_mountinfo)
6813 return -errno;
6814
6815 for (;;) {
6816 _cleanup_free_ char *path = NULL, *p = NULL;
6817 int k;
6818
6819 k = fscanf(proc_self_mountinfo,
6820 "%*s " /* (1) mount id */
6821 "%*s " /* (2) parent id */
6822 "%*s " /* (3) major:minor */
6823 "%*s " /* (4) root */
6824 "%ms " /* (5) mount point */
6825 "%*s" /* (6) mount options */
6826 "%*[^-]" /* (7) optional fields */
6827 "- " /* (8) separator */
6828 "%*s " /* (9) file system type */
6829 "%*s" /* (10) mount source */
6830 "%*s" /* (11) mount options 2 */
6831 "%*[^\n]", /* some rubbish at the end */
6832 &path);
6d313367
LP
6833 if (k != 1) {
6834 if (k == EOF)
6835 break;
6836
6837 continue;
6838 }
6839
6840 p = cunescape(path);
6841 if (!p)
6842 return -ENOMEM;
6843
6844 if (!path_startswith(p, prefix))
6845 continue;
6846
6847 if (umount2(p, flags) < 0) {
6848 r = -errno;
6849 continue;
6850 }
6851
6852 again = true;
6853 n++;
6854
6855 break;
6856 }
6857
6858 } while (again);
6859
6860 return r ? r : n;
6861}
d6797c92
LP
6862
6863int bind_remount_recursive(const char *prefix, bool ro) {
6864 _cleanup_set_free_free_ Set *done = NULL;
6865 _cleanup_free_ char *cleaned = NULL;
6866 int r;
6867
6868 /* Recursively remount a directory (and all its submounts)
6869 * read-only or read-write. If the directory is already
6870 * mounted, we reuse the mount and simply mark it
6871 * MS_BIND|MS_RDONLY (or remove the MS_RDONLY for read-write
6872 * operation). If it isn't we first make it one. Afterwards we
6873 * apply MS_BIND|MS_RDONLY (or remove MS_RDONLY) to all
6874 * submounts we can access, too. When mounts are stacked on
6875 * the same mount point we only care for each individual
6876 * "top-level" mount on each point, as we cannot
6877 * influence/access the underlying mounts anyway. We do not
6878 * have any effect on future submounts that might get
6879 * propagated, they migt be writable. This includes future
6880 * submounts that have been triggered via autofs. */
6881
6882 cleaned = strdup(prefix);
6883 if (!cleaned)
6884 return -ENOMEM;
6885
6886 path_kill_slashes(cleaned);
6887
d5099efc 6888 done = set_new(&string_hash_ops);
d6797c92
LP
6889 if (!done)
6890 return -ENOMEM;
6891
6892 for (;;) {
6893 _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
6894 _cleanup_set_free_free_ Set *todo = NULL;
6895 bool top_autofs = false;
6896 char *x;
6897
d5099efc 6898 todo = set_new(&string_hash_ops);
d6797c92
LP
6899 if (!todo)
6900 return -ENOMEM;
6901
6902 proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
6903 if (!proc_self_mountinfo)
6904 return -errno;
6905
6906 for (;;) {
6907 _cleanup_free_ char *path = NULL, *p = NULL, *type = NULL;
6908 int k;
6909
6910 k = fscanf(proc_self_mountinfo,
6911 "%*s " /* (1) mount id */
6912 "%*s " /* (2) parent id */
6913 "%*s " /* (3) major:minor */
6914 "%*s " /* (4) root */
6915 "%ms " /* (5) mount point */
6916 "%*s" /* (6) mount options (superblock) */
6917 "%*[^-]" /* (7) optional fields */
6918 "- " /* (8) separator */
6919 "%ms " /* (9) file system type */
6920 "%*s" /* (10) mount source */
6921 "%*s" /* (11) mount options (bind mount) */
6922 "%*[^\n]", /* some rubbish at the end */
6923 &path,
6924 &type);
6925 if (k != 2) {
6926 if (k == EOF)
6927 break;
6928
6929 continue;
6930 }
6931
6932 p = cunescape(path);
6933 if (!p)
6934 return -ENOMEM;
6935
6936 /* Let's ignore autofs mounts. If they aren't
6937 * triggered yet, we want to avoid triggering
6938 * them, as we don't make any guarantees for
6939 * future submounts anyway. If they are
6940 * already triggered, then we will find
6941 * another entry for this. */
6942 if (streq(type, "autofs")) {
6943 top_autofs = top_autofs || path_equal(cleaned, p);
6944 continue;
6945 }
6946
6947 if (path_startswith(p, cleaned) &&
6948 !set_contains(done, p)) {
6949
6950 r = set_consume(todo, p);
6951 p = NULL;
6952
6953 if (r == -EEXIST)
6954 continue;
6955 if (r < 0)
6956 return r;
6957 }
6958 }
6959
6960 /* If we have no submounts to process anymore and if
6961 * the root is either already done, or an autofs, we
6962 * are done */
6963 if (set_isempty(todo) &&
6964 (top_autofs || set_contains(done, cleaned)))
6965 return 0;
6966
6967 if (!set_contains(done, cleaned) &&
6968 !set_contains(todo, cleaned)) {
6969 /* The prefix directory itself is not yet a
6970 * mount, make it one. */
6971 if (mount(cleaned, cleaned, NULL, MS_BIND|MS_REC, NULL) < 0)
6972 return -errno;
6973
6974 if (mount(NULL, prefix, NULL, MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0)
6975 return -errno;
6976
6977 x = strdup(cleaned);
6978 if (!x)
6979 return -ENOMEM;
6980
6981 r = set_consume(done, x);
6982 if (r < 0)
6983 return r;
6984 }
6985
6986 while ((x = set_steal_first(todo))) {
6987
6988 r = set_consume(done, x);
6989 if (r == -EEXIST)
6990 continue;
6991 if (r < 0)
6992 return r;
6993
6994 if (mount(NULL, x, NULL, MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0) {
6995
6996 /* Deal with mount points that are
6997 * obstructed by a later mount */
6998
6999 if (errno != ENOENT)
7000 return -errno;
7001 }
7002
7003 }
7004 }
7005}
1b992147
LP
7006
7007int fflush_and_check(FILE *f) {
45c196a7 7008 assert(f);
1b992147
LP
7009
7010 errno = 0;
7011 fflush(f);
7012
7013 if (ferror(f))
7014 return errno ? -errno : -EIO;
7015
7016 return 0;
7017}
2e78fa79
LP
7018
7019char *tempfn_xxxxxx(const char *p) {
7020 const char *fn;
7021 char *t;
7022 size_t k;
7023
7024 assert(p);
7025
7026 t = new(char, strlen(p) + 1 + 6 + 1);
7027 if (!t)
7028 return NULL;
7029
7030 fn = basename(p);
7031 k = fn - p;
7032
7033 strcpy(stpcpy(stpcpy(mempcpy(t, p, k), "."), fn), "XXXXXX");
7034
7035 return t;
7036}
7037
7038char *tempfn_random(const char *p) {
7039 const char *fn;
7040 char *t, *x;
7041 uint64_t u;
7042 size_t k;
7043 unsigned i;
7044
7045 assert(p);
7046
7047 t = new(char, strlen(p) + 1 + 16 + 1);
7048 if (!t)
7049 return NULL;
7050
7051 fn = basename(p);
7052 k = fn - p;
7053
7054 x = stpcpy(stpcpy(mempcpy(t, p, k), "."), fn);
7055
7056 u = random_u64();
7057 for (i = 0; i < 16; i++) {
7058 *(x++) = hexchar(u & 0xF);
7059 u >>= 4;
7060 }
7061
7062 *x = 0;
7063
7064 return t;
7065}
fecc80c1
LP
7066
7067/* make sure the hostname is not "localhost" */
7068bool is_localhost(const char *hostname) {
7069 assert(hostname);
7070
a0627f82
LP
7071 /* This tries to identify local host and domain names
7072 * described in RFC6761 plus the redhatism of .localdomain */
fecc80c1
LP
7073
7074 return streq(hostname, "localhost") ||
7075 streq(hostname, "localhost.") ||
a0627f82
LP
7076 streq(hostname, "localdomain.") ||
7077 streq(hostname, "localdomain") ||
fecc80c1
LP
7078 endswith(hostname, ".localhost") ||
7079 endswith(hostname, ".localhost.") ||
7080 endswith(hostname, ".localdomain") ||
7081 endswith(hostname, ".localdomain.");
7082}
45035609
LP
7083
7084int take_password_lock(const char *root) {
7085
7086 struct flock flock = {
7087 .l_type = F_WRLCK,
7088 .l_whence = SEEK_SET,
7089 .l_start = 0,
7090 .l_len = 0,
7091 };
7092
7093 const char *path;
7094 int fd, r;
7095
7096 /* This is roughly the same as lckpwdf(), but not as awful. We
7097 * don't want to use alarm() and signals, hence we implement
7098 * our own trivial version of this.
7099 *
7100 * Note that shadow-utils also takes per-database locks in
7101 * addition to lckpwdf(). However, we don't given that they
7102 * are redundant as they they invoke lckpwdf() first and keep
7103 * it during everything they do. The per-database locks are
7104 * awfully racy, and thus we just won't do them. */
7105
7106 if (root)
7107 path = strappenda(root, "/etc/.pwd.lock");
7108 else
7109 path = "/etc/.pwd.lock";
7110
7111 fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0600);
7112 if (fd < 0)
7113 return -errno;
7114
7115 r = fcntl(fd, F_SETLKW, &flock);
7116 if (r < 0) {
7117 safe_close(fd);
7118 return -errno;
7119 }
7120
7121 return fd;
7122}
5261ba90
TT
7123
7124int is_symlink(const char *path) {
7125 struct stat info;
7126
7127 if (lstat(path, &info) < 0)
7128 return -errno;
7129
be57e297
LP
7130 return !!S_ISLNK(info.st_mode);
7131}
5261ba90 7132
be57e297
LP
7133int is_dir(const char* path, bool follow) {
7134 struct stat st;
d1bddcec 7135 int r;
be57e297 7136
d1bddcec
LP
7137 if (follow)
7138 r = stat(path, &st);
7139 else
7140 r = lstat(path, &st);
7141 if (r < 0)
7142 return -errno;
be57e297
LP
7143
7144 return !!S_ISDIR(st.st_mode);
a0627f82 7145}
7629889c 7146
f32d2db1 7147int unquote_first_word(const char **p, char **ret, bool relax) {
7629889c
LP
7148 _cleanup_free_ char *s = NULL;
7149 size_t allocated = 0, sz = 0;
7150
7151 enum {
7152 START,
7153 VALUE,
7154 VALUE_ESCAPE,
7155 SINGLE_QUOTE,
7156 SINGLE_QUOTE_ESCAPE,
7157 DOUBLE_QUOTE,
7158 DOUBLE_QUOTE_ESCAPE,
7159 SPACE,
7160 } state = START;
7161
7162 assert(p);
7163 assert(*p);
7164 assert(ret);
7165
7166 /* Parses the first word of a string, and returns it in
7167 * *ret. Removes all quotes in the process. When parsing fails
7168 * (because of an uneven number of quotes or similar), leaves
7169 * the pointer *p at the first invalid character. */
7170
7171 for (;;) {
7172 char c = **p;
7173
7174 switch (state) {
7175
7176 case START:
7177 if (c == 0)
7178 goto finish;
7179 else if (strchr(WHITESPACE, c))
7180 break;
7181
7182 state = VALUE;
7183 /* fallthrough */
7184
7185 case VALUE:
7186 if (c == 0)
7187 goto finish;
7188 else if (c == '\'')
7189 state = SINGLE_QUOTE;
7190 else if (c == '\\')
7191 state = VALUE_ESCAPE;
7192 else if (c == '\"')
7193 state = DOUBLE_QUOTE;
7194 else if (strchr(WHITESPACE, c))
7195 state = SPACE;
7196 else {
7197 if (!GREEDY_REALLOC(s, allocated, sz+2))
7198 return -ENOMEM;
7199
7200 s[sz++] = c;
7201 }
7202
7203 break;
7204
7205 case VALUE_ESCAPE:
f32d2db1
LP
7206 if (c == 0) {
7207 if (relax)
7208 goto finish;
7629889c 7209 return -EINVAL;
f32d2db1 7210 }
7629889c
LP
7211
7212 if (!GREEDY_REALLOC(s, allocated, sz+2))
7213 return -ENOMEM;
7214
7215 s[sz++] = c;
7216 state = VALUE;
7217
7218 break;
7219
7220 case SINGLE_QUOTE:
f32d2db1
LP
7221 if (c == 0) {
7222 if (relax)
7223 goto finish;
7629889c 7224 return -EINVAL;
f32d2db1 7225 } else if (c == '\'')
7629889c
LP
7226 state = VALUE;
7227 else if (c == '\\')
7228 state = SINGLE_QUOTE_ESCAPE;
7229 else {
7230 if (!GREEDY_REALLOC(s, allocated, sz+2))
7231 return -ENOMEM;
7232
7233 s[sz++] = c;
7234 }
7235
7236 break;
7237
7238 case SINGLE_QUOTE_ESCAPE:
f32d2db1
LP
7239 if (c == 0) {
7240 if (relax)
7241 goto finish;
7629889c 7242 return -EINVAL;
f32d2db1 7243 }
7629889c
LP
7244
7245 if (!GREEDY_REALLOC(s, allocated, sz+2))
7246 return -ENOMEM;
7247
7248 s[sz++] = c;
7249 state = SINGLE_QUOTE;
7250 break;
7251
7252 case DOUBLE_QUOTE:
7253 if (c == 0)
7254 return -EINVAL;
7255 else if (c == '\"')
7256 state = VALUE;
7257 else if (c == '\\')
7258 state = DOUBLE_QUOTE_ESCAPE;
7259 else {
7260 if (!GREEDY_REALLOC(s, allocated, sz+2))
7261 return -ENOMEM;
7262
7263 s[sz++] = c;
7264 }
7265
7266 break;
7267
7268 case DOUBLE_QUOTE_ESCAPE:
f32d2db1
LP
7269 if (c == 0) {
7270 if (relax)
7271 goto finish;
7629889c 7272 return -EINVAL;
f32d2db1 7273 }
7629889c
LP
7274
7275 if (!GREEDY_REALLOC(s, allocated, sz+2))
7276 return -ENOMEM;
7277
7278 s[sz++] = c;
7279 state = DOUBLE_QUOTE;
7280 break;
7281
7282 case SPACE:
7283 if (c == 0)
7284 goto finish;
7285 if (!strchr(WHITESPACE, c))
7286 goto finish;
7287
7288 break;
7289 }
7290
7291 (*p) ++;
7292 }
7293
7294finish:
7295 if (!s) {
7296 *ret = NULL;
7297 return 0;
7298 }
7299
7300 s[sz] = 0;
7301 *ret = s;
7302 s = NULL;
7303
7304 return 1;
7305}
7306
7307int unquote_many_words(const char **p, ...) {
7308 va_list ap;
7309 char **l;
7310 int n = 0, i, c, r;
7311
7312 /* Parses a number of words from a string, stripping any
7313 * quotes if necessary. */
7314
7315 assert(p);
7316
7317 /* Count how many words are expected */
7318 va_start(ap, p);
7319 for (;;) {
7320 if (!va_arg(ap, char **))
7321 break;
7322 n++;
7323 }
7324 va_end(ap);
7325
7326 if (n <= 0)
7327 return 0;
7328
7329 /* Read all words into a temporary array */
7330 l = newa0(char*, n);
7331 for (c = 0; c < n; c++) {
7332
f32d2db1 7333 r = unquote_first_word(p, &l[c], false);
7629889c
LP
7334 if (r < 0) {
7335 int j;
7336
081e009b 7337 for (j = 0; j < c; j++)
7629889c 7338 free(l[j]);
081e009b
LN
7339
7340 return r;
7629889c
LP
7341 }
7342
7343 if (r == 0)
7344 break;
7345 }
7346
7347 /* If we managed to parse all words, return them in the passed
7348 * in parameters */
7349 va_start(ap, p);
7350 for (i = 0; i < n; i++) {
7351 char **v;
7352
7353 v = va_arg(ap, char **);
7354 assert(v);
7355
7356 *v = l[i];
7357 }
7358 va_end(ap);
7359
7360 return c;
7361}
2928b0a8
LP
7362
7363int free_and_strdup(char **p, const char *s) {
7364 char *t;
7365
7366 assert(p);
7367
7368 /* Replaces a string pointer with an strdup()ed new string,
7369 * possibly freeing the old one. */
7370
7371 if (s) {
7372 t = strdup(s);
7373 if (!t)
7374 return -ENOMEM;
7375 } else
7376 t = NULL;
7377
7378 free(*p);
7379 *p = t;
7380
7381 return 0;
7382}
605f81a8
MS
7383
7384int sethostname_idempotent(const char *s) {
7385 int r;
7386 char buf[HOST_NAME_MAX + 1] = {};
7387
7388 assert(s);
7389
7390 r = gethostname(buf, sizeof(buf));
7391 if (r < 0)
7392 return -errno;
7393
7394 if (streq(buf, s))
7395 return 0;
7396
a9169c1c 7397 r = sethostname(s, strlen(s));
605f81a8
MS
7398 if (r < 0)
7399 return -errno;
7400
7401 return 1;
7402}