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