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