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