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