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