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