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