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