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