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