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