]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/util.c
util-lib: split out file attribute calls to chattr-util.[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 34#include <locale.h>
0a6f50c0 35#include <poll.h>
ef2f1067 36#include <pwd.h>
f6c2284a
LP
37#include <sched.h>
38#include <signal.h>
39#include <stdarg.h>
40#include <stdio.h>
41#include <stdlib.h>
42#include <string.h>
43#include <sys/file.h>
44#include <sys/ioctl.h>
87d2c1ff 45#include <sys/mman.h>
6d313367 46#include <sys/mount.h>
6afc95b7 47#include <sys/personality.h>
f6c2284a 48#include <sys/prctl.h>
f6c2284a 49#include <sys/stat.h>
abe4aa14 50#include <sys/statvfs.h>
f6c2284a
LP
51#include <sys/time.h>
52#include <sys/types.h>
53#include <sys/utsname.h>
54#include <sys/vfs.h>
55#include <sys/wait.h>
f6c2284a
LP
56#include <syslog.h>
57#include <unistd.h>
eef46c37
LP
58
59/* When we include libgen.h because we need dirname() we immediately
f6c2284a
LP
60 * undefine basename() since libgen.h defines it as a macro to the
61 * POSIX version which is really broken. We prefer GNU basename(). */
eef46c37 62#include <libgen.h>
2b6bf07d 63#undef basename
60918275 64
9bf3b535
LP
65#ifdef HAVE_SYS_AUXV_H
66#include <sys/auxv.h>
67#endif
68
f6c2284a
LP
69/* We include linux/fs.h as last of the system headers, as it
70 * otherwise conflicts with sys/mount.h. Yay, Linux is great! */
71#include <linux/fs.h>
72
3f6fd1ba 73#include "build.h"
f6c2284a
LP
74#include "def.h"
75#include "device-nodes.h"
76#include "env-util.h"
4f5dd394 77#include "escape.h"
f6c2284a 78#include "exit-status.h"
3ffd4af2 79#include "fd-util.h"
f6c2284a
LP
80#include "fileio.h"
81#include "formats-util.h"
82#include "gunicode.h"
83#include "hashmap.h"
84#include "hostname-util.h"
1dccbe19 85#include "ioprio.h"
a9f5d454 86#include "log.h"
f6c2284a
LP
87#include "macro.h"
88#include "missing.h"
c38dfac9 89#include "mkdir.h"
e4e73a63 90#include "hexdecoct.h"
6bedfcbb 91#include "parse-util.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 96#include "sparse-endian.h"
07630cea 97#include "string-util.h"
f6c2284a
LP
98#include "strv.h"
99#include "terminal-util.h"
b1d4f8e1 100#include "user-util.h"
f6c2284a 101#include "utf8.h"
4f5dd394 102#include "util.h"
3ffd4af2 103#include "virt.h"
a0956174 104#include "dirent-util.h"
56cf987f 105
012d7b42
ZJS
106/* Put this test here for a lack of better place */
107assert_cc(EAGAIN == EWOULDBLOCK);
108
9a0e6896
LP
109int saved_argc = 0;
110char **saved_argv = NULL;
9086e840 111
37f85e66 112size_t page_size(void) {
ec202eae 113 static thread_local size_t pgsz = 0;
37f85e66 114 long r;
115
87d2c1ff 116 if (_likely_(pgsz > 0))
37f85e66 117 return pgsz;
118
e67f47e5
LP
119 r = sysconf(_SC_PAGESIZE);
120 assert(r > 0);
37f85e66 121
122 pgsz = (size_t) r;
37f85e66 123 return pgsz;
124}
125
4b73a0c0
LP
126int unlink_noerrno(const char *path) {
127 PROTECT_ERRNO;
128 int r;
129
130 r = unlink(path);
131 if (r < 0)
132 return -errno;
133
134 return 0;
135}
136
34ca941c
LP
137int fchmod_umask(int fd, mode_t m) {
138 mode_t u;
139 int r;
140
141 u = umask(0777);
142 r = fchmod(fd, m & (~u)) < 0 ? -errno : 0;
143 umask(u);
144
145 return r;
146}
147
849958d1 148int readlinkat_malloc(int fd, const char *p, char **ret) {
87f0e418 149 size_t l = 100;
2d2ebd6b 150 int r;
87f0e418
LP
151
152 assert(p);
2d2ebd6b 153 assert(ret);
87f0e418
LP
154
155 for (;;) {
156 char *c;
157 ssize_t n;
158
2d2ebd6b
LP
159 c = new(char, l);
160 if (!c)
87f0e418
LP
161 return -ENOMEM;
162
849958d1 163 n = readlinkat(fd, p, c, l-1);
2d2ebd6b
LP
164 if (n < 0) {
165 r = -errno;
87f0e418 166 free(c);
2d2ebd6b 167 return r;
87f0e418
LP
168 }
169
170 if ((size_t) n < l-1) {
171 c[n] = 0;
2d2ebd6b 172 *ret = c;
87f0e418
LP
173 return 0;
174 }
175
176 free(c);
177 l *= 2;
178 }
179}
180
849958d1
LP
181int readlink_malloc(const char *p, char **ret) {
182 return readlinkat_malloc(AT_FDCWD, p, ret);
183}
184
9a67bcf2
TG
185int readlink_value(const char *p, char **ret) {
186 _cleanup_free_ char *link = NULL;
187 char *value;
188 int r;
189
190 r = readlink_malloc(p, &link);
191 if (r < 0)
192 return r;
193
194 value = basename(link);
195 if (!value)
196 return -ENOENT;
197
198 value = strdup(value);
199 if (!value)
200 return -ENOMEM;
201
202 *ret = value;
203
204 return 0;
205}
206
2c7108c4 207int readlink_and_make_absolute(const char *p, char **r) {
1058cbf2
ZJS
208 _cleanup_free_ char *target = NULL;
209 char *k;
2c7108c4
LP
210 int j;
211
212 assert(p);
213 assert(r);
214
1058cbf2
ZJS
215 j = readlink_malloc(p, &target);
216 if (j < 0)
2c7108c4
LP
217 return j;
218
219 k = file_in_same_dir(p, target);
2c7108c4
LP
220 if (!k)
221 return -ENOMEM;
222
223 *r = k;
224 return 0;
225}
226
83096483
LP
227int readlink_and_canonicalize(const char *p, char **r) {
228 char *t, *s;
229 int j;
230
231 assert(p);
232 assert(r);
233
234 j = readlink_and_make_absolute(p, &t);
235 if (j < 0)
236 return j;
237
238 s = canonicalize_file_name(t);
239 if (s) {
240 free(t);
241 *r = s;
242 } else
243 *r = t;
244
245 path_kill_slashes(*r);
246
247 return 0;
248}
249
c32dd69b
LP
250int rmdir_parents(const char *path, const char *stop) {
251 size_t l;
252 int r = 0;
253
254 assert(path);
255 assert(stop);
256
257 l = strlen(path);
258
259 /* Skip trailing slashes */
260 while (l > 0 && path[l-1] == '/')
261 l--;
262
263 while (l > 0) {
264 char *t;
265
266 /* Skip last component */
267 while (l > 0 && path[l-1] != '/')
268 l--;
269
270 /* Skip trailing slashes */
271 while (l > 0 && path[l-1] == '/')
272 l--;
273
274 if (l <= 0)
275 break;
276
277 if (!(t = strndup(path, l)))
278 return -ENOMEM;
279
280 if (path_startswith(stop, t)) {
281 free(t);
282 return 0;
283 }
284
285 r = rmdir(t);
286 free(t);
287
288 if (r < 0)
289 if (errno != ENOENT)
290 return -errno;
291 }
292
293 return 0;
294}
295
42856c10 296bool fstype_is_network(const char *fstype) {
a05f97b3 297 static const char table[] =
ba89821c 298 "afs\0"
a05f97b3
LP
299 "cifs\0"
300 "smbfs\0"
da92ca5e 301 "sshfs\0"
a05f97b3 302 "ncpfs\0"
dac70dc7 303 "ncp\0"
a05f97b3
LP
304 "nfs\0"
305 "nfs4\0"
306 "gfs\0"
67608cad
LP
307 "gfs2\0"
308 "glusterfs\0";
309
310 const char *x;
311
312 x = startswith(fstype, "fuse.");
313 if (x)
314 fstype = x;
42856c10 315
a05f97b3 316 return nulstr_contains(table, fstype);
42856c10
LP
317}
318
01f78473 319int dir_is_empty(const char *path) {
a05f97b3 320 _cleanup_closedir_ DIR *d;
ac7edd91 321 struct dirent *de;
01f78473 322
a05f97b3
LP
323 d = opendir(path);
324 if (!d)
01f78473
LP
325 return -errno;
326
ac7edd91
LP
327 FOREACH_DIRENT(de, d, return -errno)
328 return 0;
01f78473 329
ac7edd91 330 return 1;
01f78473
LP
331}
332
5b6319dc
LP
333void rename_process(const char name[8]) {
334 assert(name);
335
5d6b1584
LP
336 /* This is a like a poor man's setproctitle(). It changes the
337 * comm field, argv[0], and also the glibc's internally used
338 * name of the process. For the first one a limit of 16 chars
339 * applies, to the second one usually one of 10 (i.e. length
340 * of "/sbin/init"), to the third one one of 7 (i.e. length of
341 * "systemd"). If you pass a longer string it will be
342 * truncated */
5b6319dc 343
5d6b1584 344 prctl(PR_SET_NAME, name);
5b6319dc
LP
345
346 if (program_invocation_name)
347 strncpy(program_invocation_name, name, strlen(program_invocation_name));
9a0e6896
LP
348
349 if (saved_argc > 0) {
350 int i;
351
352 if (saved_argv[0])
353 strncpy(saved_argv[0], name, strlen(saved_argv[0]));
354
355 for (i = 1; i < saved_argc; i++) {
356 if (!saved_argv[i])
357 break;
358
29804cc1 359 memzero(saved_argv[i], strlen(saved_argv[i]));
9a0e6896
LP
360 }
361 }
5b6319dc
LP
362}
363
d1678248 364bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) {
943aad8c 365 assert(s);
d1678248
ILG
366 assert_cc(sizeof(statfs_f_type_t) >= sizeof(s->f_type));
367
368 return F_TYPE_EQUAL(s->f_type, magic_value);
369}
370
371int fd_check_fstype(int fd, statfs_f_type_t magic_value) {
372 struct statfs s;
373
374 if (fstatfs(fd, &s) < 0)
375 return -errno;
73020ab2 376
d1678248
ILG
377 return is_fs_type(&s, magic_value);
378}
379
380int path_check_fstype(const char *path, statfs_f_type_t magic_value) {
381 _cleanup_close_ int fd = -1;
382
383 fd = open(path, O_RDONLY);
384 if (fd < 0)
385 return -errno;
386
387 return fd_check_fstype(fd, magic_value);
388}
389
390bool is_temporary_fs(const struct statfs *s) {
391 return is_fs_type(s, TMPFS_MAGIC) ||
392 is_fs_type(s, RAMFS_MAGIC);
943aad8c
ZJS
393}
394
c6878637 395int fd_is_temporary_fs(int fd) {
979ef53a
DR
396 struct statfs s;
397
398 if (fstatfs(fd, &s) < 0)
399 return -errno;
400
401 return is_temporary_fs(&s);
402}
403
8c6db833
LP
404int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
405 assert(path);
406
407 /* Under the assumption that we are running privileged we
408 * first change the access mode and only then hand out
409 * ownership to avoid a window where access is too open. */
410
fed1e721 411 if (mode != MODE_INVALID)
8d53b453
LP
412 if (chmod(path, mode) < 0)
413 return -errno;
8c6db833 414
fed1e721 415 if (uid != UID_INVALID || gid != GID_INVALID)
8d53b453
LP
416 if (chown(path, uid, gid) < 0)
417 return -errno;
8c6db833
LP
418
419 return 0;
ef2f1067
LP
420}
421
f4b47811
LP
422int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid) {
423 assert(fd >= 0);
424
425 /* Under the assumption that we are running privileged we
426 * first change the access mode and only then hand out
427 * ownership to avoid a window where access is too open. */
428
fed1e721 429 if (mode != MODE_INVALID)
9588bc32
LP
430 if (fchmod(fd, mode) < 0)
431 return -errno;
f4b47811 432
fed1e721 433 if (uid != UID_INVALID || gid != GID_INVALID)
9588bc32
LP
434 if (fchown(fd, uid, gid) < 0)
435 return -errno;
f4b47811
LP
436
437 return 0;
438}
439
9d9951a4
HH
440int files_same(const char *filea, const char *fileb) {
441 struct stat a, b;
b4f10a5e 442
9d9951a4 443 if (stat(filea, &a) < 0)
b4f10a5e
LP
444 return -errno;
445
9d9951a4 446 if (stat(fileb, &b) < 0)
b4f10a5e
LP
447 return -errno;
448
9d9951a4
HH
449 return a.st_dev == b.st_dev &&
450 a.st_ino == b.st_ino;
451}
452
453int running_in_chroot(void) {
454 int ret;
455
456 ret = files_same("/proc/1/root", "/");
457 if (ret < 0)
458 return ret;
459
460 return ret == 0;
b4f10a5e
LP
461}
462
c38dfac9 463int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode) {
03e334a1 464 _cleanup_close_ int fd;
c38dfac9 465 int r;
f6144808
LP
466
467 assert(path);
468
c38dfac9
KS
469 if (parents)
470 mkdir_parents(path, 0755);
73836c5c 471
c38dfac9 472 fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, mode > 0 ? mode : 0644);
73836c5c 473 if (fd < 0)
f6144808
LP
474 return -errno;
475
c38dfac9
KS
476 if (mode > 0) {
477 r = fchmod(fd, mode);
478 if (r < 0)
479 return -errno;
480 }
481
fed1e721 482 if (uid != UID_INVALID || gid != GID_INVALID) {
c38dfac9
KS
483 r = fchown(fd, uid, gid);
484 if (r < 0)
485 return -errno;
486 }
487
3a43da28 488 if (stamp != USEC_INFINITY) {
c38dfac9
KS
489 struct timespec ts[2];
490
491 timespec_store(&ts[0], stamp);
359efc59 492 ts[1] = ts[0];
c38dfac9
KS
493 r = futimens(fd, ts);
494 } else
495 r = futimens(fd, NULL);
496 if (r < 0)
497 return -errno;
498
f6144808
LP
499 return 0;
500}
afea26ad 501
c38dfac9 502int touch(const char *path) {
fed1e721 503 return touch_file(path, false, USEC_INFINITY, UID_INVALID, GID_INVALID, 0);
c38dfac9
KS
504}
505
919ce0b7 506noreturn void freeze(void) {
720ce21d
LP
507
508 /* Make sure nobody waits for us on a socket anymore */
509 close_all_fds(NULL, 0);
510
c29597a1
LP
511 sync();
512
3c14d26c
LP
513 for (;;)
514 pause();
515}
516
00dc5d76
LP
517bool null_or_empty(struct stat *st) {
518 assert(st);
519
520 if (S_ISREG(st->st_mode) && st->st_size <= 0)
521 return true;
522
c8f26f42 523 if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
00dc5d76
LP
524 return true;
525
526 return false;
527}
528
83096483
LP
529int null_or_empty_path(const char *fn) {
530 struct stat st;
531
532 assert(fn);
533
534 if (stat(fn, &st) < 0)
535 return -errno;
536
537 return null_or_empty(&st);
538}
539
ed88bcfb
ZJS
540int null_or_empty_fd(int fd) {
541 struct stat st;
542
543 assert(fd >= 0);
544
545 if (fstat(fd, &st) < 0)
546 return -errno;
547
548 return null_or_empty(&st);
549}
550
e801700e 551static int do_execute(char **directories, usec_t timeout, char *argv[]) {
49681057 552 _cleanup_hashmap_free_free_ Hashmap *pids = NULL;
e801700e
ZJS
553 _cleanup_set_free_free_ Set *seen = NULL;
554 char **directory;
83cc030f 555
49681057
ZJS
556 /* We fork this all off from a child process so that we can
557 * somewhat cleanly make use of SIGALRM to set a time limit */
83cc030f 558
ce30c8dc
LP
559 (void) reset_all_signal_handlers();
560 (void) reset_signal_mask();
83cc030f 561
49681057 562 assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
83cc030f 563
49681057
ZJS
564 pids = hashmap_new(NULL);
565 if (!pids)
566 return log_oom();
83cc030f 567
e801700e
ZJS
568 seen = set_new(&string_hash_ops);
569 if (!seen)
570 return log_oom();
83cc030f 571
e801700e
ZJS
572 STRV_FOREACH(directory, directories) {
573 _cleanup_closedir_ DIR *d;
574 struct dirent *de;
83cc030f 575
e801700e
ZJS
576 d = opendir(*directory);
577 if (!d) {
578 if (errno == ENOENT)
579 continue;
83cc030f 580
e801700e
ZJS
581 return log_error_errno(errno, "Failed to open directory %s: %m", *directory);
582 }
83cc030f 583
e801700e
ZJS
584 FOREACH_DIRENT(de, d, break) {
585 _cleanup_free_ char *path = NULL;
586 pid_t pid;
587 int r;
588
589 if (!dirent_is_file(de))
590 continue;
83cc030f 591
e801700e
ZJS
592 if (set_contains(seen, de->d_name)) {
593 log_debug("%1$s/%2$s skipped (%2$s was already seen).", *directory, de->d_name);
594 continue;
595 }
596
597 r = set_put_strdup(seen, de->d_name);
598 if (r < 0)
599 return log_oom();
600
601 path = strjoin(*directory, "/", de->d_name, NULL);
602 if (!path)
603 return log_oom();
604
605 if (null_or_empty_path(path)) {
606 log_debug("%s is empty (a mask).", path);
607 continue;
7034e9db 608 }
83cc030f 609
e801700e
ZJS
610 pid = fork();
611 if (pid < 0) {
612 log_error_errno(errno, "Failed to fork: %m");
613 continue;
614 } else if (pid == 0) {
615 char *_argv[2];
83cc030f 616
e801700e 617 assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
83cc030f 618
e801700e
ZJS
619 if (!argv) {
620 _argv[0] = path;
621 _argv[1] = NULL;
622 argv = _argv;
623 } else
624 argv[0] = path;
625
626 execv(path, argv);
627 return log_error_errno(errno, "Failed to execute %s: %m", path);
628 }
629
630 log_debug("Spawned %s as " PID_FMT ".", path, pid);
83cc030f 631
e801700e
ZJS
632 r = hashmap_put(pids, UINT_TO_PTR(pid), path);
633 if (r < 0)
634 return log_oom();
635 path = NULL;
636 }
49681057 637 }
83cc030f 638
49681057
ZJS
639 /* Abort execution of this process after the timout. We simply
640 * rely on SIGALRM as default action terminating the process,
641 * and turn on alarm(). */
83cc030f 642
49681057
ZJS
643 if (timeout != USEC_INFINITY)
644 alarm((timeout + USEC_PER_SEC - 1) / USEC_PER_SEC);
83cc030f 645
49681057
ZJS
646 while (!hashmap_isempty(pids)) {
647 _cleanup_free_ char *path = NULL;
648 pid_t pid;
aa62a893 649
49681057
ZJS
650 pid = PTR_TO_UINT(hashmap_first_key(pids));
651 assert(pid > 0);
83cc030f 652
49681057
ZJS
653 path = hashmap_remove(pids, UINT_TO_PTR(pid));
654 assert(path);
aa62a893 655
49681057
ZJS
656 wait_for_terminate_and_warn(path, pid, true);
657 }
aa62a893 658
49681057
ZJS
659 return 0;
660}
aa62a893 661
e801700e 662void execute_directories(const char* const* directories, usec_t timeout, char *argv[]) {
49681057
ZJS
663 pid_t executor_pid;
664 int r;
e801700e
ZJS
665 char *name;
666 char **dirs = (char**) directories;
667
668 assert(!strv_isempty(dirs));
83cc030f 669
e801700e
ZJS
670 name = basename(dirs[0]);
671 assert(!isempty(name));
aa62a893 672
e801700e
ZJS
673 /* Executes all binaries in the directories in parallel and waits
674 * for them to finish. Optionally a timeout is applied. If a file
675 * with the same name exists in more than one directory, the
676 * earliest one wins. */
83cc030f 677
49681057
ZJS
678 executor_pid = fork();
679 if (executor_pid < 0) {
680 log_error_errno(errno, "Failed to fork: %m");
681 return;
682
683 } else if (executor_pid == 0) {
e801700e 684 r = do_execute(dirs, timeout, argv);
49681057 685 _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
aa62a893 686 }
83cc030f 687
e801700e 688 wait_for_terminate_and_warn(name, executor_pid, true);
83cc030f
LP
689}
690
a88c8750
TG
691bool plymouth_running(void) {
692 return access("/run/plymouth/pid", F_OK) >= 0;
693}
694
424a19f8 695int symlink_atomic(const char *from, const char *to) {
2e78fa79 696 _cleanup_free_ char *t = NULL;
ae6c3cc0 697 int r;
34ca941c
LP
698
699 assert(from);
700 assert(to);
701
14bcf25c 702 r = tempfn_random(to, NULL, &t);
ae6c3cc0
LP
703 if (r < 0)
704 return r;
34ca941c 705
424a19f8
LP
706 if (symlink(from, t) < 0)
707 return -errno;
34ca941c
LP
708
709 if (rename(t, to) < 0) {
2e78fa79
LP
710 unlink_noerrno(t);
711 return -errno;
34ca941c
LP
712 }
713
424a19f8 714 return 0;
34ca941c
LP
715}
716
875e1014
ILG
717int symlink_idempotent(const char *from, const char *to) {
718 _cleanup_free_ char *p = NULL;
719 int r;
720
721 assert(from);
722 assert(to);
723
724 if (symlink(from, to) < 0) {
725 if (errno != EEXIST)
726 return -errno;
727
728 r = readlink_malloc(to, &p);
729 if (r < 0)
730 return r;
731
732 if (!streq(p, from))
733 return -EINVAL;
734 }
735
736 return 0;
737}
738
1554afae
LP
739int mknod_atomic(const char *path, mode_t mode, dev_t dev) {
740 _cleanup_free_ char *t = NULL;
ae6c3cc0 741 int r;
1554afae
LP
742
743 assert(path);
744
14bcf25c 745 r = tempfn_random(path, NULL, &t);
ae6c3cc0
LP
746 if (r < 0)
747 return r;
1554afae
LP
748
749 if (mknod(t, mode, dev) < 0)
750 return -errno;
751
752 if (rename(t, path) < 0) {
753 unlink_noerrno(t);
754 return -errno;
755 }
756
757 return 0;
758}
759
760int mkfifo_atomic(const char *path, mode_t mode) {
761 _cleanup_free_ char *t = NULL;
ae6c3cc0 762 int r;
1554afae
LP
763
764 assert(path);
765
14bcf25c 766 r = tempfn_random(path, NULL, &t);
ae6c3cc0
LP
767 if (r < 0)
768 return r;
1554afae
LP
769
770 if (mkfifo(t, mode) < 0)
771 return -errno;
772
773 if (rename(t, path) < 0) {
774 unlink_noerrno(t);
775 return -errno;
776 }
777
778 return 0;
779}
780
4d6d6518
LP
781bool display_is_local(const char *display) {
782 assert(display);
783
784 return
785 display[0] == ':' &&
786 display[1] >= '0' &&
787 display[1] <= '9';
788}
789
790int socket_from_display(const char *display, char **path) {
791 size_t k;
792 char *f, *c;
793
794 assert(display);
795 assert(path);
796
797 if (!display_is_local(display))
798 return -EINVAL;
799
800 k = strspn(display+1, "0123456789");
801
f8294e41 802 f = new(char, strlen("/tmp/.X11-unix/X") + k + 1);
4d6d6518
LP
803 if (!f)
804 return -ENOMEM;
805
806 c = stpcpy(f, "/tmp/.X11-unix/X");
807 memcpy(c, display+1, k);
808 c[k] = 0;
809
810 *path = f;
811
812 return 0;
813}
814
8092a428 815int glob_exists(const char *path) {
7fd1b19b 816 _cleanup_globfree_ glob_t g = {};
8d98da3f 817 int k;
8092a428
LP
818
819 assert(path);
820
8092a428
LP
821 errno = 0;
822 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
823
824 if (k == GLOB_NOMATCH)
8d98da3f 825 return 0;
8092a428 826 else if (k == GLOB_NOSPACE)
8d98da3f 827 return -ENOMEM;
8092a428 828 else if (k == 0)
8d98da3f 829 return !strv_isempty(g.gl_pathv);
8092a428 830 else
8d98da3f
ZJS
831 return errno ? -errno : -EIO;
832}
8092a428 833
8d98da3f
ZJS
834int glob_extend(char ***strv, const char *path) {
835 _cleanup_globfree_ glob_t g = {};
836 int k;
837 char **p;
838
839 errno = 0;
a8ccacf5 840 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
8d98da3f
ZJS
841
842 if (k == GLOB_NOMATCH)
843 return -ENOENT;
844 else if (k == GLOB_NOSPACE)
845 return -ENOMEM;
846 else if (k != 0 || strv_isempty(g.gl_pathv))
847 return errno ? -errno : -EIO;
848
849 STRV_FOREACH(p, g.gl_pathv) {
850 k = strv_extend(strv, *p);
851 if (k < 0)
852 break;
853 }
854
855 return k;
8092a428
LP
856}
857
034a2a52 858int get_files_in_directory(const char *path, char ***list) {
893fa014
ZJS
859 _cleanup_closedir_ DIR *d = NULL;
860 size_t bufsize = 0, n = 0;
861 _cleanup_strv_free_ char **l = NULL;
034a2a52
LP
862
863 assert(path);
d60ef526
LP
864
865 /* Returns all files in a directory in *list, and the number
866 * of files as return value. If list is NULL returns only the
893fa014 867 * number. */
034a2a52
LP
868
869 d = opendir(path);
8ea913b2
LP
870 if (!d)
871 return -errno;
872
034a2a52 873 for (;;) {
7d5e9c0f 874 struct dirent *de;
034a2a52 875
3fd11280
FW
876 errno = 0;
877 de = readdir(d);
878 if (!de && errno != 0)
879 return -errno;
034a2a52
LP
880 if (!de)
881 break;
882
883 dirent_ensure_type(d, de);
884
885 if (!dirent_is_file(de))
886 continue;
887
d60ef526 888 if (list) {
893fa014
ZJS
889 /* one extra slot is needed for the terminating NULL */
890 if (!GREEDY_REALLOC(l, bufsize, n + 2))
891 return -ENOMEM;
034a2a52 892
893fa014
ZJS
893 l[n] = strdup(de->d_name);
894 if (!l[n])
895 return -ENOMEM;
034a2a52 896
893fa014 897 l[++n] = NULL;
d60ef526 898 } else
893fa014 899 n++;
034a2a52
LP
900 }
901
893fa014
ZJS
902 if (list) {
903 *list = l;
904 l = NULL; /* avoid freeing */
905 }
034a2a52 906
893fa014 907 return n;
034a2a52
LP
908}
909
b636465b 910bool is_main_thread(void) {
ec202eae 911 static thread_local int cached = 0;
b636465b
LP
912
913 if (_unlikely_(cached == 0))
914 cached = getpid() == gettid() ? 1 : -1;
915
916 return cached > 0;
917}
918
94959f0f
LP
919int block_get_whole_disk(dev_t d, dev_t *ret) {
920 char *p, *s;
921 int r;
922 unsigned n, m;
923
924 assert(ret);
925
926 /* If it has a queue this is good enough for us */
927 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", major(d), minor(d)) < 0)
928 return -ENOMEM;
929
930 r = access(p, F_OK);
931 free(p);
932
933 if (r >= 0) {
934 *ret = d;
935 return 0;
936 }
937
938 /* If it is a partition find the originating device */
939 if (asprintf(&p, "/sys/dev/block/%u:%u/partition", major(d), minor(d)) < 0)
940 return -ENOMEM;
941
942 r = access(p, F_OK);
943 free(p);
944
945 if (r < 0)
946 return -ENOENT;
947
948 /* Get parent dev_t */
949 if (asprintf(&p, "/sys/dev/block/%u:%u/../dev", major(d), minor(d)) < 0)
950 return -ENOMEM;
951
952 r = read_one_line_file(p, &s);
953 free(p);
954
955 if (r < 0)
956 return r;
957
958 r = sscanf(s, "%u:%u", &m, &n);
959 free(s);
960
961 if (r != 2)
962 return -EINVAL;
963
964 /* Only return this if it is really good enough for us. */
965 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", m, n) < 0)
966 return -ENOMEM;
967
968 r = access(p, F_OK);
969 free(p);
970
971 if (r >= 0) {
972 *ret = makedev(m, n);
973 return 0;
974 }
975
976 return -ENOENT;
977}
978
f41607a6
LP
979static const char *const ioprio_class_table[] = {
980 [IOPRIO_CLASS_NONE] = "none",
981 [IOPRIO_CLASS_RT] = "realtime",
982 [IOPRIO_CLASS_BE] = "best-effort",
983 [IOPRIO_CLASS_IDLE] = "idle"
984};
985
f8b69d1d 986DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX);
f41607a6
LP
987
988static const char *const sigchld_code_table[] = {
989 [CLD_EXITED] = "exited",
990 [CLD_KILLED] = "killed",
991 [CLD_DUMPED] = "dumped",
992 [CLD_TRAPPED] = "trapped",
993 [CLD_STOPPED] = "stopped",
994 [CLD_CONTINUED] = "continued",
995};
996
997DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
998
999static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = {
1000 [LOG_FAC(LOG_KERN)] = "kern",
1001 [LOG_FAC(LOG_USER)] = "user",
1002 [LOG_FAC(LOG_MAIL)] = "mail",
1003 [LOG_FAC(LOG_DAEMON)] = "daemon",
1004 [LOG_FAC(LOG_AUTH)] = "auth",
1005 [LOG_FAC(LOG_SYSLOG)] = "syslog",
1006 [LOG_FAC(LOG_LPR)] = "lpr",
1007 [LOG_FAC(LOG_NEWS)] = "news",
1008 [LOG_FAC(LOG_UUCP)] = "uucp",
1009 [LOG_FAC(LOG_CRON)] = "cron",
1010 [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
1011 [LOG_FAC(LOG_FTP)] = "ftp",
1012 [LOG_FAC(LOG_LOCAL0)] = "local0",
1013 [LOG_FAC(LOG_LOCAL1)] = "local1",
1014 [LOG_FAC(LOG_LOCAL2)] = "local2",
1015 [LOG_FAC(LOG_LOCAL3)] = "local3",
1016 [LOG_FAC(LOG_LOCAL4)] = "local4",
1017 [LOG_FAC(LOG_LOCAL5)] = "local5",
1018 [LOG_FAC(LOG_LOCAL6)] = "local6",
1019 [LOG_FAC(LOG_LOCAL7)] = "local7"
1020};
1021
f8b69d1d 1022DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_facility_unshifted, int, LOG_FAC(~0));
f41607a6 1023
adb8ec96
EV
1024bool log_facility_unshifted_is_valid(int facility) {
1025 return facility >= 0 && facility <= LOG_FAC(~0);
1026}
1027
f41607a6
LP
1028static const char *const log_level_table[] = {
1029 [LOG_EMERG] = "emerg",
1030 [LOG_ALERT] = "alert",
1031 [LOG_CRIT] = "crit",
1032 [LOG_ERR] = "err",
1033 [LOG_WARNING] = "warning",
1034 [LOG_NOTICE] = "notice",
1035 [LOG_INFO] = "info",
1036 [LOG_DEBUG] = "debug"
1037};
1038
f8b69d1d 1039DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_level, int, LOG_DEBUG);
f41607a6 1040
adb8ec96
EV
1041bool log_level_is_valid(int level) {
1042 return level >= 0 && level <= LOG_DEBUG;
1043}
1044
f41607a6
LP
1045static const char* const sched_policy_table[] = {
1046 [SCHED_OTHER] = "other",
1047 [SCHED_BATCH] = "batch",
1048 [SCHED_IDLE] = "idle",
1049 [SCHED_FIFO] = "fifo",
1050 [SCHED_RR] = "rr"
1051};
1052
f8b69d1d 1053DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX);
f41607a6 1054
65457142
FC
1055bool kexec_loaded(void) {
1056 bool loaded = false;
1057 char *s;
1058
1059 if (read_one_line_file("/sys/kernel/kexec_loaded", &s) >= 0) {
1060 if (s[0] == '1')
1061 loaded = true;
1062 free(s);
1063 }
1064 return loaded;
1065}
fb9de93d 1066
87d2c1ff
LP
1067int prot_from_flags(int flags) {
1068
1069 switch (flags & O_ACCMODE) {
1070
1071 case O_RDONLY:
1072 return PROT_READ;
1073
1074 case O_WRONLY:
1075 return PROT_WRITE;
1076
1077 case O_RDWR:
1078 return PROT_READ|PROT_WRITE;
1079
1080 default:
1081 return -EINVAL;
1082 }
7c99e0c1 1083}
689b9a22 1084
55d7bfc1
LP
1085void* memdup(const void *p, size_t l) {
1086 void *r;
1087
1088 assert(p);
1089
1090 r = malloc(l);
1091 if (!r)
1092 return NULL;
1093
1094 memcpy(r, p, l);
1095 return r;
1096}
bb99a35a 1097
9bdc770c 1098int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
6bb92a16 1099 bool stdout_is_tty, stderr_is_tty;
8a7c93d8
LP
1100 pid_t parent_pid, agent_pid;
1101 sigset_t ss, saved_ss;
6bb92a16
LP
1102 unsigned n, i;
1103 va_list ap;
1104 char **l;
1105
1106 assert(pid);
1107 assert(path);
1108
6bb92a16
LP
1109 /* Spawns a temporary TTY agent, making sure it goes away when
1110 * we go away */
1111
8a7c93d8
LP
1112 parent_pid = getpid();
1113
1114 /* First we temporarily block all signals, so that the new
1115 * child has them blocked initially. This way, we can be sure
1116 * that SIGTERMs are not lost we might send to the agent. */
1117 assert_se(sigfillset(&ss) >= 0);
1118 assert_se(sigprocmask(SIG_SETMASK, &ss, &saved_ss) >= 0);
1119
6bb92a16 1120 agent_pid = fork();
8a7c93d8
LP
1121 if (agent_pid < 0) {
1122 assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0);
6bb92a16 1123 return -errno;
8a7c93d8 1124 }
6bb92a16
LP
1125
1126 if (agent_pid != 0) {
8a7c93d8 1127 assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0);
6bb92a16
LP
1128 *pid = agent_pid;
1129 return 0;
1130 }
1131
1132 /* In the child:
1133 *
1134 * Make sure the agent goes away when the parent dies */
1135 if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
1136 _exit(EXIT_FAILURE);
1137
8a7c93d8
LP
1138 /* Make sure we actually can kill the agent, if we need to, in
1139 * case somebody invoked us from a shell script that trapped
1140 * SIGTERM or so... */
ce30c8dc
LP
1141 (void) reset_all_signal_handlers();
1142 (void) reset_signal_mask();
8a7c93d8 1143
6bb92a16 1144 /* Check whether our parent died before we were able
8a7c93d8 1145 * to set the death signal and unblock the signals */
6bb92a16
LP
1146 if (getppid() != parent_pid)
1147 _exit(EXIT_SUCCESS);
1148
1149 /* Don't leak fds to the agent */
9bdc770c 1150 close_all_fds(except, n_except);
6bb92a16
LP
1151
1152 stdout_is_tty = isatty(STDOUT_FILENO);
1153 stderr_is_tty = isatty(STDERR_FILENO);
1154
1155 if (!stdout_is_tty || !stderr_is_tty) {
8a7c93d8
LP
1156 int fd;
1157
6bb92a16
LP
1158 /* Detach from stdout/stderr. and reopen
1159 * /dev/tty for them. This is important to
1160 * ensure that when systemctl is started via
1161 * popen() or a similar call that expects to
1162 * read EOF we actually do generate EOF and
1163 * not delay this indefinitely by because we
1164 * keep an unused copy of stdin around. */
1165 fd = open("/dev/tty", O_WRONLY);
1166 if (fd < 0) {
56f64d95 1167 log_error_errno(errno, "Failed to open /dev/tty: %m");
6bb92a16
LP
1168 _exit(EXIT_FAILURE);
1169 }
1170
1171 if (!stdout_is_tty)
1172 dup2(fd, STDOUT_FILENO);
1173
1174 if (!stderr_is_tty)
1175 dup2(fd, STDERR_FILENO);
1176
1177 if (fd > 2)
1178 close(fd);
1179 }
1180
1181 /* Count arguments */
1182 va_start(ap, path);
1183 for (n = 0; va_arg(ap, char*); n++)
1184 ;
1185 va_end(ap);
1186
1187 /* Allocate strv */
1188 l = alloca(sizeof(char *) * (n + 1));
1189
1190 /* Fill in arguments */
1191 va_start(ap, path);
1192 for (i = 0; i <= n; i++)
1193 l[i] = va_arg(ap, char*);
1194 va_end(ap);
1195
1196 execv(path, l);
1197 _exit(EXIT_FAILURE);
1198}
68faf98c 1199
3d7415f4
LP
1200bool http_etag_is_valid(const char *etag) {
1201 if (isempty(etag))
1202 return false;
1203
1204 if (!endswith(etag, "\""))
1205 return false;
1206
1207 if (!startswith(etag, "\"") && !startswith(etag, "W/\""))
1208 return false;
1209
1210 return true;
1211}
1212
a2e03378
LP
1213bool http_url_is_valid(const char *url) {
1214 const char *p;
49dbfa7b 1215
a2e03378
LP
1216 if (isempty(url))
1217 return false;
49dbfa7b 1218
a2e03378
LP
1219 p = startswith(url, "http://");
1220 if (!p)
1221 p = startswith(url, "https://");
1222 if (!p)
1223 return false;
49dbfa7b 1224
a2e03378
LP
1225 if (isempty(p))
1226 return false;
49dbfa7b 1227
a2e03378
LP
1228 return ascii_is_valid(p);
1229}
49dbfa7b 1230
a2e03378
LP
1231bool documentation_url_is_valid(const char *url) {
1232 const char *p;
1233
1234 if (isempty(url))
1235 return false;
1236
1237 if (http_url_is_valid(url))
49dbfa7b
LP
1238 return true;
1239
a2e03378
LP
1240 p = startswith(url, "file:/");
1241 if (!p)
1242 p = startswith(url, "info:");
1243 if (!p)
1244 p = startswith(url, "man:");
1245
1246 if (isempty(p))
1247 return false;
1248
1249 return ascii_is_valid(p);
49dbfa7b 1250}
9be346c9
HH
1251
1252bool in_initrd(void) {
73020ab2 1253 static int saved = -1;
825c6fe5 1254 struct statfs s;
8f33b5b8 1255
825c6fe5
LP
1256 if (saved >= 0)
1257 return saved;
1258
1259 /* We make two checks here:
1260 *
1261 * 1. the flag file /etc/initrd-release must exist
1262 * 2. the root file system must be a memory file system
1263 *
1264 * The second check is extra paranoia, since misdetecting an
1265 * initrd can have bad bad consequences due the initrd
1266 * emptying when transititioning to the main systemd.
1267 */
1268
1269 saved = access("/etc/initrd-release", F_OK) >= 0 &&
1270 statfs("/", &s) >= 0 &&
943aad8c 1271 is_temporary_fs(&s);
9be346c9 1272
8f33b5b8 1273 return saved;
9be346c9 1274}
069cfc85 1275
0b507b17
LP
1276bool string_is_safe(const char *p) {
1277 const char *t;
1278
6294aa76
LP
1279 if (!p)
1280 return false;
0b507b17
LP
1281
1282 for (t = p; *t; t++) {
01539d6e 1283 if (*t > 0 && *t < ' ')
0b507b17
LP
1284 return false;
1285
843f6bf4 1286 if (strchr("\\\"\'\x7f", *t))
0b507b17
LP
1287 return false;
1288 }
1289
1290 return true;
1291}
cfbc22ab 1292
a9e12476
KS
1293/* hey glibc, APIs with callbacks without a user pointer are so useless */
1294void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
1c574591 1295 int (*compar) (const void *, const void *, void *), void *arg) {
a9e12476
KS
1296 size_t l, u, idx;
1297 const void *p;
1298 int comparison;
1299
1300 l = 0;
1301 u = nmemb;
1302 while (l < u) {
1303 idx = (l + u) / 2;
1304 p = (void *)(((const char *) base) + (idx * size));
1305 comparison = compar(key, p, arg);
1306 if (comparison < 0)
1307 u = idx;
1308 else if (comparison > 0)
1309 l = idx + 1;
1310 else
1311 return (void *)p;
1312 }
1313 return NULL;
1314}
09017585 1315
20f56fdd
DR
1316void init_gettext(void) {
1317 setlocale(LC_ALL, "");
1318 textdomain(GETTEXT_PACKAGE);
1319}
1320
09017585
MS
1321bool is_locale_utf8(void) {
1322 const char *set;
1323 static int cached_answer = -1;
1324
1325 if (cached_answer >= 0)
1326 goto out;
1327
1328 if (!setlocale(LC_ALL, "")) {
1329 cached_answer = true;
1330 goto out;
1331 }
1332
1333 set = nl_langinfo(CODESET);
1334 if (!set) {
1335 cached_answer = true;
1336 goto out;
1337 }
1338
f168c273 1339 if (streq(set, "UTF-8")) {
fee79e01
HH
1340 cached_answer = true;
1341 goto out;
1342 }
1343
6cf2f1d9
HH
1344 /* For LC_CTYPE=="C" return true, because CTYPE is effectly
1345 * unset and everything can do to UTF-8 nowadays. */
fee79e01
HH
1346 set = setlocale(LC_CTYPE, NULL);
1347 if (!set) {
1348 cached_answer = true;
1349 goto out;
1350 }
1351
6cf2f1d9
HH
1352 /* Check result, but ignore the result if C was set
1353 * explicitly. */
1354 cached_answer =
9797f89b 1355 STR_IN_SET(set, "C", "POSIX") &&
6cf2f1d9
HH
1356 !getenv("LC_ALL") &&
1357 !getenv("LC_CTYPE") &&
1358 !getenv("LANG");
fee79e01 1359
09017585 1360out:
6cf2f1d9 1361 return (bool) cached_answer;
09017585 1362}
c339d977
MS
1363
1364const char *draw_special_char(DrawSpecialChar ch) {
1365 static const char *draw_table[2][_DRAW_SPECIAL_CHAR_MAX] = {
6b01f1d3 1366
c339d977 1367 /* UTF-8 */ {
6b01f1d3 1368 [DRAW_TREE_VERTICAL] = "\342\224\202 ", /* │ */
45a5ff0d
MS
1369 [DRAW_TREE_BRANCH] = "\342\224\234\342\224\200", /* ├─ */
1370 [DRAW_TREE_RIGHT] = "\342\224\224\342\224\200", /* └─ */
55c0b89c 1371 [DRAW_TREE_SPACE] = " ", /* */
6b01f1d3
LP
1372 [DRAW_TRIANGULAR_BULLET] = "\342\200\243", /* ‣ */
1373 [DRAW_BLACK_CIRCLE] = "\342\227\217", /* ● */
1374 [DRAW_ARROW] = "\342\206\222", /* → */
13f8b8cb 1375 [DRAW_DASH] = "\342\200\223", /* – */
c339d977 1376 },
6b01f1d3 1377
c339d977 1378 /* ASCII fallback */ {
6b01f1d3 1379 [DRAW_TREE_VERTICAL] = "| ",
45a5ff0d
MS
1380 [DRAW_TREE_BRANCH] = "|-",
1381 [DRAW_TREE_RIGHT] = "`-",
55c0b89c 1382 [DRAW_TREE_SPACE] = " ",
6b01f1d3
LP
1383 [DRAW_TRIANGULAR_BULLET] = ">",
1384 [DRAW_BLACK_CIRCLE] = "*",
1385 [DRAW_ARROW] = "->",
13f8b8cb 1386 [DRAW_DASH] = "-",
c339d977
MS
1387 }
1388 };
1389
1390 return draw_table[!is_locale_utf8()][ch];
1391}
409bc9c3 1392
240dbaa4
LP
1393int on_ac_power(void) {
1394 bool found_offline = false, found_online = false;
1395 _cleanup_closedir_ DIR *d = NULL;
1396
1397 d = opendir("/sys/class/power_supply");
1398 if (!d)
6d890034 1399 return errno == ENOENT ? true : -errno;
240dbaa4
LP
1400
1401 for (;;) {
1402 struct dirent *de;
240dbaa4
LP
1403 _cleanup_close_ int fd = -1, device = -1;
1404 char contents[6];
1405 ssize_t n;
240dbaa4 1406
3fd11280
FW
1407 errno = 0;
1408 de = readdir(d);
1409 if (!de && errno != 0)
1410 return -errno;
240dbaa4
LP
1411
1412 if (!de)
1413 break;
1414
a34bf9db 1415 if (hidden_file(de->d_name))
240dbaa4
LP
1416 continue;
1417
1418 device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY);
1419 if (device < 0) {
1420 if (errno == ENOENT || errno == ENOTDIR)
1421 continue;
1422
1423 return -errno;
1424 }
1425
1426 fd = openat(device, "type", O_RDONLY|O_CLOEXEC|O_NOCTTY);
1427 if (fd < 0) {
1428 if (errno == ENOENT)
1429 continue;
1430
1431 return -errno;
1432 }
1433
1434 n = read(fd, contents, sizeof(contents));
1435 if (n < 0)
1436 return -errno;
1437
1438 if (n != 6 || memcmp(contents, "Mains\n", 6))
1439 continue;
1440
03e334a1 1441 safe_close(fd);
240dbaa4
LP
1442 fd = openat(device, "online", O_RDONLY|O_CLOEXEC|O_NOCTTY);
1443 if (fd < 0) {
1444 if (errno == ENOENT)
1445 continue;
1446
1447 return -errno;
1448 }
1449
1450 n = read(fd, contents, sizeof(contents));
1451 if (n < 0)
1452 return -errno;
1453
1454 if (n != 2 || contents[1] != '\n')
1455 return -EIO;
1456
1457 if (contents[0] == '1') {
1458 found_online = true;
1459 break;
1460 } else if (contents[0] == '0')
1461 found_offline = true;
1462 else
1463 return -EIO;
1464 }
1465
1466 return found_online || !found_offline;
1467}
fabe5c0e 1468
ca2d3784
ZJS
1469void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) {
1470 size_t a, newalloc;
392d5b37
LP
1471 void *q;
1472
98088803 1473 assert(p);
e93c33d4
SL
1474 assert(allocated);
1475
392d5b37
LP
1476 if (*allocated >= need)
1477 return *p;
1478
ca2d3784
ZJS
1479 newalloc = MAX(need * 2, 64u / size);
1480 a = newalloc * size;
98088803
LP
1481
1482 /* check for overflows */
ca2d3784 1483 if (a < size * need)
98088803
LP
1484 return NULL;
1485
392d5b37
LP
1486 q = realloc(*p, a);
1487 if (!q)
1488 return NULL;
1489
1490 *p = q;
ca2d3784 1491 *allocated = newalloc;
392d5b37
LP
1492 return q;
1493}
aa96c6cb 1494
ca2d3784 1495void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size) {
98088803 1496 size_t prev;
4545a231
DH
1497 uint8_t *q;
1498
98088803
LP
1499 assert(p);
1500 assert(allocated);
1501
1502 prev = *allocated;
1503
ca2d3784 1504 q = greedy_realloc(p, allocated, need, size);
4545a231
DH
1505 if (!q)
1506 return NULL;
1507
1508 if (*allocated > prev)
ca2d3784 1509 memzero(q + prev * size, (*allocated - prev) * size);
4545a231
DH
1510
1511 return q;
1512}
1513
aa96c6cb
LP
1514bool id128_is_valid(const char *s) {
1515 size_t i, l;
1516
1517 l = strlen(s);
1518 if (l == 32) {
1519
1520 /* Simple formatted 128bit hex string */
1521
1522 for (i = 0; i < l; i++) {
1523 char c = s[i];
1524
1525 if (!(c >= '0' && c <= '9') &&
1526 !(c >= 'a' && c <= 'z') &&
1527 !(c >= 'A' && c <= 'Z'))
1528 return false;
1529 }
1530
1531 } else if (l == 36) {
1532
1533 /* Formatted UUID */
1534
1535 for (i = 0; i < l; i++) {
1536 char c = s[i];
1537
1538 if ((i == 8 || i == 13 || i == 18 || i == 23)) {
1539 if (c != '-')
1540 return false;
1541 } else {
1542 if (!(c >= '0' && c <= '9') &&
1543 !(c >= 'a' && c <= 'z') &&
1544 !(c >= 'A' && c <= 'Z'))
1545 return false;
1546 }
1547 }
1548
1549 } else
1550 return false;
1551
1552 return true;
1553}
7085053a 1554
74df0fca 1555int shall_restore_state(void) {
1a299299 1556 _cleanup_free_ char *value = NULL;
74df0fca 1557 int r;
295edddf 1558
1a299299 1559 r = get_proc_cmdline_key("systemd.restore_state=", &value);
74df0fca
LP
1560 if (r < 0)
1561 return r;
1a299299
LP
1562 if (r == 0)
1563 return true;
295edddf 1564
1a299299 1565 return parse_boolean(value) != 0;
74df0fca
LP
1566}
1567
1568int proc_cmdline(char **ret) {
b5884878 1569 assert(ret);
295edddf 1570
75f86906 1571 if (detect_container() > 0)
b5884878
LP
1572 return get_process_cmdline(1, 0, false, ret);
1573 else
1574 return read_one_line_file("/proc/cmdline", ret);
295edddf 1575}
bc9fd78c 1576
059cb385 1577int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) {
141a79f4 1578 _cleanup_free_ char *line = NULL;
f32d2db1 1579 const char *p;
141a79f4
ZJS
1580 int r;
1581
059cb385
LP
1582 assert(parse_item);
1583
141a79f4
ZJS
1584 r = proc_cmdline(&line);
1585 if (r < 0)
b5884878 1586 return r;
141a79f4 1587
f32d2db1
LP
1588 p = line;
1589 for (;;) {
1590 _cleanup_free_ char *word = NULL;
1591 char *value = NULL;
141a79f4 1592
12ba2c44 1593 r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX);
f32d2db1
LP
1594 if (r < 0)
1595 return r;
1596 if (r == 0)
1597 break;
141a79f4 1598
059cb385
LP
1599 /* Filter out arguments that are intended only for the
1600 * initrd */
1601 if (!in_initrd() && startswith(word, "rd."))
1602 continue;
1603
1604 value = strchr(word, '=');
1605 if (value)
1606 *(value++) = 0;
1607
1608 r = parse_item(word, value);
1609 if (r < 0)
141a79f4 1610 return r;
141a79f4
ZJS
1611 }
1612
1613 return 0;
1614}
1615
1a299299
LP
1616int get_proc_cmdline_key(const char *key, char **value) {
1617 _cleanup_free_ char *line = NULL, *ret = NULL;
1618 bool found = false;
1619 const char *p;
1620 int r;
1621
1622 assert(key);
1623
1624 r = proc_cmdline(&line);
1625 if (r < 0)
1626 return r;
1627
1628 p = line;
1629 for (;;) {
1630 _cleanup_free_ char *word = NULL;
1631 const char *e;
1632
12ba2c44 1633 r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX);
1a299299
LP
1634 if (r < 0)
1635 return r;
1636 if (r == 0)
1637 break;
1638
1639 /* Filter out arguments that are intended only for the
1640 * initrd */
1641 if (!in_initrd() && startswith(word, "rd."))
1642 continue;
1643
1644 if (value) {
1645 e = startswith(word, key);
1646 if (!e)
1647 continue;
1648
1649 r = free_and_strdup(&ret, e);
1650 if (r < 0)
1651 return r;
1652
1653 found = true;
1654 } else {
1655 if (streq(word, key))
1656 found = true;
1657 }
1658 }
1659
1660 if (value) {
1661 *value = ret;
1662 ret = NULL;
1663 }
1664
1665 return found;
1666
1667}
1668
bc9fd78c
LP
1669int container_get_leader(const char *machine, pid_t *pid) {
1670 _cleanup_free_ char *s = NULL, *class = NULL;
1671 const char *p;
1672 pid_t leader;
1673 int r;
1674
1675 assert(machine);
1676 assert(pid);
1677
b9a8d250
LP
1678 if (!machine_name_is_valid(machine))
1679 return -EINVAL;
1680
63c372cb 1681 p = strjoina("/run/systemd/machines/", machine);
bc9fd78c
LP
1682 r = parse_env_file(p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL);
1683 if (r == -ENOENT)
1684 return -EHOSTDOWN;
1685 if (r < 0)
1686 return r;
1687 if (!s)
1688 return -EIO;
1689
1690 if (!streq_ptr(class, "container"))
1691 return -EIO;
1692
1693 r = parse_pid(s, &leader);
1694 if (r < 0)
1695 return r;
1696 if (leader <= 1)
1697 return -EIO;
1698
1699 *pid = leader;
1700 return 0;
1701}
1702
671c3419
RM
1703int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd) {
1704 _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, netnsfd = -1, usernsfd = -1;
359a06aa 1705 int rfd = -1;
bc9fd78c
LP
1706
1707 assert(pid >= 0);
bc9fd78c 1708
878cd7e9
LP
1709 if (mntns_fd) {
1710 const char *mntns;
a4475f57 1711
878cd7e9
LP
1712 mntns = procfs_file_alloca(pid, "ns/mnt");
1713 mntnsfd = open(mntns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
1714 if (mntnsfd < 0)
1715 return -errno;
1716 }
bc9fd78c 1717
878cd7e9
LP
1718 if (pidns_fd) {
1719 const char *pidns;
1720
1721 pidns = procfs_file_alloca(pid, "ns/pid");
1722 pidnsfd = open(pidns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
1723 if (pidnsfd < 0)
1724 return -errno;
1725 }
1726
1727 if (netns_fd) {
1728 const char *netns;
1729
1730 netns = procfs_file_alloca(pid, "ns/net");
1731 netnsfd = open(netns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
1732 if (netnsfd < 0)
1733 return -errno;
1734 }
1735
671c3419
RM
1736 if (userns_fd) {
1737 const char *userns;
1738
1739 userns = procfs_file_alloca(pid, "ns/user");
1740 usernsfd = open(userns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
1741 if (usernsfd < 0 && errno != ENOENT)
1742 return -errno;
1743 }
1744
878cd7e9
LP
1745 if (root_fd) {
1746 const char *root;
1747
1748 root = procfs_file_alloca(pid, "root");
1749 rfd = open(root, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
1750 if (rfd < 0)
1751 return -errno;
1752 }
1753
1754 if (pidns_fd)
1755 *pidns_fd = pidnsfd;
bc9fd78c 1756
878cd7e9
LP
1757 if (mntns_fd)
1758 *mntns_fd = mntnsfd;
1759
1760 if (netns_fd)
1761 *netns_fd = netnsfd;
1762
671c3419
RM
1763 if (userns_fd)
1764 *userns_fd = usernsfd;
1765
878cd7e9
LP
1766 if (root_fd)
1767 *root_fd = rfd;
1768
671c3419 1769 pidnsfd = mntnsfd = netnsfd = usernsfd = -1;
bc9fd78c
LP
1770
1771 return 0;
1772}
1773
671c3419
RM
1774int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd) {
1775 if (userns_fd >= 0) {
1776 /* Can't setns to your own userns, since then you could
1777 * escalate from non-root to root in your own namespace, so
1778 * check if namespaces equal before attempting to enter. */
1779 _cleanup_free_ char *userns_fd_path = NULL;
1780 int r;
1781 if (asprintf(&userns_fd_path, "/proc/self/fd/%d", userns_fd) < 0)
1782 return -ENOMEM;
1783
1784 r = files_same(userns_fd_path, "/proc/self/ns/user");
1785 if (r < 0)
1786 return r;
1787 if (r)
1788 userns_fd = -1;
1789 }
bc9fd78c 1790
878cd7e9
LP
1791 if (pidns_fd >= 0)
1792 if (setns(pidns_fd, CLONE_NEWPID) < 0)
1793 return -errno;
a4475f57 1794
878cd7e9
LP
1795 if (mntns_fd >= 0)
1796 if (setns(mntns_fd, CLONE_NEWNS) < 0)
1797 return -errno;
bc9fd78c 1798
878cd7e9
LP
1799 if (netns_fd >= 0)
1800 if (setns(netns_fd, CLONE_NEWNET) < 0)
1801 return -errno;
bc9fd78c 1802
671c3419
RM
1803 if (userns_fd >= 0)
1804 if (setns(userns_fd, CLONE_NEWUSER) < 0)
1805 return -errno;
1806
878cd7e9
LP
1807 if (root_fd >= 0) {
1808 if (fchdir(root_fd) < 0)
1809 return -errno;
1810
1811 if (chroot(".") < 0)
1812 return -errno;
1813 }
bc9fd78c 1814
b4da6d6b 1815 return reset_uid_gid();
bc9fd78c 1816}
bf108e55 1817
fdb9161c
LP
1818int fd_warn_permissions(const char *path, int fd) {
1819 struct stat st;
1820
1821 if (fstat(fd, &st) < 0)
1822 return -errno;
1823
1824 if (st.st_mode & 0111)
1825 log_warning("Configuration file %s is marked executable. Please remove executable permission bits. Proceeding anyway.", path);
1826
1827 if (st.st_mode & 0002)
1828 log_warning("Configuration file %s is marked world-writable. Please remove world writability permission bits. Proceeding anyway.", path);
1829
1830 if (getpid() == 1 && (st.st_mode & 0044) != 0044)
1831 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);
1832
1833 return 0;
1834}
6afc95b7 1835
ac45f971 1836unsigned long personality_from_string(const char *p) {
6afc95b7
LP
1837
1838 /* Parse a personality specifier. We introduce our own
1839 * identifiers that indicate specific ABIs, rather than just
1840 * hints regarding the register size, since we want to keep
1841 * things open for multiple locally supported ABIs for the
1842 * same register size. We try to reuse the ABI identifiers
1843 * used by libseccomp. */
1844
1845#if defined(__x86_64__)
1846
1847 if (streq(p, "x86"))
1848 return PER_LINUX32;
1849
1850 if (streq(p, "x86-64"))
1851 return PER_LINUX;
1852
1853#elif defined(__i386__)
1854
1855 if (streq(p, "x86"))
1856 return PER_LINUX;
7517f51e
HB
1857
1858#elif defined(__s390x__)
1859
1860 if (streq(p, "s390"))
1861 return PER_LINUX32;
1862
1863 if (streq(p, "s390x"))
1864 return PER_LINUX;
1865
1866#elif defined(__s390__)
1867
1868 if (streq(p, "s390"))
1869 return PER_LINUX;
6afc95b7
LP
1870#endif
1871
050f7277 1872 return PERSONALITY_INVALID;
6afc95b7 1873}
ac45f971
LP
1874
1875const char* personality_to_string(unsigned long p) {
1876
1877#if defined(__x86_64__)
1878
1879 if (p == PER_LINUX32)
1880 return "x86";
1881
1882 if (p == PER_LINUX)
1883 return "x86-64";
1884
1885#elif defined(__i386__)
1886
1887 if (p == PER_LINUX)
1888 return "x86";
7517f51e
HB
1889
1890#elif defined(__s390x__)
1891
1892 if (p == PER_LINUX)
1893 return "s390x";
1894
1895 if (p == PER_LINUX32)
1896 return "s390";
1897
1898#elif defined(__s390__)
1899
1900 if (p == PER_LINUX)
1901 return "s390";
1902
ac45f971
LP
1903#endif
1904
1905 return NULL;
1906}
1c231f56
LP
1907
1908uint64_t physical_memory(void) {
1909 long mem;
1910
1911 /* We return this as uint64_t in case we are running as 32bit
1912 * process on a 64bit kernel with huge amounts of memory */
1913
1914 mem = sysconf(_SC_PHYS_PAGES);
1915 assert(mem > 0);
1916
1917 return (uint64_t) mem * (uint64_t) page_size();
1918}
6db615c1 1919
966bff26 1920int update_reboot_param_file(const char *param) {
c5220a94
MO
1921 int r = 0;
1922
1923 if (param) {
4c1fc3e4 1924 r = write_string_file(REBOOT_PARAM_FILE, param, WRITE_STRING_FILE_CREATE);
c5220a94 1925 if (r < 0)
e53fc357 1926 return log_error_errno(r, "Failed to write reboot param to "REBOOT_PARAM_FILE": %m");
c5220a94 1927 } else
e53fc357 1928 (void) unlink(REBOOT_PARAM_FILE);
c5220a94 1929
e53fc357 1930 return 0;
c5220a94 1931}
6d313367 1932
5261ba90
TT
1933int is_symlink(const char *path) {
1934 struct stat info;
1935
1936 if (lstat(path, &info) < 0)
1937 return -errno;
1938
be57e297
LP
1939 return !!S_ISLNK(info.st_mode);
1940}
5261ba90 1941
be57e297
LP
1942int is_dir(const char* path, bool follow) {
1943 struct stat st;
d1bddcec 1944 int r;
be57e297 1945
d1bddcec
LP
1946 if (follow)
1947 r = stat(path, &st);
1948 else
1949 r = lstat(path, &st);
1950 if (r < 0)
1951 return -errno;
be57e297
LP
1952
1953 return !!S_ISDIR(st.st_mode);
a0627f82 1954}
7629889c 1955
ce5b3ad4
SJ
1956int is_device_node(const char *path) {
1957 struct stat info;
1958
1959 if (lstat(path, &info) < 0)
1960 return -errno;
1961
1962 return !!(S_ISBLK(info.st_mode) || S_ISCHR(info.st_mode));
1963}
1964
3d7415f4
LP
1965int syslog_parse_priority(const char **p, int *priority, bool with_facility) {
1966 int a = 0, b = 0, c = 0;
1967 int k;
1968
1969 assert(p);
1970 assert(*p);
1971 assert(priority);
1972
1973 if ((*p)[0] != '<')
1974 return 0;
1975
1976 if (!strchr(*p, '>'))
1977 return 0;
1978
1979 if ((*p)[2] == '>') {
1980 c = undecchar((*p)[1]);
1981 k = 3;
1982 } else if ((*p)[3] == '>') {
1983 b = undecchar((*p)[1]);
1984 c = undecchar((*p)[2]);
1985 k = 4;
1986 } else if ((*p)[4] == '>') {
1987 a = undecchar((*p)[1]);
1988 b = undecchar((*p)[2]);
1989 c = undecchar((*p)[3]);
1990 k = 5;
1991 } else
1992 return 0;
1993
1994 if (a < 0 || b < 0 || c < 0 ||
1995 (!with_facility && (a || b || c > 7)))
1996 return 0;
1997
1998 if (with_facility)
1999 *priority = a*100 + b*10 + c;
2000 else
2001 *priority = (*priority & LOG_FACMASK) | c;
2002
2003 *p += k;
2004 return 1;
2005}
9cad100e
BB
2006
2007ssize_t string_table_lookup(const char * const *table, size_t len, const char *key) {
2008 size_t i;
2009
2010 if (!key)
2011 return -1;
2012
2013 for (i = 0; i < len; ++i)
2014 if (streq_ptr(table[i], key))
8c721f2b 2015 return (ssize_t) i;
9cad100e
BB
2016
2017 return -1;
2018}
1c8da044 2019
f85ef957
AC
2020int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) {
2021 struct stat buf;
2022 int ret;
2023
2024 ret = renameat2(olddirfd, oldpath, newdirfd, newpath, RENAME_NOREPLACE);
2025 if (ret >= 0)
2026 return 0;
2027
715d7599
RM
2028 /* renameat2() exists since Linux 3.15, btrfs added support for it later.
2029 * If it is not implemented, fallback to another method. */
2030 if (!IN_SET(errno, EINVAL, ENOSYS))
f85ef957
AC
2031 return -errno;
2032
2033 /* The link()/unlink() fallback does not work on directories. But
2034 * renameat() without RENAME_NOREPLACE gives the same semantics on
2035 * directories, except when newpath is an *empty* directory. This is
2036 * good enough. */
2037 ret = fstatat(olddirfd, oldpath, &buf, AT_SYMLINK_NOFOLLOW);
2038 if (ret >= 0 && S_ISDIR(buf.st_mode)) {
2039 ret = renameat(olddirfd, oldpath, newdirfd, newpath);
2040 return ret >= 0 ? 0 : -errno;
2041 }
2042
2043 /* If it is not a directory, use the link()/unlink() fallback. */
2044 ret = linkat(olddirfd, oldpath, newdirfd, newpath, 0);
2045 if (ret < 0)
2046 return -errno;
2047
2048 ret = unlinkat(olddirfd, oldpath, 0);
2049 if (ret < 0) {
2050 /* backup errno before the following unlinkat() alters it */
2051 ret = errno;
2052 (void) unlinkat(newdirfd, newpath, 0);
2053 errno = ret;
2054 return -errno;
2055 }
2056
2057 return 0;
2058}
019c7fba 2059
3f6fd1ba
LP
2060int version(void) {
2061 puts(PACKAGE_STRING "\n"
2062 SYSTEMD_FEATURES);
2063 return 0;
2064}
8dd4c05b
LP
2065
2066bool fdname_is_valid(const char *s) {
2067 const char *p;
2068
0a3bb96e 2069 /* Validates a name for $LISTEN_FDNAMES. We basically allow
8dd4c05b
LP
2070 * everything ASCII that's not a control character. Also, as
2071 * special exception the ":" character is not allowed, as we
0a3bb96e 2072 * use that as field separator in $LISTEN_FDNAMES.
8dd4c05b 2073 *
0a3bb96e
LP
2074 * Note that the empty string is explicitly allowed
2075 * here. However, we limit the length of the names to 255
2076 * characters. */
8dd4c05b
LP
2077
2078 if (!s)
2079 return false;
2080
2081 for (p = s; *p; p++) {
2082 if (*p < ' ')
2083 return false;
2084 if (*p >= 127)
2085 return false;
2086 if (*p == ':')
2087 return false;
2088 }
2089
2090 return p - s < 256;
2091}
257b0719
EV
2092
2093bool oom_score_adjust_is_valid(int oa) {
2094 return oa >= OOM_SCORE_ADJ_MIN && oa <= OOM_SCORE_ADJ_MAX;
2095}