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