]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/util.c
util-lib: move a number of fs operations into fs-util.[ch]
[thirdparty/systemd.git] / src / basic / util.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <ctype.h>
23 #include <dirent.h>
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <glob.h>
27 #include <grp.h>
28 #include <langinfo.h>
29 #include <libintl.h>
30 #include <limits.h>
31 #include <linux/magic.h>
32 #include <linux/oom.h>
33 #include <linux/sched.h>
34 #include <locale.h>
35 #include <poll.h>
36 #include <pwd.h>
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>
45 #include <sys/mman.h>
46 #include <sys/mount.h>
47 #include <sys/personality.h>
48 #include <sys/prctl.h>
49 #include <sys/stat.h>
50 #include <sys/statvfs.h>
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>
56 #include <syslog.h>
57 #include <unistd.h>
58
59 /* When we include libgen.h because we need dirname() we immediately
60 * undefine basename() since libgen.h defines it as a macro to the
61 * POSIX version which is really broken. We prefer GNU basename(). */
62 #include <libgen.h>
63 #undef basename
64
65 #ifdef HAVE_SYS_AUXV_H
66 #include <sys/auxv.h>
67 #endif
68
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
73 #include "build.h"
74 #include "def.h"
75 #include "device-nodes.h"
76 #include "env-util.h"
77 #include "escape.h"
78 #include "exit-status.h"
79 #include "fd-util.h"
80 #include "fileio.h"
81 #include "formats-util.h"
82 #include "gunicode.h"
83 #include "hashmap.h"
84 #include "hostname-util.h"
85 #include "ioprio.h"
86 #include "log.h"
87 #include "macro.h"
88 #include "missing.h"
89 #include "mkdir.h"
90 #include "hexdecoct.h"
91 #include "parse-util.h"
92 #include "path-util.h"
93 #include "process-util.h"
94 #include "random-util.h"
95 #include "signal-util.h"
96 #include "sparse-endian.h"
97 #include "string-util.h"
98 #include "strv.h"
99 #include "terminal-util.h"
100 #include "user-util.h"
101 #include "utf8.h"
102 #include "util.h"
103 #include "virt.h"
104 #include "dirent-util.h"
105
106 /* Put this test here for a lack of better place */
107 assert_cc(EAGAIN == EWOULDBLOCK);
108
109 int saved_argc = 0;
110 char **saved_argv = NULL;
111
112 size_t page_size(void) {
113 static thread_local size_t pgsz = 0;
114 long r;
115
116 if (_likely_(pgsz > 0))
117 return pgsz;
118
119 r = sysconf(_SC_PAGESIZE);
120 assert(r > 0);
121
122 pgsz = (size_t) r;
123 return pgsz;
124 }
125
126 bool fstype_is_network(const char *fstype) {
127 static const char table[] =
128 "afs\0"
129 "cifs\0"
130 "smbfs\0"
131 "sshfs\0"
132 "ncpfs\0"
133 "ncp\0"
134 "nfs\0"
135 "nfs4\0"
136 "gfs\0"
137 "gfs2\0"
138 "glusterfs\0";
139
140 const char *x;
141
142 x = startswith(fstype, "fuse.");
143 if (x)
144 fstype = x;
145
146 return nulstr_contains(table, fstype);
147 }
148
149 int dir_is_empty(const char *path) {
150 _cleanup_closedir_ DIR *d;
151 struct dirent *de;
152
153 d = opendir(path);
154 if (!d)
155 return -errno;
156
157 FOREACH_DIRENT(de, d, return -errno)
158 return 0;
159
160 return 1;
161 }
162
163 void rename_process(const char name[8]) {
164 assert(name);
165
166 /* This is a like a poor man's setproctitle(). It changes the
167 * comm field, argv[0], and also the glibc's internally used
168 * name of the process. For the first one a limit of 16 chars
169 * applies, to the second one usually one of 10 (i.e. length
170 * of "/sbin/init"), to the third one one of 7 (i.e. length of
171 * "systemd"). If you pass a longer string it will be
172 * truncated */
173
174 prctl(PR_SET_NAME, name);
175
176 if (program_invocation_name)
177 strncpy(program_invocation_name, name, strlen(program_invocation_name));
178
179 if (saved_argc > 0) {
180 int i;
181
182 if (saved_argv[0])
183 strncpy(saved_argv[0], name, strlen(saved_argv[0]));
184
185 for (i = 1; i < saved_argc; i++) {
186 if (!saved_argv[i])
187 break;
188
189 memzero(saved_argv[i], strlen(saved_argv[i]));
190 }
191 }
192 }
193
194 bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) {
195 assert(s);
196 assert_cc(sizeof(statfs_f_type_t) >= sizeof(s->f_type));
197
198 return F_TYPE_EQUAL(s->f_type, magic_value);
199 }
200
201 int fd_check_fstype(int fd, statfs_f_type_t magic_value) {
202 struct statfs s;
203
204 if (fstatfs(fd, &s) < 0)
205 return -errno;
206
207 return is_fs_type(&s, magic_value);
208 }
209
210 int path_check_fstype(const char *path, statfs_f_type_t magic_value) {
211 _cleanup_close_ int fd = -1;
212
213 fd = open(path, O_RDONLY);
214 if (fd < 0)
215 return -errno;
216
217 return fd_check_fstype(fd, magic_value);
218 }
219
220 bool is_temporary_fs(const struct statfs *s) {
221 return is_fs_type(s, TMPFS_MAGIC) ||
222 is_fs_type(s, RAMFS_MAGIC);
223 }
224
225 int fd_is_temporary_fs(int fd) {
226 struct statfs s;
227
228 if (fstatfs(fd, &s) < 0)
229 return -errno;
230
231 return is_temporary_fs(&s);
232 }
233
234 int files_same(const char *filea, const char *fileb) {
235 struct stat a, b;
236
237 if (stat(filea, &a) < 0)
238 return -errno;
239
240 if (stat(fileb, &b) < 0)
241 return -errno;
242
243 return a.st_dev == b.st_dev &&
244 a.st_ino == b.st_ino;
245 }
246
247 int running_in_chroot(void) {
248 int ret;
249
250 ret = files_same("/proc/1/root", "/");
251 if (ret < 0)
252 return ret;
253
254 return ret == 0;
255 }
256
257 noreturn void freeze(void) {
258
259 /* Make sure nobody waits for us on a socket anymore */
260 close_all_fds(NULL, 0);
261
262 sync();
263
264 for (;;)
265 pause();
266 }
267
268 bool null_or_empty(struct stat *st) {
269 assert(st);
270
271 if (S_ISREG(st->st_mode) && st->st_size <= 0)
272 return true;
273
274 if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
275 return true;
276
277 return false;
278 }
279
280 int null_or_empty_path(const char *fn) {
281 struct stat st;
282
283 assert(fn);
284
285 if (stat(fn, &st) < 0)
286 return -errno;
287
288 return null_or_empty(&st);
289 }
290
291 int null_or_empty_fd(int fd) {
292 struct stat st;
293
294 assert(fd >= 0);
295
296 if (fstat(fd, &st) < 0)
297 return -errno;
298
299 return null_or_empty(&st);
300 }
301
302 static int do_execute(char **directories, usec_t timeout, char *argv[]) {
303 _cleanup_hashmap_free_free_ Hashmap *pids = NULL;
304 _cleanup_set_free_free_ Set *seen = NULL;
305 char **directory;
306
307 /* We fork this all off from a child process so that we can
308 * somewhat cleanly make use of SIGALRM to set a time limit */
309
310 (void) reset_all_signal_handlers();
311 (void) reset_signal_mask();
312
313 assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
314
315 pids = hashmap_new(NULL);
316 if (!pids)
317 return log_oom();
318
319 seen = set_new(&string_hash_ops);
320 if (!seen)
321 return log_oom();
322
323 STRV_FOREACH(directory, directories) {
324 _cleanup_closedir_ DIR *d;
325 struct dirent *de;
326
327 d = opendir(*directory);
328 if (!d) {
329 if (errno == ENOENT)
330 continue;
331
332 return log_error_errno(errno, "Failed to open directory %s: %m", *directory);
333 }
334
335 FOREACH_DIRENT(de, d, break) {
336 _cleanup_free_ char *path = NULL;
337 pid_t pid;
338 int r;
339
340 if (!dirent_is_file(de))
341 continue;
342
343 if (set_contains(seen, de->d_name)) {
344 log_debug("%1$s/%2$s skipped (%2$s was already seen).", *directory, de->d_name);
345 continue;
346 }
347
348 r = set_put_strdup(seen, de->d_name);
349 if (r < 0)
350 return log_oom();
351
352 path = strjoin(*directory, "/", de->d_name, NULL);
353 if (!path)
354 return log_oom();
355
356 if (null_or_empty_path(path)) {
357 log_debug("%s is empty (a mask).", path);
358 continue;
359 }
360
361 pid = fork();
362 if (pid < 0) {
363 log_error_errno(errno, "Failed to fork: %m");
364 continue;
365 } else if (pid == 0) {
366 char *_argv[2];
367
368 assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
369
370 if (!argv) {
371 _argv[0] = path;
372 _argv[1] = NULL;
373 argv = _argv;
374 } else
375 argv[0] = path;
376
377 execv(path, argv);
378 return log_error_errno(errno, "Failed to execute %s: %m", path);
379 }
380
381 log_debug("Spawned %s as " PID_FMT ".", path, pid);
382
383 r = hashmap_put(pids, UINT_TO_PTR(pid), path);
384 if (r < 0)
385 return log_oom();
386 path = NULL;
387 }
388 }
389
390 /* Abort execution of this process after the timout. We simply
391 * rely on SIGALRM as default action terminating the process,
392 * and turn on alarm(). */
393
394 if (timeout != USEC_INFINITY)
395 alarm((timeout + USEC_PER_SEC - 1) / USEC_PER_SEC);
396
397 while (!hashmap_isempty(pids)) {
398 _cleanup_free_ char *path = NULL;
399 pid_t pid;
400
401 pid = PTR_TO_UINT(hashmap_first_key(pids));
402 assert(pid > 0);
403
404 path = hashmap_remove(pids, UINT_TO_PTR(pid));
405 assert(path);
406
407 wait_for_terminate_and_warn(path, pid, true);
408 }
409
410 return 0;
411 }
412
413 void execute_directories(const char* const* directories, usec_t timeout, char *argv[]) {
414 pid_t executor_pid;
415 int r;
416 char *name;
417 char **dirs = (char**) directories;
418
419 assert(!strv_isempty(dirs));
420
421 name = basename(dirs[0]);
422 assert(!isempty(name));
423
424 /* Executes all binaries in the directories in parallel and waits
425 * for them to finish. Optionally a timeout is applied. If a file
426 * with the same name exists in more than one directory, the
427 * earliest one wins. */
428
429 executor_pid = fork();
430 if (executor_pid < 0) {
431 log_error_errno(errno, "Failed to fork: %m");
432 return;
433
434 } else if (executor_pid == 0) {
435 r = do_execute(dirs, timeout, argv);
436 _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
437 }
438
439 wait_for_terminate_and_warn(name, executor_pid, true);
440 }
441
442 bool plymouth_running(void) {
443 return access("/run/plymouth/pid", F_OK) >= 0;
444 }
445
446 bool display_is_local(const char *display) {
447 assert(display);
448
449 return
450 display[0] == ':' &&
451 display[1] >= '0' &&
452 display[1] <= '9';
453 }
454
455 int socket_from_display(const char *display, char **path) {
456 size_t k;
457 char *f, *c;
458
459 assert(display);
460 assert(path);
461
462 if (!display_is_local(display))
463 return -EINVAL;
464
465 k = strspn(display+1, "0123456789");
466
467 f = new(char, strlen("/tmp/.X11-unix/X") + k + 1);
468 if (!f)
469 return -ENOMEM;
470
471 c = stpcpy(f, "/tmp/.X11-unix/X");
472 memcpy(c, display+1, k);
473 c[k] = 0;
474
475 *path = f;
476
477 return 0;
478 }
479
480 int glob_exists(const char *path) {
481 _cleanup_globfree_ glob_t g = {};
482 int k;
483
484 assert(path);
485
486 errno = 0;
487 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
488
489 if (k == GLOB_NOMATCH)
490 return 0;
491 else if (k == GLOB_NOSPACE)
492 return -ENOMEM;
493 else if (k == 0)
494 return !strv_isempty(g.gl_pathv);
495 else
496 return errno ? -errno : -EIO;
497 }
498
499 int glob_extend(char ***strv, const char *path) {
500 _cleanup_globfree_ glob_t g = {};
501 int k;
502 char **p;
503
504 errno = 0;
505 k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
506
507 if (k == GLOB_NOMATCH)
508 return -ENOENT;
509 else if (k == GLOB_NOSPACE)
510 return -ENOMEM;
511 else if (k != 0 || strv_isempty(g.gl_pathv))
512 return errno ? -errno : -EIO;
513
514 STRV_FOREACH(p, g.gl_pathv) {
515 k = strv_extend(strv, *p);
516 if (k < 0)
517 break;
518 }
519
520 return k;
521 }
522
523 bool is_main_thread(void) {
524 static thread_local int cached = 0;
525
526 if (_unlikely_(cached == 0))
527 cached = getpid() == gettid() ? 1 : -1;
528
529 return cached > 0;
530 }
531
532 int block_get_whole_disk(dev_t d, dev_t *ret) {
533 char *p, *s;
534 int r;
535 unsigned n, m;
536
537 assert(ret);
538
539 /* If it has a queue this is good enough for us */
540 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", major(d), minor(d)) < 0)
541 return -ENOMEM;
542
543 r = access(p, F_OK);
544 free(p);
545
546 if (r >= 0) {
547 *ret = d;
548 return 0;
549 }
550
551 /* If it is a partition find the originating device */
552 if (asprintf(&p, "/sys/dev/block/%u:%u/partition", major(d), minor(d)) < 0)
553 return -ENOMEM;
554
555 r = access(p, F_OK);
556 free(p);
557
558 if (r < 0)
559 return -ENOENT;
560
561 /* Get parent dev_t */
562 if (asprintf(&p, "/sys/dev/block/%u:%u/../dev", major(d), minor(d)) < 0)
563 return -ENOMEM;
564
565 r = read_one_line_file(p, &s);
566 free(p);
567
568 if (r < 0)
569 return r;
570
571 r = sscanf(s, "%u:%u", &m, &n);
572 free(s);
573
574 if (r != 2)
575 return -EINVAL;
576
577 /* Only return this if it is really good enough for us. */
578 if (asprintf(&p, "/sys/dev/block/%u:%u/queue", m, n) < 0)
579 return -ENOMEM;
580
581 r = access(p, F_OK);
582 free(p);
583
584 if (r >= 0) {
585 *ret = makedev(m, n);
586 return 0;
587 }
588
589 return -ENOENT;
590 }
591
592 static const char *const ioprio_class_table[] = {
593 [IOPRIO_CLASS_NONE] = "none",
594 [IOPRIO_CLASS_RT] = "realtime",
595 [IOPRIO_CLASS_BE] = "best-effort",
596 [IOPRIO_CLASS_IDLE] = "idle"
597 };
598
599 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX);
600
601 static const char *const sigchld_code_table[] = {
602 [CLD_EXITED] = "exited",
603 [CLD_KILLED] = "killed",
604 [CLD_DUMPED] = "dumped",
605 [CLD_TRAPPED] = "trapped",
606 [CLD_STOPPED] = "stopped",
607 [CLD_CONTINUED] = "continued",
608 };
609
610 DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
611
612 static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = {
613 [LOG_FAC(LOG_KERN)] = "kern",
614 [LOG_FAC(LOG_USER)] = "user",
615 [LOG_FAC(LOG_MAIL)] = "mail",
616 [LOG_FAC(LOG_DAEMON)] = "daemon",
617 [LOG_FAC(LOG_AUTH)] = "auth",
618 [LOG_FAC(LOG_SYSLOG)] = "syslog",
619 [LOG_FAC(LOG_LPR)] = "lpr",
620 [LOG_FAC(LOG_NEWS)] = "news",
621 [LOG_FAC(LOG_UUCP)] = "uucp",
622 [LOG_FAC(LOG_CRON)] = "cron",
623 [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
624 [LOG_FAC(LOG_FTP)] = "ftp",
625 [LOG_FAC(LOG_LOCAL0)] = "local0",
626 [LOG_FAC(LOG_LOCAL1)] = "local1",
627 [LOG_FAC(LOG_LOCAL2)] = "local2",
628 [LOG_FAC(LOG_LOCAL3)] = "local3",
629 [LOG_FAC(LOG_LOCAL4)] = "local4",
630 [LOG_FAC(LOG_LOCAL5)] = "local5",
631 [LOG_FAC(LOG_LOCAL6)] = "local6",
632 [LOG_FAC(LOG_LOCAL7)] = "local7"
633 };
634
635 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_facility_unshifted, int, LOG_FAC(~0));
636
637 bool log_facility_unshifted_is_valid(int facility) {
638 return facility >= 0 && facility <= LOG_FAC(~0);
639 }
640
641 static const char *const log_level_table[] = {
642 [LOG_EMERG] = "emerg",
643 [LOG_ALERT] = "alert",
644 [LOG_CRIT] = "crit",
645 [LOG_ERR] = "err",
646 [LOG_WARNING] = "warning",
647 [LOG_NOTICE] = "notice",
648 [LOG_INFO] = "info",
649 [LOG_DEBUG] = "debug"
650 };
651
652 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_level, int, LOG_DEBUG);
653
654 bool log_level_is_valid(int level) {
655 return level >= 0 && level <= LOG_DEBUG;
656 }
657
658 static const char* const sched_policy_table[] = {
659 [SCHED_OTHER] = "other",
660 [SCHED_BATCH] = "batch",
661 [SCHED_IDLE] = "idle",
662 [SCHED_FIFO] = "fifo",
663 [SCHED_RR] = "rr"
664 };
665
666 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX);
667
668 bool kexec_loaded(void) {
669 bool loaded = false;
670 char *s;
671
672 if (read_one_line_file("/sys/kernel/kexec_loaded", &s) >= 0) {
673 if (s[0] == '1')
674 loaded = true;
675 free(s);
676 }
677 return loaded;
678 }
679
680 int prot_from_flags(int flags) {
681
682 switch (flags & O_ACCMODE) {
683
684 case O_RDONLY:
685 return PROT_READ;
686
687 case O_WRONLY:
688 return PROT_WRITE;
689
690 case O_RDWR:
691 return PROT_READ|PROT_WRITE;
692
693 default:
694 return -EINVAL;
695 }
696 }
697
698 void* memdup(const void *p, size_t l) {
699 void *r;
700
701 assert(p);
702
703 r = malloc(l);
704 if (!r)
705 return NULL;
706
707 memcpy(r, p, l);
708 return r;
709 }
710
711 int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
712 bool stdout_is_tty, stderr_is_tty;
713 pid_t parent_pid, agent_pid;
714 sigset_t ss, saved_ss;
715 unsigned n, i;
716 va_list ap;
717 char **l;
718
719 assert(pid);
720 assert(path);
721
722 /* Spawns a temporary TTY agent, making sure it goes away when
723 * we go away */
724
725 parent_pid = getpid();
726
727 /* First we temporarily block all signals, so that the new
728 * child has them blocked initially. This way, we can be sure
729 * that SIGTERMs are not lost we might send to the agent. */
730 assert_se(sigfillset(&ss) >= 0);
731 assert_se(sigprocmask(SIG_SETMASK, &ss, &saved_ss) >= 0);
732
733 agent_pid = fork();
734 if (agent_pid < 0) {
735 assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0);
736 return -errno;
737 }
738
739 if (agent_pid != 0) {
740 assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0);
741 *pid = agent_pid;
742 return 0;
743 }
744
745 /* In the child:
746 *
747 * Make sure the agent goes away when the parent dies */
748 if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
749 _exit(EXIT_FAILURE);
750
751 /* Make sure we actually can kill the agent, if we need to, in
752 * case somebody invoked us from a shell script that trapped
753 * SIGTERM or so... */
754 (void) reset_all_signal_handlers();
755 (void) reset_signal_mask();
756
757 /* Check whether our parent died before we were able
758 * to set the death signal and unblock the signals */
759 if (getppid() != parent_pid)
760 _exit(EXIT_SUCCESS);
761
762 /* Don't leak fds to the agent */
763 close_all_fds(except, n_except);
764
765 stdout_is_tty = isatty(STDOUT_FILENO);
766 stderr_is_tty = isatty(STDERR_FILENO);
767
768 if (!stdout_is_tty || !stderr_is_tty) {
769 int fd;
770
771 /* Detach from stdout/stderr. and reopen
772 * /dev/tty for them. This is important to
773 * ensure that when systemctl is started via
774 * popen() or a similar call that expects to
775 * read EOF we actually do generate EOF and
776 * not delay this indefinitely by because we
777 * keep an unused copy of stdin around. */
778 fd = open("/dev/tty", O_WRONLY);
779 if (fd < 0) {
780 log_error_errno(errno, "Failed to open /dev/tty: %m");
781 _exit(EXIT_FAILURE);
782 }
783
784 if (!stdout_is_tty)
785 dup2(fd, STDOUT_FILENO);
786
787 if (!stderr_is_tty)
788 dup2(fd, STDERR_FILENO);
789
790 if (fd > 2)
791 close(fd);
792 }
793
794 /* Count arguments */
795 va_start(ap, path);
796 for (n = 0; va_arg(ap, char*); n++)
797 ;
798 va_end(ap);
799
800 /* Allocate strv */
801 l = alloca(sizeof(char *) * (n + 1));
802
803 /* Fill in arguments */
804 va_start(ap, path);
805 for (i = 0; i <= n; i++)
806 l[i] = va_arg(ap, char*);
807 va_end(ap);
808
809 execv(path, l);
810 _exit(EXIT_FAILURE);
811 }
812
813 bool http_etag_is_valid(const char *etag) {
814 if (isempty(etag))
815 return false;
816
817 if (!endswith(etag, "\""))
818 return false;
819
820 if (!startswith(etag, "\"") && !startswith(etag, "W/\""))
821 return false;
822
823 return true;
824 }
825
826 bool http_url_is_valid(const char *url) {
827 const char *p;
828
829 if (isempty(url))
830 return false;
831
832 p = startswith(url, "http://");
833 if (!p)
834 p = startswith(url, "https://");
835 if (!p)
836 return false;
837
838 if (isempty(p))
839 return false;
840
841 return ascii_is_valid(p);
842 }
843
844 bool documentation_url_is_valid(const char *url) {
845 const char *p;
846
847 if (isempty(url))
848 return false;
849
850 if (http_url_is_valid(url))
851 return true;
852
853 p = startswith(url, "file:/");
854 if (!p)
855 p = startswith(url, "info:");
856 if (!p)
857 p = startswith(url, "man:");
858
859 if (isempty(p))
860 return false;
861
862 return ascii_is_valid(p);
863 }
864
865 bool in_initrd(void) {
866 static int saved = -1;
867 struct statfs s;
868
869 if (saved >= 0)
870 return saved;
871
872 /* We make two checks here:
873 *
874 * 1. the flag file /etc/initrd-release must exist
875 * 2. the root file system must be a memory file system
876 *
877 * The second check is extra paranoia, since misdetecting an
878 * initrd can have bad bad consequences due the initrd
879 * emptying when transititioning to the main systemd.
880 */
881
882 saved = access("/etc/initrd-release", F_OK) >= 0 &&
883 statfs("/", &s) >= 0 &&
884 is_temporary_fs(&s);
885
886 return saved;
887 }
888
889 bool string_is_safe(const char *p) {
890 const char *t;
891
892 if (!p)
893 return false;
894
895 for (t = p; *t; t++) {
896 if (*t > 0 && *t < ' ')
897 return false;
898
899 if (strchr("\\\"\'\x7f", *t))
900 return false;
901 }
902
903 return true;
904 }
905
906 /* hey glibc, APIs with callbacks without a user pointer are so useless */
907 void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
908 int (*compar) (const void *, const void *, void *), void *arg) {
909 size_t l, u, idx;
910 const void *p;
911 int comparison;
912
913 l = 0;
914 u = nmemb;
915 while (l < u) {
916 idx = (l + u) / 2;
917 p = (void *)(((const char *) base) + (idx * size));
918 comparison = compar(key, p, arg);
919 if (comparison < 0)
920 u = idx;
921 else if (comparison > 0)
922 l = idx + 1;
923 else
924 return (void *)p;
925 }
926 return NULL;
927 }
928
929 void init_gettext(void) {
930 setlocale(LC_ALL, "");
931 textdomain(GETTEXT_PACKAGE);
932 }
933
934 bool is_locale_utf8(void) {
935 const char *set;
936 static int cached_answer = -1;
937
938 if (cached_answer >= 0)
939 goto out;
940
941 if (!setlocale(LC_ALL, "")) {
942 cached_answer = true;
943 goto out;
944 }
945
946 set = nl_langinfo(CODESET);
947 if (!set) {
948 cached_answer = true;
949 goto out;
950 }
951
952 if (streq(set, "UTF-8")) {
953 cached_answer = true;
954 goto out;
955 }
956
957 /* For LC_CTYPE=="C" return true, because CTYPE is effectly
958 * unset and everything can do to UTF-8 nowadays. */
959 set = setlocale(LC_CTYPE, NULL);
960 if (!set) {
961 cached_answer = true;
962 goto out;
963 }
964
965 /* Check result, but ignore the result if C was set
966 * explicitly. */
967 cached_answer =
968 STR_IN_SET(set, "C", "POSIX") &&
969 !getenv("LC_ALL") &&
970 !getenv("LC_CTYPE") &&
971 !getenv("LANG");
972
973 out:
974 return (bool) cached_answer;
975 }
976
977 const char *draw_special_char(DrawSpecialChar ch) {
978 static const char *draw_table[2][_DRAW_SPECIAL_CHAR_MAX] = {
979
980 /* UTF-8 */ {
981 [DRAW_TREE_VERTICAL] = "\342\224\202 ", /* │ */
982 [DRAW_TREE_BRANCH] = "\342\224\234\342\224\200", /* ├─ */
983 [DRAW_TREE_RIGHT] = "\342\224\224\342\224\200", /* └─ */
984 [DRAW_TREE_SPACE] = " ", /* */
985 [DRAW_TRIANGULAR_BULLET] = "\342\200\243", /* ‣ */
986 [DRAW_BLACK_CIRCLE] = "\342\227\217", /* ● */
987 [DRAW_ARROW] = "\342\206\222", /* → */
988 [DRAW_DASH] = "\342\200\223", /* – */
989 },
990
991 /* ASCII fallback */ {
992 [DRAW_TREE_VERTICAL] = "| ",
993 [DRAW_TREE_BRANCH] = "|-",
994 [DRAW_TREE_RIGHT] = "`-",
995 [DRAW_TREE_SPACE] = " ",
996 [DRAW_TRIANGULAR_BULLET] = ">",
997 [DRAW_BLACK_CIRCLE] = "*",
998 [DRAW_ARROW] = "->",
999 [DRAW_DASH] = "-",
1000 }
1001 };
1002
1003 return draw_table[!is_locale_utf8()][ch];
1004 }
1005
1006 int on_ac_power(void) {
1007 bool found_offline = false, found_online = false;
1008 _cleanup_closedir_ DIR *d = NULL;
1009
1010 d = opendir("/sys/class/power_supply");
1011 if (!d)
1012 return errno == ENOENT ? true : -errno;
1013
1014 for (;;) {
1015 struct dirent *de;
1016 _cleanup_close_ int fd = -1, device = -1;
1017 char contents[6];
1018 ssize_t n;
1019
1020 errno = 0;
1021 de = readdir(d);
1022 if (!de && errno != 0)
1023 return -errno;
1024
1025 if (!de)
1026 break;
1027
1028 if (hidden_file(de->d_name))
1029 continue;
1030
1031 device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY);
1032 if (device < 0) {
1033 if (errno == ENOENT || errno == ENOTDIR)
1034 continue;
1035
1036 return -errno;
1037 }
1038
1039 fd = openat(device, "type", O_RDONLY|O_CLOEXEC|O_NOCTTY);
1040 if (fd < 0) {
1041 if (errno == ENOENT)
1042 continue;
1043
1044 return -errno;
1045 }
1046
1047 n = read(fd, contents, sizeof(contents));
1048 if (n < 0)
1049 return -errno;
1050
1051 if (n != 6 || memcmp(contents, "Mains\n", 6))
1052 continue;
1053
1054 safe_close(fd);
1055 fd = openat(device, "online", O_RDONLY|O_CLOEXEC|O_NOCTTY);
1056 if (fd < 0) {
1057 if (errno == ENOENT)
1058 continue;
1059
1060 return -errno;
1061 }
1062
1063 n = read(fd, contents, sizeof(contents));
1064 if (n < 0)
1065 return -errno;
1066
1067 if (n != 2 || contents[1] != '\n')
1068 return -EIO;
1069
1070 if (contents[0] == '1') {
1071 found_online = true;
1072 break;
1073 } else if (contents[0] == '0')
1074 found_offline = true;
1075 else
1076 return -EIO;
1077 }
1078
1079 return found_online || !found_offline;
1080 }
1081
1082 void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) {
1083 size_t a, newalloc;
1084 void *q;
1085
1086 assert(p);
1087 assert(allocated);
1088
1089 if (*allocated >= need)
1090 return *p;
1091
1092 newalloc = MAX(need * 2, 64u / size);
1093 a = newalloc * size;
1094
1095 /* check for overflows */
1096 if (a < size * need)
1097 return NULL;
1098
1099 q = realloc(*p, a);
1100 if (!q)
1101 return NULL;
1102
1103 *p = q;
1104 *allocated = newalloc;
1105 return q;
1106 }
1107
1108 void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size) {
1109 size_t prev;
1110 uint8_t *q;
1111
1112 assert(p);
1113 assert(allocated);
1114
1115 prev = *allocated;
1116
1117 q = greedy_realloc(p, allocated, need, size);
1118 if (!q)
1119 return NULL;
1120
1121 if (*allocated > prev)
1122 memzero(q + prev * size, (*allocated - prev) * size);
1123
1124 return q;
1125 }
1126
1127 bool id128_is_valid(const char *s) {
1128 size_t i, l;
1129
1130 l = strlen(s);
1131 if (l == 32) {
1132
1133 /* Simple formatted 128bit hex string */
1134
1135 for (i = 0; i < l; i++) {
1136 char c = s[i];
1137
1138 if (!(c >= '0' && c <= '9') &&
1139 !(c >= 'a' && c <= 'z') &&
1140 !(c >= 'A' && c <= 'Z'))
1141 return false;
1142 }
1143
1144 } else if (l == 36) {
1145
1146 /* Formatted UUID */
1147
1148 for (i = 0; i < l; i++) {
1149 char c = s[i];
1150
1151 if ((i == 8 || i == 13 || i == 18 || i == 23)) {
1152 if (c != '-')
1153 return false;
1154 } else {
1155 if (!(c >= '0' && c <= '9') &&
1156 !(c >= 'a' && c <= 'z') &&
1157 !(c >= 'A' && c <= 'Z'))
1158 return false;
1159 }
1160 }
1161
1162 } else
1163 return false;
1164
1165 return true;
1166 }
1167
1168 int shall_restore_state(void) {
1169 _cleanup_free_ char *value = NULL;
1170 int r;
1171
1172 r = get_proc_cmdline_key("systemd.restore_state=", &value);
1173 if (r < 0)
1174 return r;
1175 if (r == 0)
1176 return true;
1177
1178 return parse_boolean(value) != 0;
1179 }
1180
1181 int proc_cmdline(char **ret) {
1182 assert(ret);
1183
1184 if (detect_container() > 0)
1185 return get_process_cmdline(1, 0, false, ret);
1186 else
1187 return read_one_line_file("/proc/cmdline", ret);
1188 }
1189
1190 int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) {
1191 _cleanup_free_ char *line = NULL;
1192 const char *p;
1193 int r;
1194
1195 assert(parse_item);
1196
1197 r = proc_cmdline(&line);
1198 if (r < 0)
1199 return r;
1200
1201 p = line;
1202 for (;;) {
1203 _cleanup_free_ char *word = NULL;
1204 char *value = NULL;
1205
1206 r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX);
1207 if (r < 0)
1208 return r;
1209 if (r == 0)
1210 break;
1211
1212 /* Filter out arguments that are intended only for the
1213 * initrd */
1214 if (!in_initrd() && startswith(word, "rd."))
1215 continue;
1216
1217 value = strchr(word, '=');
1218 if (value)
1219 *(value++) = 0;
1220
1221 r = parse_item(word, value);
1222 if (r < 0)
1223 return r;
1224 }
1225
1226 return 0;
1227 }
1228
1229 int get_proc_cmdline_key(const char *key, char **value) {
1230 _cleanup_free_ char *line = NULL, *ret = NULL;
1231 bool found = false;
1232 const char *p;
1233 int r;
1234
1235 assert(key);
1236
1237 r = proc_cmdline(&line);
1238 if (r < 0)
1239 return r;
1240
1241 p = line;
1242 for (;;) {
1243 _cleanup_free_ char *word = NULL;
1244 const char *e;
1245
1246 r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX);
1247 if (r < 0)
1248 return r;
1249 if (r == 0)
1250 break;
1251
1252 /* Filter out arguments that are intended only for the
1253 * initrd */
1254 if (!in_initrd() && startswith(word, "rd."))
1255 continue;
1256
1257 if (value) {
1258 e = startswith(word, key);
1259 if (!e)
1260 continue;
1261
1262 r = free_and_strdup(&ret, e);
1263 if (r < 0)
1264 return r;
1265
1266 found = true;
1267 } else {
1268 if (streq(word, key))
1269 found = true;
1270 }
1271 }
1272
1273 if (value) {
1274 *value = ret;
1275 ret = NULL;
1276 }
1277
1278 return found;
1279
1280 }
1281
1282 int container_get_leader(const char *machine, pid_t *pid) {
1283 _cleanup_free_ char *s = NULL, *class = NULL;
1284 const char *p;
1285 pid_t leader;
1286 int r;
1287
1288 assert(machine);
1289 assert(pid);
1290
1291 if (!machine_name_is_valid(machine))
1292 return -EINVAL;
1293
1294 p = strjoina("/run/systemd/machines/", machine);
1295 r = parse_env_file(p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL);
1296 if (r == -ENOENT)
1297 return -EHOSTDOWN;
1298 if (r < 0)
1299 return r;
1300 if (!s)
1301 return -EIO;
1302
1303 if (!streq_ptr(class, "container"))
1304 return -EIO;
1305
1306 r = parse_pid(s, &leader);
1307 if (r < 0)
1308 return r;
1309 if (leader <= 1)
1310 return -EIO;
1311
1312 *pid = leader;
1313 return 0;
1314 }
1315
1316 int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd) {
1317 _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, netnsfd = -1, usernsfd = -1;
1318 int rfd = -1;
1319
1320 assert(pid >= 0);
1321
1322 if (mntns_fd) {
1323 const char *mntns;
1324
1325 mntns = procfs_file_alloca(pid, "ns/mnt");
1326 mntnsfd = open(mntns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
1327 if (mntnsfd < 0)
1328 return -errno;
1329 }
1330
1331 if (pidns_fd) {
1332 const char *pidns;
1333
1334 pidns = procfs_file_alloca(pid, "ns/pid");
1335 pidnsfd = open(pidns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
1336 if (pidnsfd < 0)
1337 return -errno;
1338 }
1339
1340 if (netns_fd) {
1341 const char *netns;
1342
1343 netns = procfs_file_alloca(pid, "ns/net");
1344 netnsfd = open(netns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
1345 if (netnsfd < 0)
1346 return -errno;
1347 }
1348
1349 if (userns_fd) {
1350 const char *userns;
1351
1352 userns = procfs_file_alloca(pid, "ns/user");
1353 usernsfd = open(userns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
1354 if (usernsfd < 0 && errno != ENOENT)
1355 return -errno;
1356 }
1357
1358 if (root_fd) {
1359 const char *root;
1360
1361 root = procfs_file_alloca(pid, "root");
1362 rfd = open(root, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
1363 if (rfd < 0)
1364 return -errno;
1365 }
1366
1367 if (pidns_fd)
1368 *pidns_fd = pidnsfd;
1369
1370 if (mntns_fd)
1371 *mntns_fd = mntnsfd;
1372
1373 if (netns_fd)
1374 *netns_fd = netnsfd;
1375
1376 if (userns_fd)
1377 *userns_fd = usernsfd;
1378
1379 if (root_fd)
1380 *root_fd = rfd;
1381
1382 pidnsfd = mntnsfd = netnsfd = usernsfd = -1;
1383
1384 return 0;
1385 }
1386
1387 int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd) {
1388 if (userns_fd >= 0) {
1389 /* Can't setns to your own userns, since then you could
1390 * escalate from non-root to root in your own namespace, so
1391 * check if namespaces equal before attempting to enter. */
1392 _cleanup_free_ char *userns_fd_path = NULL;
1393 int r;
1394 if (asprintf(&userns_fd_path, "/proc/self/fd/%d", userns_fd) < 0)
1395 return -ENOMEM;
1396
1397 r = files_same(userns_fd_path, "/proc/self/ns/user");
1398 if (r < 0)
1399 return r;
1400 if (r)
1401 userns_fd = -1;
1402 }
1403
1404 if (pidns_fd >= 0)
1405 if (setns(pidns_fd, CLONE_NEWPID) < 0)
1406 return -errno;
1407
1408 if (mntns_fd >= 0)
1409 if (setns(mntns_fd, CLONE_NEWNS) < 0)
1410 return -errno;
1411
1412 if (netns_fd >= 0)
1413 if (setns(netns_fd, CLONE_NEWNET) < 0)
1414 return -errno;
1415
1416 if (userns_fd >= 0)
1417 if (setns(userns_fd, CLONE_NEWUSER) < 0)
1418 return -errno;
1419
1420 if (root_fd >= 0) {
1421 if (fchdir(root_fd) < 0)
1422 return -errno;
1423
1424 if (chroot(".") < 0)
1425 return -errno;
1426 }
1427
1428 return reset_uid_gid();
1429 }
1430
1431 unsigned long personality_from_string(const char *p) {
1432
1433 /* Parse a personality specifier. We introduce our own
1434 * identifiers that indicate specific ABIs, rather than just
1435 * hints regarding the register size, since we want to keep
1436 * things open for multiple locally supported ABIs for the
1437 * same register size. We try to reuse the ABI identifiers
1438 * used by libseccomp. */
1439
1440 #if defined(__x86_64__)
1441
1442 if (streq(p, "x86"))
1443 return PER_LINUX32;
1444
1445 if (streq(p, "x86-64"))
1446 return PER_LINUX;
1447
1448 #elif defined(__i386__)
1449
1450 if (streq(p, "x86"))
1451 return PER_LINUX;
1452
1453 #elif defined(__s390x__)
1454
1455 if (streq(p, "s390"))
1456 return PER_LINUX32;
1457
1458 if (streq(p, "s390x"))
1459 return PER_LINUX;
1460
1461 #elif defined(__s390__)
1462
1463 if (streq(p, "s390"))
1464 return PER_LINUX;
1465 #endif
1466
1467 return PERSONALITY_INVALID;
1468 }
1469
1470 const char* personality_to_string(unsigned long p) {
1471
1472 #if defined(__x86_64__)
1473
1474 if (p == PER_LINUX32)
1475 return "x86";
1476
1477 if (p == PER_LINUX)
1478 return "x86-64";
1479
1480 #elif defined(__i386__)
1481
1482 if (p == PER_LINUX)
1483 return "x86";
1484
1485 #elif defined(__s390x__)
1486
1487 if (p == PER_LINUX)
1488 return "s390x";
1489
1490 if (p == PER_LINUX32)
1491 return "s390";
1492
1493 #elif defined(__s390__)
1494
1495 if (p == PER_LINUX)
1496 return "s390";
1497
1498 #endif
1499
1500 return NULL;
1501 }
1502
1503 uint64_t physical_memory(void) {
1504 long mem;
1505
1506 /* We return this as uint64_t in case we are running as 32bit
1507 * process on a 64bit kernel with huge amounts of memory */
1508
1509 mem = sysconf(_SC_PHYS_PAGES);
1510 assert(mem > 0);
1511
1512 return (uint64_t) mem * (uint64_t) page_size();
1513 }
1514
1515 int update_reboot_param_file(const char *param) {
1516 int r = 0;
1517
1518 if (param) {
1519 r = write_string_file(REBOOT_PARAM_FILE, param, WRITE_STRING_FILE_CREATE);
1520 if (r < 0)
1521 return log_error_errno(r, "Failed to write reboot param to "REBOOT_PARAM_FILE": %m");
1522 } else
1523 (void) unlink(REBOOT_PARAM_FILE);
1524
1525 return 0;
1526 }
1527
1528 int is_symlink(const char *path) {
1529 struct stat info;
1530
1531 if (lstat(path, &info) < 0)
1532 return -errno;
1533
1534 return !!S_ISLNK(info.st_mode);
1535 }
1536
1537 int is_dir(const char* path, bool follow) {
1538 struct stat st;
1539 int r;
1540
1541 if (follow)
1542 r = stat(path, &st);
1543 else
1544 r = lstat(path, &st);
1545 if (r < 0)
1546 return -errno;
1547
1548 return !!S_ISDIR(st.st_mode);
1549 }
1550
1551 int is_device_node(const char *path) {
1552 struct stat info;
1553
1554 if (lstat(path, &info) < 0)
1555 return -errno;
1556
1557 return !!(S_ISBLK(info.st_mode) || S_ISCHR(info.st_mode));
1558 }
1559
1560 int syslog_parse_priority(const char **p, int *priority, bool with_facility) {
1561 int a = 0, b = 0, c = 0;
1562 int k;
1563
1564 assert(p);
1565 assert(*p);
1566 assert(priority);
1567
1568 if ((*p)[0] != '<')
1569 return 0;
1570
1571 if (!strchr(*p, '>'))
1572 return 0;
1573
1574 if ((*p)[2] == '>') {
1575 c = undecchar((*p)[1]);
1576 k = 3;
1577 } else if ((*p)[3] == '>') {
1578 b = undecchar((*p)[1]);
1579 c = undecchar((*p)[2]);
1580 k = 4;
1581 } else if ((*p)[4] == '>') {
1582 a = undecchar((*p)[1]);
1583 b = undecchar((*p)[2]);
1584 c = undecchar((*p)[3]);
1585 k = 5;
1586 } else
1587 return 0;
1588
1589 if (a < 0 || b < 0 || c < 0 ||
1590 (!with_facility && (a || b || c > 7)))
1591 return 0;
1592
1593 if (with_facility)
1594 *priority = a*100 + b*10 + c;
1595 else
1596 *priority = (*priority & LOG_FACMASK) | c;
1597
1598 *p += k;
1599 return 1;
1600 }
1601
1602 ssize_t string_table_lookup(const char * const *table, size_t len, const char *key) {
1603 size_t i;
1604
1605 if (!key)
1606 return -1;
1607
1608 for (i = 0; i < len; ++i)
1609 if (streq_ptr(table[i], key))
1610 return (ssize_t) i;
1611
1612 return -1;
1613 }
1614
1615 int version(void) {
1616 puts(PACKAGE_STRING "\n"
1617 SYSTEMD_FEATURES);
1618 return 0;
1619 }
1620
1621 bool fdname_is_valid(const char *s) {
1622 const char *p;
1623
1624 /* Validates a name for $LISTEN_FDNAMES. We basically allow
1625 * everything ASCII that's not a control character. Also, as
1626 * special exception the ":" character is not allowed, as we
1627 * use that as field separator in $LISTEN_FDNAMES.
1628 *
1629 * Note that the empty string is explicitly allowed
1630 * here. However, we limit the length of the names to 255
1631 * characters. */
1632
1633 if (!s)
1634 return false;
1635
1636 for (p = s; *p; p++) {
1637 if (*p < ' ')
1638 return false;
1639 if (*p >= 127)
1640 return false;
1641 if (*p == ':')
1642 return false;
1643 }
1644
1645 return p - s < 256;
1646 }
1647
1648 bool oom_score_adjust_is_valid(int oa) {
1649 return oa >= OOM_SCORE_ADJ_MIN && oa <= OOM_SCORE_ADJ_MAX;
1650 }