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