]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/util.c
login: assing /dev/console logins to seat0
[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
d1122ad5
LP
4290bool tty_is_console(const char *tty) {
4291 assert(tty);
4292
4293 if (startswith(tty, "/dev/"))
4294 tty += 5;
4295
4296 return streq(tty, "console");
4297}
4298
98a28fef
LP
4299int vtnr_from_tty(const char *tty) {
4300 int i, r;
4301
4302 assert(tty);
4303
4304 if (startswith(tty, "/dev/"))
4305 tty += 5;
4306
4307 if (!startswith(tty, "tty") )
4308 return -EINVAL;
4309
4310 if (tty[3] < '0' || tty[3] > '9')
4311 return -EINVAL;
4312
4313 r = safe_atoi(tty+3, &i);
4314 if (r < 0)
4315 return r;
4316
4317 if (i < 0 || i > 63)
4318 return -EINVAL;
4319
4320 return i;
f212ac12
LP
4321}
4322
3043935f 4323bool tty_is_vc_resolve(const char *tty) {
3030ccd7 4324 char *active = NULL;
3043935f 4325 bool b;
3030ccd7 4326
e3aa71c3
LP
4327 assert(tty);
4328
4329 if (startswith(tty, "/dev/"))
4330 tty += 5;
4331
3d9a4122
LP
4332 /* Resolve where /dev/console is pointing to, if /sys is
4333 * actually ours (i.e. not read-only-mounted which is a sign
4334 * for container setups) */
4335 if (streq(tty, "console") && path_is_read_only_fs("/sys") <= 0)
3030ccd7 4336 if (read_one_line_file("/sys/class/tty/console/active", &active) >= 0) {
079a09fb
LP
4337 /* If multiple log outputs are configured the
4338 * last one is what /dev/console points to */
3043935f
LP
4339 tty = strrchr(active, ' ');
4340 if (tty)
079a09fb
LP
4341 tty++;
4342 else
4343 tty = active;
3030ccd7
LP
4344 }
4345
3043935f 4346 b = tty_is_vc(tty);
3030ccd7 4347 free(active);
e3aa71c3 4348
3043935f
LP
4349 return b;
4350}
4351
4352const char *default_term_for_tty(const char *tty) {
4353 assert(tty);
4354
4355 return tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt100";
e3aa71c3
LP
4356}
4357
87d2c1ff 4358bool dirent_is_file(const struct dirent *de) {
fb19a739
LP
4359 assert(de);
4360
4361 if (ignore_file(de->d_name))
4362 return false;
4363
4364 if (de->d_type != DT_REG &&
4365 de->d_type != DT_LNK &&
4366 de->d_type != DT_UNKNOWN)
4367 return false;
4368
4369 return true;
4370}
4371
87d2c1ff
LP
4372bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
4373 assert(de);
4374
4375 if (!dirent_is_file(de))
4376 return false;
4377
4378 return endswith(de->d_name, suffix);
4379}
4380
83cc030f
LP
4381void execute_directory(const char *directory, DIR *d, char *argv[]) {
4382 DIR *_d = NULL;
4383 struct dirent *de;
4384 Hashmap *pids = NULL;
4385
4386 assert(directory);
4387
4388 /* Executes all binaries in a directory in parallel and waits
4389 * until all they all finished. */
4390
4391 if (!d) {
4392 if (!(_d = opendir(directory))) {
4393
4394 if (errno == ENOENT)
4395 return;
4396
4397 log_error("Failed to enumerate directory %s: %m", directory);
4398 return;
4399 }
4400
4401 d = _d;
4402 }
4403
4404 if (!(pids = hashmap_new(trivial_hash_func, trivial_compare_func))) {
4405 log_error("Failed to allocate set.");
4406 goto finish;
4407 }
4408
4409 while ((de = readdir(d))) {
4410 char *path;
4411 pid_t pid;
4412 int k;
4413
fb19a739 4414 if (!dirent_is_file(de))
83cc030f
LP
4415 continue;
4416
4417 if (asprintf(&path, "%s/%s", directory, de->d_name) < 0) {
4418 log_error("Out of memory");
4419 continue;
4420 }
4421
4422 if ((pid = fork()) < 0) {
4423 log_error("Failed to fork: %m");
4424 free(path);
4425 continue;
4426 }
4427
4428 if (pid == 0) {
4429 char *_argv[2];
4430 /* Child */
4431
4432 if (!argv) {
4433 _argv[0] = path;
4434 _argv[1] = NULL;
4435 argv = _argv;
4436 } else
4437 if (!argv[0])
4438 argv[0] = path;
4439
4440 execv(path, argv);
4441
4442 log_error("Failed to execute %s: %m", path);
4443 _exit(EXIT_FAILURE);
4444 }
4445
4446 log_debug("Spawned %s as %lu", path, (unsigned long) pid);
4447
4448 if ((k = hashmap_put(pids, UINT_TO_PTR(pid), path)) < 0) {
4449 log_error("Failed to add PID to set: %s", strerror(-k));
4450 free(path);
4451 }
4452 }
4453
4454 while (!hashmap_isempty(pids)) {
ec3f9b53 4455 pid_t pid = PTR_TO_UINT(hashmap_first_key(pids));
83cc030f
LP
4456 siginfo_t si;
4457 char *path;
4458
4459 zero(si);
ec3f9b53 4460 if (waitid(P_PID, pid, &si, WEXITED) < 0) {
83cc030f
LP
4461
4462 if (errno == EINTR)
4463 continue;
4464
4465 log_error("waitid() failed: %m");
4466 goto finish;
4467 }
4468
4469 if ((path = hashmap_remove(pids, UINT_TO_PTR(si.si_pid)))) {
4470 if (!is_clean_exit(si.si_code, si.si_status)) {
4471 if (si.si_code == CLD_EXITED)
4472 log_error("%s exited with exit status %i.", path, si.si_status);
4473 else
4474 log_error("%s terminated by signal %s.", path, signal_to_string(si.si_status));
4475 } else
4476 log_debug("%s exited successfully.", path);
4477
4478 free(path);
4479 }
4480 }
4481
4482finish:
4483 if (_d)
4484 closedir(_d);
4485
4486 if (pids)
4487 hashmap_free_free(pids);
4488}
4489
430c18ed
LP
4490int kill_and_sigcont(pid_t pid, int sig) {
4491 int r;
4492
4493 r = kill(pid, sig) < 0 ? -errno : 0;
4494
4495 if (r >= 0)
4496 kill(pid, SIGCONT);
4497
4498 return r;
4499}
4500
05feefe0
LP
4501bool nulstr_contains(const char*nulstr, const char *needle) {
4502 const char *i;
4503
4504 if (!nulstr)
4505 return false;
4506
4507 NULSTR_FOREACH(i, nulstr)
4508 if (streq(i, needle))
4509 return true;
4510
4511 return false;
4512}
4513
6faa1114 4514bool plymouth_running(void) {
9408a2d2 4515 return access("/run/plymouth/pid", F_OK) >= 0;
6faa1114
LP
4516}
4517
7c3b203c
LP
4518void parse_syslog_priority(char **p, int *priority) {
4519 int a = 0, b = 0, c = 0;
4520 int k;
4521
4522 assert(p);
4523 assert(*p);
4524 assert(priority);
4525
4526 if ((*p)[0] != '<')
4527 return;
4528
4529 if (!strchr(*p, '>'))
4530 return;
4531
4532 if ((*p)[2] == '>') {
4533 c = undecchar((*p)[1]);
4534 k = 3;
4535 } else if ((*p)[3] == '>') {
4536 b = undecchar((*p)[1]);
4537 c = undecchar((*p)[2]);
4538 k = 4;
4539 } else if ((*p)[4] == '>') {
4540 a = undecchar((*p)[1]);
4541 b = undecchar((*p)[2]);
4542 c = undecchar((*p)[3]);
4543 k = 5;
4544 } else
4545 return;
4546
4547 if (a < 0 || b < 0 || c < 0)
4548 return;
4549
4550 *priority = a*100+b*10+c;
4551 *p += k;
4552}
4553
87d2c1ff
LP
4554void skip_syslog_pid(char **buf) {
4555 char *p;
4556
4557 assert(buf);
4558 assert(*buf);
4559
4560 p = *buf;
4561
4562 if (*p != '[')
4563 return;
4564
4565 p++;
4566 p += strspn(p, "0123456789");
4567
4568 if (*p != ']')
4569 return;
4570
4571 p++;
4572
4573 *buf = p;
4574}
4575
4576void skip_syslog_date(char **buf) {
4577 enum {
4578 LETTER,
4579 SPACE,
4580 NUMBER,
4581 SPACE_OR_NUMBER,
4582 COLON
4583 } sequence[] = {
4584 LETTER, LETTER, LETTER,
4585 SPACE,
4586 SPACE_OR_NUMBER, NUMBER,
4587 SPACE,
4588 SPACE_OR_NUMBER, NUMBER,
4589 COLON,
4590 SPACE_OR_NUMBER, NUMBER,
4591 COLON,
4592 SPACE_OR_NUMBER, NUMBER,
4593 SPACE
4594 };
4595
4596 char *p;
4597 unsigned i;
4598
4599 assert(buf);
4600 assert(*buf);
4601
4602 p = *buf;
4603
4604 for (i = 0; i < ELEMENTSOF(sequence); i++, p++) {
4605
4606 if (!*p)
4607 return;
4608
4609 switch (sequence[i]) {
4610
4611 case SPACE:
4612 if (*p != ' ')
4613 return;
4614 break;
4615
4616 case SPACE_OR_NUMBER:
4617 if (*p == ' ')
4618 break;
4619
4620 /* fall through */
4621
4622 case NUMBER:
4623 if (*p < '0' || *p > '9')
4624 return;
4625
4626 break;
4627
4628 case LETTER:
4629 if (!(*p >= 'A' && *p <= 'Z') &&
4630 !(*p >= 'a' && *p <= 'z'))
4631 return;
4632
4633 break;
4634
4635 case COLON:
4636 if (*p != ':')
4637 return;
4638 break;
4639
4640 }
4641 }
4642
4643 *buf = p;
4644}
4645
9beb3f4d
LP
4646char* strshorten(char *s, size_t l) {
4647 assert(s);
4648
4649 if (l < strlen(s))
4650 s[l] = 0;
4651
4652 return s;
4653}
4654
4655static bool hostname_valid_char(char c) {
4656 return
4657 (c >= 'a' && c <= 'z') ||
4658 (c >= 'A' && c <= 'Z') ||
4659 (c >= '0' && c <= '9') ||
4660 c == '-' ||
4661 c == '_' ||
4662 c == '.';
4663}
4664
4665bool hostname_is_valid(const char *s) {
4666 const char *p;
4667
4668 if (isempty(s))
4669 return false;
4670
4671 for (p = s; *p; p++)
4672 if (!hostname_valid_char(*p))
4673 return false;
4674
4675 if (p-s > HOST_NAME_MAX)
4676 return false;
4677
4678 return true;
4679}
4680
4681char* hostname_cleanup(char *s) {
4682 char *p, *d;
4683
4684 for (p = s, d = s; *p; p++)
4685 if ((*p >= 'a' && *p <= 'z') ||
4686 (*p >= 'A' && *p <= 'Z') ||
4687 (*p >= '0' && *p <= '9') ||
4688 *p == '-' ||
4689 *p == '_' ||
4690 *p == '.')
4691 *(d++) = *p;
4692
4693 *d = 0;
4694
4695 strshorten(s, HOST_NAME_MAX);
4696 return s;
4697}
4698
1325aa42
LP
4699int pipe_eof(int fd) {
4700 struct pollfd pollfd;
4701 int r;
4702
4703 zero(pollfd);
4704 pollfd.fd = fd;
4705 pollfd.events = POLLIN|POLLHUP;
4706
4707 r = poll(&pollfd, 1, 0);
4708 if (r < 0)
4709 return -errno;
4710
4711 if (r == 0)
4712 return 0;
4713
4714 return pollfd.revents & POLLHUP;
4715}
4716
8f2d43a0 4717int fd_wait_for_event(int fd, int event, usec_t t) {
df50185b
LP
4718 struct pollfd pollfd;
4719 int r;
4720
4721 zero(pollfd);
4722 pollfd.fd = fd;
4723 pollfd.events = event;
4724
8f2d43a0 4725 r = poll(&pollfd, 1, t == (usec_t) -1 ? -1 : (int) (t / USEC_PER_MSEC));
df50185b
LP
4726 if (r < 0)
4727 return -errno;
4728
4729 if (r == 0)
4730 return 0;
4731
4732 return pollfd.revents;
4733}
4734
5a3ab509
LP
4735int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
4736 FILE *f;
4737 char *t;
4738 const char *fn;
4739 size_t k;
4740 int fd;
4741
4742 assert(path);
4743 assert(_f);
4744 assert(_temp_path);
4745
4746 t = new(char, strlen(path) + 1 + 6 + 1);
4747 if (!t)
4748 return -ENOMEM;
4749
4750 fn = file_name_from_path(path);
4751 k = fn-path;
4752 memcpy(t, path, k);
4753 t[k] = '.';
4754 stpcpy(stpcpy(t+k+1, fn), "XXXXXX");
4755
4756 fd = mkostemp(t, O_WRONLY|O_CLOEXEC);
4757 if (fd < 0) {
4758 free(t);
4759 return -errno;
4760 }
4761
4762 f = fdopen(fd, "we");
4763 if (!f) {
4764 unlink(t);
4765 free(t);
4766 return -errno;
4767 }
4768
4769 *_f = f;
4770 *_temp_path = t;
4771
4772 return 0;
4773}
4774
6ea832a2 4775int terminal_vhangup_fd(int fd) {
5a3ab509
LP
4776 assert(fd >= 0);
4777
6ea832a2
LP
4778 if (ioctl(fd, TIOCVHANGUP) < 0)
4779 return -errno;
4780
4781 return 0;
4782}
4783
4784int terminal_vhangup(const char *name) {
4785 int fd, r;
4786
4787 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
4788 if (fd < 0)
4789 return fd;
4790
4791 r = terminal_vhangup_fd(fd);
4792 close_nointr_nofail(fd);
4793
4794 return r;
4795}
4796
4797int vt_disallocate(const char *name) {
4798 int fd, r;
4799 unsigned u;
6ea832a2
LP
4800
4801 /* Deallocate the VT if possible. If not possible
4802 * (i.e. because it is the active one), at least clear it
4803 * entirely (including the scrollback buffer) */
4804
b83bc4e9
LP
4805 if (!startswith(name, "/dev/"))
4806 return -EINVAL;
4807
4808 if (!tty_is_vc(name)) {
4809 /* So this is not a VT. I guess we cannot deallocate
4810 * it then. But let's at least clear the screen */
4811
4812 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
4813 if (fd < 0)
4814 return fd;
4815
8585357a
LP
4816 loop_write(fd,
4817 "\033[r" /* clear scrolling region */
4818 "\033[H" /* move home */
4819 "\033[2J", /* clear screen */
4820 10, false);
b83bc4e9
LP
4821 close_nointr_nofail(fd);
4822
4823 return 0;
4824 }
6ea832a2
LP
4825
4826 if (!startswith(name, "/dev/tty"))
4827 return -EINVAL;
4828
4829 r = safe_atou(name+8, &u);
4830 if (r < 0)
4831 return r;
4832
4833 if (u <= 0)
b83bc4e9 4834 return -EINVAL;
6ea832a2 4835
b83bc4e9 4836 /* Try to deallocate */
6ea832a2
LP
4837 fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
4838 if (fd < 0)
4839 return fd;
4840
4841 r = ioctl(fd, VT_DISALLOCATE, u);
b83bc4e9 4842 close_nointr_nofail(fd);
6ea832a2 4843
b83bc4e9
LP
4844 if (r >= 0)
4845 return 0;
6ea832a2 4846
b83bc4e9 4847 if (errno != EBUSY)
6ea832a2 4848 return -errno;
6ea832a2 4849
b83bc4e9
LP
4850 /* Couldn't deallocate, so let's clear it fully with
4851 * scrollback */
4852 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
6ea832a2 4853 if (fd < 0)
b83bc4e9 4854 return fd;
6ea832a2 4855
8585357a
LP
4856 loop_write(fd,
4857 "\033[r" /* clear scrolling region */
4858 "\033[H" /* move home */
4859 "\033[3J", /* clear screen including scrollback, requires Linux 2.6.40 */
4860 10, false);
b83bc4e9 4861 close_nointr_nofail(fd);
6ea832a2 4862
b83bc4e9 4863 return 0;
6ea832a2
LP
4864}
4865
db1413d7
KS
4866static int files_add(Hashmap *h, const char *path, const char *suffix) {
4867 DIR *dir;
f782b8d0 4868 struct dirent buffer, *de;
db1413d7
KS
4869 int r = 0;
4870
4871 dir = opendir(path);
4872 if (!dir) {
4873 if (errno == ENOENT)
4874 return 0;
4875 return -errno;
4876 }
4877
f782b8d0
LP
4878 for (;;) {
4879 int k;
223a3558 4880 char *p, *f;
f782b8d0
LP
4881
4882 k = readdir_r(dir, &buffer, &de);
4883 if (k != 0) {
4884 r = -k;
4885 goto finish;
4886 }
4887
4888 if (!de)
4889 break;
db1413d7 4890
87d2c1ff 4891 if (!dirent_is_file_with_suffix(de, suffix))
db1413d7
KS
4892 continue;
4893
223a3558 4894 if (asprintf(&p, "%s/%s", path, de->d_name) < 0) {
db1413d7
KS
4895 r = -ENOMEM;
4896 goto finish;
4897 }
4898
223a3558
KS
4899 f = canonicalize_file_name(p);
4900 if (!f) {
4901 log_error("Failed to canonicalize file name '%s': %m", p);
4902 free(p);
4903 continue;
4904 }
4905 free(p);
4906
db1413d7 4907 log_debug("found: %s\n", f);
f782b8d0 4908 if (hashmap_put(h, file_name_from_path(f), f) <= 0)
db1413d7
KS
4909 free(f);
4910 }
4911
4912finish:
4913 closedir(dir);
4914 return r;
4915}
4916
4917static int base_cmp(const void *a, const void *b) {
4918 const char *s1, *s2;
4919
4920 s1 = *(char * const *)a;
4921 s2 = *(char * const *)b;
4922 return strcmp(file_name_from_path(s1), file_name_from_path(s2));
4923}
4924
44143309 4925int conf_files_list(char ***strv, const char *suffix, const char *dir, ...) {
223a3558
KS
4926 Hashmap *fh = NULL;
4927 char **dirs = NULL;
db1413d7 4928 char **files = NULL;
223a3558 4929 char **p;
db1413d7 4930 va_list ap;
44143309 4931 int r = 0;
db1413d7 4932
223a3558
KS
4933 va_start(ap, dir);
4934 dirs = strv_new_ap(dir, ap);
4935 va_end(ap);
4936 if (!dirs) {
4937 r = -ENOMEM;
4938 goto finish;
4939 }
4940 if (!strv_path_canonicalize(dirs)) {
4941 r = -ENOMEM;
4942 goto finish;
4943 }
4944 if (!strv_uniq(dirs)) {
4945 r = -ENOMEM;
4946 goto finish;
4947 }
4948
db1413d7
KS
4949 fh = hashmap_new(string_hash_func, string_compare_func);
4950 if (!fh) {
44143309 4951 r = -ENOMEM;
db1413d7
KS
4952 goto finish;
4953 }
4954
223a3558
KS
4955 STRV_FOREACH(p, dirs) {
4956 if (files_add(fh, *p, suffix) < 0) {
db1413d7 4957 log_error("Failed to search for files.");
44143309 4958 r = -EINVAL;
db1413d7
KS
4959 goto finish;
4960 }
db1413d7 4961 }
db1413d7
KS
4962
4963 files = hashmap_get_strv(fh);
4964 if (files == NULL) {
4965 log_error("Failed to compose list of files.");
44143309 4966 r = -ENOMEM;
db1413d7
KS
4967 goto finish;
4968 }
4969
4970 qsort(files, hashmap_size(fh), sizeof(char *), base_cmp);
8d0e38a2 4971
db1413d7 4972finish:
223a3558 4973 strv_free(dirs);
db1413d7 4974 hashmap_free(fh);
44143309
KS
4975 *strv = files;
4976 return r;
db1413d7 4977}
7948c4df 4978
2076cf88 4979int hwclock_is_localtime(void) {
7948c4df 4980 FILE *f;
7948c4df
KS
4981 bool local = false;
4982
4983 /*
4984 * The third line of adjtime is "UTC" or "LOCAL" or nothing.
4985 * # /etc/adjtime
2076cf88 4986 * 0.0 0 0
7948c4df
KS
4987 * 0
4988 * UTC
4989 */
4990 f = fopen("/etc/adjtime", "re");
4991 if (f) {
2076cf88
LP
4992 char line[LINE_MAX];
4993 bool b;
4994
4995 b = fgets(line, sizeof(line), f) &&
4996 fgets(line, sizeof(line), f) &&
4997 fgets(line, sizeof(line), f);
4998
7948c4df 4999 fclose(f);
2076cf88
LP
5000
5001 if (!b)
5002 return -EIO;
5003
5004
5005 truncate_nl(line);
5006 local = streq(line, "LOCAL");
5007
5008 } else if (errno != -ENOENT)
5009 return -errno;
5010
7948c4df
KS
5011 return local;
5012}
5013
ff4daf5a 5014int hwclock_apply_localtime_delta(int *min) {
7948c4df 5015 const struct timeval *tv_null = NULL;
2076cf88 5016 struct timespec ts;
7948c4df
KS
5017 struct tm *tm;
5018 int minuteswest;
5019 struct timezone tz;
5020
2076cf88
LP
5021 assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0);
5022 assert_se(tm = localtime(&ts.tv_sec));
7948c4df
KS
5023 minuteswest = tm->tm_gmtoff / 60;
5024
5025 tz.tz_minuteswest = -minuteswest;
5026 tz.tz_dsttime = 0; /* DST_NONE*/
5027
5028 /*
5029 * If the hardware clock does not run in UTC, but in local time:
5030 * The very first time we set the kernel's timezone, it will warp
5031 * the clock so that it runs in UTC instead of local time.
5032 */
5033 if (settimeofday(tv_null, &tz) < 0)
5034 return -errno;
ff4daf5a
KS
5035 if (min)
5036 *min = minuteswest;
5037 return 0;
2076cf88
LP
5038}
5039
5040int hwclock_reset_localtime_delta(void) {
5041 const struct timeval *tv_null = NULL;
5042 struct timezone tz;
5043
5044 tz.tz_minuteswest = 0;
5045 tz.tz_dsttime = 0; /* DST_NONE*/
5046
5047 if (settimeofday(tv_null, &tz) < 0)
5048 return -errno;
5049
5050 return 0;
7948c4df
KS
5051}
5052
51122dc9
LP
5053int rtc_open(int flags) {
5054 int fd;
5055 DIR *d;
5056
7c697168
LP
5057 /* First, we try to make use of the /dev/rtc symlink. If that
5058 * doesn't exist, we open the first RTC which has hctosys=1
5059 * set. If we don't find any we just take the first RTC that
5060 * exists at all. */
5061
5062 fd = open("/dev/rtc", flags);
5063 if (fd >= 0)
5064 return fd;
51122dc9
LP
5065
5066 d = opendir("/sys/class/rtc");
5067 if (!d)
5068 goto fallback;
5069
5070 for (;;) {
5071 char *p, *v;
5072 struct dirent buf, *de;
5073 int r;
5074
5075 r = readdir_r(d, &buf, &de);
5076 if (r != 0)
5077 goto fallback;
5078
5079 if (!de)
5080 goto fallback;
5081
5082 if (ignore_file(de->d_name))
5083 continue;
5084
5085 p = join("/sys/class/rtc/", de->d_name, "/hctosys", NULL);
5086 if (!p) {
5087 closedir(d);
5088 return -ENOMEM;
5089 }
5090
5091 r = read_one_line_file(p, &v);
5092 free(p);
5093
5094 if (r < 0)
5095 continue;
5096
5097 r = parse_boolean(v);
5098 free(v);
5099
5100 if (r <= 0)
5101 continue;
5102
5103 p = strappend("/dev/", de->d_name);
5104 fd = open(p, flags);
5105 free(p);
5106
5107 if (fd >= 0) {
5108 closedir(d);
5109 return fd;
5110 }
5111 }
5112
5113fallback:
5114 if (d)
5115 closedir(d);
5116
5117 fd = open("/dev/rtc0", flags);
5118 if (fd < 0)
5119 return -errno;
5120
5121 return fd;
5122}
5123
7948c4df
KS
5124int hwclock_get_time(struct tm *tm) {
5125 int fd;
5126 int err = 0;
5127
2076cf88
LP
5128 assert(tm);
5129
51122dc9 5130 fd = rtc_open(O_RDONLY|O_CLOEXEC);
7948c4df
KS
5131 if (fd < 0)
5132 return -errno;
2076cf88
LP
5133
5134 /* This leaves the timezone fields of struct tm
5135 * uninitialized! */
7948c4df
KS
5136 if (ioctl(fd, RTC_RD_TIME, tm) < 0)
5137 err = -errno;
2076cf88
LP
5138
5139 /* We don't now daylight saving, so we reset this in order not
5140 * to confused mktime(). */
5141 tm->tm_isdst = -1;
5142
5143 close_nointr_nofail(fd);
7948c4df
KS
5144
5145 return err;
5146}
5147
5148int hwclock_set_time(const struct tm *tm) {
5149 int fd;
5150 int err = 0;
5151
2076cf88
LP
5152 assert(tm);
5153
51122dc9 5154 fd = rtc_open(O_RDONLY|O_CLOEXEC);
7948c4df
KS
5155 if (fd < 0)
5156 return -errno;
2076cf88 5157
7948c4df
KS
5158 if (ioctl(fd, RTC_SET_TIME, tm) < 0)
5159 err = -errno;
2076cf88
LP
5160
5161 close_nointr_nofail(fd);
7948c4df
KS
5162
5163 return err;
5164}
f41607a6 5165
34ca941c
LP
5166int copy_file(const char *from, const char *to) {
5167 int r, fdf, fdt;
5168
5169 assert(from);
5170 assert(to);
5171
5172 fdf = open(from, O_RDONLY|O_CLOEXEC|O_NOCTTY);
5173 if (fdf < 0)
5174 return -errno;
5175
5176 fdt = open(to, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOCTTY, 0644);
5177 if (fdt < 0) {
5178 close_nointr_nofail(fdf);
5179 return -errno;
5180 }
5181
5182 for (;;) {
5183 char buf[PIPE_BUF];
5184 ssize_t n, k;
5185
5186 n = read(fdf, buf, sizeof(buf));
5187 if (n < 0) {
5188 r = -errno;
5189
5190 close_nointr_nofail(fdf);
5191 close_nointr(fdt);
5192 unlink(to);
5193
5194 return r;
5195 }
5196
5197 if (n == 0)
5198 break;
5199
5200 errno = 0;
5201 k = loop_write(fdt, buf, n, false);
5202 if (n != k) {
5203 r = k < 0 ? k : (errno ? -errno : -EIO);
5204
5205 close_nointr_nofail(fdf);
5206 close_nointr(fdt);
5207
5208 unlink(to);
5209 return r;
5210 }
5211 }
5212
5213 close_nointr_nofail(fdf);
5214 r = close_nointr(fdt);
5215
5216 if (r < 0) {
5217 unlink(to);
5218 return r;
5219 }
5220
5221 return 0;
5222}
5223
5224int symlink_or_copy(const char *from, const char *to) {
5225 char *pf = NULL, *pt = NULL;
5226 struct stat a, b;
5227 int r;
5228
5229 assert(from);
5230 assert(to);
5231
5232 if (parent_of_path(from, &pf) < 0 ||
5233 parent_of_path(to, &pt) < 0) {
5234 r = -ENOMEM;
5235 goto finish;
5236 }
5237
5238 if (stat(pf, &a) < 0 ||
5239 stat(pt, &b) < 0) {
5240 r = -errno;
5241 goto finish;
5242 }
5243
5244 if (a.st_dev != b.st_dev) {
5245 free(pf);
5246 free(pt);
5247
5248 return copy_file(from, to);
5249 }
5250
5251 if (symlink(from, to) < 0) {
5252 r = -errno;
5253 goto finish;
5254 }
5255
5256 r = 0;
5257
5258finish:
5259 free(pf);
5260 free(pt);
5261
5262 return r;
5263}
5264
5265int symlink_or_copy_atomic(const char *from, const char *to) {
5266 char *t, *x;
5267 const char *fn;
5268 size_t k;
5269 unsigned long long ull;
5270 unsigned i;
5271 int r;
5272
5273 assert(from);
5274 assert(to);
5275
5276 t = new(char, strlen(to) + 1 + 16 + 1);
5277 if (!t)
5278 return -ENOMEM;
5279
5280 fn = file_name_from_path(to);
5281 k = fn-to;
5282 memcpy(t, to, k);
5283 t[k] = '.';
5284 x = stpcpy(t+k+1, fn);
5285
5286 ull = random_ull();
5287 for (i = 0; i < 16; i++) {
5288 *(x++) = hexchar(ull & 0xF);
5289 ull >>= 4;
5290 }
5291
5292 *x = 0;
5293
5294 r = symlink_or_copy(from, t);
5295 if (r < 0) {
5296 unlink(t);
5297 free(t);
5298 return r;
5299 }
5300
5301 if (rename(t, to) < 0) {
5302 r = -errno;
5303 unlink(t);
5304 free(t);
5305 return r;
5306 }
5307
5308 free(t);
5309 return r;
5310}
5311
4d6d6518
LP
5312bool display_is_local(const char *display) {
5313 assert(display);
5314
5315 return
5316 display[0] == ':' &&
5317 display[1] >= '0' &&
5318 display[1] <= '9';
5319}
5320
5321int socket_from_display(const char *display, char **path) {
5322 size_t k;
5323 char *f, *c;
5324
5325 assert(display);
5326 assert(path);
5327
5328 if (!display_is_local(display))
5329 return -EINVAL;
5330
5331 k = strspn(display+1, "0123456789");
5332
5333 f = new(char, sizeof("/tmp/.X11-unix/X") + k);
5334 if (!f)
5335 return -ENOMEM;
5336
5337 c = stpcpy(f, "/tmp/.X11-unix/X");
5338 memcpy(c, display+1, k);
5339 c[k] = 0;
5340
5341 *path = f;
5342
5343 return 0;
5344}
5345
1cccf435
MV
5346int get_user_creds(const char **username, uid_t *uid, gid_t *gid, const char **home) {
5347 struct passwd *p;
ddd88763 5348 uid_t u;
1cccf435
MV
5349
5350 assert(username);
5351 assert(*username);
1cccf435
MV
5352
5353 /* We enforce some special rules for uid=0: in order to avoid
5354 * NSS lookups for root we hardcode its data. */
5355
5356 if (streq(*username, "root") || streq(*username, "0")) {
5357 *username = "root";
4b67834e
LP
5358
5359 if (uid)
5360 *uid = 0;
5361
5362 if (gid)
5363 *gid = 0;
5364
5365 if (home)
5366 *home = "/root";
1cccf435
MV
5367 return 0;
5368 }
5369
ddd88763 5370 if (parse_uid(*username, &u) >= 0) {
1cccf435 5371 errno = 0;
ddd88763 5372 p = getpwuid(u);
1cccf435
MV
5373
5374 /* If there are multiple users with the same id, make
5375 * sure to leave $USER to the configured value instead
5376 * of the first occurrence in the database. However if
5377 * the uid was configured by a numeric uid, then let's
5378 * pick the real username from /etc/passwd. */
5379 if (p)
5380 *username = p->pw_name;
5381 } else {
5382 errno = 0;
5383 p = getpwnam(*username);
5384 }
5385
5386 if (!p)
5387 return errno != 0 ? -errno : -ESRCH;
5388
4b67834e
LP
5389 if (uid)
5390 *uid = p->pw_uid;
5391
5392 if (gid)
5393 *gid = p->pw_gid;
5394
5395 if (home)
5396 *home = p->pw_dir;
5397
5398 return 0;
5399}
5400
5401int get_group_creds(const char **groupname, gid_t *gid) {
5402 struct group *g;
5403 gid_t id;
5404
5405 assert(groupname);
5406
5407 /* We enforce some special rules for gid=0: in order to avoid
5408 * NSS lookups for root we hardcode its data. */
5409
5410 if (streq(*groupname, "root") || streq(*groupname, "0")) {
5411 *groupname = "root";
5412
5413 if (gid)
5414 *gid = 0;
5415
5416 return 0;
5417 }
5418
5419 if (parse_gid(*groupname, &id) >= 0) {
5420 errno = 0;
5421 g = getgrgid(id);
5422
5423 if (g)
5424 *groupname = g->gr_name;
5425 } else {
5426 errno = 0;
5427 g = getgrnam(*groupname);
5428 }
5429
5430 if (!g)
5431 return errno != 0 ? -errno : -ESRCH;
5432
5433 if (gid)
5434 *gid = g->gr_gid;
5435
1cccf435
MV
5436 return 0;
5437}
5438
43673799
LP
5439int in_group(const char *name) {
5440 gid_t gid, *gids;
5441 int ngroups_max, r, i;
5442
5443 r = get_group_creds(&name, &gid);
5444 if (r < 0)
5445 return r;
5446
5447 if (getgid() == gid)
5448 return 1;
5449
5450 if (getegid() == gid)
5451 return 1;
5452
5453 ngroups_max = sysconf(_SC_NGROUPS_MAX);
5454 assert(ngroups_max > 0);
5455
5456 gids = alloca(sizeof(gid_t) * ngroups_max);
5457
5458 r = getgroups(ngroups_max, gids);
5459 if (r < 0)
5460 return -errno;
5461
5462 for (i = 0; i < r; i++)
5463 if (gids[i] == gid)
5464 return 1;
5465
5466 return 0;
5467}
5468
8092a428
LP
5469int glob_exists(const char *path) {
5470 glob_t g;
5471 int r, k;
5472
5473 assert(path);
5474
5475 zero(g);
5476 errno = 0;
5477 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
5478
5479 if (k == GLOB_NOMATCH)
5480 r = 0;
5481 else if (k == GLOB_NOSPACE)
5482 r = -ENOMEM;
5483 else if (k == 0)
5484 r = !strv_isempty(g.gl_pathv);
5485 else
5486 r = errno ? -errno : -EIO;
5487
5488 globfree(&g);
5489
5490 return r;
5491}
5492
83096483
LP
5493int dirent_ensure_type(DIR *d, struct dirent *de) {
5494 struct stat st;
5495
5496 assert(d);
5497 assert(de);
5498
5499 if (de->d_type != DT_UNKNOWN)
5500 return 0;
5501
5502 if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
5503 return -errno;
5504
5505 de->d_type =
5506 S_ISREG(st.st_mode) ? DT_REG :
5507 S_ISDIR(st.st_mode) ? DT_DIR :
5508 S_ISLNK(st.st_mode) ? DT_LNK :
5509 S_ISFIFO(st.st_mode) ? DT_FIFO :
5510 S_ISSOCK(st.st_mode) ? DT_SOCK :
5511 S_ISCHR(st.st_mode) ? DT_CHR :
5512 S_ISBLK(st.st_mode) ? DT_BLK :
5513 DT_UNKNOWN;
5514
5515 return 0;
5516}
5517
5518int in_search_path(const char *path, char **search) {
5519 char **i, *parent;
5520 int r;
5521
5522 r = parent_of_path(path, &parent);
5523 if (r < 0)
5524 return r;
5525
5526 r = 0;
5527
5528 STRV_FOREACH(i, search) {
5529 if (path_equal(parent, *i)) {
5530 r = 1;
5531 break;
5532 }
5533 }
5534
5535 free(parent);
5536
5537 return r;
5538}
5539
034a2a52
LP
5540int get_files_in_directory(const char *path, char ***list) {
5541 DIR *d;
5542 int r = 0;
5543 unsigned n = 0;
5544 char **l = NULL;
5545
5546 assert(path);
d60ef526
LP
5547
5548 /* Returns all files in a directory in *list, and the number
5549 * of files as return value. If list is NULL returns only the
5550 * number */
034a2a52
LP
5551
5552 d = opendir(path);
8ea913b2
LP
5553 if (!d)
5554 return -errno;
5555
034a2a52
LP
5556 for (;;) {
5557 struct dirent buffer, *de;
5558 int k;
5559
5560 k = readdir_r(d, &buffer, &de);
5561 if (k != 0) {
5562 r = -k;
5563 goto finish;
5564 }
5565
5566 if (!de)
5567 break;
5568
5569 dirent_ensure_type(d, de);
5570
5571 if (!dirent_is_file(de))
5572 continue;
5573
d60ef526
LP
5574 if (list) {
5575 if ((unsigned) r >= n) {
5576 char **t;
034a2a52 5577
d60ef526
LP
5578 n = MAX(16, 2*r);
5579 t = realloc(l, sizeof(char*) * n);
5580 if (!t) {
5581 r = -ENOMEM;
5582 goto finish;
5583 }
034a2a52 5584
d60ef526
LP
5585 l = t;
5586 }
034a2a52 5587
d60ef526 5588 assert((unsigned) r < n);
034a2a52 5589
d60ef526
LP
5590 l[r] = strdup(de->d_name);
5591 if (!l[r]) {
5592 r = -ENOMEM;
5593 goto finish;
5594 }
034a2a52 5595
d60ef526
LP
5596 l[++r] = NULL;
5597 } else
5598 r++;
034a2a52
LP
5599 }
5600
5601finish:
5602 if (d)
5603 closedir(d);
5604
d60ef526
LP
5605 if (r >= 0) {
5606 if (list)
5607 *list = l;
5608 } else
034a2a52
LP
5609 strv_free(l);
5610
5611 return r;
5612}
5613
911a4828
LP
5614char *join(const char *x, ...) {
5615 va_list ap;
5616 size_t l;
5617 char *r, *p;
5618
5619 va_start(ap, x);
5620
5621 if (x) {
5622 l = strlen(x);
5623
5624 for (;;) {
5625 const char *t;
5626
5627 t = va_arg(ap, const char *);
5628 if (!t)
5629 break;
5630
5631 l += strlen(t);
5632 }
5633 } else
5634 l = 0;
5635
5636 va_end(ap);
5637
5638 r = new(char, l+1);
5639 if (!r)
5640 return NULL;
5641
5642 if (x) {
5643 p = stpcpy(r, x);
5644
5645 va_start(ap, x);
5646
5647 for (;;) {
5648 const char *t;
5649
5650 t = va_arg(ap, const char *);
5651 if (!t)
5652 break;
5653
5654 p = stpcpy(p, t);
5655 }
8ea913b2
LP
5656
5657 va_end(ap);
911a4828
LP
5658 } else
5659 r[0] = 0;
5660
5661 return r;
5662}
5663
b636465b
LP
5664bool is_main_thread(void) {
5665 static __thread int cached = 0;
5666
5667 if (_unlikely_(cached == 0))
5668 cached = getpid() == gettid() ? 1 : -1;
5669
5670 return cached > 0;
5671}
5672
94959f0f
LP
5673int block_get_whole_disk(dev_t d, dev_t *ret) {
5674 char *p, *s;
5675 int r;
5676 unsigned n, m;
5677
5678 assert(ret);
5679
5680 /* If it has a queue this is good enough for us */
5681 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", major(d), minor(d)) < 0)
5682 return -ENOMEM;
5683
5684 r = access(p, F_OK);
5685 free(p);
5686
5687 if (r >= 0) {
5688 *ret = d;
5689 return 0;
5690 }
5691
5692 /* If it is a partition find the originating device */
5693 if (asprintf(&p, "/sys/dev/block/%u:%u/partition", major(d), minor(d)) < 0)
5694 return -ENOMEM;
5695
5696 r = access(p, F_OK);
5697 free(p);
5698
5699 if (r < 0)
5700 return -ENOENT;
5701
5702 /* Get parent dev_t */
5703 if (asprintf(&p, "/sys/dev/block/%u:%u/../dev", major(d), minor(d)) < 0)
5704 return -ENOMEM;
5705
5706 r = read_one_line_file(p, &s);
5707 free(p);
5708
5709 if (r < 0)
5710 return r;
5711
5712 r = sscanf(s, "%u:%u", &m, &n);
5713 free(s);
5714
5715 if (r != 2)
5716 return -EINVAL;
5717
5718 /* Only return this if it is really good enough for us. */
5719 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", m, n) < 0)
5720 return -ENOMEM;
5721
5722 r = access(p, F_OK);
5723 free(p);
5724
5725 if (r >= 0) {
5726 *ret = makedev(m, n);
5727 return 0;
5728 }
5729
5730 return -ENOENT;
5731}
5732
8d53b453 5733int file_is_priv_sticky(const char *p) {
ad293f5a
LP
5734 struct stat st;
5735
5736 assert(p);
5737
5738 if (lstat(p, &st) < 0)
5739 return -errno;
5740
5741 return
8d53b453 5742 (st.st_uid == 0 || st.st_uid == getuid()) &&
ad293f5a
LP
5743 (st.st_mode & S_ISVTX);
5744}
94959f0f 5745
f41607a6
LP
5746static const char *const ioprio_class_table[] = {
5747 [IOPRIO_CLASS_NONE] = "none",
5748 [IOPRIO_CLASS_RT] = "realtime",
5749 [IOPRIO_CLASS_BE] = "best-effort",
5750 [IOPRIO_CLASS_IDLE] = "idle"
5751};
5752
5753DEFINE_STRING_TABLE_LOOKUP(ioprio_class, int);
5754
5755static const char *const sigchld_code_table[] = {
5756 [CLD_EXITED] = "exited",
5757 [CLD_KILLED] = "killed",
5758 [CLD_DUMPED] = "dumped",
5759 [CLD_TRAPPED] = "trapped",
5760 [CLD_STOPPED] = "stopped",
5761 [CLD_CONTINUED] = "continued",
5762};
5763
5764DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
5765
5766static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = {
5767 [LOG_FAC(LOG_KERN)] = "kern",
5768 [LOG_FAC(LOG_USER)] = "user",
5769 [LOG_FAC(LOG_MAIL)] = "mail",
5770 [LOG_FAC(LOG_DAEMON)] = "daemon",
5771 [LOG_FAC(LOG_AUTH)] = "auth",
5772 [LOG_FAC(LOG_SYSLOG)] = "syslog",
5773 [LOG_FAC(LOG_LPR)] = "lpr",
5774 [LOG_FAC(LOG_NEWS)] = "news",
5775 [LOG_FAC(LOG_UUCP)] = "uucp",
5776 [LOG_FAC(LOG_CRON)] = "cron",
5777 [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
5778 [LOG_FAC(LOG_FTP)] = "ftp",
5779 [LOG_FAC(LOG_LOCAL0)] = "local0",
5780 [LOG_FAC(LOG_LOCAL1)] = "local1",
5781 [LOG_FAC(LOG_LOCAL2)] = "local2",
5782 [LOG_FAC(LOG_LOCAL3)] = "local3",
5783 [LOG_FAC(LOG_LOCAL4)] = "local4",
5784 [LOG_FAC(LOG_LOCAL5)] = "local5",
5785 [LOG_FAC(LOG_LOCAL6)] = "local6",
5786 [LOG_FAC(LOG_LOCAL7)] = "local7"
5787};
5788
5789DEFINE_STRING_TABLE_LOOKUP(log_facility_unshifted, int);
5790
5791static const char *const log_level_table[] = {
5792 [LOG_EMERG] = "emerg",
5793 [LOG_ALERT] = "alert",
5794 [LOG_CRIT] = "crit",
5795 [LOG_ERR] = "err",
5796 [LOG_WARNING] = "warning",
5797 [LOG_NOTICE] = "notice",
5798 [LOG_INFO] = "info",
5799 [LOG_DEBUG] = "debug"
5800};
5801
5802DEFINE_STRING_TABLE_LOOKUP(log_level, int);
5803
5804static const char* const sched_policy_table[] = {
5805 [SCHED_OTHER] = "other",
5806 [SCHED_BATCH] = "batch",
5807 [SCHED_IDLE] = "idle",
5808 [SCHED_FIFO] = "fifo",
5809 [SCHED_RR] = "rr"
5810};
5811
5812DEFINE_STRING_TABLE_LOOKUP(sched_policy, int);
5813
5814static const char* const rlimit_table[] = {
5815 [RLIMIT_CPU] = "LimitCPU",
5816 [RLIMIT_FSIZE] = "LimitFSIZE",
5817 [RLIMIT_DATA] = "LimitDATA",
5818 [RLIMIT_STACK] = "LimitSTACK",
5819 [RLIMIT_CORE] = "LimitCORE",
5820 [RLIMIT_RSS] = "LimitRSS",
5821 [RLIMIT_NOFILE] = "LimitNOFILE",
5822 [RLIMIT_AS] = "LimitAS",
5823 [RLIMIT_NPROC] = "LimitNPROC",
5824 [RLIMIT_MEMLOCK] = "LimitMEMLOCK",
5825 [RLIMIT_LOCKS] = "LimitLOCKS",
5826 [RLIMIT_SIGPENDING] = "LimitSIGPENDING",
5827 [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE",
5828 [RLIMIT_NICE] = "LimitNICE",
5829 [RLIMIT_RTPRIO] = "LimitRTPRIO",
5830 [RLIMIT_RTTIME] = "LimitRTTIME"
5831};
5832
5833DEFINE_STRING_TABLE_LOOKUP(rlimit, int);
5834
5835static const char* const ip_tos_table[] = {
5836 [IPTOS_LOWDELAY] = "low-delay",
5837 [IPTOS_THROUGHPUT] = "throughput",
5838 [IPTOS_RELIABILITY] = "reliability",
5839 [IPTOS_LOWCOST] = "low-cost",
5840};
5841
5842DEFINE_STRING_TABLE_LOOKUP(ip_tos, int);
5843
4e240ab0 5844static const char *const __signal_table[] = {
f41607a6
LP
5845 [SIGHUP] = "HUP",
5846 [SIGINT] = "INT",
5847 [SIGQUIT] = "QUIT",
5848 [SIGILL] = "ILL",
5849 [SIGTRAP] = "TRAP",
5850 [SIGABRT] = "ABRT",
5851 [SIGBUS] = "BUS",
5852 [SIGFPE] = "FPE",
5853 [SIGKILL] = "KILL",
5854 [SIGUSR1] = "USR1",
5855 [SIGSEGV] = "SEGV",
5856 [SIGUSR2] = "USR2",
5857 [SIGPIPE] = "PIPE",
5858 [SIGALRM] = "ALRM",
5859 [SIGTERM] = "TERM",
5860#ifdef SIGSTKFLT
5861 [SIGSTKFLT] = "STKFLT", /* Linux on SPARC doesn't know SIGSTKFLT */
5862#endif
5863 [SIGCHLD] = "CHLD",
5864 [SIGCONT] = "CONT",
5865 [SIGSTOP] = "STOP",
5866 [SIGTSTP] = "TSTP",
5867 [SIGTTIN] = "TTIN",
5868 [SIGTTOU] = "TTOU",
5869 [SIGURG] = "URG",
5870 [SIGXCPU] = "XCPU",
5871 [SIGXFSZ] = "XFSZ",
5872 [SIGVTALRM] = "VTALRM",
5873 [SIGPROF] = "PROF",
5874 [SIGWINCH] = "WINCH",
5875 [SIGIO] = "IO",
5876 [SIGPWR] = "PWR",
5877 [SIGSYS] = "SYS"
5878};
5879
4e240ab0
MS
5880DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int);
5881
5882const char *signal_to_string(int signo) {
5883 static __thread char buf[12];
5884 const char *name;
5885
5886 name = __signal_to_string(signo);
5887 if (name)
5888 return name;
5889
5890 if (signo >= SIGRTMIN && signo <= SIGRTMAX)
5891 snprintf(buf, sizeof(buf) - 1, "RTMIN+%d", signo - SIGRTMIN);
5892 else
5893 snprintf(buf, sizeof(buf) - 1, "%d", signo);
5894 char_array_0(buf);
5895 return buf;
5896}
5897
5898int signal_from_string(const char *s) {
5899 int signo;
5900 int offset = 0;
5901 unsigned u;
5902
5903 signo =__signal_from_string(s);
5904 if (signo > 0)
5905 return signo;
5906
5907 if (startswith(s, "RTMIN+")) {
5908 s += 6;
5909 offset = SIGRTMIN;
5910 }
5911 if (safe_atou(s, &u) >= 0) {
5912 signo = (int) u + offset;
5913 if (signo > 0 && signo < _NSIG)
5914 return signo;
5915 }
5916 return -1;
5917}
65457142
FC
5918
5919bool kexec_loaded(void) {
5920 bool loaded = false;
5921 char *s;
5922
5923 if (read_one_line_file("/sys/kernel/kexec_loaded", &s) >= 0) {
5924 if (s[0] == '1')
5925 loaded = true;
5926 free(s);
5927 }
5928 return loaded;
5929}
fb9de93d
LP
5930
5931int strdup_or_null(const char *a, char **b) {
5932 char *c;
5933
5934 assert(b);
5935
5936 if (!a) {
5937 *b = NULL;
5938 return 0;
5939 }
5940
5941 c = strdup(a);
5942 if (!c)
5943 return -ENOMEM;
5944
5945 *b = c;
5946 return 0;
5947}
64685e0c 5948
87d2c1ff
LP
5949int prot_from_flags(int flags) {
5950
5951 switch (flags & O_ACCMODE) {
5952
5953 case O_RDONLY:
5954 return PROT_READ;
5955
5956 case O_WRONLY:
5957 return PROT_WRITE;
5958
5959 case O_RDWR:
5960 return PROT_READ|PROT_WRITE;
5961
5962 default:
5963 return -EINVAL;
5964 }
7c99e0c1 5965}
689b9a22 5966
babfc091 5967char *format_bytes(char *buf, size_t l, off_t t) {
c0f99c21 5968 unsigned i;
babfc091
LP
5969
5970 static const struct {
5971 const char *suffix;
5972 off_t factor;
5973 } table[] = {
32895bb3
LP
5974 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
5975 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
babfc091
LP
5976 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
5977 { "G", 1024ULL*1024ULL*1024ULL },
5978 { "M", 1024ULL*1024ULL },
5979 { "K", 1024ULL },
5980 };
5981
5982 for (i = 0; i < ELEMENTSOF(table); i++) {
5983
5984 if (t >= table[i].factor) {
5985 snprintf(buf, l,
5986 "%llu.%llu%s",
5987 (unsigned long long) (t / table[i].factor),
5988 (unsigned long long) (((t*10ULL) / table[i].factor) % 10ULL),
5989 table[i].suffix);
5990
5991 goto finish;
5992 }
5993 }
5994
5995 snprintf(buf, l, "%lluB", (unsigned long long) t);
5996
5997finish:
5998 buf[l-1] = 0;
5999 return buf;
6000
6001}
55d7bfc1
LP
6002
6003void* memdup(const void *p, size_t l) {
6004 void *r;
6005
6006 assert(p);
6007
6008 r = malloc(l);
6009 if (!r)
6010 return NULL;
6011
6012 memcpy(r, p, l);
6013 return r;
6014}
bb99a35a
LP
6015
6016int fd_inc_sndbuf(int fd, size_t n) {
6017 int r, value;
6018 socklen_t l = sizeof(value);
6019
6020 r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
6021 if (r >= 0 &&
6022 l == sizeof(value) &&
6023 (size_t) value >= n*2)
6024 return 0;
6025
6026 value = (int) n;
6027 r = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value));
6028 if (r < 0)
6029 return -errno;
6030
6031 return 1;
6032}
6033
6034int fd_inc_rcvbuf(int fd, size_t n) {
6035 int r, value;
6036 socklen_t l = sizeof(value);
6037
6038 r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
6039 if (r >= 0 &&
6040 l == sizeof(value) &&
6041 (size_t) value >= n*2)
6042 return 0;
6043
6044 value = (int) n;
6045 r = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value));
6046 if (r < 0)
6047 return -errno;
6048
6049 return 1;
6050}
6bb92a16 6051
9bdc770c 6052int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
6bb92a16
LP
6053 pid_t parent_pid, agent_pid;
6054 int fd;
6055 bool stdout_is_tty, stderr_is_tty;
6056 unsigned n, i;
6057 va_list ap;
6058 char **l;
6059
6060 assert(pid);
6061 assert(path);
6062
6063 parent_pid = getpid();
6064
6065 /* Spawns a temporary TTY agent, making sure it goes away when
6066 * we go away */
6067
6068 agent_pid = fork();
6069 if (agent_pid < 0)
6070 return -errno;
6071
6072 if (agent_pid != 0) {
6073 *pid = agent_pid;
6074 return 0;
6075 }
6076
6077 /* In the child:
6078 *
6079 * Make sure the agent goes away when the parent dies */
6080 if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
6081 _exit(EXIT_FAILURE);
6082
6083 /* Check whether our parent died before we were able
6084 * to set the death signal */
6085 if (getppid() != parent_pid)
6086 _exit(EXIT_SUCCESS);
6087
6088 /* Don't leak fds to the agent */
9bdc770c 6089 close_all_fds(except, n_except);
6bb92a16
LP
6090
6091 stdout_is_tty = isatty(STDOUT_FILENO);
6092 stderr_is_tty = isatty(STDERR_FILENO);
6093
6094 if (!stdout_is_tty || !stderr_is_tty) {
6095 /* Detach from stdout/stderr. and reopen
6096 * /dev/tty for them. This is important to
6097 * ensure that when systemctl is started via
6098 * popen() or a similar call that expects to
6099 * read EOF we actually do generate EOF and
6100 * not delay this indefinitely by because we
6101 * keep an unused copy of stdin around. */
6102 fd = open("/dev/tty", O_WRONLY);
6103 if (fd < 0) {
6104 log_error("Failed to open /dev/tty: %m");
6105 _exit(EXIT_FAILURE);
6106 }
6107
6108 if (!stdout_is_tty)
6109 dup2(fd, STDOUT_FILENO);
6110
6111 if (!stderr_is_tty)
6112 dup2(fd, STDERR_FILENO);
6113
6114 if (fd > 2)
6115 close(fd);
6116 }
6117
6118 /* Count arguments */
6119 va_start(ap, path);
6120 for (n = 0; va_arg(ap, char*); n++)
6121 ;
6122 va_end(ap);
6123
6124 /* Allocate strv */
6125 l = alloca(sizeof(char *) * (n + 1));
6126
6127 /* Fill in arguments */
6128 va_start(ap, path);
6129 for (i = 0; i <= n; i++)
6130 l[i] = va_arg(ap, char*);
6131 va_end(ap);
6132
6133 execv(path, l);
6134 _exit(EXIT_FAILURE);
6135}
68faf98c
LP
6136
6137int setrlimit_closest(int resource, const struct rlimit *rlim) {
6138 struct rlimit highest, fixed;
6139
6140 assert(rlim);
6141
6142 if (setrlimit(resource, rlim) >= 0)
6143 return 0;
6144
6145 if (errno != EPERM)
6146 return -errno;
6147
6148 /* So we failed to set the desired setrlimit, then let's try
6149 * to get as close as we can */
6150 assert_se(getrlimit(resource, &highest) == 0);
6151
6152 fixed.rlim_cur = MIN(rlim->rlim_cur, highest.rlim_max);
6153 fixed.rlim_max = MIN(rlim->rlim_max, highest.rlim_max);
6154
6155 if (setrlimit(resource, &fixed) < 0)
6156 return -errno;
6157
6158 return 0;
6159}
3d9a4122
LP
6160
6161int path_is_read_only_fs(const char *path) {
6162 struct statvfs st;
6163
6164 assert(path);
6165
6166 if (statvfs(path, &st) < 0)
6167 return -errno;
6168
6169 return !!(st.f_flag & ST_RDONLY);
6170}