]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/util.c
util: split out escaping code into escape.[ch]
[thirdparty/systemd.git] / src / basic / 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
f6c2284a
LP
22#include <ctype.h>
23#include <dirent.h>
60918275 24#include <errno.h>
f6c2284a
LP
25#include <fcntl.h>
26#include <glob.h>
27#include <grp.h>
28#include <langinfo.h>
20f56fdd 29#include <libintl.h>
f6c2284a
LP
30#include <limits.h>
31#include <linux/magic.h>
257b0719 32#include <linux/oom.h>
ef886c6a 33#include <linux/sched.h>
f6c2284a
LP
34#include <locale.h>
35#include <netinet/ip.h>
0a6f50c0 36#include <poll.h>
ef2f1067 37#include <pwd.h>
f6c2284a
LP
38#include <sched.h>
39#include <signal.h>
40#include <stdarg.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44#include <sys/file.h>
45#include <sys/ioctl.h>
87d2c1ff 46#include <sys/mman.h>
6d313367 47#include <sys/mount.h>
6afc95b7 48#include <sys/personality.h>
f6c2284a
LP
49#include <sys/prctl.h>
50#include <sys/resource.h>
51#include <sys/stat.h>
abe4aa14 52#include <sys/statvfs.h>
f6c2284a
LP
53#include <sys/time.h>
54#include <sys/types.h>
55#include <sys/utsname.h>
56#include <sys/vfs.h>
57#include <sys/wait.h>
58#include <sys/xattr.h>
59#include <syslog.h>
60#include <unistd.h>
eef46c37
LP
61
62/* When we include libgen.h because we need dirname() we immediately
f6c2284a
LP
63 * undefine basename() since libgen.h defines it as a macro to the
64 * POSIX version which is really broken. We prefer GNU basename(). */
eef46c37 65#include <libgen.h>
2b6bf07d 66#undef basename
60918275 67
9bf3b535
LP
68#ifdef HAVE_SYS_AUXV_H
69#include <sys/auxv.h>
70#endif
71
f6c2284a
LP
72/* We include linux/fs.h as last of the system headers, as it
73 * otherwise conflicts with sys/mount.h. Yay, Linux is great! */
74#include <linux/fs.h>
75
3f6fd1ba 76#include "build.h"
f6c2284a
LP
77#include "def.h"
78#include "device-nodes.h"
79#include "env-util.h"
4f5dd394 80#include "escape.h"
f6c2284a
LP
81#include "exit-status.h"
82#include "fileio.h"
83#include "formats-util.h"
84#include "gunicode.h"
85#include "hashmap.h"
86#include "hostname-util.h"
1dccbe19 87#include "ioprio.h"
a9f5d454 88#include "log.h"
f6c2284a
LP
89#include "macro.h"
90#include "missing.h"
c38dfac9 91#include "mkdir.h"
9eb977db 92#include "path-util.h"
0b452006 93#include "process-util.h"
3df3e884 94#include "random-util.h"
24882e06 95#include "signal-util.h"
f6c2284a
LP
96#include "sparse-endian.h"
97#include "strv.h"
98#include "terminal-util.h"
99#include "utf8.h"
f6c2284a 100#include "virt.h"
4f5dd394 101#include "util.h"
56cf987f 102
012d7b42
ZJS
103/* Put this test here for a lack of better place */
104assert_cc(EAGAIN == EWOULDBLOCK);
105
9a0e6896
LP
106int saved_argc = 0;
107char **saved_argv = NULL;
9086e840 108
37f85e66 109size_t page_size(void) {
ec202eae 110 static thread_local size_t pgsz = 0;
37f85e66 111 long r;
112
87d2c1ff 113 if (_likely_(pgsz > 0))
37f85e66 114 return pgsz;
115
e67f47e5
LP
116 r = sysconf(_SC_PAGESIZE);
117 assert(r > 0);
37f85e66 118
119 pgsz = (size_t) r;
37f85e66 120 return pgsz;
121}
122
c030a850 123int strcmp_ptr(const char *a, const char *b) {
e05797fb 124
c030a850 125 /* Like strcmp(), but tries to make sense of NULL pointers */
e05797fb 126 if (a && b)
c030a850
NK
127 return strcmp(a, b);
128
129 if (!a && b)
130 return -1;
e05797fb 131
c030a850
NK
132 if (a && !b)
133 return 1;
e05797fb 134
c030a850
NK
135 return 0;
136}
137
138bool streq_ptr(const char *a, const char *b) {
139 return strcmp_ptr(a, b) == 0;
e05797fb
LP
140}
141
8c7c140f 142char* endswith(const char *s, const char *postfix) {
60918275
LP
143 size_t sl, pl;
144
145 assert(s);
146 assert(postfix);
147
148 sl = strlen(s);
149 pl = strlen(postfix);
150
d4d0d4db 151 if (pl == 0)
8c7c140f 152 return (char*) s + sl;
d4d0d4db 153
60918275 154 if (sl < pl)
8c7c140f
LP
155 return NULL;
156
157 if (memcmp(s + sl - pl, postfix, pl) != 0)
158 return NULL;
60918275 159
8c7c140f 160 return (char*) s + sl - pl;
60918275
LP
161}
162
d3226d77
ZJS
163char* endswith_no_case(const char *s, const char *postfix) {
164 size_t sl, pl;
165
166 assert(s);
167 assert(postfix);
168
169 sl = strlen(s);
170 pl = strlen(postfix);
171
172 if (pl == 0)
173 return (char*) s + sl;
174
175 if (sl < pl)
176 return NULL;
177
178 if (strcasecmp(s + sl - pl, postfix) != 0)
179 return NULL;
180
181 return (char*) s + sl - pl;
182}
183
5cb36f41 184char* first_word(const char *s, const char *word) {
79d6d816 185 size_t sl, wl;
5cb36f41 186 const char *p;
79d6d816
LP
187
188 assert(s);
189 assert(word);
190
5cb36f41
LP
191 /* Checks if the string starts with the specified word, either
192 * followed by NUL or by whitespace. Returns a pointer to the
193 * NUL or the first character after the whitespace. */
194
79d6d816
LP
195 sl = strlen(s);
196 wl = strlen(word);
197
198 if (sl < wl)
5cb36f41 199 return NULL;
79d6d816 200
d4d0d4db 201 if (wl == 0)
5cb36f41 202 return (char*) s;
d4d0d4db 203
79d6d816 204 if (memcmp(s, word, wl) != 0)
5cb36f41
LP
205 return NULL;
206
207 p = s + wl;
208 if (*p == 0)
209 return (char*) p;
210
211 if (!strchr(WHITESPACE, *p))
212 return NULL;
79d6d816 213
5cb36f41
LP
214 p += strspn(p, WHITESPACE);
215 return (char*) p;
79d6d816
LP
216}
217
42f4e3c4 218int close_nointr(int fd) {
b0ee8068 219 assert(fd >= 0);
a9f85faf
LP
220
221 if (close(fd) >= 0)
222 return 0;
223
224 /*
225 * Just ignore EINTR; a retry loop is the wrong thing to do on
226 * Linux.
227 *
228 * http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
229 * https://bugzilla.gnome.org/show_bug.cgi?id=682819
230 * http://utcc.utoronto.ca/~cks/space/blog/unix/CloseEINTR
231 * https://sites.google.com/site/michaelsafyan/software-engineering/checkforeintrwheninvokingclosethinkagain
232 */
233 if (errno == EINTR)
d96ea504 234 return 0;
a9f85faf
LP
235
236 return -errno;
60918275 237}
85261803 238
03e334a1
LP
239int safe_close(int fd) {
240
241 /*
242 * Like close_nointr() but cannot fail. Guarantees errno is
243 * unchanged. Is a NOP with negative fds passed, and returns
244 * -1, so that it can be used in this syntax:
245 *
246 * fd = safe_close(fd);
247 */
85f136b5 248
03e334a1
LP
249 if (fd >= 0) {
250 PROTECT_ERRNO;
d96ea504
LP
251
252 /* The kernel might return pretty much any error code
253 * via close(), but the fd will be closed anyway. The
254 * only condition we want to check for here is whether
255 * the fd was invalid at all... */
256
257 assert_se(close_nointr(fd) != -EBADF);
03e334a1 258 }
85f136b5 259
03e334a1 260 return -1;
85f136b5
LP
261}
262
5b6319dc
LP
263void close_many(const int fds[], unsigned n_fd) {
264 unsigned i;
265
2c93b4ef
LP
266 assert(fds || n_fd <= 0);
267
5b6319dc 268 for (i = 0; i < n_fd; i++)
03e334a1 269 safe_close(fds[i]);
5b6319dc
LP
270}
271
74ca738f
LP
272int fclose_nointr(FILE *f) {
273 assert(f);
274
275 /* Same as close_nointr(), but for fclose() */
276
277 if (fclose(f) == 0)
278 return 0;
279
280 if (errno == EINTR)
281 return 0;
282
283 return -errno;
284}
285
286FILE* safe_fclose(FILE *f) {
287
288 /* Same as safe_close(), but for fclose() */
289
290 if (f) {
291 PROTECT_ERRNO;
292
293 assert_se(fclose_nointr(f) != EBADF);
294 }
295
296 return NULL;
297}
298
ed0d4022
LP
299DIR* safe_closedir(DIR *d) {
300
301 if (d) {
302 PROTECT_ERRNO;
303
304 assert_se(closedir(d) >= 0 || errno != EBADF);
305 }
306
307 return NULL;
308}
309
4b73a0c0
LP
310int unlink_noerrno(const char *path) {
311 PROTECT_ERRNO;
312 int r;
313
314 r = unlink(path);
315 if (r < 0)
316 return -errno;
317
318 return 0;
319}
320
85261803
LP
321int parse_boolean(const char *v) {
322 assert(v);
323
0f625d0b 324 if (streq(v, "1") || strcaseeq(v, "yes") || strcaseeq(v, "y") || strcaseeq(v, "true") || strcaseeq(v, "t") || strcaseeq(v, "on"))
85261803 325 return 1;
0f625d0b 326 else if (streq(v, "0") || strcaseeq(v, "no") || strcaseeq(v, "n") || strcaseeq(v, "false") || strcaseeq(v, "f") || strcaseeq(v, "off"))
85261803
LP
327 return 0;
328
329 return -EINVAL;
330}
331
3ba686c1 332int parse_pid(const char *s, pid_t* ret_pid) {
0b172489 333 unsigned long ul = 0;
3ba686c1
LP
334 pid_t pid;
335 int r;
336
337 assert(s);
338 assert(ret_pid);
339
e67f47e5
LP
340 r = safe_atolu(s, &ul);
341 if (r < 0)
3ba686c1
LP
342 return r;
343
344 pid = (pid_t) ul;
345
346 if ((unsigned long) pid != ul)
347 return -ERANGE;
348
349 if (pid <= 0)
350 return -ERANGE;
351
352 *ret_pid = pid;
353 return 0;
354}
355
a1f686da
LP
356bool uid_is_valid(uid_t uid) {
357
358 /* Some libc APIs use UID_INVALID as special placeholder */
359 if (uid == (uid_t) 0xFFFFFFFF)
360 return false;
361
362 /* A long time ago UIDs where 16bit, hence explicitly avoid the 16bit -1 too */
363 if (uid == (uid_t) 0xFFFF)
364 return false;
365
366 return true;
367}
368
034a2a52
LP
369int parse_uid(const char *s, uid_t* ret_uid) {
370 unsigned long ul = 0;
371 uid_t uid;
372 int r;
373
374 assert(s);
034a2a52 375
e67f47e5
LP
376 r = safe_atolu(s, &ul);
377 if (r < 0)
034a2a52
LP
378 return r;
379
380 uid = (uid_t) ul;
381
382 if ((unsigned long) uid != ul)
383 return -ERANGE;
384
a1f686da 385 if (!uid_is_valid(uid))
ef5c570e
LP
386 return -ENXIO; /* we return ENXIO instead of EINVAL
387 * here, to make it easy to distuingish
388 * invalid numeric uids invalid
389 * strings. */
306a55c8 390
8b0849e9
LP
391 if (ret_uid)
392 *ret_uid = uid;
393
034a2a52
LP
394 return 0;
395}
396
85261803
LP
397int safe_atou(const char *s, unsigned *ret_u) {
398 char *x = NULL;
034c6ed7 399 unsigned long l;
85261803
LP
400
401 assert(s);
402 assert(ret_u);
403
404 errno = 0;
405 l = strtoul(s, &x, 0);
406
f3910003 407 if (!x || x == s || *x || errno)
48deb058 408 return errno > 0 ? -errno : -EINVAL;
85261803 409
034c6ed7 410 if ((unsigned long) (unsigned) l != l)
85261803
LP
411 return -ERANGE;
412
413 *ret_u = (unsigned) l;
414 return 0;
415}
416
417int safe_atoi(const char *s, int *ret_i) {
418 char *x = NULL;
034c6ed7 419 long l;
85261803
LP
420
421 assert(s);
422 assert(ret_i);
423
424 errno = 0;
425 l = strtol(s, &x, 0);
426
f3910003 427 if (!x || x == s || *x || errno)
48deb058 428 return errno > 0 ? -errno : -EINVAL;
85261803 429
034c6ed7 430 if ((long) (int) l != l)
85261803
LP
431 return -ERANGE;
432
034c6ed7
LP
433 *ret_i = (int) l;
434 return 0;
435}
436
b914e211
LP
437int safe_atou8(const char *s, uint8_t *ret) {
438 char *x = NULL;
439 unsigned long l;
440
441 assert(s);
442 assert(ret);
443
444 errno = 0;
445 l = strtoul(s, &x, 0);
446
447 if (!x || x == s || *x || errno)
448 return errno > 0 ? -errno : -EINVAL;
449
450 if ((unsigned long) (uint8_t) l != l)
451 return -ERANGE;
452
453 *ret = (uint8_t) l;
454 return 0;
455}
456
781fa938
LP
457int safe_atou16(const char *s, uint16_t *ret) {
458 char *x = NULL;
459 unsigned long l;
460
461 assert(s);
462 assert(ret);
463
464 errno = 0;
465 l = strtoul(s, &x, 0);
466
467 if (!x || x == s || *x || errno)
468 return errno > 0 ? -errno : -EINVAL;
469
470 if ((unsigned long) (uint16_t) l != l)
471 return -ERANGE;
472
473 *ret = (uint16_t) l;
474 return 0;
475}
476
477int safe_atoi16(const char *s, int16_t *ret) {
478 char *x = NULL;
479 long l;
480
481 assert(s);
482 assert(ret);
483
484 errno = 0;
485 l = strtol(s, &x, 0);
486
487 if (!x || x == s || *x || errno)
488 return errno > 0 ? -errno : -EINVAL;
489
490 if ((long) (int16_t) l != l)
491 return -ERANGE;
492
493 *ret = (int16_t) l;
494 return 0;
495}
496
034c6ed7
LP
497int safe_atollu(const char *s, long long unsigned *ret_llu) {
498 char *x = NULL;
499 unsigned long long l;
500
501 assert(s);
502 assert(ret_llu);
503
504 errno = 0;
505 l = strtoull(s, &x, 0);
506
f3910003 507 if (!x || x == s || *x || errno)
034c6ed7
LP
508 return errno ? -errno : -EINVAL;
509
510 *ret_llu = l;
511 return 0;
512}
513
514int safe_atolli(const char *s, long long int *ret_lli) {
515 char *x = NULL;
516 long long l;
517
518 assert(s);
519 assert(ret_lli);
520
521 errno = 0;
522 l = strtoll(s, &x, 0);
523
f3910003 524 if (!x || x == s || *x || errno)
034c6ed7
LP
525 return errno ? -errno : -EINVAL;
526
527 *ret_lli = l;
85261803
LP
528 return 0;
529}
a41e8209 530
f7900e25
TA
531int safe_atod(const char *s, double *ret_d) {
532 char *x = NULL;
32b2634e 533 double d = 0;
0193ad26 534 locale_t loc;
f7900e25
TA
535
536 assert(s);
537 assert(ret_d);
538
0193ad26
CR
539 loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0);
540 if (loc == (locale_t) 0)
541 return -errno;
f7900e25 542
0193ad26
CR
543 errno = 0;
544 d = strtod_l(s, &x, loc);
545
546 if (!x || x == s || *x || errno) {
547 freelocale(loc);
f7900e25 548 return errno ? -errno : -EINVAL;
0193ad26 549 }
f7900e25 550
0193ad26 551 freelocale(loc);
f7900e25
TA
552 *ret_d = (double) d;
553 return 0;
554}
555
bf85c24d
SP
556static size_t strcspn_escaped(const char *s, const char *reject) {
557 bool escaped = false;
ba774317 558 int n;
bf85c24d
SP
559
560 for (n=0; s[n]; n++) {
561 if (escaped)
562 escaped = false;
563 else if (s[n] == '\\')
564 escaped = true;
565 else if (strchr(reject, s[n]))
a2a5291b 566 break;
bf85c24d 567 }
ba774317 568
a2a5291b
ZJS
569 /* if s ends in \, return index of previous char */
570 return n - escaped;
bf85c24d
SP
571}
572
a41e8209 573/* Split a string into words. */
a2a5291b
ZJS
574const char* split(const char **state, size_t *l, const char *separator, bool quoted) {
575 const char *current;
a41e8209 576
a2a5291b 577 current = *state;
a41e8209 578
a2a5291b
ZJS
579 if (!*current) {
580 assert(**state == '\0');
a41e8209 581 return NULL;
a2a5291b 582 }
a41e8209 583
65d2ebdc 584 current += strspn(current, separator);
a2a5291b
ZJS
585 if (!*current) {
586 *state = current;
70f75a52 587 return NULL;
a2a5291b 588 }
70f75a52 589
bf85c24d 590 if (quoted && strchr("\'\"", *current)) {
a2a5291b
ZJS
591 char quotechars[2] = {*current, '\0'};
592
593 *l = strcspn_escaped(current + 1, quotechars);
470dca63 594 if (current[*l + 1] == '\0' || current[*l + 1] != quotechars[0] ||
a2a5291b 595 (current[*l + 2] && !strchr(separator, current[*l + 2]))) {
cc13b327 596 /* right quote missing or garbage at the end */
a2a5291b
ZJS
597 *state = current;
598 return NULL;
599 }
a2a5291b 600 *state = current++ + *l + 2;
bf85c24d
SP
601 } else if (quoted) {
602 *l = strcspn_escaped(current, separator);
ba774317
ZJS
603 if (current[*l] && !strchr(separator, current[*l])) {
604 /* unfinished escape */
605 *state = current;
606 return NULL;
607 }
a2a5291b 608 *state = current + *l;
034c6ed7 609 } else {
bf85c24d 610 *l = strcspn(current, separator);
a2a5291b 611 *state = current + *l;
034c6ed7
LP
612 }
613
a2a5291b 614 return current;
034c6ed7
LP
615}
616
34ca941c
LP
617int fchmod_umask(int fd, mode_t m) {
618 mode_t u;
619 int r;
620
621 u = umask(0777);
622 r = fchmod(fd, m & (~u)) < 0 ? -errno : 0;
623 umask(u);
624
625 return r;
626}
627
7072ced8
LP
628char *truncate_nl(char *s) {
629 assert(s);
630
631 s[strcspn(s, NEWLINE)] = 0;
632 return s;
633}
634
fab56fc5
LP
635char *strnappend(const char *s, const char *suffix, size_t b) {
636 size_t a;
44d8db9e
LP
637 char *r;
638
fab56fc5
LP
639 if (!s && !suffix)
640 return strdup("");
641
642 if (!s)
643 return strndup(suffix, b);
644
645 if (!suffix)
646 return strdup(s);
647
44d8db9e
LP
648 assert(s);
649 assert(suffix);
650
651 a = strlen(s);
aa408e77 652 if (b > ((size_t) -1) - a)
040f18ea 653 return NULL;
44d8db9e 654
040f18ea
LP
655 r = new(char, a+b+1);
656 if (!r)
44d8db9e
LP
657 return NULL;
658
659 memcpy(r, s, a);
660 memcpy(r+a, suffix, b);
661 r[a+b] = 0;
662
663 return r;
664}
87f0e418 665
fab56fc5
LP
666char *strappend(const char *s, const char *suffix) {
667 return strnappend(s, suffix, suffix ? strlen(suffix) : 0);
668}
669
849958d1 670int readlinkat_malloc(int fd, const char *p, char **ret) {
87f0e418 671 size_t l = 100;
2d2ebd6b 672 int r;
87f0e418
LP
673
674 assert(p);
2d2ebd6b 675 assert(ret);
87f0e418
LP
676
677 for (;;) {
678 char *c;
679 ssize_t n;
680
2d2ebd6b
LP
681 c = new(char, l);
682 if (!c)
87f0e418
LP
683 return -ENOMEM;
684
849958d1 685 n = readlinkat(fd, p, c, l-1);
2d2ebd6b
LP
686 if (n < 0) {
687 r = -errno;
87f0e418 688 free(c);
2d2ebd6b 689 return r;
87f0e418
LP
690 }
691
692 if ((size_t) n < l-1) {
693 c[n] = 0;
2d2ebd6b 694 *ret = c;
87f0e418
LP
695 return 0;
696 }
697
698 free(c);
699 l *= 2;
700 }
701}
702
849958d1
LP
703int readlink_malloc(const char *p, char **ret) {
704 return readlinkat_malloc(AT_FDCWD, p, ret);
705}
706
9a67bcf2
TG
707int readlink_value(const char *p, char **ret) {
708 _cleanup_free_ char *link = NULL;
709 char *value;
710 int r;
711
712 r = readlink_malloc(p, &link);
713 if (r < 0)
714 return r;
715
716 value = basename(link);
717 if (!value)
718 return -ENOENT;
719
720 value = strdup(value);
721 if (!value)
722 return -ENOMEM;
723
724 *ret = value;
725
726 return 0;
727}
728
2c7108c4 729int readlink_and_make_absolute(const char *p, char **r) {
1058cbf2
ZJS
730 _cleanup_free_ char *target = NULL;
731 char *k;
2c7108c4
LP
732 int j;
733
734 assert(p);
735 assert(r);
736
1058cbf2
ZJS
737 j = readlink_malloc(p, &target);
738 if (j < 0)
2c7108c4
LP
739 return j;
740
741 k = file_in_same_dir(p, target);
2c7108c4
LP
742 if (!k)
743 return -ENOMEM;
744
745 *r = k;
746 return 0;
747}
748
83096483
LP
749int readlink_and_canonicalize(const char *p, char **r) {
750 char *t, *s;
751 int j;
752
753 assert(p);
754 assert(r);
755
756 j = readlink_and_make_absolute(p, &t);
757 if (j < 0)
758 return j;
759
760 s = canonicalize_file_name(t);
761 if (s) {
762 free(t);
763 *r = s;
764 } else
765 *r = t;
766
767 path_kill_slashes(*r);
768
769 return 0;
770}
771
4a72ff34 772char *strstrip(char *s) {
57a8eca8 773 char *e;
4a72ff34
LP
774
775 /* Drops trailing whitespace. Modifies the string in
776 * place. Returns pointer to first non-space character */
777
778 s += strspn(s, WHITESPACE);
779
57a8eca8
LP
780 for (e = strchr(s, 0); e > s; e --)
781 if (!strchr(WHITESPACE, e[-1]))
782 break;
4a72ff34 783
57a8eca8 784 *e = 0;
4a72ff34
LP
785
786 return s;
4a72ff34
LP
787}
788
ee9b5e01
LP
789char *delete_chars(char *s, const char *bad) {
790 char *f, *t;
791
792 /* Drops all whitespace, regardless where in the string */
793
794 for (f = s, t = s; *f; f++) {
795 if (strchr(bad, *f))
796 continue;
797
798 *(t++) = *f;
799 }
800
801 *t = 0;
802
803 return s;
804}
805
4a72ff34 806char *file_in_same_dir(const char *path, const char *filename) {
ebd93cb6 807 char *e, *ret;
4a72ff34
LP
808 size_t k;
809
810 assert(path);
811 assert(filename);
812
813 /* This removes the last component of path and appends
814 * filename, unless the latter is absolute anyway or the
815 * former isn't */
816
817 if (path_is_absolute(filename))
818 return strdup(filename);
819
ebd93cb6
LP
820 e = strrchr(path, '/');
821 if (!e)
4a72ff34
LP
822 return strdup(filename);
823
824 k = strlen(filename);
ebd93cb6
LP
825 ret = new(char, (e + 1 - path) + k + 1);
826 if (!ret)
4a72ff34
LP
827 return NULL;
828
ebd93cb6
LP
829 memcpy(mempcpy(ret, path, e + 1 - path), filename, k + 1);
830 return ret;
4a72ff34 831}
fb624d04 832
c32dd69b
LP
833int rmdir_parents(const char *path, const char *stop) {
834 size_t l;
835 int r = 0;
836
837 assert(path);
838 assert(stop);
839
840 l = strlen(path);
841
842 /* Skip trailing slashes */
843 while (l > 0 && path[l-1] == '/')
844 l--;
845
846 while (l > 0) {
847 char *t;
848
849 /* Skip last component */
850 while (l > 0 && path[l-1] != '/')
851 l--;
852
853 /* Skip trailing slashes */
854 while (l > 0 && path[l-1] == '/')
855 l--;
856
857 if (l <= 0)
858 break;
859
860 if (!(t = strndup(path, l)))
861 return -ENOMEM;
862
863 if (path_startswith(stop, t)) {
864 free(t);
865 return 0;
866 }
867
868 r = rmdir(t);
869 free(t);
870
871 if (r < 0)
872 if (errno != ENOENT)
873 return -errno;
874 }
875
876 return 0;
877}
878
fb624d04
LP
879char hexchar(int x) {
880 static const char table[16] = "0123456789abcdef";
881
882 return table[x & 15];
883}
4fe88d28
LP
884
885int unhexchar(char c) {
886
887 if (c >= '0' && c <= '9')
888 return c - '0';
889
890 if (c >= 'a' && c <= 'f')
ea430986 891 return c - 'a' + 10;
4fe88d28
LP
892
893 if (c >= 'A' && c <= 'F')
ea430986 894 return c - 'A' + 10;
4fe88d28 895
7e8185ef 896 return -EINVAL;
4fe88d28
LP
897}
898
66e35261
LP
899char *hexmem(const void *p, size_t l) {
900 char *r, *z;
901 const uint8_t *x;
902
903 z = r = malloc(l * 2 + 1);
904 if (!r)
905 return NULL;
906
907 for (x = p; x < (const uint8_t*) p + l; x++) {
908 *(z++) = hexchar(*x >> 4);
909 *(z++) = hexchar(*x & 15);
910 }
911
912 *z = 0;
913 return r;
914}
915
30494563
TG
916int unhexmem(const char *p, size_t l, void **mem, size_t *len) {
917 _cleanup_free_ uint8_t *r = NULL;
918 uint8_t *z;
2181a7f5
LP
919 const char *x;
920
30494563
TG
921 assert(mem);
922 assert(len);
2181a7f5
LP
923 assert(p);
924
925 z = r = malloc((l + 1) / 2 + 1);
926 if (!r)
30494563 927 return -ENOMEM;
2181a7f5
LP
928
929 for (x = p; x < p + l; x += 2) {
930 int a, b;
931
932 a = unhexchar(x[0]);
30494563
TG
933 if (a < 0)
934 return a;
935 else if (x+1 < p + l) {
2181a7f5 936 b = unhexchar(x[1]);
30494563
TG
937 if (b < 0)
938 return b;
939 } else
2181a7f5
LP
940 b = 0;
941
942 *(z++) = (uint8_t) a << 4 | (uint8_t) b;
943 }
944
945 *z = 0;
30494563
TG
946
947 *mem = r;
948 r = NULL;
949 *len = (l + 1) / 2;
950
951 return 0;
2181a7f5
LP
952}
953
75c0cab1
TG
954/* https://tools.ietf.org/html/rfc4648#section-6
955 * Notice that base32hex differs from base32 in the alphabet it uses.
956 * The distinction is that the base32hex representation preserves the
957 * order of the underlying data when compared as bytestrings, this is
958 * useful when representing NSEC3 hashes, as one can then verify the
959 * order of hashes directly from their representation. */
919a7f5f
TG
960char base32hexchar(int x) {
961 static const char table[32] = "0123456789"
962 "ABCDEFGHIJKLMNOPQRSTUV";
963
964 return table[x & 31];
965}
966
967int unbase32hexchar(char c) {
968 unsigned offset;
969
970 if (c >= '0' && c <= '9')
971 return c - '0';
972
973 offset = '9' - '0' + 1;
974
975 if (c >= 'A' && c <= 'V')
976 return c - 'A' + offset;
977
978 return -EINVAL;
979}
980
981char *base32hexmem(const void *p, size_t l, bool padding) {
982 char *r, *z;
983 const uint8_t *x;
984 size_t len;
985
986 if (padding)
987 /* five input bytes makes eight output bytes, padding is added so we must round up */
988 len = 8 * (l + 4) / 5;
989 else {
990 /* same, but round down as there is no padding */
991 len = 8 * l / 5;
992
993 switch (l % 5) {
994 case 4:
995 len += 7;
996 break;
997 case 3:
998 len += 5;
999 break;
1000 case 2:
1001 len += 4;
1002 break;
1003 case 1:
1004 len += 2;
1005 break;
1006 }
1007 }
1008
1009 z = r = malloc(len + 1);
1010 if (!r)
1011 return NULL;
1012
1013 for (x = p; x < (const uint8_t*) p + (l / 5) * 5; x += 5) {
1014 /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ
1015 x[3] == QQQQQQQQ; x[4] == WWWWWWWW */
1016 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
1017 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
1018 *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
1019 *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
1020 *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */
1021 *(z++) = base32hexchar((x[3] & 127) >> 2); /* 000QQQQQ */
1022 *(z++) = base32hexchar((x[3] & 3) << 3 | x[4] >> 5); /* 000QQWWW */
1023 *(z++) = base32hexchar((x[4] & 31)); /* 000WWWWW */
1024 }
1025
1026 switch (l % 5) {
1027 case 4:
1028 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
1029 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
1030 *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
1031 *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
1032 *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */
1033 *(z++) = base32hexchar((x[3] & 127) >> 2); /* 000QQQQQ */
1034 *(z++) = base32hexchar((x[3] & 3) << 3); /* 000QQ000 */
1035 if (padding)
1036 *(z++) = '=';
1037
1038 break;
1039
1040 case 3:
1041 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
1042 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
1043 *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
1044 *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
1045 *(z++) = base32hexchar((x[2] & 15) << 1); /* 000ZZZZ0 */
1046 if (padding) {
1047 *(z++) = '=';
1048 *(z++) = '=';
1049 *(z++) = '=';
1050 }
1051
1052 break;
1053
1054 case 2:
1055 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
1056 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
1057 *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
1058 *(z++) = base32hexchar((x[1] & 1) << 4); /* 000Y0000 */
1059 if (padding) {
1060 *(z++) = '=';
1061 *(z++) = '=';
1062 *(z++) = '=';
1063 *(z++) = '=';
1064 }
1065
1066 break;
1067
1068 case 1:
1069 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
1070 *(z++) = base32hexchar((x[0] & 7) << 2); /* 000XXX00 */
1071 if (padding) {
1072 *(z++) = '=';
1073 *(z++) = '=';
1074 *(z++) = '=';
1075 *(z++) = '=';
1076 *(z++) = '=';
1077 *(z++) = '=';
1078 }
1079
1080 break;
1081 }
1082
1083 *z = 0;
1084 return r;
1085}
1086
1087int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_len) {
1088 _cleanup_free_ uint8_t *r = NULL;
1089 int a, b, c, d, e, f, g, h;
1090 uint8_t *z;
1091 const char *x;
1092 size_t len;
1093 unsigned pad = 0;
1094
1095 assert(p);
1096
1097 /* padding ensures any base32hex input has input divisible by 8 */
1098 if (padding && l % 8 != 0)
1099 return -EINVAL;
1100
1101 if (padding) {
1102 /* strip the padding */
1103 while (l > 0 && p[l - 1] == '=' && pad < 7) {
1104 pad ++;
1105 l --;
1106 }
1107 }
1108
1109 /* a group of eight input bytes needs five output bytes, in case of
1110 padding we need to add some extra bytes */
1111 len = (l / 8) * 5;
1112
1113 switch (l % 8) {
1114 case 7:
1115 len += 4;
1116 break;
1117 case 5:
1118 len += 3;
1119 break;
1120 case 4:
1121 len += 2;
1122 break;
1123 case 2:
1124 len += 1;
1125 break;
1126 case 0:
1127 break;
1128 default:
1129 return -EINVAL;
1130 }
1131
1132 z = r = malloc(len + 1);
1133 if (!r)
1134 return -ENOMEM;
1135
1136 for (x = p; x < p + (l / 8) * 8; x += 8) {
1137 /* a == 000XXXXX; b == 000YYYYY; c == 000ZZZZZ; d == 000WWWWW
1138 e == 000SSSSS; f == 000QQQQQ; g == 000VVVVV; h == 000RRRRR */
1139 a = unbase32hexchar(x[0]);
1140 if (a < 0)
1141 return -EINVAL;
1142
1143 b = unbase32hexchar(x[1]);
1144 if (b < 0)
1145 return -EINVAL;
1146
1147 c = unbase32hexchar(x[2]);
1148 if (c < 0)
1149 return -EINVAL;
1150
1151 d = unbase32hexchar(x[3]);
1152 if (d < 0)
1153 return -EINVAL;
1154
1155 e = unbase32hexchar(x[4]);
1156 if (e < 0)
1157 return -EINVAL;
1158
1159 f = unbase32hexchar(x[5]);
1160 if (f < 0)
1161 return -EINVAL;
1162
1163 g = unbase32hexchar(x[6]);
1164 if (g < 0)
1165 return -EINVAL;
1166
1167 h = unbase32hexchar(x[7]);
1168 if (h < 0)
1169 return -EINVAL;
1170
1171 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
1172 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
1173 *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */
1174 *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */
1175 *(z++) = (uint8_t) g << 5 | (uint8_t) h; /* VVVRRRRR */
1176 }
1177
1178 switch (l % 8) {
1179 case 7:
1180 a = unbase32hexchar(x[0]);
1181 if (a < 0)
1182 return -EINVAL;
1183
1184 b = unbase32hexchar(x[1]);
1185 if (b < 0)
1186 return -EINVAL;
1187
1188 c = unbase32hexchar(x[2]);
1189 if (c < 0)
1190 return -EINVAL;
1191
1192 d = unbase32hexchar(x[3]);
1193 if (d < 0)
1194 return -EINVAL;
1195
1196 e = unbase32hexchar(x[4]);
1197 if (e < 0)
1198 return -EINVAL;
1199
1200 f = unbase32hexchar(x[5]);
1201 if (f < 0)
1202 return -EINVAL;
1203
1204 g = unbase32hexchar(x[6]);
1205 if (g < 0)
1206 return -EINVAL;
1207
1208 /* g == 000VV000 */
1209 if (g & 7)
1210 return -EINVAL;
1211
1212 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
1213 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
1214 *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */
1215 *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */
1216
1217 break;
1218 case 5:
1219 a = unbase32hexchar(x[0]);
1220 if (a < 0)
1221 return -EINVAL;
1222
1223 b = unbase32hexchar(x[1]);
1224 if (b < 0)
1225 return -EINVAL;
1226
1227 c = unbase32hexchar(x[2]);
1228 if (c < 0)
1229 return -EINVAL;
1230
1231 d = unbase32hexchar(x[3]);
1232 if (d < 0)
1233 return -EINVAL;
1234
1235 e = unbase32hexchar(x[4]);
1236 if (e < 0)
1237 return -EINVAL;
1238
1239 /* e == 000SSSS0 */
1240 if (e & 1)
1241 return -EINVAL;
1242
1243 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
1244 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
1245 *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */
1246
1247 break;
1248 case 4:
1249 a = unbase32hexchar(x[0]);
1250 if (a < 0)
1251 return -EINVAL;
1252
1253 b = unbase32hexchar(x[1]);
1254 if (b < 0)
1255 return -EINVAL;
1256
1257 c = unbase32hexchar(x[2]);
1258 if (c < 0)
1259 return -EINVAL;
1260
1261 d = unbase32hexchar(x[3]);
1262 if (d < 0)
1263 return -EINVAL;
1264
1265 /* d == 000W0000 */
1266 if (d & 15)
1267 return -EINVAL;
1268
1269 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
1270 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
1271
1272 break;
1273 case 2:
1274 a = unbase32hexchar(x[0]);
1275 if (a < 0)
1276 return -EINVAL;
1277
1278 b = unbase32hexchar(x[1]);
1279 if (b < 0)
1280 return -EINVAL;
1281
1282 /* b == 000YYY00 */
1283 if (b & 3)
1284 return -EINVAL;
1285
1286 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
1287
1288 break;
1289 case 0:
1290 break;
1291 default:
1292 return -EINVAL;
1293 }
1294
1295 *z = 0;
1296
1297 *mem = r;
1298 r = NULL;
1299 *_len = len;
1300
1301 return 0;
1302}
1303
13a5d76b
TG
1304/* https://tools.ietf.org/html/rfc4648#section-4 */
1305char base64char(int x) {
1306 static const char table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1307 "abcdefghijklmnopqrstuvwxyz"
1308 "0123456789+/";
1309 return table[x & 63];
1310}
1311
1312int unbase64char(char c) {
1313 unsigned offset;
1314
1315 if (c >= 'A' && c <= 'Z')
1316 return c - 'A';
1317
1318 offset = 'Z' - 'A' + 1;
1319
1320 if (c >= 'a' && c <= 'z')
1321 return c - 'a' + offset;
1322
1323 offset += 'z' - 'a' + 1;
1324
1325 if (c >= '0' && c <= '9')
1326 return c - '0' + offset;
1327
1328 offset += '9' - '0' + 1;
1329
1330 if (c == '+')
1331 return offset;
1332
1333 offset ++;
1334
1335 if (c == '/')
1336 return offset;
1337
1338 return -EINVAL;
1339}
1340
1341char *base64mem(const void *p, size_t l) {
1342 char *r, *z;
1343 const uint8_t *x;
1344
1345 /* three input bytes makes four output bytes, padding is added so we must round up */
1346 z = r = malloc(4 * (l + 2) / 3 + 1);
1347 if (!r)
1348 return NULL;
1349
1350 for (x = p; x < (const uint8_t*) p + (l / 3) * 3; x += 3) {
1351 /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ */
1352 *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
1353 *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */
1354 *(z++) = base64char((x[1] & 15) << 2 | x[2] >> 6); /* 00YYYYZZ */
1355 *(z++) = base64char(x[2] & 63); /* 00ZZZZZZ */
1356 }
1357
1358 switch (l % 3) {
1359 case 2:
1360 *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
1361 *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */
1362 *(z++) = base64char((x[1] & 15) << 2); /* 00YYYY00 */
1363 *(z++) = '=';
1364
1365 break;
1366 case 1:
1367 *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
1368 *(z++) = base64char((x[0] & 3) << 4); /* 00XX0000 */
1369 *(z++) = '=';
1370 *(z++) = '=';
1371
1372 break;
1373 }
1374
1375 *z = 0;
1376 return r;
1377}
1378
1379int unbase64mem(const char *p, size_t l, void **mem, size_t *_len) {
2a2953b3 1380 _cleanup_free_ uint8_t *r = NULL;
13a5d76b 1381 int a, b, c, d;
2a2953b3 1382 uint8_t *z;
13a5d76b
TG
1383 const char *x;
1384 size_t len;
1385
1386 assert(p);
1387
1388 /* padding ensures any base63 input has input divisible by 4 */
1389 if (l % 4 != 0)
1390 return -EINVAL;
1391
1392 /* strip the padding */
1393 if (l > 0 && p[l - 1] == '=')
1394 l --;
1395 if (l > 0 && p[l - 1] == '=')
1396 l --;
1397
1398 /* a group of four input bytes needs three output bytes, in case of
1399 padding we need to add two or three extra bytes */
1400 len = (l / 4) * 3 + (l % 4 ? (l % 4) - 1 : 0);
1401
1402 z = r = malloc(len + 1);
1403 if (!r)
1404 return -ENOMEM;
1405
1406 for (x = p; x < p + (l / 4) * 4; x += 4) {
1407 /* a == 00XXXXXX; b == 00YYYYYY; c == 00ZZZZZZ; d == 00WWWWWW */
1408 a = unbase64char(x[0]);
1409 if (a < 0)
1410 return -EINVAL;
1411
1412 b = unbase64char(x[1]);
1413 if (b < 0)
1414 return -EINVAL;
1415
1416 c = unbase64char(x[2]);
1417 if (c < 0)
1418 return -EINVAL;
1419
1420 d = unbase64char(x[3]);
1421 if (d < 0)
1422 return -EINVAL;
1423
1424 *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
1425 *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
1426 *(z++) = (uint8_t) c << 6 | (uint8_t) d; /* ZZWWWWWW */
1427 }
1428
1429 switch (l % 4) {
1430 case 3:
1431 a = unbase64char(x[0]);
1432 if (a < 0)
1433 return -EINVAL;
1434
1435 b = unbase64char(x[1]);
1436 if (b < 0)
1437 return -EINVAL;
1438
1439 c = unbase64char(x[2]);
1440 if (c < 0)
1441 return -EINVAL;
1442
1443 /* c == 00ZZZZ00 */
1444 if (c & 3)
1445 return -EINVAL;
1446
1447 *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
1448 *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
1449
1450 break;
1451 case 2:
1452 a = unbase64char(x[0]);
1453 if (a < 0)
1454 return -EINVAL;
1455
1456 b = unbase64char(x[1]);
1457 if (b < 0)
1458 return -EINVAL;
1459
1460 /* b == 00YY0000 */
1461 if (b & 15)
1462 return -EINVAL;
1463
1464 *(z++) = (uint8_t) a << 2 | (uint8_t) (b >> 4); /* XXXXXXYY */
1465
1466 break;
919a7f5f
TG
1467 case 0:
1468
1469 break;
1470 default:
1471 return -EINVAL;
13a5d76b
TG
1472 }
1473
1474 *z = 0;
1475
1476 *mem = r;
1477 r = NULL;
1478 *_len = len;
1479
1480 return 0;
1481}
1482
4fe88d28
LP
1483char octchar(int x) {
1484 return '0' + (x & 7);
1485}
1486
1487int unoctchar(char c) {
1488
1489 if (c >= '0' && c <= '7')
1490 return c - '0';
1491
7e8185ef 1492 return -EINVAL;
4fe88d28
LP
1493}
1494
5af98f82
LP
1495char decchar(int x) {
1496 return '0' + (x % 10);
1497}
1498
1499int undecchar(char c) {
1500
1501 if (c >= '0' && c <= '9')
1502 return c - '0';
1503
7e8185ef 1504 return -EINVAL;
5af98f82
LP
1505}
1506
67d51650 1507char *ascii_strlower(char *t) {
4fe88d28
LP
1508 char *p;
1509
67d51650 1510 assert(t);
4fe88d28 1511
67d51650 1512 for (p = t; *p; p++)
4fe88d28
LP
1513 if (*p >= 'A' && *p <= 'Z')
1514 *p = *p - 'A' + 'a';
1515
67d51650 1516 return t;
4fe88d28 1517}
1dccbe19 1518
a34bf9db 1519_pure_ static bool hidden_file_allow_backup(const char *filename) {
c85dc17b
LP
1520 assert(filename);
1521
1522 return
1523 filename[0] == '.' ||
6c78be3c 1524 streq(filename, "lost+found") ||
e472d476
LP
1525 streq(filename, "aquota.user") ||
1526 streq(filename, "aquota.group") ||
c85dc17b
LP
1527 endswith(filename, ".rpmnew") ||
1528 endswith(filename, ".rpmsave") ||
1529 endswith(filename, ".rpmorig") ||
1530 endswith(filename, ".dpkg-old") ||
1531 endswith(filename, ".dpkg-new") ||
0cdfd26e 1532 endswith(filename, ".dpkg-tmp") ||
c7088e49
MP
1533 endswith(filename, ".dpkg-dist") ||
1534 endswith(filename, ".dpkg-bak") ||
1535 endswith(filename, ".dpkg-backup") ||
1536 endswith(filename, ".dpkg-remove") ||
c85dc17b
LP
1537 endswith(filename, ".swp");
1538}
1539
a34bf9db 1540bool hidden_file(const char *filename) {
a228a22f
LP
1541 assert(filename);
1542
1543 if (endswith(filename, "~"))
93f1a063 1544 return true;
a228a22f 1545
a34bf9db 1546 return hidden_file_allow_backup(filename);
a228a22f
LP
1547}
1548
3a0ecb08 1549int fd_nonblock(int fd, bool nonblock) {
be8f4e9e 1550 int flags, nflags;
3a0ecb08
LP
1551
1552 assert(fd >= 0);
1553
be8f4e9e
LP
1554 flags = fcntl(fd, F_GETFL, 0);
1555 if (flags < 0)
3a0ecb08
LP
1556 return -errno;
1557
1558 if (nonblock)
be8f4e9e 1559 nflags = flags | O_NONBLOCK;
3a0ecb08 1560 else
be8f4e9e
LP
1561 nflags = flags & ~O_NONBLOCK;
1562
1563 if (nflags == flags)
1564 return 0;
3a0ecb08 1565
34b42c96 1566 if (fcntl(fd, F_SETFL, nflags) < 0)
3a0ecb08
LP
1567 return -errno;
1568
1569 return 0;
1570}
1571
1572int fd_cloexec(int fd, bool cloexec) {
be8f4e9e 1573 int flags, nflags;
3a0ecb08
LP
1574
1575 assert(fd >= 0);
1576
be8f4e9e
LP
1577 flags = fcntl(fd, F_GETFD, 0);
1578 if (flags < 0)
3a0ecb08
LP
1579 return -errno;
1580
1581 if (cloexec)
be8f4e9e 1582 nflags = flags | FD_CLOEXEC;
3a0ecb08 1583 else
be8f4e9e
LP
1584 nflags = flags & ~FD_CLOEXEC;
1585
1586 if (nflags == flags)
1587 return 0;
3a0ecb08 1588
34b42c96 1589 if (fcntl(fd, F_SETFD, nflags) < 0)
3a0ecb08
LP
1590 return -errno;
1591
1592 return 0;
1593}
1594
44a6b1b6 1595_pure_ static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
b19be9eb
LP
1596 unsigned i;
1597
1598 assert(n_fdset == 0 || fdset);
1599
1600 for (i = 0; i < n_fdset; i++)
1601 if (fdset[i] == fd)
1602 return true;
1603
1604 return false;
1605}
1606
a0d40ac5 1607int close_all_fds(const int except[], unsigned n_except) {
e1d75803 1608 _cleanup_closedir_ DIR *d = NULL;
a0d40ac5
LP
1609 struct dirent *de;
1610 int r = 0;
1611
b19be9eb
LP
1612 assert(n_except == 0 || except);
1613
1614 d = opendir("/proc/self/fd");
1615 if (!d) {
1616 int fd;
1617 struct rlimit rl;
1618
1619 /* When /proc isn't available (for example in chroots)
1620 * the fallback is brute forcing through the fd
1621 * table */
1622
1623 assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0);
1624 for (fd = 3; fd < (int) rl.rlim_max; fd ++) {
1625
1626 if (fd_in_set(fd, except, n_except))
1627 continue;
1628
1629 if (close_nointr(fd) < 0)
1630 if (errno != EBADF && r == 0)
1631 r = -errno;
1632 }
1633
1634 return r;
1635 }
a0d40ac5
LP
1636
1637 while ((de = readdir(d))) {
a7610064 1638 int fd = -1;
a0d40ac5 1639
a34bf9db 1640 if (hidden_file(de->d_name))
a0d40ac5
LP
1641 continue;
1642
720ce21d
LP
1643 if (safe_atoi(de->d_name, &fd) < 0)
1644 /* Let's better ignore this, just in case */
1645 continue;
a0d40ac5
LP
1646
1647 if (fd < 3)
1648 continue;
1649
1650 if (fd == dirfd(d))
1651 continue;
1652
b19be9eb
LP
1653 if (fd_in_set(fd, except, n_except))
1654 continue;
a0d40ac5 1655
720ce21d 1656 if (close_nointr(fd) < 0) {
2f357920 1657 /* Valgrind has its own FD and doesn't want to have it closed */
720ce21d
LP
1658 if (errno != EBADF && r == 0)
1659 r = -errno;
2f357920 1660 }
a0d40ac5
LP
1661 }
1662
a0d40ac5
LP
1663 return r;
1664}
1665
db12775d
LP
1666bool chars_intersect(const char *a, const char *b) {
1667 const char *p;
1668
1669 /* Returns true if any of the chars in a are in b. */
1670 for (p = a; *p; p++)
1671 if (strchr(b, *p))
1672 return true;
1673
1674 return false;
1675}
1676
42856c10 1677bool fstype_is_network(const char *fstype) {
a05f97b3 1678 static const char table[] =
ba89821c 1679 "afs\0"
a05f97b3
LP
1680 "cifs\0"
1681 "smbfs\0"
da92ca5e 1682 "sshfs\0"
a05f97b3 1683 "ncpfs\0"
dac70dc7 1684 "ncp\0"
a05f97b3
LP
1685 "nfs\0"
1686 "nfs4\0"
1687 "gfs\0"
67608cad
LP
1688 "gfs2\0"
1689 "glusterfs\0";
1690
1691 const char *x;
1692
1693 x = startswith(fstype, "fuse.");
1694 if (x)
1695 fstype = x;
42856c10 1696
a05f97b3 1697 return nulstr_contains(table, fstype);
42856c10
LP
1698}
1699
80876c20 1700int flush_fd(int fd) {
b92bea5d
ZJS
1701 struct pollfd pollfd = {
1702 .fd = fd,
1703 .events = POLLIN,
1704 };
80876c20
LP
1705
1706 for (;;) {
20c03b7b 1707 char buf[LINE_MAX];
80876c20
LP
1708 ssize_t l;
1709 int r;
1710
e62d8c39
ZJS
1711 r = poll(&pollfd, 1, 0);
1712 if (r < 0) {
80876c20
LP
1713 if (errno == EINTR)
1714 continue;
1715
1716 return -errno;
80876c20 1717
e62d8c39 1718 } else if (r == 0)
80876c20
LP
1719 return 0;
1720
e62d8c39
ZJS
1721 l = read(fd, buf, sizeof(buf));
1722 if (l < 0) {
80876c20
LP
1723
1724 if (errno == EINTR)
1725 continue;
1726
1727 if (errno == EAGAIN)
1728 return 0;
1729
1730 return -errno;
e62d8c39 1731 } else if (l == 0)
80876c20
LP
1732 return 0;
1733 }
1734}
1735
3d94f76c 1736void safe_close_pair(int p[]) {
8d567588
LP
1737 assert(p);
1738
3d94f76c
LP
1739 if (p[0] == p[1]) {
1740 /* Special case pairs which use the same fd in both
1741 * directions... */
1742 p[0] = p[1] = safe_close(p[0]);
1743 return;
8d567588
LP
1744 }
1745
3d94f76c
LP
1746 p[0] = safe_close(p[0]);
1747 p[1] = safe_close(p[1]);
8d567588
LP
1748}
1749
eb22ac37 1750ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) {
7d5dd5e0 1751 uint8_t *p = buf;
8d567588
LP
1752 ssize_t n = 0;
1753
1754 assert(fd >= 0);
1755 assert(buf);
1756
4fdae6c8
LP
1757 /* If called with nbytes == 0, let's call read() at least
1758 * once, to validate the operation */
1759
1760 if (nbytes > (size_t) SSIZE_MAX)
1761 return -EINVAL;
1762
1763 do {
8d567588
LP
1764 ssize_t k;
1765
7d5dd5e0 1766 k = read(fd, p, nbytes);
6ce830fa
LP
1767 if (k < 0) {
1768 if (errno == EINTR)
1769 continue;
8d567588 1770
6ce830fa 1771 if (errno == EAGAIN && do_poll) {
8d567588 1772
6ce830fa
LP
1773 /* We knowingly ignore any return value here,
1774 * and expect that any error/EOF is reported
1775 * via read() */
8d567588 1776
4fdae6c8 1777 (void) fd_wait_for_event(fd, POLLIN, USEC_INFINITY);
6ce830fa
LP
1778 continue;
1779 }
1780
1781 return n > 0 ? n : -errno;
7d5dd5e0 1782 }
8d567588 1783
6ce830fa
LP
1784 if (k == 0)
1785 return n;
8d567588 1786
4fdae6c8
LP
1787 assert((size_t) k <= nbytes);
1788
8d567588
LP
1789 p += k;
1790 nbytes -= k;
1791 n += k;
4fdae6c8 1792 } while (nbytes > 0);
8d567588
LP
1793
1794 return n;
1795}
1796
a6dcc7e5
ZJS
1797int loop_read_exact(int fd, void *buf, size_t nbytes, bool do_poll) {
1798 ssize_t n;
1799
1800 n = loop_read(fd, buf, nbytes, do_poll);
1801 if (n < 0)
4fdae6c8 1802 return (int) n;
a6dcc7e5
ZJS
1803 if ((size_t) n != nbytes)
1804 return -EIO;
4fdae6c8 1805
a6dcc7e5
ZJS
1806 return 0;
1807}
1808
553acb7b 1809int loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
7d5dd5e0 1810 const uint8_t *p = buf;
eb22ac37
LP
1811
1812 assert(fd >= 0);
1813 assert(buf);
1814
4fdae6c8
LP
1815 if (nbytes > (size_t) SSIZE_MAX)
1816 return -EINVAL;
553acb7b 1817
8c7e28a1 1818 do {
eb22ac37
LP
1819 ssize_t k;
1820
fe652127 1821 k = write(fd, p, nbytes);
6ce830fa
LP
1822 if (k < 0) {
1823 if (errno == EINTR)
1824 continue;
eb22ac37 1825
6ce830fa
LP
1826 if (errno == EAGAIN && do_poll) {
1827 /* We knowingly ignore any return value here,
1828 * and expect that any error/EOF is reported
1829 * via write() */
eb22ac37 1830
4fdae6c8 1831 (void) fd_wait_for_event(fd, POLLOUT, USEC_INFINITY);
6ce830fa
LP
1832 continue;
1833 }
eb22ac37 1834
6ce830fa 1835 return -errno;
7d5dd5e0 1836 }
eb22ac37 1837
4fdae6c8 1838 if (_unlikely_(nbytes > 0 && k == 0)) /* Can't really happen */
6ce830fa 1839 return -EIO;
eb22ac37 1840
4fdae6c8
LP
1841 assert((size_t) k <= nbytes);
1842
eb22ac37
LP
1843 p += k;
1844 nbytes -= k;
8c7e28a1 1845 } while (nbytes > 0);
eb22ac37 1846
553acb7b 1847 return 0;
eb22ac37
LP
1848}
1849
59f448cf 1850int parse_size(const char *t, uint64_t base, uint64_t *size) {
5556b5fe 1851
55ede093 1852 /* Soo, sometimes we want to parse IEC binary suffixes, and
5556b5fe
LP
1853 * sometimes SI decimal suffixes. This function can parse
1854 * both. Which one is the right way depends on the
1855 * context. Wikipedia suggests that SI is customary for
30a5b782 1856 * hardware metrics and network speeds, while IEC is
5556b5fe
LP
1857 * customary for most data sizes used by software and volatile
1858 * (RAM) memory. Hence be careful which one you pick!
1859 *
1860 * In either case we use just K, M, G as suffix, and not Ki,
1861 * Mi, Gi or so (as IEC would suggest). That's because that's
1862 * frickin' ugly. But this means you really need to make sure
1863 * to document which base you are parsing when you use this
1864 * call. */
1865
1866 struct table {
ab1f0633 1867 const char *suffix;
b32ff512 1868 unsigned long long factor;
5556b5fe
LP
1869 };
1870
1871 static const struct table iec[] = {
32895bb3 1872 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
840292be
ZJS
1873 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
1874 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
1875 { "G", 1024ULL*1024ULL*1024ULL },
1876 { "M", 1024ULL*1024ULL },
1877 { "K", 1024ULL },
59f448cf
LP
1878 { "B", 1ULL },
1879 { "", 1ULL },
ab1f0633
LP
1880 };
1881
5556b5fe 1882 static const struct table si[] = {
5556b5fe 1883 { "E", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
840292be
ZJS
1884 { "P", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
1885 { "T", 1000ULL*1000ULL*1000ULL*1000ULL },
1886 { "G", 1000ULL*1000ULL*1000ULL },
1887 { "M", 1000ULL*1000ULL },
1888 { "K", 1000ULL },
59f448cf
LP
1889 { "B", 1ULL },
1890 { "", 1ULL },
5556b5fe
LP
1891 };
1892
1893 const struct table *table;
ab1f0633 1894 const char *p;
b32ff512 1895 unsigned long long r = 0;
840292be 1896 unsigned n_entries, start_pos = 0;
ab1f0633
LP
1897
1898 assert(t);
5556b5fe
LP
1899 assert(base == 1000 || base == 1024);
1900 assert(size);
1901
1902 if (base == 1000) {
1903 table = si;
1904 n_entries = ELEMENTSOF(si);
1905 } else {
1906 table = iec;
1907 n_entries = ELEMENTSOF(iec);
1908 }
ab1f0633
LP
1909
1910 p = t;
1911 do {
59f448cf 1912 unsigned long long l, tmp;
9480794b 1913 double frac = 0;
ab1f0633
LP
1914 char *e;
1915 unsigned i;
1916
59f448cf
LP
1917 p += strspn(p, WHITESPACE);
1918 if (*p == '-')
1919 return -ERANGE;
ab1f0633 1920
59f448cf
LP
1921 errno = 0;
1922 l = strtoull(p, &e, 10);
8333c77e 1923 if (errno > 0)
ab1f0633 1924 return -errno;
ab1f0633
LP
1925 if (e == p)
1926 return -EINVAL;
1927
9480794b
ZJS
1928 if (*e == '.') {
1929 e++;
59f448cf
LP
1930
1931 /* strtoull() itself would accept space/+/- */
9480794b 1932 if (*e >= '0' && *e <= '9') {
59f448cf 1933 unsigned long long l2;
9480794b
ZJS
1934 char *e2;
1935
9480794b 1936 l2 = strtoull(e, &e2, 10);
59f448cf 1937 if (errno > 0)
9480794b
ZJS
1938 return -errno;
1939
1940 /* Ignore failure. E.g. 10.M is valid */
1941 frac = l2;
1942 for (; e < e2; e++)
1943 frac /= 10;
1944 }
1945 }
1946
ab1f0633
LP
1947 e += strspn(e, WHITESPACE);
1948
840292be 1949 for (i = start_pos; i < n_entries; i++)
59f448cf 1950 if (startswith(e, table[i].suffix))
ab1f0633 1951 break;
ab1f0633 1952
5556b5fe 1953 if (i >= n_entries)
ab1f0633
LP
1954 return -EINVAL;
1955
59f448cf
LP
1956 if (l + (frac > 0) > ULLONG_MAX / table[i].factor)
1957 return -ERANGE;
1958
1959 tmp = l * table[i].factor + (unsigned long long) (frac * table[i].factor);
1960 if (tmp > ULLONG_MAX - r)
1961 return -ERANGE;
1962
1963 r += tmp;
1964 if ((unsigned long long) (uint64_t) r != r)
1965 return -ERANGE;
1966
1967 p = e + strlen(table[i].suffix);
1968
1969 start_pos = i + 1;
1970
b32ff512 1971 } while (*p);
ab1f0633 1972
5556b5fe 1973 *size = r;
ab1f0633
LP
1974
1975 return 0;
1976}
1977
8407a5d0
LP
1978bool is_device_path(const char *path) {
1979
1980 /* Returns true on paths that refer to a device, either in
1981 * sysfs or in /dev */
1982
1983 return
1984 path_startswith(path, "/dev/") ||
1985 path_startswith(path, "/sys/");
1986}
1987
01f78473 1988int dir_is_empty(const char *path) {
a05f97b3 1989 _cleanup_closedir_ DIR *d;
ac7edd91 1990 struct dirent *de;
01f78473 1991
a05f97b3
LP
1992 d = opendir(path);
1993 if (!d)
01f78473
LP
1994 return -errno;
1995
ac7edd91
LP
1996 FOREACH_DIRENT(de, d, return -errno)
1997 return 0;
01f78473 1998
ac7edd91 1999 return 1;
01f78473
LP
2000}
2001
844ec79b
ZJS
2002char* dirname_malloc(const char *path) {
2003 char *d, *dir, *dir2;
2004
2005 d = strdup(path);
2006 if (!d)
2007 return NULL;
2008 dir = dirname(d);
2009 assert(dir);
2010
2011 if (dir != d) {
2012 dir2 = strdup(dir);
2013 free(d);
2014 return dir2;
2015 }
2016
2017 return dir;
2018}
2019
5b6319dc
LP
2020void rename_process(const char name[8]) {
2021 assert(name);
2022
5d6b1584
LP
2023 /* This is a like a poor man's setproctitle(). It changes the
2024 * comm field, argv[0], and also the glibc's internally used
2025 * name of the process. For the first one a limit of 16 chars
2026 * applies, to the second one usually one of 10 (i.e. length
2027 * of "/sbin/init"), to the third one one of 7 (i.e. length of
2028 * "systemd"). If you pass a longer string it will be
2029 * truncated */
5b6319dc 2030
5d6b1584 2031 prctl(PR_SET_NAME, name);
5b6319dc
LP
2032
2033 if (program_invocation_name)
2034 strncpy(program_invocation_name, name, strlen(program_invocation_name));
9a0e6896
LP
2035
2036 if (saved_argc > 0) {
2037 int i;
2038
2039 if (saved_argv[0])
2040 strncpy(saved_argv[0], name, strlen(saved_argv[0]));
2041
2042 for (i = 1; i < saved_argc; i++) {
2043 if (!saved_argv[i])
2044 break;
2045
29804cc1 2046 memzero(saved_argv[i], strlen(saved_argv[i]));
9a0e6896
LP
2047 }
2048 }
5b6319dc
LP
2049}
2050
f1566e63 2051char *lookup_uid(uid_t uid) {
ef2f1067 2052 long bufsize;
a05f97b3
LP
2053 char *name;
2054 _cleanup_free_ char *buf = NULL;
ef2f1067 2055 struct passwd pwbuf, *pw = NULL;
ef2f1067
LP
2056
2057 /* Shortcut things to avoid NSS lookups */
2058 if (uid == 0)
2059 return strdup("root");
2060
7c5f152a
LP
2061 bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
2062 if (bufsize <= 0)
ef2f1067
LP
2063 bufsize = 4096;
2064
7c5f152a
LP
2065 buf = malloc(bufsize);
2066 if (!buf)
ef2f1067
LP
2067 return NULL;
2068
a05f97b3
LP
2069 if (getpwuid_r(uid, &pwbuf, buf, bufsize, &pw) == 0 && pw)
2070 return strdup(pw->pw_name);
ef2f1067 2071
de0671ee 2072 if (asprintf(&name, UID_FMT, uid) < 0)
ef2f1067
LP
2073 return NULL;
2074
2075 return name;
2076}
2077
7c5f152a
LP
2078char* getlogname_malloc(void) {
2079 uid_t uid;
2080 struct stat st;
2081
2082 if (isatty(STDIN_FILENO) && fstat(STDIN_FILENO, &st) >= 0)
2083 uid = st.st_uid;
2084 else
2085 uid = getuid();
2086
2087 return lookup_uid(uid);
2088}
2089
2090char *getusername_malloc(void) {
2091 const char *e;
2092
2093 e = getenv("USER");
2094 if (e)
2095 return strdup(e);
2096
2097 return lookup_uid(getuid());
2098}
2099
d1678248 2100bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) {
943aad8c 2101 assert(s);
d1678248
ILG
2102 assert_cc(sizeof(statfs_f_type_t) >= sizeof(s->f_type));
2103
2104 return F_TYPE_EQUAL(s->f_type, magic_value);
2105}
2106
2107int fd_check_fstype(int fd, statfs_f_type_t magic_value) {
2108 struct statfs s;
2109
2110 if (fstatfs(fd, &s) < 0)
2111 return -errno;
73020ab2 2112
d1678248
ILG
2113 return is_fs_type(&s, magic_value);
2114}
2115
2116int path_check_fstype(const char *path, statfs_f_type_t magic_value) {
2117 _cleanup_close_ int fd = -1;
2118
2119 fd = open(path, O_RDONLY);
2120 if (fd < 0)
2121 return -errno;
2122
2123 return fd_check_fstype(fd, magic_value);
2124}
2125
2126bool is_temporary_fs(const struct statfs *s) {
2127 return is_fs_type(s, TMPFS_MAGIC) ||
2128 is_fs_type(s, RAMFS_MAGIC);
943aad8c
ZJS
2129}
2130
c6878637 2131int fd_is_temporary_fs(int fd) {
979ef53a
DR
2132 struct statfs s;
2133
2134 if (fstatfs(fd, &s) < 0)
2135 return -errno;
2136
2137 return is_temporary_fs(&s);
2138}
2139
8c6db833
LP
2140int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
2141 assert(path);
2142
2143 /* Under the assumption that we are running privileged we
2144 * first change the access mode and only then hand out
2145 * ownership to avoid a window where access is too open. */
2146
fed1e721 2147 if (mode != MODE_INVALID)
8d53b453
LP
2148 if (chmod(path, mode) < 0)
2149 return -errno;
8c6db833 2150
fed1e721 2151 if (uid != UID_INVALID || gid != GID_INVALID)
8d53b453
LP
2152 if (chown(path, uid, gid) < 0)
2153 return -errno;
8c6db833
LP
2154
2155 return 0;
ef2f1067
LP
2156}
2157
f4b47811
LP
2158int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid) {
2159 assert(fd >= 0);
2160
2161 /* Under the assumption that we are running privileged we
2162 * first change the access mode and only then hand out
2163 * ownership to avoid a window where access is too open. */
2164
fed1e721 2165 if (mode != MODE_INVALID)
9588bc32
LP
2166 if (fchmod(fd, mode) < 0)
2167 return -errno;
f4b47811 2168
fed1e721 2169 if (uid != UID_INVALID || gid != GID_INVALID)
9588bc32
LP
2170 if (fchown(fd, uid, gid) < 0)
2171 return -errno;
f4b47811
LP
2172
2173 return 0;
2174}
2175
9d9951a4
HH
2176int files_same(const char *filea, const char *fileb) {
2177 struct stat a, b;
b4f10a5e 2178
9d9951a4 2179 if (stat(filea, &a) < 0)
b4f10a5e
LP
2180 return -errno;
2181
9d9951a4 2182 if (stat(fileb, &b) < 0)
b4f10a5e
LP
2183 return -errno;
2184
9d9951a4
HH
2185 return a.st_dev == b.st_dev &&
2186 a.st_ino == b.st_ino;
2187}
2188
2189int running_in_chroot(void) {
2190 int ret;
2191
2192 ret = files_same("/proc/1/root", "/");
2193 if (ret < 0)
2194 return ret;
2195
2196 return ret == 0;
b4f10a5e
LP
2197}
2198
f405e86d 2199static char *ascii_ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
72f59706 2200 size_t x;
8fe914ec
LP
2201 char *r;
2202
2203 assert(s);
2204 assert(percent <= 100);
72f59706 2205 assert(new_length >= 3);
8fe914ec 2206
72f59706
LP
2207 if (old_length <= 3 || old_length <= new_length)
2208 return strndup(s, old_length);
8fe914ec 2209
72f59706
LP
2210 r = new0(char, new_length+1);
2211 if (!r)
a6f0104a 2212 return NULL;
8fe914ec 2213
72f59706 2214 x = (new_length * percent) / 100;
8fe914ec 2215
72f59706
LP
2216 if (x > new_length - 3)
2217 x = new_length - 3;
8fe914ec
LP
2218
2219 memcpy(r, s, x);
2220 r[x] = '.';
2221 r[x+1] = '.';
2222 r[x+2] = '.';
2223 memcpy(r + x + 3,
72f59706
LP
2224 s + old_length - (new_length - x - 3),
2225 new_length - x - 3);
8fe914ec
LP
2226
2227 return r;
2228}
2229
f405e86d
SL
2230char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
2231 size_t x;
2232 char *e;
2233 const char *i, *j;
2234 unsigned k, len, len2;
2235
2236 assert(s);
2237 assert(percent <= 100);
2238 assert(new_length >= 3);
2239
2240 /* if no multibyte characters use ascii_ellipsize_mem for speed */
2241 if (ascii_is_valid(s))
2242 return ascii_ellipsize_mem(s, old_length, new_length, percent);
2243
2244 if (old_length <= 3 || old_length <= new_length)
2245 return strndup(s, old_length);
2246
2247 x = (new_length * percent) / 100;
2248
2249 if (x > new_length - 3)
2250 x = new_length - 3;
2251
2252 k = 0;
2253 for (i = s; k < x && i < s + old_length; i = utf8_next_char(i)) {
2254 int c;
2255
2256 c = utf8_encoded_to_unichar(i);
2257 if (c < 0)
2258 return NULL;
2259 k += unichar_iswide(c) ? 2 : 1;
2260 }
2261
2262 if (k > x) /* last character was wide and went over quota */
2263 x ++;
2264
2265 for (j = s + old_length; k < new_length && j > i; ) {
2266 int c;
2267
2268 j = utf8_prev_char(j);
2269 c = utf8_encoded_to_unichar(j);
2270 if (c < 0)
2271 return NULL;
2272 k += unichar_iswide(c) ? 2 : 1;
2273 }
2274 assert(i <= j);
2275
2276 /* we don't actually need to ellipsize */
2277 if (i == j)
2278 return memdup(s, old_length + 1);
2279
2280 /* make space for ellipsis */
2281 j = utf8_next_char(j);
2282
2283 len = i - s;
2284 len2 = s + old_length - j;
2285 e = new(char, len + 3 + len2 + 1);
2286 if (!e)
2287 return NULL;
2288
2289 /*
2290 printf("old_length=%zu new_length=%zu x=%zu len=%u len2=%u k=%u\n",
2291 old_length, new_length, x, len, len2, k);
2292 */
2293
2294 memcpy(e, s, len);
2295 e[len] = 0xe2; /* tri-dot ellipsis: … */
2296 e[len + 1] = 0x80;
2297 e[len + 2] = 0xa6;
2298
2299 memcpy(e + len + 3, j, len2 + 1);
2300
2301 return e;
2302}
2303
72f59706
LP
2304char *ellipsize(const char *s, size_t length, unsigned percent) {
2305 return ellipsize_mem(s, strlen(s), length, percent);
2306}
2307
c38dfac9 2308int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode) {
03e334a1 2309 _cleanup_close_ int fd;
c38dfac9 2310 int r;
f6144808
LP
2311
2312 assert(path);
2313
c38dfac9
KS
2314 if (parents)
2315 mkdir_parents(path, 0755);
73836c5c 2316
c38dfac9 2317 fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, mode > 0 ? mode : 0644);
73836c5c 2318 if (fd < 0)
f6144808
LP
2319 return -errno;
2320
c38dfac9
KS
2321 if (mode > 0) {
2322 r = fchmod(fd, mode);
2323 if (r < 0)
2324 return -errno;
2325 }
2326
fed1e721 2327 if (uid != UID_INVALID || gid != GID_INVALID) {
c38dfac9
KS
2328 r = fchown(fd, uid, gid);
2329 if (r < 0)
2330 return -errno;
2331 }
2332
3a43da28 2333 if (stamp != USEC_INFINITY) {
c38dfac9
KS
2334 struct timespec ts[2];
2335
2336 timespec_store(&ts[0], stamp);
359efc59 2337 ts[1] = ts[0];
c38dfac9
KS
2338 r = futimens(fd, ts);
2339 } else
2340 r = futimens(fd, NULL);
2341 if (r < 0)
2342 return -errno;
2343
f6144808
LP
2344 return 0;
2345}
afea26ad 2346
c38dfac9 2347int touch(const char *path) {
fed1e721 2348 return touch_file(path, false, USEC_INFINITY, UID_INVALID, GID_INVALID, 0);
c38dfac9
KS
2349}
2350
e1eaca26 2351static char *unquote(const char *s, const char* quotes) {
11ce3427
LP
2352 size_t l;
2353 assert(s);
2354
73836c5c
LP
2355 /* This is rather stupid, simply removes the heading and
2356 * trailing quotes if there is one. Doesn't care about
e1eaca26
LP
2357 * escaping or anything.
2358 *
2359 * DON'T USE THIS FOR NEW CODE ANYMORE!*/
73836c5c 2360
31ed59c5
LP
2361 l = strlen(s);
2362 if (l < 2)
11ce3427
LP
2363 return strdup(s);
2364
97c4a07d 2365 if (strchr(quotes, s[0]) && s[l-1] == s[0])
11ce3427
LP
2366 return strndup(s+1, l-2);
2367
2368 return strdup(s);
2369}
2370
919ce0b7 2371noreturn void freeze(void) {
720ce21d
LP
2372
2373 /* Make sure nobody waits for us on a socket anymore */
2374 close_all_fds(NULL, 0);
2375
c29597a1
LP
2376 sync();
2377
3c14d26c
LP
2378 for (;;)
2379 pause();
2380}
2381
00dc5d76
LP
2382bool null_or_empty(struct stat *st) {
2383 assert(st);
2384
2385 if (S_ISREG(st->st_mode) && st->st_size <= 0)
2386 return true;
2387
c8f26f42 2388 if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
00dc5d76
LP
2389 return true;
2390
2391 return false;
2392}
2393
83096483
LP
2394int null_or_empty_path(const char *fn) {
2395 struct stat st;
2396
2397 assert(fn);
2398
2399 if (stat(fn, &st) < 0)
2400 return -errno;
2401
2402 return null_or_empty(&st);
2403}
2404
ed88bcfb
ZJS
2405int null_or_empty_fd(int fd) {
2406 struct stat st;
2407
2408 assert(fd >= 0);
2409
2410 if (fstat(fd, &st) < 0)
2411 return -errno;
2412
2413 return null_or_empty(&st);
2414}
2415
a247755d 2416DIR *xopendirat(int fd, const char *name, int flags) {
c4731d11
LP
2417 int nfd;
2418 DIR *d;
2419
dd94c17e
LP
2420 assert(!(flags & O_CREAT));
2421
2422 nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags, 0);
73836c5c 2423 if (nfd < 0)
c4731d11
LP
2424 return NULL;
2425
73836c5c
LP
2426 d = fdopendir(nfd);
2427 if (!d) {
03e334a1 2428 safe_close(nfd);
c4731d11
LP
2429 return NULL;
2430 }
2431
2432 return d;
3b63d2d3
LP
2433}
2434
383182b5 2435static char *tag_to_udev_node(const char *tagvalue, const char *by) {
22f5f628 2436 _cleanup_free_ char *t = NULL, *u = NULL;
22f5f628 2437 size_t enc_len;
e23a0ce8 2438
e1eaca26 2439 u = unquote(tagvalue, QUOTES);
6db615c1 2440 if (!u)
383182b5 2441 return NULL;
e23a0ce8 2442
1d5989fd 2443 enc_len = strlen(u) * 4 + 1;
22f5f628 2444 t = new(char, enc_len);
6db615c1 2445 if (!t)
383182b5 2446 return NULL;
e23a0ce8 2447
8f6ce71f 2448 if (encode_devnode_name(u, t, enc_len) < 0)
22f5f628 2449 return NULL;
e23a0ce8 2450
6db615c1 2451 return strjoin("/dev/disk/by-", by, "/", t, NULL);
383182b5 2452}
e23a0ce8 2453
383182b5 2454char *fstab_node_to_udev_node(const char *p) {
faa368e3
LP
2455 assert(p);
2456
383182b5
DR
2457 if (startswith(p, "LABEL="))
2458 return tag_to_udev_node(p+6, "label");
e23a0ce8 2459
383182b5
DR
2460 if (startswith(p, "UUID="))
2461 return tag_to_udev_node(p+5, "uuid");
e23a0ce8 2462
84cc2abf
DR
2463 if (startswith(p, "PARTUUID="))
2464 return tag_to_udev_node(p+9, "partuuid");
2465
2466 if (startswith(p, "PARTLABEL="))
2467 return tag_to_udev_node(p+10, "partlabel");
2468
e23a0ce8
LP
2469 return strdup(p);
2470}
2471
87d2c1ff 2472bool dirent_is_file(const struct dirent *de) {
fb19a739
LP
2473 assert(de);
2474
a34bf9db 2475 if (hidden_file(de->d_name))
fb19a739
LP
2476 return false;
2477
2478 if (de->d_type != DT_REG &&
2479 de->d_type != DT_LNK &&
2480 de->d_type != DT_UNKNOWN)
2481 return false;
2482
2483 return true;
2484}
2485
87d2c1ff
LP
2486bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
2487 assert(de);
2488
a228a22f
LP
2489 if (de->d_type != DT_REG &&
2490 de->d_type != DT_LNK &&
2491 de->d_type != DT_UNKNOWN)
2492 return false;
2493
a34bf9db 2494 if (hidden_file_allow_backup(de->d_name))
87d2c1ff
LP
2495 return false;
2496
2497 return endswith(de->d_name, suffix);
2498}
2499
e801700e 2500static int do_execute(char **directories, usec_t timeout, char *argv[]) {
49681057 2501 _cleanup_hashmap_free_free_ Hashmap *pids = NULL;
e801700e
ZJS
2502 _cleanup_set_free_free_ Set *seen = NULL;
2503 char **directory;
83cc030f 2504
49681057
ZJS
2505 /* We fork this all off from a child process so that we can
2506 * somewhat cleanly make use of SIGALRM to set a time limit */
83cc030f 2507
ce30c8dc
LP
2508 (void) reset_all_signal_handlers();
2509 (void) reset_signal_mask();
83cc030f 2510
49681057 2511 assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
83cc030f 2512
49681057
ZJS
2513 pids = hashmap_new(NULL);
2514 if (!pids)
2515 return log_oom();
83cc030f 2516
e801700e
ZJS
2517 seen = set_new(&string_hash_ops);
2518 if (!seen)
2519 return log_oom();
83cc030f 2520
e801700e
ZJS
2521 STRV_FOREACH(directory, directories) {
2522 _cleanup_closedir_ DIR *d;
2523 struct dirent *de;
83cc030f 2524
e801700e
ZJS
2525 d = opendir(*directory);
2526 if (!d) {
2527 if (errno == ENOENT)
2528 continue;
83cc030f 2529
e801700e
ZJS
2530 return log_error_errno(errno, "Failed to open directory %s: %m", *directory);
2531 }
83cc030f 2532
e801700e
ZJS
2533 FOREACH_DIRENT(de, d, break) {
2534 _cleanup_free_ char *path = NULL;
2535 pid_t pid;
2536 int r;
2537
2538 if (!dirent_is_file(de))
2539 continue;
83cc030f 2540
e801700e
ZJS
2541 if (set_contains(seen, de->d_name)) {
2542 log_debug("%1$s/%2$s skipped (%2$s was already seen).", *directory, de->d_name);
2543 continue;
2544 }
2545
2546 r = set_put_strdup(seen, de->d_name);
2547 if (r < 0)
2548 return log_oom();
2549
2550 path = strjoin(*directory, "/", de->d_name, NULL);
2551 if (!path)
2552 return log_oom();
2553
2554 if (null_or_empty_path(path)) {
2555 log_debug("%s is empty (a mask).", path);
2556 continue;
7034e9db 2557 }
83cc030f 2558
e801700e
ZJS
2559 pid = fork();
2560 if (pid < 0) {
2561 log_error_errno(errno, "Failed to fork: %m");
2562 continue;
2563 } else if (pid == 0) {
2564 char *_argv[2];
83cc030f 2565
e801700e 2566 assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
83cc030f 2567
e801700e
ZJS
2568 if (!argv) {
2569 _argv[0] = path;
2570 _argv[1] = NULL;
2571 argv = _argv;
2572 } else
2573 argv[0] = path;
2574
2575 execv(path, argv);
2576 return log_error_errno(errno, "Failed to execute %s: %m", path);
2577 }
2578
2579 log_debug("Spawned %s as " PID_FMT ".", path, pid);
83cc030f 2580
e801700e
ZJS
2581 r = hashmap_put(pids, UINT_TO_PTR(pid), path);
2582 if (r < 0)
2583 return log_oom();
2584 path = NULL;
2585 }
49681057 2586 }
83cc030f 2587
49681057
ZJS
2588 /* Abort execution of this process after the timout. We simply
2589 * rely on SIGALRM as default action terminating the process,
2590 * and turn on alarm(). */
83cc030f 2591
49681057
ZJS
2592 if (timeout != USEC_INFINITY)
2593 alarm((timeout + USEC_PER_SEC - 1) / USEC_PER_SEC);
83cc030f 2594
49681057
ZJS
2595 while (!hashmap_isempty(pids)) {
2596 _cleanup_free_ char *path = NULL;
2597 pid_t pid;
aa62a893 2598
49681057
ZJS
2599 pid = PTR_TO_UINT(hashmap_first_key(pids));
2600 assert(pid > 0);
83cc030f 2601
49681057
ZJS
2602 path = hashmap_remove(pids, UINT_TO_PTR(pid));
2603 assert(path);
aa62a893 2604
49681057
ZJS
2605 wait_for_terminate_and_warn(path, pid, true);
2606 }
aa62a893 2607
49681057
ZJS
2608 return 0;
2609}
aa62a893 2610
e801700e 2611void execute_directories(const char* const* directories, usec_t timeout, char *argv[]) {
49681057
ZJS
2612 pid_t executor_pid;
2613 int r;
e801700e
ZJS
2614 char *name;
2615 char **dirs = (char**) directories;
2616
2617 assert(!strv_isempty(dirs));
83cc030f 2618
e801700e
ZJS
2619 name = basename(dirs[0]);
2620 assert(!isempty(name));
aa62a893 2621
e801700e
ZJS
2622 /* Executes all binaries in the directories in parallel and waits
2623 * for them to finish. Optionally a timeout is applied. If a file
2624 * with the same name exists in more than one directory, the
2625 * earliest one wins. */
83cc030f 2626
49681057
ZJS
2627 executor_pid = fork();
2628 if (executor_pid < 0) {
2629 log_error_errno(errno, "Failed to fork: %m");
2630 return;
2631
2632 } else if (executor_pid == 0) {
e801700e 2633 r = do_execute(dirs, timeout, argv);
49681057 2634 _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
aa62a893 2635 }
83cc030f 2636
e801700e 2637 wait_for_terminate_and_warn(name, executor_pid, true);
83cc030f
LP
2638}
2639
05feefe0
LP
2640bool nulstr_contains(const char*nulstr, const char *needle) {
2641 const char *i;
2642
2643 if (!nulstr)
2644 return false;
2645
2646 NULSTR_FOREACH(i, nulstr)
2647 if (streq(i, needle))
2648 return true;
2649
2650 return false;
2651}
2652
a88c8750
TG
2653bool plymouth_running(void) {
2654 return access("/run/plymouth/pid", F_OK) >= 0;
2655}
2656
9beb3f4d
LP
2657char* strshorten(char *s, size_t l) {
2658 assert(s);
2659
2660 if (l < strlen(s))
2661 s[l] = 0;
2662
2663 return s;
2664}
2665
1325aa42 2666int pipe_eof(int fd) {
b92bea5d
ZJS
2667 struct pollfd pollfd = {
2668 .fd = fd,
2669 .events = POLLIN|POLLHUP,
2670 };
1325aa42 2671
d37a91e8
LP
2672 int r;
2673
1325aa42
LP
2674 r = poll(&pollfd, 1, 0);
2675 if (r < 0)
2676 return -errno;
2677
2678 if (r == 0)
2679 return 0;
2680
2681 return pollfd.revents & POLLHUP;
2682}
2683
8f2d43a0 2684int fd_wait_for_event(int fd, int event, usec_t t) {
968d3d24 2685
b92bea5d
ZJS
2686 struct pollfd pollfd = {
2687 .fd = fd,
2688 .events = event,
2689 };
df50185b 2690
968d3d24
LP
2691 struct timespec ts;
2692 int r;
2693
3a43da28 2694 r = ppoll(&pollfd, 1, t == USEC_INFINITY ? NULL : timespec_store(&ts, t), NULL);
df50185b
LP
2695 if (r < 0)
2696 return -errno;
2697
2698 if (r == 0)
2699 return 0;
2700
2701 return pollfd.revents;
2702}
2703
5a3ab509
LP
2704int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
2705 FILE *f;
2706 char *t;
ae6c3cc0 2707 int r, fd;
5a3ab509
LP
2708
2709 assert(path);
2710 assert(_f);
2711 assert(_temp_path);
2712
14bcf25c 2713 r = tempfn_xxxxxx(path, NULL, &t);
ae6c3cc0
LP
2714 if (r < 0)
2715 return r;
5a3ab509 2716
2d5bdf5b 2717 fd = mkostemp_safe(t, O_WRONLY|O_CLOEXEC);
5a3ab509
LP
2718 if (fd < 0) {
2719 free(t);
2720 return -errno;
2721 }
2722
2723 f = fdopen(fd, "we");
2724 if (!f) {
64ee7ab4 2725 unlink_noerrno(t);
5a3ab509 2726 free(t);
ac521356 2727 safe_close(fd);
5a3ab509
LP
2728 return -errno;
2729 }
2730
2731 *_f = f;
2732 *_temp_path = t;
2733
2734 return 0;
2735}
2736
424a19f8 2737int symlink_atomic(const char *from, const char *to) {
2e78fa79 2738 _cleanup_free_ char *t = NULL;
ae6c3cc0 2739 int r;
34ca941c
LP
2740
2741 assert(from);
2742 assert(to);
2743
14bcf25c 2744 r = tempfn_random(to, NULL, &t);
ae6c3cc0
LP
2745 if (r < 0)
2746 return r;
34ca941c 2747
424a19f8
LP
2748 if (symlink(from, t) < 0)
2749 return -errno;
34ca941c
LP
2750
2751 if (rename(t, to) < 0) {
2e78fa79
LP
2752 unlink_noerrno(t);
2753 return -errno;
34ca941c
LP
2754 }
2755
424a19f8 2756 return 0;
34ca941c
LP
2757}
2758
875e1014
ILG
2759int symlink_idempotent(const char *from, const char *to) {
2760 _cleanup_free_ char *p = NULL;
2761 int r;
2762
2763 assert(from);
2764 assert(to);
2765
2766 if (symlink(from, to) < 0) {
2767 if (errno != EEXIST)
2768 return -errno;
2769
2770 r = readlink_malloc(to, &p);
2771 if (r < 0)
2772 return r;
2773
2774 if (!streq(p, from))
2775 return -EINVAL;
2776 }
2777
2778 return 0;
2779}
2780
1554afae
LP
2781int mknod_atomic(const char *path, mode_t mode, dev_t dev) {
2782 _cleanup_free_ char *t = NULL;
ae6c3cc0 2783 int r;
1554afae
LP
2784
2785 assert(path);
2786
14bcf25c 2787 r = tempfn_random(path, NULL, &t);
ae6c3cc0
LP
2788 if (r < 0)
2789 return r;
1554afae
LP
2790
2791 if (mknod(t, mode, dev) < 0)
2792 return -errno;
2793
2794 if (rename(t, path) < 0) {
2795 unlink_noerrno(t);
2796 return -errno;
2797 }
2798
2799 return 0;
2800}
2801
2802int mkfifo_atomic(const char *path, mode_t mode) {
2803 _cleanup_free_ char *t = NULL;
ae6c3cc0 2804 int r;
1554afae
LP
2805
2806 assert(path);
2807
14bcf25c 2808 r = tempfn_random(path, NULL, &t);
ae6c3cc0
LP
2809 if (r < 0)
2810 return r;
1554afae
LP
2811
2812 if (mkfifo(t, mode) < 0)
2813 return -errno;
2814
2815 if (rename(t, path) < 0) {
2816 unlink_noerrno(t);
2817 return -errno;
2818 }
2819
2820 return 0;
2821}
2822
4d6d6518
LP
2823bool display_is_local(const char *display) {
2824 assert(display);
2825
2826 return
2827 display[0] == ':' &&
2828 display[1] >= '0' &&
2829 display[1] <= '9';
2830}
2831
2832int socket_from_display(const char *display, char **path) {
2833 size_t k;
2834 char *f, *c;
2835
2836 assert(display);
2837 assert(path);
2838
2839 if (!display_is_local(display))
2840 return -EINVAL;
2841
2842 k = strspn(display+1, "0123456789");
2843
f8294e41 2844 f = new(char, strlen("/tmp/.X11-unix/X") + k + 1);
4d6d6518
LP
2845 if (!f)
2846 return -ENOMEM;
2847
2848 c = stpcpy(f, "/tmp/.X11-unix/X");
2849 memcpy(c, display+1, k);
2850 c[k] = 0;
2851
2852 *path = f;
2853
2854 return 0;
2855}
2856
d05c5031
LP
2857int get_user_creds(
2858 const char **username,
2859 uid_t *uid, gid_t *gid,
2860 const char **home,
2861 const char **shell) {
2862
1cccf435 2863 struct passwd *p;
ddd88763 2864 uid_t u;
1cccf435
MV
2865
2866 assert(username);
2867 assert(*username);
1cccf435
MV
2868
2869 /* We enforce some special rules for uid=0: in order to avoid
2870 * NSS lookups for root we hardcode its data. */
2871
2872 if (streq(*username, "root") || streq(*username, "0")) {
2873 *username = "root";
4b67834e
LP
2874
2875 if (uid)
2876 *uid = 0;
2877
2878 if (gid)
2879 *gid = 0;
2880
2881 if (home)
2882 *home = "/root";
d05c5031
LP
2883
2884 if (shell)
2885 *shell = "/bin/sh";
2886
1cccf435
MV
2887 return 0;
2888 }
2889
ddd88763 2890 if (parse_uid(*username, &u) >= 0) {
1cccf435 2891 errno = 0;
ddd88763 2892 p = getpwuid(u);
1cccf435
MV
2893
2894 /* If there are multiple users with the same id, make
2895 * sure to leave $USER to the configured value instead
2896 * of the first occurrence in the database. However if
2897 * the uid was configured by a numeric uid, then let's
2898 * pick the real username from /etc/passwd. */
2899 if (p)
2900 *username = p->pw_name;
2901 } else {
2902 errno = 0;
2903 p = getpwnam(*username);
2904 }
2905
2906 if (!p)
8333c77e 2907 return errno > 0 ? -errno : -ESRCH;
1cccf435 2908
4b67834e
LP
2909 if (uid)
2910 *uid = p->pw_uid;
2911
2912 if (gid)
2913 *gid = p->pw_gid;
2914
2915 if (home)
2916 *home = p->pw_dir;
2917
d05c5031
LP
2918 if (shell)
2919 *shell = p->pw_shell;
2920
4b67834e
LP
2921 return 0;
2922}
2923
59164be4
LP
2924char* uid_to_name(uid_t uid) {
2925 struct passwd *p;
2926 char *r;
2927
2928 if (uid == 0)
2929 return strdup("root");
2930
2931 p = getpwuid(uid);
2932 if (p)
2933 return strdup(p->pw_name);
2934
de0671ee 2935 if (asprintf(&r, UID_FMT, uid) < 0)
59164be4
LP
2936 return NULL;
2937
2938 return r;
2939}
2940
4468addc
LP
2941char* gid_to_name(gid_t gid) {
2942 struct group *p;
2943 char *r;
2944
2945 if (gid == 0)
2946 return strdup("root");
2947
2948 p = getgrgid(gid);
2949 if (p)
2950 return strdup(p->gr_name);
2951
de0671ee 2952 if (asprintf(&r, GID_FMT, gid) < 0)
4468addc
LP
2953 return NULL;
2954
2955 return r;
2956}
2957
4b67834e
LP
2958int get_group_creds(const char **groupname, gid_t *gid) {
2959 struct group *g;
2960 gid_t id;
2961
2962 assert(groupname);
2963
2964 /* We enforce some special rules for gid=0: in order to avoid
2965 * NSS lookups for root we hardcode its data. */
2966
2967 if (streq(*groupname, "root") || streq(*groupname, "0")) {
2968 *groupname = "root";
2969
2970 if (gid)
2971 *gid = 0;
2972
2973 return 0;
2974 }
2975
2976 if (parse_gid(*groupname, &id) >= 0) {
2977 errno = 0;
2978 g = getgrgid(id);
2979
2980 if (g)
2981 *groupname = g->gr_name;
2982 } else {
2983 errno = 0;
2984 g = getgrnam(*groupname);
2985 }
2986
2987 if (!g)
8333c77e 2988 return errno > 0 ? -errno : -ESRCH;
4b67834e
LP
2989
2990 if (gid)
2991 *gid = g->gr_gid;
2992
1cccf435
MV
2993 return 0;
2994}
2995
4468addc
LP
2996int in_gid(gid_t gid) {
2997 gid_t *gids;
43673799
LP
2998 int ngroups_max, r, i;
2999
43673799
LP
3000 if (getgid() == gid)
3001 return 1;
3002
3003 if (getegid() == gid)
3004 return 1;
3005
3006 ngroups_max = sysconf(_SC_NGROUPS_MAX);
3007 assert(ngroups_max > 0);
3008
3009 gids = alloca(sizeof(gid_t) * ngroups_max);
3010
3011 r = getgroups(ngroups_max, gids);
3012 if (r < 0)
3013 return -errno;
3014
3015 for (i = 0; i < r; i++)
3016 if (gids[i] == gid)
3017 return 1;
3018
3019 return 0;
3020}
3021
4468addc
LP
3022int in_group(const char *name) {
3023 int r;
3024 gid_t gid;
3025
3026 r = get_group_creds(&name, &gid);
3027 if (r < 0)
3028 return r;
3029
3030 return in_gid(gid);
3031}
3032
8092a428 3033int glob_exists(const char *path) {
7fd1b19b 3034 _cleanup_globfree_ glob_t g = {};
8d98da3f 3035 int k;
8092a428
LP
3036
3037 assert(path);
3038
8092a428
LP
3039 errno = 0;
3040 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
3041
3042 if (k == GLOB_NOMATCH)
8d98da3f 3043 return 0;
8092a428 3044 else if (k == GLOB_NOSPACE)
8d98da3f 3045 return -ENOMEM;
8092a428 3046 else if (k == 0)
8d98da3f 3047 return !strv_isempty(g.gl_pathv);
8092a428 3048 else
8d98da3f
ZJS
3049 return errno ? -errno : -EIO;
3050}
8092a428 3051
8d98da3f
ZJS
3052int glob_extend(char ***strv, const char *path) {
3053 _cleanup_globfree_ glob_t g = {};
3054 int k;
3055 char **p;
3056
3057 errno = 0;
a8ccacf5 3058 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
8d98da3f
ZJS
3059
3060 if (k == GLOB_NOMATCH)
3061 return -ENOENT;
3062 else if (k == GLOB_NOSPACE)
3063 return -ENOMEM;
3064 else if (k != 0 || strv_isempty(g.gl_pathv))
3065 return errno ? -errno : -EIO;
3066
3067 STRV_FOREACH(p, g.gl_pathv) {
3068 k = strv_extend(strv, *p);
3069 if (k < 0)
3070 break;
3071 }
3072
3073 return k;
8092a428
LP
3074}
3075
83096483
LP
3076int dirent_ensure_type(DIR *d, struct dirent *de) {
3077 struct stat st;
3078
3079 assert(d);
3080 assert(de);
3081
3082 if (de->d_type != DT_UNKNOWN)
3083 return 0;
3084
3085 if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
3086 return -errno;
3087
3088 de->d_type =
3089 S_ISREG(st.st_mode) ? DT_REG :
3090 S_ISDIR(st.st_mode) ? DT_DIR :
3091 S_ISLNK(st.st_mode) ? DT_LNK :
3092 S_ISFIFO(st.st_mode) ? DT_FIFO :
3093 S_ISSOCK(st.st_mode) ? DT_SOCK :
3094 S_ISCHR(st.st_mode) ? DT_CHR :
3095 S_ISBLK(st.st_mode) ? DT_BLK :
3096 DT_UNKNOWN;
3097
3098 return 0;
3099}
3100
034a2a52 3101int get_files_in_directory(const char *path, char ***list) {
893fa014
ZJS
3102 _cleanup_closedir_ DIR *d = NULL;
3103 size_t bufsize = 0, n = 0;
3104 _cleanup_strv_free_ char **l = NULL;
034a2a52
LP
3105
3106 assert(path);
d60ef526
LP
3107
3108 /* Returns all files in a directory in *list, and the number
3109 * of files as return value. If list is NULL returns only the
893fa014 3110 * number. */
034a2a52
LP
3111
3112 d = opendir(path);
8ea913b2
LP
3113 if (!d)
3114 return -errno;
3115
034a2a52 3116 for (;;) {
7d5e9c0f 3117 struct dirent *de;
034a2a52 3118
3fd11280
FW
3119 errno = 0;
3120 de = readdir(d);
3121 if (!de && errno != 0)
3122 return -errno;
034a2a52
LP
3123 if (!de)
3124 break;
3125
3126 dirent_ensure_type(d, de);
3127
3128 if (!dirent_is_file(de))
3129 continue;
3130
d60ef526 3131 if (list) {
893fa014
ZJS
3132 /* one extra slot is needed for the terminating NULL */
3133 if (!GREEDY_REALLOC(l, bufsize, n + 2))
3134 return -ENOMEM;
034a2a52 3135
893fa014
ZJS
3136 l[n] = strdup(de->d_name);
3137 if (!l[n])
3138 return -ENOMEM;
034a2a52 3139
893fa014 3140 l[++n] = NULL;
d60ef526 3141 } else
893fa014 3142 n++;
034a2a52
LP
3143 }
3144
893fa014
ZJS
3145 if (list) {
3146 *list = l;
3147 l = NULL; /* avoid freeing */
3148 }
034a2a52 3149
893fa014 3150 return n;
034a2a52
LP
3151}
3152
b7def684 3153char *strjoin(const char *x, ...) {
911a4828
LP
3154 va_list ap;
3155 size_t l;
3156 char *r, *p;
3157
3158 va_start(ap, x);
3159
3160 if (x) {
3161 l = strlen(x);
3162
3163 for (;;) {
3164 const char *t;
040f18ea 3165 size_t n;
911a4828
LP
3166
3167 t = va_arg(ap, const char *);
3168 if (!t)
3169 break;
3170
040f18ea 3171 n = strlen(t);
e98055de
LN
3172 if (n > ((size_t) -1) - l) {
3173 va_end(ap);
040f18ea 3174 return NULL;
e98055de 3175 }
040f18ea
LP
3176
3177 l += n;
911a4828
LP
3178 }
3179 } else
3180 l = 0;
3181
3182 va_end(ap);
3183
3184 r = new(char, l+1);
3185 if (!r)
3186 return NULL;
3187
3188 if (x) {
3189 p = stpcpy(r, x);
3190
3191 va_start(ap, x);
3192
3193 for (;;) {
3194 const char *t;
3195
3196 t = va_arg(ap, const char *);
3197 if (!t)
3198 break;
3199
3200 p = stpcpy(p, t);
3201 }
8ea913b2
LP
3202
3203 va_end(ap);
911a4828
LP
3204 } else
3205 r[0] = 0;
3206
3207 return r;
3208}
3209
b636465b 3210bool is_main_thread(void) {
ec202eae 3211 static thread_local int cached = 0;
b636465b
LP
3212
3213 if (_unlikely_(cached == 0))
3214 cached = getpid() == gettid() ? 1 : -1;
3215
3216 return cached > 0;
3217}
3218
94959f0f
LP
3219int block_get_whole_disk(dev_t d, dev_t *ret) {
3220 char *p, *s;
3221 int r;
3222 unsigned n, m;
3223
3224 assert(ret);
3225
3226 /* If it has a queue this is good enough for us */
3227 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", major(d), minor(d)) < 0)
3228 return -ENOMEM;
3229
3230 r = access(p, F_OK);
3231 free(p);
3232
3233 if (r >= 0) {
3234 *ret = d;
3235 return 0;
3236 }
3237
3238 /* If it is a partition find the originating device */
3239 if (asprintf(&p, "/sys/dev/block/%u:%u/partition", major(d), minor(d)) < 0)
3240 return -ENOMEM;
3241
3242 r = access(p, F_OK);
3243 free(p);
3244
3245 if (r < 0)
3246 return -ENOENT;
3247
3248 /* Get parent dev_t */
3249 if (asprintf(&p, "/sys/dev/block/%u:%u/../dev", major(d), minor(d)) < 0)
3250 return -ENOMEM;
3251
3252 r = read_one_line_file(p, &s);
3253 free(p);
3254
3255 if (r < 0)
3256 return r;
3257
3258 r = sscanf(s, "%u:%u", &m, &n);
3259 free(s);
3260
3261 if (r != 2)
3262 return -EINVAL;
3263
3264 /* Only return this if it is really good enough for us. */
3265 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", m, n) < 0)
3266 return -ENOMEM;
3267
3268 r = access(p, F_OK);
3269 free(p);
3270
3271 if (r >= 0) {
3272 *ret = makedev(m, n);
3273 return 0;
3274 }
3275
3276 return -ENOENT;
3277}
3278
f41607a6
LP
3279static const char *const ioprio_class_table[] = {
3280 [IOPRIO_CLASS_NONE] = "none",
3281 [IOPRIO_CLASS_RT] = "realtime",
3282 [IOPRIO_CLASS_BE] = "best-effort",
3283 [IOPRIO_CLASS_IDLE] = "idle"
3284};
3285
f8b69d1d 3286DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX);
f41607a6
LP
3287
3288static const char *const sigchld_code_table[] = {
3289 [CLD_EXITED] = "exited",
3290 [CLD_KILLED] = "killed",
3291 [CLD_DUMPED] = "dumped",
3292 [CLD_TRAPPED] = "trapped",
3293 [CLD_STOPPED] = "stopped",
3294 [CLD_CONTINUED] = "continued",
3295};
3296
3297DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
3298
3299static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = {
3300 [LOG_FAC(LOG_KERN)] = "kern",
3301 [LOG_FAC(LOG_USER)] = "user",
3302 [LOG_FAC(LOG_MAIL)] = "mail",
3303 [LOG_FAC(LOG_DAEMON)] = "daemon",
3304 [LOG_FAC(LOG_AUTH)] = "auth",
3305 [LOG_FAC(LOG_SYSLOG)] = "syslog",
3306 [LOG_FAC(LOG_LPR)] = "lpr",
3307 [LOG_FAC(LOG_NEWS)] = "news",
3308 [LOG_FAC(LOG_UUCP)] = "uucp",
3309 [LOG_FAC(LOG_CRON)] = "cron",
3310 [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
3311 [LOG_FAC(LOG_FTP)] = "ftp",
3312 [LOG_FAC(LOG_LOCAL0)] = "local0",
3313 [LOG_FAC(LOG_LOCAL1)] = "local1",
3314 [LOG_FAC(LOG_LOCAL2)] = "local2",
3315 [LOG_FAC(LOG_LOCAL3)] = "local3",
3316 [LOG_FAC(LOG_LOCAL4)] = "local4",
3317 [LOG_FAC(LOG_LOCAL5)] = "local5",
3318 [LOG_FAC(LOG_LOCAL6)] = "local6",
3319 [LOG_FAC(LOG_LOCAL7)] = "local7"
3320};
3321
f8b69d1d 3322DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_facility_unshifted, int, LOG_FAC(~0));
f41607a6 3323
adb8ec96
EV
3324bool log_facility_unshifted_is_valid(int facility) {
3325 return facility >= 0 && facility <= LOG_FAC(~0);
3326}
3327
f41607a6
LP
3328static const char *const log_level_table[] = {
3329 [LOG_EMERG] = "emerg",
3330 [LOG_ALERT] = "alert",
3331 [LOG_CRIT] = "crit",
3332 [LOG_ERR] = "err",
3333 [LOG_WARNING] = "warning",
3334 [LOG_NOTICE] = "notice",
3335 [LOG_INFO] = "info",
3336 [LOG_DEBUG] = "debug"
3337};
3338
f8b69d1d 3339DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_level, int, LOG_DEBUG);
f41607a6 3340
adb8ec96
EV
3341bool log_level_is_valid(int level) {
3342 return level >= 0 && level <= LOG_DEBUG;
3343}
3344
f41607a6
LP
3345static const char* const sched_policy_table[] = {
3346 [SCHED_OTHER] = "other",
3347 [SCHED_BATCH] = "batch",
3348 [SCHED_IDLE] = "idle",
3349 [SCHED_FIFO] = "fifo",
3350 [SCHED_RR] = "rr"
3351};
3352
f8b69d1d 3353DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX);
f41607a6 3354
517d56b1 3355static const char* const rlimit_table[_RLIMIT_MAX] = {
f41607a6
LP
3356 [RLIMIT_CPU] = "LimitCPU",
3357 [RLIMIT_FSIZE] = "LimitFSIZE",
3358 [RLIMIT_DATA] = "LimitDATA",
3359 [RLIMIT_STACK] = "LimitSTACK",
3360 [RLIMIT_CORE] = "LimitCORE",
3361 [RLIMIT_RSS] = "LimitRSS",
3362 [RLIMIT_NOFILE] = "LimitNOFILE",
3363 [RLIMIT_AS] = "LimitAS",
3364 [RLIMIT_NPROC] = "LimitNPROC",
3365 [RLIMIT_MEMLOCK] = "LimitMEMLOCK",
3366 [RLIMIT_LOCKS] = "LimitLOCKS",
3367 [RLIMIT_SIGPENDING] = "LimitSIGPENDING",
3368 [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE",
3369 [RLIMIT_NICE] = "LimitNICE",
3370 [RLIMIT_RTPRIO] = "LimitRTPRIO",
3371 [RLIMIT_RTTIME] = "LimitRTTIME"
3372};
3373
3374DEFINE_STRING_TABLE_LOOKUP(rlimit, int);
3375
3376static const char* const ip_tos_table[] = {
3377 [IPTOS_LOWDELAY] = "low-delay",
3378 [IPTOS_THROUGHPUT] = "throughput",
3379 [IPTOS_RELIABILITY] = "reliability",
3380 [IPTOS_LOWCOST] = "low-cost",
3381};
3382
f8b69d1d 3383DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
f41607a6 3384
65457142
FC
3385bool kexec_loaded(void) {
3386 bool loaded = false;
3387 char *s;
3388
3389 if (read_one_line_file("/sys/kernel/kexec_loaded", &s) >= 0) {
3390 if (s[0] == '1')
3391 loaded = true;
3392 free(s);
3393 }
3394 return loaded;
3395}
fb9de93d 3396
87d2c1ff
LP
3397int prot_from_flags(int flags) {
3398
3399 switch (flags & O_ACCMODE) {
3400
3401 case O_RDONLY:
3402 return PROT_READ;
3403
3404 case O_WRONLY:
3405 return PROT_WRITE;
3406
3407 case O_RDWR:
3408 return PROT_READ|PROT_WRITE;
3409
3410 default:
3411 return -EINVAL;
3412 }
7c99e0c1 3413}
689b9a22 3414
59f448cf 3415char *format_bytes(char *buf, size_t l, uint64_t t) {
c0f99c21 3416 unsigned i;
babfc091
LP
3417
3418 static const struct {
3419 const char *suffix;
59f448cf 3420 uint64_t factor;
babfc091 3421 } table[] = {
59f448cf
LP
3422 { "E", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
3423 { "P", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
3424 { "T", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
3425 { "G", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
3426 { "M", UINT64_C(1024)*UINT64_C(1024) },
3427 { "K", UINT64_C(1024) },
babfc091
LP
3428 };
3429
59f448cf 3430 if (t == (uint64_t) -1)
f02ca522
LP
3431 return NULL;
3432
babfc091
LP
3433 for (i = 0; i < ELEMENTSOF(table); i++) {
3434
3435 if (t >= table[i].factor) {
3436 snprintf(buf, l,
59f448cf
LP
3437 "%" PRIu64 ".%" PRIu64 "%s",
3438 t / table[i].factor,
3439 ((t*UINT64_C(10)) / table[i].factor) % UINT64_C(10),
babfc091
LP
3440 table[i].suffix);
3441
3442 goto finish;
3443 }
3444 }
3445
59f448cf 3446 snprintf(buf, l, "%" PRIu64 "B", t);
babfc091
LP
3447
3448finish:
3449 buf[l-1] = 0;
3450 return buf;
3451
3452}
55d7bfc1
LP
3453
3454void* memdup(const void *p, size_t l) {
3455 void *r;
3456
3457 assert(p);
3458
3459 r = malloc(l);
3460 if (!r)
3461 return NULL;
3462
3463 memcpy(r, p, l);
3464 return r;
3465}
bb99a35a
LP
3466
3467int fd_inc_sndbuf(int fd, size_t n) {
3468 int r, value;
3469 socklen_t l = sizeof(value);
3470
3471 r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
92d75ca4 3472 if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
bb99a35a
LP
3473 return 0;
3474
92d75ca4
LP
3475 /* If we have the privileges we will ignore the kernel limit. */
3476
bb99a35a 3477 value = (int) n;
92d75ca4
LP
3478 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUFFORCE, &value, sizeof(value)) < 0)
3479 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value)) < 0)
3480 return -errno;
bb99a35a
LP
3481
3482 return 1;
3483}
3484
3485int fd_inc_rcvbuf(int fd, size_t n) {
3486 int r, value;
3487 socklen_t l = sizeof(value);
3488
3489 r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
92d75ca4 3490 if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
bb99a35a
LP
3491 return 0;
3492
92d75ca4 3493 /* If we have the privileges we will ignore the kernel limit. */
bb99a35a 3494
92d75ca4
LP
3495 value = (int) n;
3496 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value)) < 0)
3497 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) < 0)
3498 return -errno;
bb99a35a
LP
3499 return 1;
3500}
6bb92a16 3501
9bdc770c 3502int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
6bb92a16 3503 bool stdout_is_tty, stderr_is_tty;
8a7c93d8
LP
3504 pid_t parent_pid, agent_pid;
3505 sigset_t ss, saved_ss;
6bb92a16
LP
3506 unsigned n, i;
3507 va_list ap;
3508 char **l;
3509
3510 assert(pid);
3511 assert(path);
3512
6bb92a16
LP
3513 /* Spawns a temporary TTY agent, making sure it goes away when
3514 * we go away */
3515
8a7c93d8
LP
3516 parent_pid = getpid();
3517
3518 /* First we temporarily block all signals, so that the new
3519 * child has them blocked initially. This way, we can be sure
3520 * that SIGTERMs are not lost we might send to the agent. */
3521 assert_se(sigfillset(&ss) >= 0);
3522 assert_se(sigprocmask(SIG_SETMASK, &ss, &saved_ss) >= 0);
3523
6bb92a16 3524 agent_pid = fork();
8a7c93d8
LP
3525 if (agent_pid < 0) {
3526 assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0);
6bb92a16 3527 return -errno;
8a7c93d8 3528 }
6bb92a16
LP
3529
3530 if (agent_pid != 0) {
8a7c93d8 3531 assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0);
6bb92a16
LP
3532 *pid = agent_pid;
3533 return 0;
3534 }
3535
3536 /* In the child:
3537 *
3538 * Make sure the agent goes away when the parent dies */
3539 if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
3540 _exit(EXIT_FAILURE);
3541
8a7c93d8
LP
3542 /* Make sure we actually can kill the agent, if we need to, in
3543 * case somebody invoked us from a shell script that trapped
3544 * SIGTERM or so... */
ce30c8dc
LP
3545 (void) reset_all_signal_handlers();
3546 (void) reset_signal_mask();
8a7c93d8 3547
6bb92a16 3548 /* Check whether our parent died before we were able
8a7c93d8 3549 * to set the death signal and unblock the signals */
6bb92a16
LP
3550 if (getppid() != parent_pid)
3551 _exit(EXIT_SUCCESS);
3552
3553 /* Don't leak fds to the agent */
9bdc770c 3554 close_all_fds(except, n_except);
6bb92a16
LP
3555
3556 stdout_is_tty = isatty(STDOUT_FILENO);
3557 stderr_is_tty = isatty(STDERR_FILENO);
3558
3559 if (!stdout_is_tty || !stderr_is_tty) {
8a7c93d8
LP
3560 int fd;
3561
6bb92a16
LP
3562 /* Detach from stdout/stderr. and reopen
3563 * /dev/tty for them. This is important to
3564 * ensure that when systemctl is started via
3565 * popen() or a similar call that expects to
3566 * read EOF we actually do generate EOF and
3567 * not delay this indefinitely by because we
3568 * keep an unused copy of stdin around. */
3569 fd = open("/dev/tty", O_WRONLY);
3570 if (fd < 0) {
56f64d95 3571 log_error_errno(errno, "Failed to open /dev/tty: %m");
6bb92a16
LP
3572 _exit(EXIT_FAILURE);
3573 }
3574
3575 if (!stdout_is_tty)
3576 dup2(fd, STDOUT_FILENO);
3577
3578 if (!stderr_is_tty)
3579 dup2(fd, STDERR_FILENO);
3580
3581 if (fd > 2)
3582 close(fd);
3583 }
3584
3585 /* Count arguments */
3586 va_start(ap, path);
3587 for (n = 0; va_arg(ap, char*); n++)
3588 ;
3589 va_end(ap);
3590
3591 /* Allocate strv */
3592 l = alloca(sizeof(char *) * (n + 1));
3593
3594 /* Fill in arguments */
3595 va_start(ap, path);
3596 for (i = 0; i <= n; i++)
3597 l[i] = va_arg(ap, char*);
3598 va_end(ap);
3599
3600 execv(path, l);
3601 _exit(EXIT_FAILURE);
3602}
68faf98c
LP
3603
3604int setrlimit_closest(int resource, const struct rlimit *rlim) {
3605 struct rlimit highest, fixed;
3606
3607 assert(rlim);
3608
3609 if (setrlimit(resource, rlim) >= 0)
3610 return 0;
3611
3612 if (errno != EPERM)
3613 return -errno;
3614
3615 /* So we failed to set the desired setrlimit, then let's try
3616 * to get as close as we can */
3617 assert_se(getrlimit(resource, &highest) == 0);
3618
3619 fixed.rlim_cur = MIN(rlim->rlim_cur, highest.rlim_max);
3620 fixed.rlim_max = MIN(rlim->rlim_max, highest.rlim_max);
3621
3622 if (setrlimit(resource, &fixed) < 0)
3623 return -errno;
3624
3625 return 0;
3626}
3d9a4122 3627
3d7415f4
LP
3628bool http_etag_is_valid(const char *etag) {
3629 if (isempty(etag))
3630 return false;
3631
3632 if (!endswith(etag, "\""))
3633 return false;
3634
3635 if (!startswith(etag, "\"") && !startswith(etag, "W/\""))
3636 return false;
3637
3638 return true;
3639}
3640
a2e03378
LP
3641bool http_url_is_valid(const char *url) {
3642 const char *p;
49dbfa7b 3643
a2e03378
LP
3644 if (isempty(url))
3645 return false;
49dbfa7b 3646
a2e03378
LP
3647 p = startswith(url, "http://");
3648 if (!p)
3649 p = startswith(url, "https://");
3650 if (!p)
3651 return false;
49dbfa7b 3652
a2e03378
LP
3653 if (isempty(p))
3654 return false;
49dbfa7b 3655
a2e03378
LP
3656 return ascii_is_valid(p);
3657}
49dbfa7b 3658
a2e03378
LP
3659bool documentation_url_is_valid(const char *url) {
3660 const char *p;
3661
3662 if (isempty(url))
3663 return false;
3664
3665 if (http_url_is_valid(url))
49dbfa7b
LP
3666 return true;
3667
a2e03378
LP
3668 p = startswith(url, "file:/");
3669 if (!p)
3670 p = startswith(url, "info:");
3671 if (!p)
3672 p = startswith(url, "man:");
3673
3674 if (isempty(p))
3675 return false;
3676
3677 return ascii_is_valid(p);
49dbfa7b 3678}
9be346c9
HH
3679
3680bool in_initrd(void) {
73020ab2 3681 static int saved = -1;
825c6fe5 3682 struct statfs s;
8f33b5b8 3683
825c6fe5
LP
3684 if (saved >= 0)
3685 return saved;
3686
3687 /* We make two checks here:
3688 *
3689 * 1. the flag file /etc/initrd-release must exist
3690 * 2. the root file system must be a memory file system
3691 *
3692 * The second check is extra paranoia, since misdetecting an
3693 * initrd can have bad bad consequences due the initrd
3694 * emptying when transititioning to the main systemd.
3695 */
3696
3697 saved = access("/etc/initrd-release", F_OK) >= 0 &&
3698 statfs("/", &s) >= 0 &&
943aad8c 3699 is_temporary_fs(&s);
9be346c9 3700
8f33b5b8 3701 return saved;
9be346c9 3702}
069cfc85 3703
7c5f152a 3704int get_home_dir(char **_h) {
2cfbd749 3705 struct passwd *p;
7c5f152a 3706 const char *e;
2cfbd749 3707 char *h;
7c5f152a 3708 uid_t u;
7c5f152a
LP
3709
3710 assert(_h);
3711
3712 /* Take the user specified one */
9a00f57a
LP
3713 e = secure_getenv("HOME");
3714 if (e && path_is_absolute(e)) {
7c5f152a
LP
3715 h = strdup(e);
3716 if (!h)
3717 return -ENOMEM;
3718
3719 *_h = h;
3720 return 0;
3721 }
3722
3723 /* Hardcode home directory for root to avoid NSS */
3724 u = getuid();
3725 if (u == 0) {
3726 h = strdup("/root");
3727 if (!h)
3728 return -ENOMEM;
3729
3730 *_h = h;
3731 return 0;
3732 }
3733
3734 /* Check the database... */
3735 errno = 0;
3736 p = getpwuid(u);
3737 if (!p)
bcb161b0 3738 return errno > 0 ? -errno : -ESRCH;
7c5f152a
LP
3739
3740 if (!path_is_absolute(p->pw_dir))
3741 return -EINVAL;
3742
3743 h = strdup(p->pw_dir);
3744 if (!h)
3745 return -ENOMEM;
3746
3747 *_h = h;
3748 return 0;
3749}
3750
2cfbd749
LP
3751int get_shell(char **_s) {
3752 struct passwd *p;
3753 const char *e;
3754 char *s;
3755 uid_t u;
3756
3757 assert(_s);
3758
3759 /* Take the user specified one */
3760 e = getenv("SHELL");
3761 if (e) {
3762 s = strdup(e);
3763 if (!s)
3764 return -ENOMEM;
3765
3766 *_s = s;
3767 return 0;
3768 }
3769
3770 /* Hardcode home directory for root to avoid NSS */
3771 u = getuid();
3772 if (u == 0) {
3773 s = strdup("/bin/sh");
3774 if (!s)
3775 return -ENOMEM;
3776
3777 *_s = s;
3778 return 0;
3779 }
3780
3781 /* Check the database... */
3782 errno = 0;
3783 p = getpwuid(u);
3784 if (!p)
3785 return errno > 0 ? -errno : -ESRCH;
3786
3787 if (!path_is_absolute(p->pw_shell))
3788 return -EINVAL;
3789
3790 s = strdup(p->pw_shell);
3791 if (!s)
3792 return -ENOMEM;
3793
3794 *_s = s;
3795 return 0;
3796}
3797
ae6c3cc0 3798bool filename_is_valid(const char *p) {
0b507b17
LP
3799
3800 if (isempty(p))
3801 return false;
3802
3803 if (strchr(p, '/'))
3804 return false;
3805
3806 if (streq(p, "."))
3807 return false;
3808
3809 if (streq(p, ".."))
3810 return false;
3811
3812 if (strlen(p) > FILENAME_MAX)
3813 return false;
3814
3815 return true;
3816}
3817
3818bool string_is_safe(const char *p) {
3819 const char *t;
3820
6294aa76
LP
3821 if (!p)
3822 return false;
0b507b17
LP
3823
3824 for (t = p; *t; t++) {
01539d6e 3825 if (*t > 0 && *t < ' ')
0b507b17
LP
3826 return false;
3827
843f6bf4 3828 if (strchr("\\\"\'\x7f", *t))
0b507b17
LP
3829 return false;
3830 }
3831
3832 return true;
3833}
cfbc22ab 3834
ac4c8d6d 3835/**
6294aa76
LP
3836 * Check if a string contains control characters. If 'ok' is non-NULL
3837 * it may be a string containing additional CCs to be considered OK.
ac4c8d6d 3838 */
6294aa76 3839bool string_has_cc(const char *p, const char *ok) {
4d1a6904
LP
3840 const char *t;
3841
3842 assert(p);
3843
3a8a9163 3844 for (t = p; *t; t++) {
6294aa76 3845 if (ok && strchr(ok, *t))
1cb1767a 3846 continue;
6294aa76
LP
3847
3848 if (*t > 0 && *t < ' ')
4d1a6904
LP
3849 return true;
3850
3a8a9163
LP
3851 if (*t == 127)
3852 return true;
3853 }
3854
4d1a6904
LP
3855 return false;
3856}
3857
e884315e
LP
3858bool path_is_safe(const char *p) {
3859
3860 if (isempty(p))
3861 return false;
3862
3863 if (streq(p, "..") || startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../"))
3864 return false;
3865
6442185a 3866 if (strlen(p)+1 > PATH_MAX)
e884315e
LP
3867 return false;
3868
3869 /* The following two checks are not really dangerous, but hey, they still are confusing */
3870 if (streq(p, ".") || startswith(p, "./") || endswith(p, "/.") || strstr(p, "/./"))
3871 return false;
3872
3873 if (strstr(p, "//"))
3874 return false;
3875
3876 return true;
3877}
3878
a9e12476
KS
3879/* hey glibc, APIs with callbacks without a user pointer are so useless */
3880void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
1c574591 3881 int (*compar) (const void *, const void *, void *), void *arg) {
a9e12476
KS
3882 size_t l, u, idx;
3883 const void *p;
3884 int comparison;
3885
3886 l = 0;
3887 u = nmemb;
3888 while (l < u) {
3889 idx = (l + u) / 2;
3890 p = (void *)(((const char *) base) + (idx * size));
3891 comparison = compar(key, p, arg);
3892 if (comparison < 0)
3893 u = idx;
3894 else if (comparison > 0)
3895 l = idx + 1;
3896 else
3897 return (void *)p;
3898 }
3899 return NULL;
3900}
09017585 3901
20f56fdd
DR
3902void init_gettext(void) {
3903 setlocale(LC_ALL, "");
3904 textdomain(GETTEXT_PACKAGE);
3905}
3906
09017585
MS
3907bool is_locale_utf8(void) {
3908 const char *set;
3909 static int cached_answer = -1;
3910
3911 if (cached_answer >= 0)
3912 goto out;
3913
3914 if (!setlocale(LC_ALL, "")) {
3915 cached_answer = true;
3916 goto out;
3917 }
3918
3919 set = nl_langinfo(CODESET);
3920 if (!set) {
3921 cached_answer = true;
3922 goto out;
3923 }
3924
f168c273 3925 if (streq(set, "UTF-8")) {
fee79e01
HH
3926 cached_answer = true;
3927 goto out;
3928 }
3929
6cf2f1d9
HH
3930 /* For LC_CTYPE=="C" return true, because CTYPE is effectly
3931 * unset and everything can do to UTF-8 nowadays. */
fee79e01
HH
3932 set = setlocale(LC_CTYPE, NULL);
3933 if (!set) {
3934 cached_answer = true;
3935 goto out;
3936 }
3937
6cf2f1d9
HH
3938 /* Check result, but ignore the result if C was set
3939 * explicitly. */
3940 cached_answer =
9797f89b 3941 STR_IN_SET(set, "C", "POSIX") &&
6cf2f1d9
HH
3942 !getenv("LC_ALL") &&
3943 !getenv("LC_CTYPE") &&
3944 !getenv("LANG");
fee79e01 3945
09017585 3946out:
6cf2f1d9 3947 return (bool) cached_answer;
09017585 3948}
c339d977
MS
3949
3950const char *draw_special_char(DrawSpecialChar ch) {
3951 static const char *draw_table[2][_DRAW_SPECIAL_CHAR_MAX] = {
6b01f1d3 3952
c339d977 3953 /* UTF-8 */ {
6b01f1d3 3954 [DRAW_TREE_VERTICAL] = "\342\224\202 ", /* │ */
45a5ff0d
MS
3955 [DRAW_TREE_BRANCH] = "\342\224\234\342\224\200", /* ├─ */
3956 [DRAW_TREE_RIGHT] = "\342\224\224\342\224\200", /* └─ */
55c0b89c 3957 [DRAW_TREE_SPACE] = " ", /* */
6b01f1d3
LP
3958 [DRAW_TRIANGULAR_BULLET] = "\342\200\243", /* ‣ */
3959 [DRAW_BLACK_CIRCLE] = "\342\227\217", /* ● */
3960 [DRAW_ARROW] = "\342\206\222", /* → */
13f8b8cb 3961 [DRAW_DASH] = "\342\200\223", /* – */
c339d977 3962 },
6b01f1d3 3963
c339d977 3964 /* ASCII fallback */ {
6b01f1d3 3965 [DRAW_TREE_VERTICAL] = "| ",
45a5ff0d
MS
3966 [DRAW_TREE_BRANCH] = "|-",
3967 [DRAW_TREE_RIGHT] = "`-",
55c0b89c 3968 [DRAW_TREE_SPACE] = " ",
6b01f1d3
LP
3969 [DRAW_TRIANGULAR_BULLET] = ">",
3970 [DRAW_BLACK_CIRCLE] = "*",
3971 [DRAW_ARROW] = "->",
13f8b8cb 3972 [DRAW_DASH] = "-",
c339d977
MS
3973 }
3974 };
3975
3976 return draw_table[!is_locale_utf8()][ch];
3977}
409bc9c3
LP
3978
3979char *strreplace(const char *text, const char *old_string, const char *new_string) {
3980 const char *f;
3981 char *t, *r;
3982 size_t l, old_len, new_len;
3983
3984 assert(text);
3985 assert(old_string);
3986 assert(new_string);
3987
3988 old_len = strlen(old_string);
3989 new_len = strlen(new_string);
3990
3991 l = strlen(text);
3992 r = new(char, l+1);
3993 if (!r)
3994 return NULL;
3995
3996 f = text;
3997 t = r;
3998 while (*f) {
3999 char *a;
4000 size_t d, nl;
4001
4002 if (!startswith(f, old_string)) {
4003 *(t++) = *(f++);
4004 continue;
4005 }
4006
4007 d = t - r;
4008 nl = l - old_len + new_len;
4009 a = realloc(r, nl + 1);
4010 if (!a)
4011 goto oom;
4012
4013 l = nl;
4014 r = a;
4015 t = r + d;
4016
4017 t = stpcpy(t, new_string);
4018 f += old_len;
4019 }
4020
4021 *t = 0;
4022 return r;
4023
4024oom:
4025 free(r);
4026 return NULL;
4027}
e8bc0ea2
LP
4028
4029char *strip_tab_ansi(char **ibuf, size_t *_isz) {
660ddc72 4030 const char *i, *begin = NULL;
e8bc0ea2
LP
4031 enum {
4032 STATE_OTHER,
4033 STATE_ESCAPE,
4034 STATE_BRACKET
4035 } state = STATE_OTHER;
4036 char *obuf = NULL;
4037 size_t osz = 0, isz;
4038 FILE *f;
4039
4040 assert(ibuf);
4041 assert(*ibuf);
4042
4043 /* Strips ANSI color and replaces TABs by 8 spaces */
4044
4045 isz = _isz ? *_isz : strlen(*ibuf);
4046
4047 f = open_memstream(&obuf, &osz);
4048 if (!f)
4049 return NULL;
4050
4051 for (i = *ibuf; i < *ibuf + isz + 1; i++) {
4052
4053 switch (state) {
4054
4055 case STATE_OTHER:
4056 if (i >= *ibuf + isz) /* EOT */
4057 break;
4058 else if (*i == '\x1B')
4059 state = STATE_ESCAPE;
4060 else if (*i == '\t')
4061 fputs(" ", f);
4062 else
4063 fputc(*i, f);
4064 break;
4065
4066 case STATE_ESCAPE:
4067 if (i >= *ibuf + isz) { /* EOT */
4068 fputc('\x1B', f);
4069 break;
4070 } else if (*i == '[') {
4071 state = STATE_BRACKET;
4072 begin = i + 1;
4073 } else {
4074 fputc('\x1B', f);
4075 fputc(*i, f);
4076 state = STATE_OTHER;
4077 }
4078
4079 break;
4080
4081 case STATE_BRACKET:
4082
4083 if (i >= *ibuf + isz || /* EOT */
4084 (!(*i >= '0' && *i <= '9') && *i != ';' && *i != 'm')) {
4085 fputc('\x1B', f);
4086 fputc('[', f);
4087 state = STATE_OTHER;
4088 i = begin-1;
4089 } else if (*i == 'm')
4090 state = STATE_OTHER;
4091 break;
4092 }
4093 }
4094
4095 if (ferror(f)) {
4096 fclose(f);
4097 free(obuf);
4098 return NULL;
4099 }
4100
4101 fclose(f);
4102
4103 free(*ibuf);
4104 *ibuf = obuf;
4105
4106 if (_isz)
4107 *_isz = osz;
4108
4109 return obuf;
4110}
240dbaa4
LP
4111
4112int on_ac_power(void) {
4113 bool found_offline = false, found_online = false;
4114 _cleanup_closedir_ DIR *d = NULL;
4115
4116 d = opendir("/sys/class/power_supply");
4117 if (!d)
6d890034 4118 return errno == ENOENT ? true : -errno;
240dbaa4
LP
4119
4120 for (;;) {
4121 struct dirent *de;
240dbaa4
LP
4122 _cleanup_close_ int fd = -1, device = -1;
4123 char contents[6];
4124 ssize_t n;
240dbaa4 4125
3fd11280
FW
4126 errno = 0;
4127 de = readdir(d);
4128 if (!de && errno != 0)
4129 return -errno;
240dbaa4
LP
4130
4131 if (!de)
4132 break;
4133
a34bf9db 4134 if (hidden_file(de->d_name))
240dbaa4
LP
4135 continue;
4136
4137 device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY);
4138 if (device < 0) {
4139 if (errno == ENOENT || errno == ENOTDIR)
4140 continue;
4141
4142 return -errno;
4143 }
4144
4145 fd = openat(device, "type", O_RDONLY|O_CLOEXEC|O_NOCTTY);
4146 if (fd < 0) {
4147 if (errno == ENOENT)
4148 continue;
4149
4150 return -errno;
4151 }
4152
4153 n = read(fd, contents, sizeof(contents));
4154 if (n < 0)
4155 return -errno;
4156
4157 if (n != 6 || memcmp(contents, "Mains\n", 6))
4158 continue;
4159
03e334a1 4160 safe_close(fd);
240dbaa4
LP
4161 fd = openat(device, "online", O_RDONLY|O_CLOEXEC|O_NOCTTY);
4162 if (fd < 0) {
4163 if (errno == ENOENT)
4164 continue;
4165
4166 return -errno;
4167 }
4168
4169 n = read(fd, contents, sizeof(contents));
4170 if (n < 0)
4171 return -errno;
4172
4173 if (n != 2 || contents[1] != '\n')
4174 return -EIO;
4175
4176 if (contents[0] == '1') {
4177 found_online = true;
4178 break;
4179 } else if (contents[0] == '0')
4180 found_offline = true;
4181 else
4182 return -EIO;
4183 }
4184
4185 return found_online || !found_offline;
4186}
fabe5c0e 4187
4cf7ea55 4188static int search_and_fopen_internal(const char *path, const char *mode, const char *root, char **search, FILE **_f) {
fabe5c0e
LP
4189 char **i;
4190
4191 assert(path);
4192 assert(mode);
4193 assert(_f);
4194
7d8da2c9 4195 if (!path_strv_resolve_uniq(search, root))
fabe5c0e
LP
4196 return -ENOMEM;
4197
4198 STRV_FOREACH(i, search) {
4199 _cleanup_free_ char *p = NULL;
4200 FILE *f;
4201
375eadd9
MM
4202 if (root)
4203 p = strjoin(root, *i, "/", path, NULL);
4204 else
4205 p = strjoin(*i, "/", path, NULL);
fabe5c0e
LP
4206 if (!p)
4207 return -ENOMEM;
4208
4209 f = fopen(p, mode);
4210 if (f) {
4211 *_f = f;
4212 return 0;
4213 }
4214
4215 if (errno != ENOENT)
4216 return -errno;
4217 }
4218
4219 return -ENOENT;
4220}
4221
4cf7ea55 4222int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f) {
fabe5c0e
LP
4223 _cleanup_strv_free_ char **copy = NULL;
4224
4225 assert(path);
4226 assert(mode);
4227 assert(_f);
4228
4229 if (path_is_absolute(path)) {
4230 FILE *f;
4231
4232 f = fopen(path, mode);
4233 if (f) {
4234 *_f = f;
4235 return 0;
4236 }
4237
4238 return -errno;
4239 }
4240
4241 copy = strv_copy((char**) search);
4242 if (!copy)
4243 return -ENOMEM;
4244
4cf7ea55 4245 return search_and_fopen_internal(path, mode, root, copy, _f);
fabe5c0e
LP
4246}
4247
4cf7ea55 4248int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f) {
fabe5c0e
LP
4249 _cleanup_strv_free_ char **s = NULL;
4250
4251 if (path_is_absolute(path)) {
4252 FILE *f;
4253
4254 f = fopen(path, mode);
4255 if (f) {
4256 *_f = f;
4257 return 0;
4258 }
4259
4260 return -errno;
4261 }
4262
4263 s = strv_split_nulstr(search);
4264 if (!s)
4265 return -ENOMEM;
4266
4cf7ea55 4267 return search_and_fopen_internal(path, mode, root, s, _f);
fabe5c0e 4268}
c17ec25e 4269
66e35261
LP
4270char *strextend(char **x, ...) {
4271 va_list ap;
4272 size_t f, l;
4273 char *r, *p;
4274
4275 assert(x);
4276
4277 l = f = *x ? strlen(*x) : 0;
4278
4279 va_start(ap, x);
4280 for (;;) {
4281 const char *t;
4282 size_t n;
4283
4284 t = va_arg(ap, const char *);
4285 if (!t)
4286 break;
4287
4288 n = strlen(t);
4289 if (n > ((size_t) -1) - l) {
4290 va_end(ap);
4291 return NULL;
4292 }
4293
4294 l += n;
4295 }
4296 va_end(ap);
4297
4298 r = realloc(*x, l+1);
4299 if (!r)
4300 return NULL;
4301
4302 p = r + f;
4303
4304 va_start(ap, x);
4305 for (;;) {
4306 const char *t;
4307
4308 t = va_arg(ap, const char *);
4309 if (!t)
4310 break;
4311
4312 p = stpcpy(p, t);
4313 }
4314 va_end(ap);
4315
4316 *p = 0;
4317 *x = r;
4318
4319 return r + l;
4320}
9a17484d
LP
4321
4322char *strrep(const char *s, unsigned n) {
4323 size_t l;
4324 char *r, *p;
4325 unsigned i;
4326
4327 assert(s);
4328
4329 l = strlen(s);
4330 p = r = malloc(l * n + 1);
4331 if (!r)
4332 return NULL;
4333
4334 for (i = 0; i < n; i++)
4335 p = stpcpy(p, s);
4336
4337 *p = 0;
4338 return r;
4339}
392d5b37 4340
ca2d3784
ZJS
4341void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) {
4342 size_t a, newalloc;
392d5b37
LP
4343 void *q;
4344
98088803 4345 assert(p);
e93c33d4
SL
4346 assert(allocated);
4347
392d5b37
LP
4348 if (*allocated >= need)
4349 return *p;
4350
ca2d3784
ZJS
4351 newalloc = MAX(need * 2, 64u / size);
4352 a = newalloc * size;
98088803
LP
4353
4354 /* check for overflows */
ca2d3784 4355 if (a < size * need)
98088803
LP
4356 return NULL;
4357
392d5b37
LP
4358 q = realloc(*p, a);
4359 if (!q)
4360 return NULL;
4361
4362 *p = q;
ca2d3784 4363 *allocated = newalloc;
392d5b37
LP
4364 return q;
4365}
aa96c6cb 4366
ca2d3784 4367void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size) {
98088803 4368 size_t prev;
4545a231
DH
4369 uint8_t *q;
4370
98088803
LP
4371 assert(p);
4372 assert(allocated);
4373
4374 prev = *allocated;
4375
ca2d3784 4376 q = greedy_realloc(p, allocated, need, size);
4545a231
DH
4377 if (!q)
4378 return NULL;
4379
4380 if (*allocated > prev)
ca2d3784 4381 memzero(q + prev * size, (*allocated - prev) * size);
4545a231
DH
4382
4383 return q;
4384}
4385
aa96c6cb
LP
4386bool id128_is_valid(const char *s) {
4387 size_t i, l;
4388
4389 l = strlen(s);
4390 if (l == 32) {
4391
4392 /* Simple formatted 128bit hex string */
4393
4394 for (i = 0; i < l; i++) {
4395 char c = s[i];
4396
4397 if (!(c >= '0' && c <= '9') &&
4398 !(c >= 'a' && c <= 'z') &&
4399 !(c >= 'A' && c <= 'Z'))
4400 return false;
4401 }
4402
4403 } else if (l == 36) {
4404
4405 /* Formatted UUID */
4406
4407 for (i = 0; i < l; i++) {
4408 char c = s[i];
4409
4410 if ((i == 8 || i == 13 || i == 18 || i == 23)) {
4411 if (c != '-')
4412 return false;
4413 } else {
4414 if (!(c >= '0' && c <= '9') &&
4415 !(c >= 'a' && c <= 'z') &&
4416 !(c >= 'A' && c <= 'Z'))
4417 return false;
4418 }
4419 }
4420
4421 } else
4422 return false;
4423
4424 return true;
4425}
7085053a 4426
d4ac85c6
LP
4427int split_pair(const char *s, const char *sep, char **l, char **r) {
4428 char *x, *a, *b;
4429
4430 assert(s);
4431 assert(sep);
4432 assert(l);
4433 assert(r);
4434
4435 if (isempty(sep))
4436 return -EINVAL;
4437
4438 x = strstr(s, sep);
4439 if (!x)
4440 return -EINVAL;
4441
4442 a = strndup(s, x - s);
4443 if (!a)
4444 return -ENOMEM;
4445
4446 b = strdup(x + strlen(sep));
4447 if (!b) {
4448 free(a);
4449 return -ENOMEM;
4450 }
4451
4452 *l = a;
4453 *r = b;
4454
4455 return 0;
4456}
295edddf 4457
74df0fca 4458int shall_restore_state(void) {
1a299299 4459 _cleanup_free_ char *value = NULL;
74df0fca 4460 int r;
295edddf 4461
1a299299 4462 r = get_proc_cmdline_key("systemd.restore_state=", &value);
74df0fca
LP
4463 if (r < 0)
4464 return r;
1a299299
LP
4465 if (r == 0)
4466 return true;
295edddf 4467
1a299299 4468 return parse_boolean(value) != 0;
74df0fca
LP
4469}
4470
4471int proc_cmdline(char **ret) {
b5884878 4472 assert(ret);
295edddf 4473
75f86906 4474 if (detect_container() > 0)
b5884878
LP
4475 return get_process_cmdline(1, 0, false, ret);
4476 else
4477 return read_one_line_file("/proc/cmdline", ret);
295edddf 4478}
bc9fd78c 4479
059cb385 4480int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) {
141a79f4 4481 _cleanup_free_ char *line = NULL;
f32d2db1 4482 const char *p;
141a79f4
ZJS
4483 int r;
4484
059cb385
LP
4485 assert(parse_item);
4486
141a79f4
ZJS
4487 r = proc_cmdline(&line);
4488 if (r < 0)
b5884878 4489 return r;
141a79f4 4490
f32d2db1
LP
4491 p = line;
4492 for (;;) {
4493 _cleanup_free_ char *word = NULL;
4494 char *value = NULL;
141a79f4 4495
12ba2c44 4496 r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX);
f32d2db1
LP
4497 if (r < 0)
4498 return r;
4499 if (r == 0)
4500 break;
141a79f4 4501
059cb385
LP
4502 /* Filter out arguments that are intended only for the
4503 * initrd */
4504 if (!in_initrd() && startswith(word, "rd."))
4505 continue;
4506
4507 value = strchr(word, '=');
4508 if (value)
4509 *(value++) = 0;
4510
4511 r = parse_item(word, value);
4512 if (r < 0)
141a79f4 4513 return r;
141a79f4
ZJS
4514 }
4515
4516 return 0;
4517}
4518
1a299299
LP
4519int get_proc_cmdline_key(const char *key, char **value) {
4520 _cleanup_free_ char *line = NULL, *ret = NULL;
4521 bool found = false;
4522 const char *p;
4523 int r;
4524
4525 assert(key);
4526
4527 r = proc_cmdline(&line);
4528 if (r < 0)
4529 return r;
4530
4531 p = line;
4532 for (;;) {
4533 _cleanup_free_ char *word = NULL;
4534 const char *e;
4535
12ba2c44 4536 r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX);
1a299299
LP
4537 if (r < 0)
4538 return r;
4539 if (r == 0)
4540 break;
4541
4542 /* Filter out arguments that are intended only for the
4543 * initrd */
4544 if (!in_initrd() && startswith(word, "rd."))
4545 continue;
4546
4547 if (value) {
4548 e = startswith(word, key);
4549 if (!e)
4550 continue;
4551
4552 r = free_and_strdup(&ret, e);
4553 if (r < 0)
4554 return r;
4555
4556 found = true;
4557 } else {
4558 if (streq(word, key))
4559 found = true;
4560 }
4561 }
4562
4563 if (value) {
4564 *value = ret;
4565 ret = NULL;
4566 }
4567
4568 return found;
4569
4570}
4571
bc9fd78c
LP
4572int container_get_leader(const char *machine, pid_t *pid) {
4573 _cleanup_free_ char *s = NULL, *class = NULL;
4574 const char *p;
4575 pid_t leader;
4576 int r;
4577
4578 assert(machine);
4579 assert(pid);
4580
b9a8d250
LP
4581 if (!machine_name_is_valid(machine))
4582 return -EINVAL;
4583
63c372cb 4584 p = strjoina("/run/systemd/machines/", machine);
bc9fd78c
LP
4585 r = parse_env_file(p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL);
4586 if (r == -ENOENT)
4587 return -EHOSTDOWN;
4588 if (r < 0)
4589 return r;
4590 if (!s)
4591 return -EIO;
4592
4593 if (!streq_ptr(class, "container"))
4594 return -EIO;
4595
4596 r = parse_pid(s, &leader);
4597 if (r < 0)
4598 return r;
4599 if (leader <= 1)
4600 return -EIO;
4601
4602 *pid = leader;
4603 return 0;
4604}
4605
671c3419
RM
4606int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd) {
4607 _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, netnsfd = -1, usernsfd = -1;
359a06aa 4608 int rfd = -1;
bc9fd78c
LP
4609
4610 assert(pid >= 0);
bc9fd78c 4611
878cd7e9
LP
4612 if (mntns_fd) {
4613 const char *mntns;
a4475f57 4614
878cd7e9
LP
4615 mntns = procfs_file_alloca(pid, "ns/mnt");
4616 mntnsfd = open(mntns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
4617 if (mntnsfd < 0)
4618 return -errno;
4619 }
bc9fd78c 4620
878cd7e9
LP
4621 if (pidns_fd) {
4622 const char *pidns;
4623
4624 pidns = procfs_file_alloca(pid, "ns/pid");
4625 pidnsfd = open(pidns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
4626 if (pidnsfd < 0)
4627 return -errno;
4628 }
4629
4630 if (netns_fd) {
4631 const char *netns;
4632
4633 netns = procfs_file_alloca(pid, "ns/net");
4634 netnsfd = open(netns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
4635 if (netnsfd < 0)
4636 return -errno;
4637 }
4638
671c3419
RM
4639 if (userns_fd) {
4640 const char *userns;
4641
4642 userns = procfs_file_alloca(pid, "ns/user");
4643 usernsfd = open(userns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
4644 if (usernsfd < 0 && errno != ENOENT)
4645 return -errno;
4646 }
4647
878cd7e9
LP
4648 if (root_fd) {
4649 const char *root;
4650
4651 root = procfs_file_alloca(pid, "root");
4652 rfd = open(root, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
4653 if (rfd < 0)
4654 return -errno;
4655 }
4656
4657 if (pidns_fd)
4658 *pidns_fd = pidnsfd;
bc9fd78c 4659
878cd7e9
LP
4660 if (mntns_fd)
4661 *mntns_fd = mntnsfd;
4662
4663 if (netns_fd)
4664 *netns_fd = netnsfd;
4665
671c3419
RM
4666 if (userns_fd)
4667 *userns_fd = usernsfd;
4668
878cd7e9
LP
4669 if (root_fd)
4670 *root_fd = rfd;
4671
671c3419 4672 pidnsfd = mntnsfd = netnsfd = usernsfd = -1;
bc9fd78c
LP
4673
4674 return 0;
4675}
4676
671c3419
RM
4677int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd) {
4678 if (userns_fd >= 0) {
4679 /* Can't setns to your own userns, since then you could
4680 * escalate from non-root to root in your own namespace, so
4681 * check if namespaces equal before attempting to enter. */
4682 _cleanup_free_ char *userns_fd_path = NULL;
4683 int r;
4684 if (asprintf(&userns_fd_path, "/proc/self/fd/%d", userns_fd) < 0)
4685 return -ENOMEM;
4686
4687 r = files_same(userns_fd_path, "/proc/self/ns/user");
4688 if (r < 0)
4689 return r;
4690 if (r)
4691 userns_fd = -1;
4692 }
bc9fd78c 4693
878cd7e9
LP
4694 if (pidns_fd >= 0)
4695 if (setns(pidns_fd, CLONE_NEWPID) < 0)
4696 return -errno;
a4475f57 4697
878cd7e9
LP
4698 if (mntns_fd >= 0)
4699 if (setns(mntns_fd, CLONE_NEWNS) < 0)
4700 return -errno;
bc9fd78c 4701
878cd7e9
LP
4702 if (netns_fd >= 0)
4703 if (setns(netns_fd, CLONE_NEWNET) < 0)
4704 return -errno;
bc9fd78c 4705
671c3419
RM
4706 if (userns_fd >= 0)
4707 if (setns(userns_fd, CLONE_NEWUSER) < 0)
4708 return -errno;
4709
878cd7e9
LP
4710 if (root_fd >= 0) {
4711 if (fchdir(root_fd) < 0)
4712 return -errno;
4713
4714 if (chroot(".") < 0)
4715 return -errno;
4716 }
bc9fd78c 4717
b4da6d6b 4718 return reset_uid_gid();
bc9fd78c 4719}
bf108e55 4720
eff05270
LP
4721int getpeercred(int fd, struct ucred *ucred) {
4722 socklen_t n = sizeof(struct ucred);
4723 struct ucred u;
4724 int r;
4725
4726 assert(fd >= 0);
4727 assert(ucred);
4728
4729 r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &u, &n);
4730 if (r < 0)
4731 return -errno;
4732
4733 if (n != sizeof(struct ucred))
4734 return -EIO;
4735
4736 /* Check if the data is actually useful and not suppressed due
4737 * to namespacing issues */
4738 if (u.pid <= 0)
4739 return -ENODATA;
fed1e721 4740 if (u.uid == UID_INVALID)
62028d9c 4741 return -ENODATA;
fed1e721 4742 if (u.gid == GID_INVALID)
62028d9c 4743 return -ENODATA;
eff05270
LP
4744
4745 *ucred = u;
4746 return 0;
4747}
4748
4749int getpeersec(int fd, char **ret) {
4750 socklen_t n = 64;
4751 char *s;
4752 int r;
4753
4754 assert(fd >= 0);
4755 assert(ret);
4756
4757 s = new0(char, n);
4758 if (!s)
4759 return -ENOMEM;
4760
4761 r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
4762 if (r < 0) {
4763 free(s);
4764
4765 if (errno != ERANGE)
4766 return -errno;
4767
4768 s = new0(char, n);
4769 if (!s)
4770 return -ENOMEM;
4771
4772 r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
4773 if (r < 0) {
4774 free(s);
4775 return -errno;
4776 }
4777 }
4778
ae98841e
LP
4779 if (isempty(s)) {
4780 free(s);
15411c0c 4781 return -EOPNOTSUPP;
ae98841e
LP
4782 }
4783
eff05270
LP
4784 *ret = s;
4785 return 0;
4786}
8e33886e 4787
0f010ef2 4788/* This is much like like mkostemp() but is subject to umask(). */
65b3903f 4789int mkostemp_safe(char *pattern, int flags) {
2d5bdf5b 4790 _cleanup_umask_ mode_t u;
0f010ef2 4791 int fd;
65b3903f 4792
d37a91e8 4793 assert(pattern);
65b3903f 4794
2d5bdf5b
LP
4795 u = umask(077);
4796
0f010ef2
ZJS
4797 fd = mkostemp(pattern, flags);
4798 if (fd < 0)
4799 return -errno;
65b3903f 4800
0f010ef2 4801 return fd;
65b3903f
ZJS
4802}
4803
8e33886e 4804int open_tmpfile(const char *path, int flags) {
8e33886e 4805 char *p;
a6afc4ae
LP
4806 int fd;
4807
4808 assert(path);
8e33886e
ZJS
4809
4810#ifdef O_TMPFILE
7736202c 4811 /* Try O_TMPFILE first, if it is supported */
a765f344 4812 fd = open(path, flags|O_TMPFILE|O_EXCL, S_IRUSR|S_IWUSR);
8e33886e
ZJS
4813 if (fd >= 0)
4814 return fd;
4815#endif
7736202c
LP
4816
4817 /* Fall back to unguessable name + unlinking */
63c372cb 4818 p = strjoina(path, "/systemd-tmp-XXXXXX");
8e33886e 4819
a6afc4ae 4820 fd = mkostemp_safe(p, flags);
8e33886e 4821 if (fd < 0)
65b3903f 4822 return fd;
8e33886e
ZJS
4823
4824 unlink(p);
4825 return fd;
4826}
fdb9161c
LP
4827
4828int fd_warn_permissions(const char *path, int fd) {
4829 struct stat st;
4830
4831 if (fstat(fd, &st) < 0)
4832 return -errno;
4833
4834 if (st.st_mode & 0111)
4835 log_warning("Configuration file %s is marked executable. Please remove executable permission bits. Proceeding anyway.", path);
4836
4837 if (st.st_mode & 0002)
4838 log_warning("Configuration file %s is marked world-writable. Please remove world writability permission bits. Proceeding anyway.", path);
4839
4840 if (getpid() == 1 && (st.st_mode & 0044) != 0044)
4841 log_warning("Configuration file %s is marked world-inaccessible. This has no effect as configuration data is accessible via APIs without restrictions. Proceeding anyway.", path);
4842
4843 return 0;
4844}
6afc95b7 4845
ac45f971 4846unsigned long personality_from_string(const char *p) {
6afc95b7
LP
4847
4848 /* Parse a personality specifier. We introduce our own
4849 * identifiers that indicate specific ABIs, rather than just
4850 * hints regarding the register size, since we want to keep
4851 * things open for multiple locally supported ABIs for the
4852 * same register size. We try to reuse the ABI identifiers
4853 * used by libseccomp. */
4854
4855#if defined(__x86_64__)
4856
4857 if (streq(p, "x86"))
4858 return PER_LINUX32;
4859
4860 if (streq(p, "x86-64"))
4861 return PER_LINUX;
4862
4863#elif defined(__i386__)
4864
4865 if (streq(p, "x86"))
4866 return PER_LINUX;
7517f51e
HB
4867
4868#elif defined(__s390x__)
4869
4870 if (streq(p, "s390"))
4871 return PER_LINUX32;
4872
4873 if (streq(p, "s390x"))
4874 return PER_LINUX;
4875
4876#elif defined(__s390__)
4877
4878 if (streq(p, "s390"))
4879 return PER_LINUX;
6afc95b7
LP
4880#endif
4881
050f7277 4882 return PERSONALITY_INVALID;
6afc95b7 4883}
ac45f971
LP
4884
4885const char* personality_to_string(unsigned long p) {
4886
4887#if defined(__x86_64__)
4888
4889 if (p == PER_LINUX32)
4890 return "x86";
4891
4892 if (p == PER_LINUX)
4893 return "x86-64";
4894
4895#elif defined(__i386__)
4896
4897 if (p == PER_LINUX)
4898 return "x86";
7517f51e
HB
4899
4900#elif defined(__s390x__)
4901
4902 if (p == PER_LINUX)
4903 return "s390x";
4904
4905 if (p == PER_LINUX32)
4906 return "s390";
4907
4908#elif defined(__s390__)
4909
4910 if (p == PER_LINUX)
4911 return "s390";
4912
ac45f971
LP
4913#endif
4914
4915 return NULL;
4916}
1c231f56
LP
4917
4918uint64_t physical_memory(void) {
4919 long mem;
4920
4921 /* We return this as uint64_t in case we are running as 32bit
4922 * process on a 64bit kernel with huge amounts of memory */
4923
4924 mem = sysconf(_SC_PHYS_PAGES);
4925 assert(mem > 0);
4926
4927 return (uint64_t) mem * (uint64_t) page_size();
4928}
6db615c1 4929
29bfbcd6
LP
4930void hexdump(FILE *f, const void *p, size_t s) {
4931 const uint8_t *b = p;
4932 unsigned n = 0;
4933
4934 assert(s == 0 || b);
4935
4936 while (s > 0) {
4937 size_t i;
4938
4939 fprintf(f, "%04x ", n);
4940
4941 for (i = 0; i < 16; i++) {
4942
4943 if (i >= s)
4944 fputs(" ", f);
4945 else
4946 fprintf(f, "%02x ", b[i]);
4947
4948 if (i == 7)
4949 fputc(' ', f);
4950 }
4951
4952 fputc(' ', f);
4953
4954 for (i = 0; i < 16; i++) {
4955
4956 if (i >= s)
4957 fputc(' ', f);
4958 else
4959 fputc(isprint(b[i]) ? (char) b[i] : '.', f);
4960 }
4961
4962 fputc('\n', f);
4963
4964 if (s < 16)
4965 break;
4966
4967 n += 16;
4968 b += 16;
4969 s -= 16;
4970 }
4971}
c5220a94 4972
966bff26 4973int update_reboot_param_file(const char *param) {
c5220a94
MO
4974 int r = 0;
4975
4976 if (param) {
4c1fc3e4 4977 r = write_string_file(REBOOT_PARAM_FILE, param, WRITE_STRING_FILE_CREATE);
c5220a94 4978 if (r < 0)
e53fc357 4979 return log_error_errno(r, "Failed to write reboot param to "REBOOT_PARAM_FILE": %m");
c5220a94 4980 } else
e53fc357 4981 (void) unlink(REBOOT_PARAM_FILE);
c5220a94 4982
e53fc357 4983 return 0;
c5220a94 4984}
6d313367
LP
4985
4986int umount_recursive(const char *prefix, int flags) {
4987 bool again;
4988 int n = 0, r;
4989
4990 /* Try to umount everything recursively below a
4991 * directory. Also, take care of stacked mounts, and keep
4992 * unmounting them until they are gone. */
4993
4994 do {
4995 _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
4996
4997 again = false;
4998 r = 0;
4999
5000 proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
5001 if (!proc_self_mountinfo)
5002 return -errno;
5003
5004 for (;;) {
5005 _cleanup_free_ char *path = NULL, *p = NULL;
5006 int k;
5007
5008 k = fscanf(proc_self_mountinfo,
5009 "%*s " /* (1) mount id */
5010 "%*s " /* (2) parent id */
5011 "%*s " /* (3) major:minor */
5012 "%*s " /* (4) root */
5013 "%ms " /* (5) mount point */
5014 "%*s" /* (6) mount options */
5015 "%*[^-]" /* (7) optional fields */
5016 "- " /* (8) separator */
5017 "%*s " /* (9) file system type */
5018 "%*s" /* (10) mount source */
5019 "%*s" /* (11) mount options 2 */
5020 "%*[^\n]", /* some rubbish at the end */
5021 &path);
6d313367
LP
5022 if (k != 1) {
5023 if (k == EOF)
5024 break;
5025
5026 continue;
5027 }
5028
527b7a42
LP
5029 r = cunescape(path, UNESCAPE_RELAX, &p);
5030 if (r < 0)
5031 return r;
6d313367
LP
5032
5033 if (!path_startswith(p, prefix))
5034 continue;
5035
5036 if (umount2(p, flags) < 0) {
5037 r = -errno;
5038 continue;
5039 }
5040
5041 again = true;
5042 n++;
5043
5044 break;
5045 }
5046
5047 } while (again);
5048
5049 return r ? r : n;
5050}
d6797c92 5051
abe4aa14
TM
5052static int get_mount_flags(const char *path, unsigned long *flags) {
5053 struct statvfs buf;
5054
5055 if (statvfs(path, &buf) < 0)
5056 return -errno;
5057 *flags = buf.f_flag;
5058 return 0;
5059}
5060
d6797c92
LP
5061int bind_remount_recursive(const char *prefix, bool ro) {
5062 _cleanup_set_free_free_ Set *done = NULL;
5063 _cleanup_free_ char *cleaned = NULL;
5064 int r;
5065
5066 /* Recursively remount a directory (and all its submounts)
5067 * read-only or read-write. If the directory is already
5068 * mounted, we reuse the mount and simply mark it
5069 * MS_BIND|MS_RDONLY (or remove the MS_RDONLY for read-write
5070 * operation). If it isn't we first make it one. Afterwards we
5071 * apply MS_BIND|MS_RDONLY (or remove MS_RDONLY) to all
5072 * submounts we can access, too. When mounts are stacked on
5073 * the same mount point we only care for each individual
5074 * "top-level" mount on each point, as we cannot
5075 * influence/access the underlying mounts anyway. We do not
5076 * have any effect on future submounts that might get
5077 * propagated, they migt be writable. This includes future
5078 * submounts that have been triggered via autofs. */
5079
5080 cleaned = strdup(prefix);
5081 if (!cleaned)
5082 return -ENOMEM;
5083
5084 path_kill_slashes(cleaned);
5085
d5099efc 5086 done = set_new(&string_hash_ops);
d6797c92
LP
5087 if (!done)
5088 return -ENOMEM;
5089
5090 for (;;) {
5091 _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
5092 _cleanup_set_free_free_ Set *todo = NULL;
5093 bool top_autofs = false;
5094 char *x;
abe4aa14 5095 unsigned long orig_flags;
d6797c92 5096
d5099efc 5097 todo = set_new(&string_hash_ops);
d6797c92
LP
5098 if (!todo)
5099 return -ENOMEM;
5100
5101 proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
5102 if (!proc_self_mountinfo)
5103 return -errno;
5104
5105 for (;;) {
5106 _cleanup_free_ char *path = NULL, *p = NULL, *type = NULL;
5107 int k;
5108
5109 k = fscanf(proc_self_mountinfo,
5110 "%*s " /* (1) mount id */
5111 "%*s " /* (2) parent id */
5112 "%*s " /* (3) major:minor */
5113 "%*s " /* (4) root */
5114 "%ms " /* (5) mount point */
5115 "%*s" /* (6) mount options (superblock) */
5116 "%*[^-]" /* (7) optional fields */
5117 "- " /* (8) separator */
5118 "%ms " /* (9) file system type */
5119 "%*s" /* (10) mount source */
5120 "%*s" /* (11) mount options (bind mount) */
5121 "%*[^\n]", /* some rubbish at the end */
5122 &path,
5123 &type);
5124 if (k != 2) {
5125 if (k == EOF)
5126 break;
5127
5128 continue;
5129 }
5130
527b7a42
LP
5131 r = cunescape(path, UNESCAPE_RELAX, &p);
5132 if (r < 0)
5133 return r;
d6797c92
LP
5134
5135 /* Let's ignore autofs mounts. If they aren't
5136 * triggered yet, we want to avoid triggering
5137 * them, as we don't make any guarantees for
5138 * future submounts anyway. If they are
5139 * already triggered, then we will find
5140 * another entry for this. */
5141 if (streq(type, "autofs")) {
5142 top_autofs = top_autofs || path_equal(cleaned, p);
5143 continue;
5144 }
5145
5146 if (path_startswith(p, cleaned) &&
5147 !set_contains(done, p)) {
5148
5149 r = set_consume(todo, p);
5150 p = NULL;
5151
5152 if (r == -EEXIST)
5153 continue;
5154 if (r < 0)
5155 return r;
5156 }
5157 }
5158
5159 /* If we have no submounts to process anymore and if
5160 * the root is either already done, or an autofs, we
5161 * are done */
5162 if (set_isempty(todo) &&
5163 (top_autofs || set_contains(done, cleaned)))
5164 return 0;
5165
5166 if (!set_contains(done, cleaned) &&
5167 !set_contains(todo, cleaned)) {
5168 /* The prefix directory itself is not yet a
5169 * mount, make it one. */
5170 if (mount(cleaned, cleaned, NULL, MS_BIND|MS_REC, NULL) < 0)
5171 return -errno;
5172
a7e07206
LP
5173 orig_flags = 0;
5174 (void) get_mount_flags(cleaned, &orig_flags);
abe4aa14 5175 orig_flags &= ~MS_RDONLY;
a7e07206 5176
abe4aa14 5177 if (mount(NULL, prefix, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0)
d6797c92
LP
5178 return -errno;
5179
5180 x = strdup(cleaned);
5181 if (!x)
5182 return -ENOMEM;
5183
5184 r = set_consume(done, x);
5185 if (r < 0)
5186 return r;
5187 }
5188
5189 while ((x = set_steal_first(todo))) {
5190
f871aeed 5191 r = set_consume(done, x);
85d834ae 5192 if (r == -EEXIST || r == 0)
d6797c92 5193 continue;
f871aeed 5194 if (r < 0)
d6797c92
LP
5195 return r;
5196
a7e07206
LP
5197 /* Try to reuse the original flag set, but
5198 * don't care for errors, in case of
5199 * obstructed mounts */
5200 orig_flags = 0;
5201 (void) get_mount_flags(x, &orig_flags);
abe4aa14 5202 orig_flags &= ~MS_RDONLY;
a7e07206 5203
abe4aa14 5204 if (mount(NULL, x, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0) {
f871aeed 5205
d6797c92
LP
5206 /* Deal with mount points that are
5207 * obstructed by a later mount */
5208
f871aeed 5209 if (errno != ENOENT)
d6797c92
LP
5210 return -errno;
5211 }
f871aeed 5212
d6797c92
LP
5213 }
5214 }
5215}
1b992147
LP
5216
5217int fflush_and_check(FILE *f) {
45c196a7 5218 assert(f);
1b992147
LP
5219
5220 errno = 0;
5221 fflush(f);
5222
5223 if (ferror(f))
5224 return errno ? -errno : -EIO;
5225
5226 return 0;
5227}
2e78fa79 5228
14bcf25c 5229int tempfn_xxxxxx(const char *p, const char *extra, char **ret) {
2e78fa79
LP
5230 const char *fn;
5231 char *t;
2e78fa79
LP
5232
5233 assert(p);
ae6c3cc0
LP
5234 assert(ret);
5235
c4e34a61
LP
5236 /*
5237 * Turns this:
5238 * /foo/bar/waldo
5239 *
5240 * Into this:
14bcf25c 5241 * /foo/bar/.#<extra>waldoXXXXXX
c4e34a61
LP
5242 */
5243
ae6c3cc0
LP
5244 fn = basename(p);
5245 if (!filename_is_valid(fn))
5246 return -EINVAL;
2e78fa79 5247
14bcf25c
LP
5248 if (extra == NULL)
5249 extra = "";
5250
5251 t = new(char, strlen(p) + 2 + strlen(extra) + 6 + 1);
2e78fa79 5252 if (!t)
ae6c3cc0 5253 return -ENOMEM;
2e78fa79 5254
14bcf25c 5255 strcpy(stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), extra), fn), "XXXXXX");
2e78fa79 5256
c4e34a61 5257 *ret = path_kill_slashes(t);
ae6c3cc0 5258 return 0;
2e78fa79
LP
5259}
5260
14bcf25c 5261int tempfn_random(const char *p, const char *extra, char **ret) {
2e78fa79
LP
5262 const char *fn;
5263 char *t, *x;
5264 uint64_t u;
2e78fa79
LP
5265 unsigned i;
5266
5267 assert(p);
ae6c3cc0
LP
5268 assert(ret);
5269
c4e34a61
LP
5270 /*
5271 * Turns this:
5272 * /foo/bar/waldo
5273 *
5274 * Into this:
14bcf25c 5275 * /foo/bar/.#<extra>waldobaa2a261115984a9
c4e34a61
LP
5276 */
5277
ae6c3cc0
LP
5278 fn = basename(p);
5279 if (!filename_is_valid(fn))
5280 return -EINVAL;
2e78fa79 5281
14bcf25c
LP
5282 if (!extra)
5283 extra = "";
5284
5285 t = new(char, strlen(p) + 2 + strlen(extra) + 16 + 1);
2e78fa79 5286 if (!t)
ae6c3cc0 5287 return -ENOMEM;
2e78fa79 5288
14bcf25c 5289 x = stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), extra), fn);
2e78fa79
LP
5290
5291 u = random_u64();
5292 for (i = 0; i < 16; i++) {
5293 *(x++) = hexchar(u & 0xF);
5294 u >>= 4;
5295 }
5296
5297 *x = 0;
5298
c4e34a61
LP
5299 *ret = path_kill_slashes(t);
5300 return 0;
5301}
5302
14bcf25c 5303int tempfn_random_child(const char *p, const char *extra, char **ret) {
c4e34a61
LP
5304 char *t, *x;
5305 uint64_t u;
5306 unsigned i;
5307
5308 assert(p);
5309 assert(ret);
5310
5311 /* Turns this:
5312 * /foo/bar/waldo
5313 * Into this:
14bcf25c 5314 * /foo/bar/waldo/.#<extra>3c2b6219aa75d7d0
c4e34a61
LP
5315 */
5316
14bcf25c
LP
5317 if (!extra)
5318 extra = "";
5319
5320 t = new(char, strlen(p) + 3 + strlen(extra) + 16 + 1);
c4e34a61
LP
5321 if (!t)
5322 return -ENOMEM;
5323
14bcf25c 5324 x = stpcpy(stpcpy(stpcpy(t, p), "/.#"), extra);
c4e34a61
LP
5325
5326 u = random_u64();
5327 for (i = 0; i < 16; i++) {
5328 *(x++) = hexchar(u & 0xF);
5329 u >>= 4;
5330 }
5331
5332 *x = 0;
5333
5334 *ret = path_kill_slashes(t);
ae6c3cc0 5335 return 0;
2e78fa79 5336}
fecc80c1 5337
45035609
LP
5338int take_password_lock(const char *root) {
5339
5340 struct flock flock = {
5341 .l_type = F_WRLCK,
5342 .l_whence = SEEK_SET,
5343 .l_start = 0,
5344 .l_len = 0,
5345 };
5346
5347 const char *path;
5348 int fd, r;
5349
5350 /* This is roughly the same as lckpwdf(), but not as awful. We
5351 * don't want to use alarm() and signals, hence we implement
5352 * our own trivial version of this.
5353 *
5354 * Note that shadow-utils also takes per-database locks in
5355 * addition to lckpwdf(). However, we don't given that they
5356 * are redundant as they they invoke lckpwdf() first and keep
5357 * it during everything they do. The per-database locks are
5358 * awfully racy, and thus we just won't do them. */
5359
5360 if (root)
63c372cb 5361 path = strjoina(root, "/etc/.pwd.lock");
45035609
LP
5362 else
5363 path = "/etc/.pwd.lock";
5364
5365 fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0600);
5366 if (fd < 0)
5367 return -errno;
5368
5369 r = fcntl(fd, F_SETLKW, &flock);
5370 if (r < 0) {
5371 safe_close(fd);
5372 return -errno;
5373 }
5374
5375 return fd;
5376}
5261ba90
TT
5377
5378int is_symlink(const char *path) {
5379 struct stat info;
5380
5381 if (lstat(path, &info) < 0)
5382 return -errno;
5383
be57e297
LP
5384 return !!S_ISLNK(info.st_mode);
5385}
5261ba90 5386
be57e297
LP
5387int is_dir(const char* path, bool follow) {
5388 struct stat st;
d1bddcec 5389 int r;
be57e297 5390
d1bddcec
LP
5391 if (follow)
5392 r = stat(path, &st);
5393 else
5394 r = lstat(path, &st);
5395 if (r < 0)
5396 return -errno;
be57e297
LP
5397
5398 return !!S_ISDIR(st.st_mode);
a0627f82 5399}
7629889c 5400
ce5b3ad4
SJ
5401int is_device_node(const char *path) {
5402 struct stat info;
5403
5404 if (lstat(path, &info) < 0)
5405 return -errno;
5406
5407 return !!(S_ISBLK(info.st_mode) || S_ISCHR(info.st_mode));
5408}
5409
2928b0a8
LP
5410int free_and_strdup(char **p, const char *s) {
5411 char *t;
5412
5413 assert(p);
5414
5415 /* Replaces a string pointer with an strdup()ed new string,
5416 * possibly freeing the old one. */
5417
4b64536e
LP
5418 if (streq_ptr(*p, s))
5419 return 0;
5420
2928b0a8
LP
5421 if (s) {
5422 t = strdup(s);
5423 if (!t)
5424 return -ENOMEM;
5425 } else
5426 t = NULL;
5427
5428 free(*p);
5429 *p = t;
5430
4b64536e 5431 return 1;
2928b0a8 5432}
605f81a8 5433
10f9c755 5434ssize_t fgetxattrat_fake(int dirfd, const char *filename, const char *attribute, void *value, size_t size, int flags) {
df241a67 5435 char fn[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
10f9c755
LP
5436 _cleanup_close_ int fd = -1;
5437 ssize_t l;
5438
5439 /* The kernel doesn't have a fgetxattrat() command, hence let's emulate one */
5440
df241a67 5441 fd = openat(dirfd, filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH|(flags & AT_SYMLINK_NOFOLLOW ? O_NOFOLLOW : 0));
10f9c755
LP
5442 if (fd < 0)
5443 return -errno;
5444
df241a67
LP
5445 xsprintf(fn, "/proc/self/fd/%i", fd);
5446
5447 l = getxattr(fn, attribute, value, size);
10f9c755
LP
5448 if (l < 0)
5449 return -errno;
5450
5451 return l;
5452}
5453
5454static int parse_crtime(le64_t le, usec_t *usec) {
4a4d89b6 5455 uint64_t u;
10f9c755
LP
5456
5457 assert(usec);
5458
5459 u = le64toh(le);
5460 if (u == 0 || u == (uint64_t) -1)
5461 return -EIO;
5462
5463 *usec = (usec_t) u;
5464 return 0;
5465}
5466
5467int fd_getcrtime(int fd, usec_t *usec) {
4a4d89b6
LP
5468 le64_t le;
5469 ssize_t n;
5470
5471 assert(fd >= 0);
5472 assert(usec);
5473
5474 /* Until Linux gets a real concept of birthtime/creation time,
5475 * let's fake one with xattrs */
5476
5477 n = fgetxattr(fd, "user.crtime_usec", &le, sizeof(le));
5478 if (n < 0)
5479 return -errno;
5480 if (n != sizeof(le))
5481 return -EIO;
5482
10f9c755
LP
5483 return parse_crtime(le, usec);
5484}
5485
5486int fd_getcrtime_at(int dirfd, const char *name, usec_t *usec, int flags) {
5487 le64_t le;
5488 ssize_t n;
5489
5490 n = fgetxattrat_fake(dirfd, name, "user.crtime_usec", &le, sizeof(le), flags);
5491 if (n < 0)
5492 return -errno;
5493 if (n != sizeof(le))
4a4d89b6
LP
5494 return -EIO;
5495
10f9c755 5496 return parse_crtime(le, usec);
4a4d89b6
LP
5497}
5498
5499int path_getcrtime(const char *p, usec_t *usec) {
4a4d89b6
LP
5500 le64_t le;
5501 ssize_t n;
5502
5503 assert(p);
5504 assert(usec);
5505
5506 n = getxattr(p, "user.crtime_usec", &le, sizeof(le));
5507 if (n < 0)
5508 return -errno;
5509 if (n != sizeof(le))
5510 return -EIO;
5511
10f9c755 5512 return parse_crtime(le, usec);
4a4d89b6
LP
5513}
5514
5515int fd_setcrtime(int fd, usec_t usec) {
5516 le64_t le;
5517
5518 assert(fd >= 0);
5519
d61b600d
LP
5520 if (usec <= 0)
5521 usec = now(CLOCK_REALTIME);
5522
4a4d89b6 5523 le = htole64((uint64_t) usec);
2c39ea52 5524 if (fsetxattr(fd, "user.crtime_usec", &le, sizeof(le), 0) < 0)
4a4d89b6
LP
5525 return -errno;
5526
5527 return 0;
5528}
a354329f
LP
5529
5530int same_fd(int a, int b) {
5531 struct stat sta, stb;
f7ad54a3
LP
5532 pid_t pid;
5533 int r, fa, fb;
a354329f
LP
5534
5535 assert(a >= 0);
5536 assert(b >= 0);
5537
f7ad54a3
LP
5538 /* Compares two file descriptors. Note that semantics are
5539 * quite different depending on whether we have kcmp() or we
5540 * don't. If we have kcmp() this will only return true for
5541 * dup()ed file descriptors, but not otherwise. If we don't
5542 * have kcmp() this will also return true for two fds of the same
5543 * file, created by separate open() calls. Since we use this
5544 * call mostly for filtering out duplicates in the fd store
5545 * this difference hopefully doesn't matter too much. */
5546
a354329f
LP
5547 if (a == b)
5548 return true;
5549
f7ad54a3
LP
5550 /* Try to use kcmp() if we have it. */
5551 pid = getpid();
5552 r = kcmp(pid, pid, KCMP_FILE, a, b);
5553 if (r == 0)
5554 return true;
5555 if (r > 0)
5556 return false;
5557 if (errno != ENOSYS)
5558 return -errno;
5559
5560 /* We don't have kcmp(), use fstat() instead. */
a354329f
LP
5561 if (fstat(a, &sta) < 0)
5562 return -errno;
5563
5564 if (fstat(b, &stb) < 0)
5565 return -errno;
5566
5567 if ((sta.st_mode & S_IFMT) != (stb.st_mode & S_IFMT))
5568 return false;
5569
f7ad54a3
LP
5570 /* We consider all device fds different, since two device fds
5571 * might refer to quite different device contexts even though
5572 * they share the same inode and backing dev_t. */
a354329f 5573
f7ad54a3
LP
5574 if (S_ISCHR(sta.st_mode) || S_ISBLK(sta.st_mode))
5575 return false;
5576
5577 if (sta.st_dev != stb.st_dev || sta.st_ino != stb.st_ino)
5578 return false;
5579
5580 /* The fds refer to the same inode on disk, let's also check
5581 * if they have the same fd flags. This is useful to
45afd519 5582 * distinguish the read and write side of a pipe created with
f7ad54a3
LP
5583 * pipe(). */
5584 fa = fcntl(a, F_GETFL);
5585 if (fa < 0)
5586 return -errno;
5587
5588 fb = fcntl(b, F_GETFL);
5589 if (fb < 0)
5590 return -errno;
5591
5592 return fa == fb;
a354329f 5593}
11689d2a 5594
1ed8f8c1 5595int chattr_fd(int fd, unsigned value, unsigned mask) {
45030287 5596 unsigned old_attr, new_attr;
03091baa 5597 struct stat st;
11689d2a
LP
5598
5599 assert(fd >= 0);
5600
03091baa
LP
5601 if (fstat(fd, &st) < 0)
5602 return -errno;
5603
5604 /* Explicitly check whether this is a regular file or
5605 * directory. If it is anything else (such as a device node or
5606 * fifo), then the ioctl will not hit the file systems but
5607 * possibly drivers, where the ioctl might have different
5608 * effects. Notably, DRM is using the same ioctl() number. */
5609
5610 if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode))
5611 return -ENOTTY;
5612
45030287
LP
5613 if (mask == 0)
5614 return 0;
5615
11689d2a
LP
5616 if (ioctl(fd, FS_IOC_GETFLAGS, &old_attr) < 0)
5617 return -errno;
5618
1ed8f8c1 5619 new_attr = (old_attr & ~mask) | (value & mask);
11689d2a
LP
5620 if (new_attr == old_attr)
5621 return 0;
5622
5623 if (ioctl(fd, FS_IOC_SETFLAGS, &new_attr) < 0)
5624 return -errno;
5625
1ed8f8c1 5626 return 1;
11689d2a
LP
5627}
5628
1ed8f8c1 5629int chattr_path(const char *p, unsigned value, unsigned mask) {
11689d2a
LP
5630 _cleanup_close_ int fd = -1;
5631
45030287
LP
5632 assert(p);
5633
5634 if (mask == 0)
5635 return 0;
5636
01b72568 5637 fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
11689d2a
LP
5638 if (fd < 0)
5639 return -errno;
5640
1ed8f8c1 5641 return chattr_fd(fd, value, mask);
5b9fbd35
GB
5642}
5643
01b72568 5644int read_attr_fd(int fd, unsigned *ret) {
03091baa
LP
5645 struct stat st;
5646
01b72568
LP
5647 assert(fd >= 0);
5648
03091baa
LP
5649 if (fstat(fd, &st) < 0)
5650 return -errno;
5651
5652 if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode))
5653 return -ENOTTY;
5654
01b72568
LP
5655 if (ioctl(fd, FS_IOC_GETFLAGS, ret) < 0)
5656 return -errno;
5657
5658 return 0;
5659}
5660
5661int read_attr_path(const char *p, unsigned *ret) {
5662 _cleanup_close_ int fd = -1;
5663
5664 assert(p);
5665 assert(ret);
5666
5667 fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
5668 if (fd < 0)
5669 return -errno;
5670
5671 return read_attr_fd(fd, ret);
5672}
30535c16 5673
ff6a7460
LP
5674static size_t nul_length(const uint8_t *p, size_t sz) {
5675 size_t n = 0;
5676
5677 while (sz > 0) {
5678 if (*p != 0)
5679 break;
5680
5681 n++;
5682 p++;
5683 sz--;
5684 }
5685
5686 return n;
5687}
5688
5689ssize_t sparse_write(int fd, const void *p, size_t sz, size_t run_length) {
5690 const uint8_t *q, *w, *e;
5691 ssize_t l;
5692
5693 q = w = p;
5694 e = q + sz;
5695 while (q < e) {
5696 size_t n;
5697
5698 n = nul_length(q, e - q);
5699
5700 /* If there are more than the specified run length of
5701 * NUL bytes, or if this is the beginning or the end
5702 * of the buffer, then seek instead of write */
5703 if ((n > run_length) ||
5704 (n > 0 && q == p) ||
5705 (n > 0 && q + n >= e)) {
5706 if (q > w) {
5707 l = write(fd, w, q - w);
5708 if (l < 0)
5709 return -errno;
5710 if (l != q -w)
5711 return -EIO;
5712 }
5713
5714 if (lseek(fd, n, SEEK_CUR) == (off_t) -1)
5715 return -errno;
5716
5717 q += n;
5718 w = q;
5719 } else if (n > 0)
5720 q += n;
5721 else
5722 q ++;
5723 }
5724
5725 if (q > w) {
5726 l = write(fd, w, q - w);
5727 if (l < 0)
5728 return -errno;
5729 if (l != q - w)
5730 return -EIO;
5731 }
5732
5733 return q - (const uint8_t*) p;
5734}
3576d631
LP
5735
5736void sigkill_wait(pid_t *pid) {
5737 if (!pid)
5738 return;
5739 if (*pid <= 1)
5740 return;
5741
5742 if (kill(*pid, SIGKILL) > 0)
5743 (void) wait_for_terminate(*pid, NULL);
5744}
3d7415f4
LP
5745
5746int syslog_parse_priority(const char **p, int *priority, bool with_facility) {
5747 int a = 0, b = 0, c = 0;
5748 int k;
5749
5750 assert(p);
5751 assert(*p);
5752 assert(priority);
5753
5754 if ((*p)[0] != '<')
5755 return 0;
5756
5757 if (!strchr(*p, '>'))
5758 return 0;
5759
5760 if ((*p)[2] == '>') {
5761 c = undecchar((*p)[1]);
5762 k = 3;
5763 } else if ((*p)[3] == '>') {
5764 b = undecchar((*p)[1]);
5765 c = undecchar((*p)[2]);
5766 k = 4;
5767 } else if ((*p)[4] == '>') {
5768 a = undecchar((*p)[1]);
5769 b = undecchar((*p)[2]);
5770 c = undecchar((*p)[3]);
5771 k = 5;
5772 } else
5773 return 0;
5774
5775 if (a < 0 || b < 0 || c < 0 ||
5776 (!with_facility && (a || b || c > 7)))
5777 return 0;
5778
5779 if (with_facility)
5780 *priority = a*100 + b*10 + c;
5781 else
5782 *priority = (*priority & LOG_FACMASK) | c;
5783
5784 *p += k;
5785 return 1;
5786}
9cad100e
BB
5787
5788ssize_t string_table_lookup(const char * const *table, size_t len, const char *key) {
5789 size_t i;
5790
5791 if (!key)
5792 return -1;
5793
5794 for (i = 0; i < len; ++i)
5795 if (streq_ptr(table[i], key))
8c721f2b 5796 return (ssize_t) i;
9cad100e
BB
5797
5798 return -1;
5799}
1c8da044
LP
5800
5801void cmsg_close_all(struct msghdr *mh) {
5802 struct cmsghdr *cmsg;
5803
5804 assert(mh);
5805
2a1288ff 5806 CMSG_FOREACH(cmsg, mh)
1c8da044
LP
5807 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
5808 close_many((int*) CMSG_DATA(cmsg), (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int));
5809}
f85ef957
AC
5810
5811int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) {
5812 struct stat buf;
5813 int ret;
5814
5815 ret = renameat2(olddirfd, oldpath, newdirfd, newpath, RENAME_NOREPLACE);
5816 if (ret >= 0)
5817 return 0;
5818
715d7599
RM
5819 /* renameat2() exists since Linux 3.15, btrfs added support for it later.
5820 * If it is not implemented, fallback to another method. */
5821 if (!IN_SET(errno, EINVAL, ENOSYS))
f85ef957
AC
5822 return -errno;
5823
5824 /* The link()/unlink() fallback does not work on directories. But
5825 * renameat() without RENAME_NOREPLACE gives the same semantics on
5826 * directories, except when newpath is an *empty* directory. This is
5827 * good enough. */
5828 ret = fstatat(olddirfd, oldpath, &buf, AT_SYMLINK_NOFOLLOW);
5829 if (ret >= 0 && S_ISDIR(buf.st_mode)) {
5830 ret = renameat(olddirfd, oldpath, newdirfd, newpath);
5831 return ret >= 0 ? 0 : -errno;
5832 }
5833
5834 /* If it is not a directory, use the link()/unlink() fallback. */
5835 ret = linkat(olddirfd, oldpath, newdirfd, newpath, 0);
5836 if (ret < 0)
5837 return -errno;
5838
5839 ret = unlinkat(olddirfd, oldpath, 0);
5840 if (ret < 0) {
5841 /* backup errno before the following unlinkat() alters it */
5842 ret = errno;
5843 (void) unlinkat(newdirfd, newpath, 0);
5844 errno = ret;
5845 return -errno;
5846 }
5847
5848 return 0;
5849}
019c7fba 5850
2ff7b0a5
LP
5851int parse_mode(const char *s, mode_t *ret) {
5852 char *x;
5853 long l;
5854
5855 assert(s);
5856 assert(ret);
5857
5858 errno = 0;
5859 l = strtol(s, &x, 8);
5860 if (errno != 0)
5861 return -errno;
5862
5863 if (!x || x == s || *x)
5864 return -EINVAL;
5865 if (l < 0 || l > 07777)
5866 return -ERANGE;
5867
5868 *ret = (mode_t) l;
5869 return 0;
5870}
6458ec20
LP
5871
5872int mount_move_root(const char *path) {
5873 assert(path);
5874
5875 if (chdir(path) < 0)
5876 return -errno;
5877
5878 if (mount(path, "/", NULL, MS_MOVE, NULL) < 0)
5879 return -errno;
5880
5881 if (chroot(".") < 0)
5882 return -errno;
5883
5884 if (chdir("/") < 0)
5885 return -errno;
5886
5887 return 0;
5888}
b4da6d6b
LP
5889
5890int reset_uid_gid(void) {
5891
5892 if (setgroups(0, NULL) < 0)
5893 return -errno;
5894
5895 if (setresgid(0, 0, 0) < 0)
5896 return -errno;
5897
5898 if (setresuid(0, 0, 0) < 0)
5899 return -errno;
5900
5901 return 0;
5902}
7b9c9ab8
WC
5903
5904int getxattr_malloc(const char *path, const char *name, char **value, bool allow_symlink) {
5905 char *v;
5906 size_t l;
5907 ssize_t n;
5908
5909 assert(path);
5910 assert(name);
5911 assert(value);
5912
5913 for (l = 100; ; l = (size_t) n + 1) {
5914 v = new0(char, l);
5915 if (!v)
5916 return -ENOMEM;
5917
5918 if (allow_symlink)
5919 n = lgetxattr(path, name, v, l);
5920 else
5921 n = getxattr(path, name, v, l);
5922
5923 if (n >= 0 && (size_t) n < l) {
5924 *value = v;
5925 return n;
5926 }
5927
5928 free(v);
5929
5930 if (n < 0 && errno != ERANGE)
5931 return -errno;
5932
5933 if (allow_symlink)
5934 n = lgetxattr(path, name, NULL, 0);
5935 else
5936 n = getxattr(path, name, NULL, 0);
5937 if (n < 0)
5938 return -errno;
5939 }
5940}
5941
5942int fgetxattr_malloc(int fd, const char *name, char **value) {
5943 char *v;
5944 size_t l;
5945 ssize_t n;
5946
5947 assert(fd >= 0);
5948 assert(name);
5949 assert(value);
5950
5951 for (l = 100; ; l = (size_t) n + 1) {
5952 v = new0(char, l);
5953 if (!v)
5954 return -ENOMEM;
5955
5956 n = fgetxattr(fd, name, v, l);
5957
5958 if (n >= 0 && (size_t) n < l) {
5959 *value = v;
5960 return n;
5961 }
5962
5963 free(v);
5964
5965 if (n < 0 && errno != ERANGE)
5966 return -errno;
5967
5968 n = fgetxattr(fd, name, NULL, 0);
5969 if (n < 0)
5970 return -errno;
5971 }
5972}
d9603714 5973
3ee897d6 5974int send_one_fd(int transport_fd, int fd, int flags) {
d9603714
DH
5975 union {
5976 struct cmsghdr cmsghdr;
5977 uint8_t buf[CMSG_SPACE(sizeof(int))];
5978 } control = {};
5979 struct msghdr mh = {
5980 .msg_control = &control,
5981 .msg_controllen = sizeof(control),
5982 };
5983 struct cmsghdr *cmsg;
d9603714
DH
5984
5985 assert(transport_fd >= 0);
5986 assert(fd >= 0);
5987
5988 cmsg = CMSG_FIRSTHDR(&mh);
5989 cmsg->cmsg_level = SOL_SOCKET;
5990 cmsg->cmsg_type = SCM_RIGHTS;
5991 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
5992 memcpy(CMSG_DATA(cmsg), &fd, sizeof(int));
5993
5994 mh.msg_controllen = CMSG_SPACE(sizeof(int));
3ee897d6 5995 if (sendmsg(transport_fd, &mh, MSG_NOSIGNAL | flags) < 0)
d9603714
DH
5996 return -errno;
5997
5998 return 0;
5999}
6000
3ee897d6 6001int receive_one_fd(int transport_fd, int flags) {
d9603714
DH
6002 union {
6003 struct cmsghdr cmsghdr;
6004 uint8_t buf[CMSG_SPACE(sizeof(int))];
6005 } control = {};
6006 struct msghdr mh = {
6007 .msg_control = &control,
6008 .msg_controllen = sizeof(control),
6009 };
3ee897d6 6010 struct cmsghdr *cmsg, *found = NULL;
d9603714
DH
6011
6012 assert(transport_fd >= 0);
6013
6014 /*
3ee897d6
LP
6015 * Receive a single FD via @transport_fd. We don't care for
6016 * the transport-type. We retrieve a single FD at most, so for
6017 * packet-based transports, the caller must ensure to send
6018 * only a single FD per packet. This is best used in
6019 * combination with send_one_fd().
d9603714
DH
6020 */
6021
3ee897d6 6022 if (recvmsg(transport_fd, &mh, MSG_NOSIGNAL | MSG_CMSG_CLOEXEC | flags) < 0)
d9603714
DH
6023 return -errno;
6024
3ee897d6
LP
6025 CMSG_FOREACH(cmsg, &mh) {
6026 if (cmsg->cmsg_level == SOL_SOCKET &&
6027 cmsg->cmsg_type == SCM_RIGHTS &&
6028 cmsg->cmsg_len == CMSG_LEN(sizeof(int))) {
6029 assert(!found);
6030 found = cmsg;
6031 break;
6032 }
6033 }
6034
6035 if (!found) {
d9603714
DH
6036 cmsg_close_all(&mh);
6037 return -EIO;
6038 }
6039
3ee897d6 6040 return *(int*) CMSG_DATA(found);
d9603714 6041}
189d5bac
LP
6042
6043void nop_signal_handler(int sig) {
6044 /* nothing here */
6045}
3f6fd1ba
LP
6046
6047int version(void) {
6048 puts(PACKAGE_STRING "\n"
6049 SYSTEMD_FEATURES);
6050 return 0;
6051}
8dd4c05b
LP
6052
6053bool fdname_is_valid(const char *s) {
6054 const char *p;
6055
0a3bb96e 6056 /* Validates a name for $LISTEN_FDNAMES. We basically allow
8dd4c05b
LP
6057 * everything ASCII that's not a control character. Also, as
6058 * special exception the ":" character is not allowed, as we
0a3bb96e 6059 * use that as field separator in $LISTEN_FDNAMES.
8dd4c05b 6060 *
0a3bb96e
LP
6061 * Note that the empty string is explicitly allowed
6062 * here. However, we limit the length of the names to 255
6063 * characters. */
8dd4c05b
LP
6064
6065 if (!s)
6066 return false;
6067
6068 for (p = s; *p; p++) {
6069 if (*p < ' ')
6070 return false;
6071 if (*p >= 127)
6072 return false;
6073 if (*p == ':')
6074 return false;
6075 }
6076
6077 return p - s < 256;
6078}
257b0719
EV
6079
6080bool oom_score_adjust_is_valid(int oa) {
6081 return oa >= OOM_SCORE_ADJ_MIN && oa <= OOM_SCORE_ADJ_MAX;
6082}
1602b008
LP
6083
6084void string_erase(char *x) {
6085
6086 if (!x)
6087 return;
6088
6089 /* A delicious drop of snake-oil! To be called on memory where
6090 * we stored passphrases or so, after we used them. */
6091
6092 memory_erase(x, strlen(x));
6093}
6094
ab84f5b9
ZJS
6095char *string_free_erase(char *s) {
6096 if (!s)
6097 return NULL;
1602b008 6098
ab84f5b9
ZJS
6099 string_erase(s);
6100 return mfree(s);
1602b008 6101}