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