1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
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.
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.
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/>.
31 #include <linux/magic.h>
32 #include <linux/oom.h>
33 #include <linux/sched.h>
44 #include <sys/ioctl.h>
46 #include <sys/mount.h>
47 #include <sys/personality.h>
48 #include <sys/prctl.h>
50 #include <sys/statvfs.h>
52 #include <sys/types.h>
53 #include <sys/utsname.h>
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(). */
65 #ifdef HAVE_SYS_AUXV_H
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! */
75 #include "device-nodes.h"
78 #include "exit-status.h"
81 #include "formats-util.h"
84 #include "hostname-util.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"
99 #include "terminal-util.h"
100 #include "user-util.h"
104 #include "dirent-util.h"
106 /* Put this test here for a lack of better place */
107 assert_cc(EAGAIN
== EWOULDBLOCK
);
110 char **saved_argv
= NULL
;
112 size_t page_size(void) {
113 static thread_local
size_t pgsz
= 0;
116 if (_likely_(pgsz
> 0))
119 r
= sysconf(_SC_PAGESIZE
);
126 bool fstype_is_network(const char *fstype
) {
127 static const char table
[] =
142 x
= startswith(fstype
, "fuse.");
146 return nulstr_contains(table
, fstype
);
149 int dir_is_empty(const char *path
) {
150 _cleanup_closedir_
DIR *d
;
157 FOREACH_DIRENT(de
, d
, return -errno
)
163 void rename_process(const char name
[8]) {
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
174 prctl(PR_SET_NAME
, name
);
176 if (program_invocation_name
)
177 strncpy(program_invocation_name
, name
, strlen(program_invocation_name
));
179 if (saved_argc
> 0) {
183 strncpy(saved_argv
[0], name
, strlen(saved_argv
[0]));
185 for (i
= 1; i
< saved_argc
; i
++) {
189 memzero(saved_argv
[i
], strlen(saved_argv
[i
]));
194 bool is_fs_type(const struct statfs
*s
, statfs_f_type_t magic_value
) {
196 assert_cc(sizeof(statfs_f_type_t
) >= sizeof(s
->f_type
));
198 return F_TYPE_EQUAL(s
->f_type
, magic_value
);
201 int fd_check_fstype(int fd
, statfs_f_type_t magic_value
) {
204 if (fstatfs(fd
, &s
) < 0)
207 return is_fs_type(&s
, magic_value
);
210 int path_check_fstype(const char *path
, statfs_f_type_t magic_value
) {
211 _cleanup_close_
int fd
= -1;
213 fd
= open(path
, O_RDONLY
);
217 return fd_check_fstype(fd
, magic_value
);
220 bool is_temporary_fs(const struct statfs
*s
) {
221 return is_fs_type(s
, TMPFS_MAGIC
) ||
222 is_fs_type(s
, RAMFS_MAGIC
);
225 int fd_is_temporary_fs(int fd
) {
228 if (fstatfs(fd
, &s
) < 0)
231 return is_temporary_fs(&s
);
234 int files_same(const char *filea
, const char *fileb
) {
237 if (stat(filea
, &a
) < 0)
240 if (stat(fileb
, &b
) < 0)
243 return a
.st_dev
== b
.st_dev
&&
244 a
.st_ino
== b
.st_ino
;
247 int running_in_chroot(void) {
250 ret
= files_same("/proc/1/root", "/");
257 noreturn
void freeze(void) {
259 /* Make sure nobody waits for us on a socket anymore */
260 close_all_fds(NULL
, 0);
268 bool null_or_empty(struct stat
*st
) {
271 if (S_ISREG(st
->st_mode
) && st
->st_size
<= 0)
274 if (S_ISCHR(st
->st_mode
) || S_ISBLK(st
->st_mode
))
280 int null_or_empty_path(const char *fn
) {
285 if (stat(fn
, &st
) < 0)
288 return null_or_empty(&st
);
291 int null_or_empty_fd(int fd
) {
296 if (fstat(fd
, &st
) < 0)
299 return null_or_empty(&st
);
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
;
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 */
310 (void) reset_all_signal_handlers();
311 (void) reset_signal_mask();
313 assert_se(prctl(PR_SET_PDEATHSIG
, SIGTERM
) == 0);
315 pids
= hashmap_new(NULL
);
319 seen
= set_new(&string_hash_ops
);
323 STRV_FOREACH(directory
, directories
) {
324 _cleanup_closedir_
DIR *d
;
327 d
= opendir(*directory
);
332 return log_error_errno(errno
, "Failed to open directory %s: %m", *directory
);
335 FOREACH_DIRENT(de
, d
, break) {
336 _cleanup_free_
char *path
= NULL
;
340 if (!dirent_is_file(de
))
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
);
348 r
= set_put_strdup(seen
, de
->d_name
);
352 path
= strjoin(*directory
, "/", de
->d_name
, NULL
);
356 if (null_or_empty_path(path
)) {
357 log_debug("%s is empty (a mask).", path
);
363 log_error_errno(errno
, "Failed to fork: %m");
365 } else if (pid
== 0) {
368 assert_se(prctl(PR_SET_PDEATHSIG
, SIGTERM
) == 0);
378 return log_error_errno(errno
, "Failed to execute %s: %m", path
);
381 log_debug("Spawned %s as " PID_FMT
".", path
, pid
);
383 r
= hashmap_put(pids
, UINT_TO_PTR(pid
), path
);
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(). */
394 if (timeout
!= USEC_INFINITY
)
395 alarm((timeout
+ USEC_PER_SEC
- 1) / USEC_PER_SEC
);
397 while (!hashmap_isempty(pids
)) {
398 _cleanup_free_
char *path
= NULL
;
401 pid
= PTR_TO_UINT(hashmap_first_key(pids
));
404 path
= hashmap_remove(pids
, UINT_TO_PTR(pid
));
407 wait_for_terminate_and_warn(path
, pid
, true);
413 void execute_directories(const char* const* directories
, usec_t timeout
, char *argv
[]) {
417 char **dirs
= (char**) directories
;
419 assert(!strv_isempty(dirs
));
421 name
= basename(dirs
[0]);
422 assert(!isempty(name
));
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. */
429 executor_pid
= fork();
430 if (executor_pid
< 0) {
431 log_error_errno(errno
, "Failed to fork: %m");
434 } else if (executor_pid
== 0) {
435 r
= do_execute(dirs
, timeout
, argv
);
436 _exit(r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
);
439 wait_for_terminate_and_warn(name
, executor_pid
, true);
442 bool plymouth_running(void) {
443 return access("/run/plymouth/pid", F_OK
) >= 0;
446 bool display_is_local(const char *display
) {
455 int socket_from_display(const char *display
, char **path
) {
462 if (!display_is_local(display
))
465 k
= strspn(display
+1, "0123456789");
467 f
= new(char, strlen("/tmp/.X11-unix/X") + k
+ 1);
471 c
= stpcpy(f
, "/tmp/.X11-unix/X");
472 memcpy(c
, display
+1, k
);
480 int glob_exists(const char *path
) {
481 _cleanup_globfree_ glob_t g
= {};
487 k
= glob(path
, GLOB_NOSORT
|GLOB_BRACE
, NULL
, &g
);
489 if (k
== GLOB_NOMATCH
)
491 else if (k
== GLOB_NOSPACE
)
494 return !strv_isempty(g
.gl_pathv
);
496 return errno
? -errno
: -EIO
;
499 int glob_extend(char ***strv
, const char *path
) {
500 _cleanup_globfree_ glob_t g
= {};
505 k
= glob(path
, GLOB_NOSORT
|GLOB_BRACE
, NULL
, &g
);
507 if (k
== GLOB_NOMATCH
)
509 else if (k
== GLOB_NOSPACE
)
511 else if (k
!= 0 || strv_isempty(g
.gl_pathv
))
512 return errno
? -errno
: -EIO
;
514 STRV_FOREACH(p
, g
.gl_pathv
) {
515 k
= strv_extend(strv
, *p
);
523 bool is_main_thread(void) {
524 static thread_local
int cached
= 0;
526 if (_unlikely_(cached
== 0))
527 cached
= getpid() == gettid() ? 1 : -1;
532 int block_get_whole_disk(dev_t d
, dev_t
*ret
) {
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)
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)
561 /* Get parent dev_t */
562 if (asprintf(&p
, "/sys/dev/block/%u:%u/../dev", major(d
), minor(d
)) < 0)
565 r
= read_one_line_file(p
, &s
);
571 r
= sscanf(s
, "%u:%u", &m
, &n
);
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)
585 *ret
= makedev(m
, n
);
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"
599 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class
, int, INT_MAX
);
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",
610 DEFINE_STRING_TABLE_LOOKUP(sigchld_code
, int);
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"
635 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_facility_unshifted
, int, LOG_FAC(~0));
637 bool log_facility_unshifted_is_valid(int facility
) {
638 return facility
>= 0 && facility
<= LOG_FAC(~0);
641 static const char *const log_level_table
[] = {
642 [LOG_EMERG
] = "emerg",
643 [LOG_ALERT
] = "alert",
646 [LOG_WARNING
] = "warning",
647 [LOG_NOTICE
] = "notice",
649 [LOG_DEBUG
] = "debug"
652 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_level
, int, LOG_DEBUG
);
654 bool log_level_is_valid(int level
) {
655 return level
>= 0 && level
<= LOG_DEBUG
;
658 static const char* const sched_policy_table
[] = {
659 [SCHED_OTHER
] = "other",
660 [SCHED_BATCH
] = "batch",
661 [SCHED_IDLE
] = "idle",
662 [SCHED_FIFO
] = "fifo",
666 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy
, int, INT_MAX
);
668 bool kexec_loaded(void) {
672 if (read_one_line_file("/sys/kernel/kexec_loaded", &s
) >= 0) {
680 int prot_from_flags(int flags
) {
682 switch (flags
& O_ACCMODE
) {
691 return PROT_READ
|PROT_WRITE
;
698 void* memdup(const void *p
, size_t l
) {
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
;
722 /* Spawns a temporary TTY agent, making sure it goes away when
725 parent_pid
= getpid();
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);
735 assert_se(sigprocmask(SIG_SETMASK
, &saved_ss
, NULL
) >= 0);
739 if (agent_pid
!= 0) {
740 assert_se(sigprocmask(SIG_SETMASK
, &saved_ss
, NULL
) >= 0);
747 * Make sure the agent goes away when the parent dies */
748 if (prctl(PR_SET_PDEATHSIG
, SIGTERM
) < 0)
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();
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
)
762 /* Don't leak fds to the agent */
763 close_all_fds(except
, n_except
);
765 stdout_is_tty
= isatty(STDOUT_FILENO
);
766 stderr_is_tty
= isatty(STDERR_FILENO
);
768 if (!stdout_is_tty
|| !stderr_is_tty
) {
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
);
780 log_error_errno(errno
, "Failed to open /dev/tty: %m");
785 dup2(fd
, STDOUT_FILENO
);
788 dup2(fd
, STDERR_FILENO
);
794 /* Count arguments */
796 for (n
= 0; va_arg(ap
, char*); n
++)
801 l
= alloca(sizeof(char *) * (n
+ 1));
803 /* Fill in arguments */
805 for (i
= 0; i
<= n
; i
++)
806 l
[i
] = va_arg(ap
, char*);
813 bool http_etag_is_valid(const char *etag
) {
817 if (!endswith(etag
, "\""))
820 if (!startswith(etag
, "\"") && !startswith(etag
, "W/\""))
826 bool http_url_is_valid(const char *url
) {
832 p
= startswith(url
, "http://");
834 p
= startswith(url
, "https://");
841 return ascii_is_valid(p
);
844 bool documentation_url_is_valid(const char *url
) {
850 if (http_url_is_valid(url
))
853 p
= startswith(url
, "file:/");
855 p
= startswith(url
, "info:");
857 p
= startswith(url
, "man:");
862 return ascii_is_valid(p
);
865 bool in_initrd(void) {
866 static int saved
= -1;
872 /* We make two checks here:
874 * 1. the flag file /etc/initrd-release must exist
875 * 2. the root file system must be a memory file system
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.
882 saved
= access("/etc/initrd-release", F_OK
) >= 0 &&
883 statfs("/", &s
) >= 0 &&
889 bool string_is_safe(const char *p
) {
895 for (t
= p
; *t
; t
++) {
896 if (*t
> 0 && *t
< ' ')
899 if (strchr("\\\"\'\x7f", *t
))
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
) {
917 p
= (void *)(((const char *) base
) + (idx
* size
));
918 comparison
= compar(key
, p
, arg
);
921 else if (comparison
> 0)
929 void init_gettext(void) {
930 setlocale(LC_ALL
, "");
931 textdomain(GETTEXT_PACKAGE
);
934 bool is_locale_utf8(void) {
936 static int cached_answer
= -1;
938 if (cached_answer
>= 0)
941 if (!setlocale(LC_ALL
, "")) {
942 cached_answer
= true;
946 set
= nl_langinfo(CODESET
);
948 cached_answer
= true;
952 if (streq(set
, "UTF-8")) {
953 cached_answer
= true;
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
);
961 cached_answer
= true;
965 /* Check result, but ignore the result if C was set
968 STR_IN_SET(set
, "C", "POSIX") &&
970 !getenv("LC_CTYPE") &&
974 return (bool) cached_answer
;
977 const char *draw_special_char(DrawSpecialChar ch
) {
978 static const char *draw_table
[2][_DRAW_SPECIAL_CHAR_MAX
] = {
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", /* – */
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
] = "*",
1003 return draw_table
[!is_locale_utf8()][ch
];
1006 int on_ac_power(void) {
1007 bool found_offline
= false, found_online
= false;
1008 _cleanup_closedir_
DIR *d
= NULL
;
1010 d
= opendir("/sys/class/power_supply");
1012 return errno
== ENOENT
? true : -errno
;
1016 _cleanup_close_
int fd
= -1, device
= -1;
1022 if (!de
&& errno
!= 0)
1028 if (hidden_file(de
->d_name
))
1031 device
= openat(dirfd(d
), de
->d_name
, O_DIRECTORY
|O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
1033 if (errno
== ENOENT
|| errno
== ENOTDIR
)
1039 fd
= openat(device
, "type", O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
1041 if (errno
== ENOENT
)
1047 n
= read(fd
, contents
, sizeof(contents
));
1051 if (n
!= 6 || memcmp(contents
, "Mains\n", 6))
1055 fd
= openat(device
, "online", O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
1057 if (errno
== ENOENT
)
1063 n
= read(fd
, contents
, sizeof(contents
));
1067 if (n
!= 2 || contents
[1] != '\n')
1070 if (contents
[0] == '1') {
1071 found_online
= true;
1073 } else if (contents
[0] == '0')
1074 found_offline
= true;
1079 return found_online
|| !found_offline
;
1082 void* greedy_realloc(void **p
, size_t *allocated
, size_t need
, size_t size
) {
1089 if (*allocated
>= need
)
1092 newalloc
= MAX(need
* 2, 64u / size
);
1093 a
= newalloc
* size
;
1095 /* check for overflows */
1096 if (a
< size
* need
)
1104 *allocated
= newalloc
;
1108 void* greedy_realloc0(void **p
, size_t *allocated
, size_t need
, size_t size
) {
1117 q
= greedy_realloc(p
, allocated
, need
, size
);
1121 if (*allocated
> prev
)
1122 memzero(q
+ prev
* size
, (*allocated
- prev
) * size
);
1127 bool id128_is_valid(const char *s
) {
1133 /* Simple formatted 128bit hex string */
1135 for (i
= 0; i
< l
; i
++) {
1138 if (!(c
>= '0' && c
<= '9') &&
1139 !(c
>= 'a' && c
<= 'z') &&
1140 !(c
>= 'A' && c
<= 'Z'))
1144 } else if (l
== 36) {
1146 /* Formatted UUID */
1148 for (i
= 0; i
< l
; i
++) {
1151 if ((i
== 8 || i
== 13 || i
== 18 || i
== 23)) {
1155 if (!(c
>= '0' && c
<= '9') &&
1156 !(c
>= 'a' && c
<= 'z') &&
1157 !(c
>= 'A' && c
<= 'Z'))
1168 int shall_restore_state(void) {
1169 _cleanup_free_
char *value
= NULL
;
1172 r
= get_proc_cmdline_key("systemd.restore_state=", &value
);
1178 return parse_boolean(value
) != 0;
1181 int proc_cmdline(char **ret
) {
1184 if (detect_container() > 0)
1185 return get_process_cmdline(1, 0, false, ret
);
1187 return read_one_line_file("/proc/cmdline", ret
);
1190 int parse_proc_cmdline(int (*parse_item
)(const char *key
, const char *value
)) {
1191 _cleanup_free_
char *line
= NULL
;
1197 r
= proc_cmdline(&line
);
1203 _cleanup_free_
char *word
= NULL
;
1206 r
= extract_first_word(&p
, &word
, NULL
, EXTRACT_QUOTES
|EXTRACT_RELAX
);
1212 /* Filter out arguments that are intended only for the
1214 if (!in_initrd() && startswith(word
, "rd."))
1217 value
= strchr(word
, '=');
1221 r
= parse_item(word
, value
);
1229 int get_proc_cmdline_key(const char *key
, char **value
) {
1230 _cleanup_free_
char *line
= NULL
, *ret
= NULL
;
1237 r
= proc_cmdline(&line
);
1243 _cleanup_free_
char *word
= NULL
;
1246 r
= extract_first_word(&p
, &word
, NULL
, EXTRACT_QUOTES
|EXTRACT_RELAX
);
1252 /* Filter out arguments that are intended only for the
1254 if (!in_initrd() && startswith(word
, "rd."))
1258 e
= startswith(word
, key
);
1262 r
= free_and_strdup(&ret
, e
);
1268 if (streq(word
, key
))
1282 int container_get_leader(const char *machine
, pid_t
*pid
) {
1283 _cleanup_free_
char *s
= NULL
, *class = NULL
;
1291 if (!machine_name_is_valid(machine
))
1294 p
= strjoina("/run/systemd/machines/", machine
);
1295 r
= parse_env_file(p
, NEWLINE
, "LEADER", &s
, "CLASS", &class, NULL
);
1303 if (!streq_ptr(class, "container"))
1306 r
= parse_pid(s
, &leader
);
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;
1325 mntns
= procfs_file_alloca(pid
, "ns/mnt");
1326 mntnsfd
= open(mntns
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
);
1334 pidns
= procfs_file_alloca(pid
, "ns/pid");
1335 pidnsfd
= open(pidns
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
);
1343 netns
= procfs_file_alloca(pid
, "ns/net");
1344 netnsfd
= open(netns
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
);
1352 userns
= procfs_file_alloca(pid
, "ns/user");
1353 usernsfd
= open(userns
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
);
1354 if (usernsfd
< 0 && errno
!= ENOENT
)
1361 root
= procfs_file_alloca(pid
, "root");
1362 rfd
= open(root
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
);
1368 *pidns_fd
= pidnsfd
;
1371 *mntns_fd
= mntnsfd
;
1374 *netns_fd
= netnsfd
;
1377 *userns_fd
= usernsfd
;
1382 pidnsfd
= mntnsfd
= netnsfd
= usernsfd
= -1;
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
;
1394 if (asprintf(&userns_fd_path
, "/proc/self/fd/%d", userns_fd
) < 0)
1397 r
= files_same(userns_fd_path
, "/proc/self/ns/user");
1405 if (setns(pidns_fd
, CLONE_NEWPID
) < 0)
1409 if (setns(mntns_fd
, CLONE_NEWNS
) < 0)
1413 if (setns(netns_fd
, CLONE_NEWNET
) < 0)
1417 if (setns(userns_fd
, CLONE_NEWUSER
) < 0)
1421 if (fchdir(root_fd
) < 0)
1424 if (chroot(".") < 0)
1428 return reset_uid_gid();
1431 unsigned long personality_from_string(const char *p
) {
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. */
1440 #if defined(__x86_64__)
1442 if (streq(p
, "x86"))
1445 if (streq(p
, "x86-64"))
1448 #elif defined(__i386__)
1450 if (streq(p
, "x86"))
1453 #elif defined(__s390x__)
1455 if (streq(p
, "s390"))
1458 if (streq(p
, "s390x"))
1461 #elif defined(__s390__)
1463 if (streq(p
, "s390"))
1467 return PERSONALITY_INVALID
;
1470 const char* personality_to_string(unsigned long p
) {
1472 #if defined(__x86_64__)
1474 if (p
== PER_LINUX32
)
1480 #elif defined(__i386__)
1485 #elif defined(__s390x__)
1490 if (p
== PER_LINUX32
)
1493 #elif defined(__s390__)
1503 uint64_t physical_memory(void) {
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 */
1509 mem
= sysconf(_SC_PHYS_PAGES
);
1512 return (uint64_t) mem
* (uint64_t) page_size();
1515 int update_reboot_param_file(const char *param
) {
1519 r
= write_string_file(REBOOT_PARAM_FILE
, param
, WRITE_STRING_FILE_CREATE
);
1521 return log_error_errno(r
, "Failed to write reboot param to "REBOOT_PARAM_FILE
": %m");
1523 (void) unlink(REBOOT_PARAM_FILE
);
1528 int is_symlink(const char *path
) {
1531 if (lstat(path
, &info
) < 0)
1534 return !!S_ISLNK(info
.st_mode
);
1537 int is_dir(const char* path
, bool follow
) {
1542 r
= stat(path
, &st
);
1544 r
= lstat(path
, &st
);
1548 return !!S_ISDIR(st
.st_mode
);
1551 int is_device_node(const char *path
) {
1554 if (lstat(path
, &info
) < 0)
1557 return !!(S_ISBLK(info
.st_mode
) || S_ISCHR(info
.st_mode
));
1560 int syslog_parse_priority(const char **p
, int *priority
, bool with_facility
) {
1561 int a
= 0, b
= 0, c
= 0;
1571 if (!strchr(*p
, '>'))
1574 if ((*p
)[2] == '>') {
1575 c
= undecchar((*p
)[1]);
1577 } else if ((*p
)[3] == '>') {
1578 b
= undecchar((*p
)[1]);
1579 c
= undecchar((*p
)[2]);
1581 } else if ((*p
)[4] == '>') {
1582 a
= undecchar((*p
)[1]);
1583 b
= undecchar((*p
)[2]);
1584 c
= undecchar((*p
)[3]);
1589 if (a
< 0 || b
< 0 || c
< 0 ||
1590 (!with_facility
&& (a
|| b
|| c
> 7)))
1594 *priority
= a
*100 + b
*10 + c
;
1596 *priority
= (*priority
& LOG_FACMASK
) | c
;
1602 ssize_t
string_table_lookup(const char * const *table
, size_t len
, const char *key
) {
1608 for (i
= 0; i
< len
; ++i
)
1609 if (streq_ptr(table
[i
], key
))
1616 puts(PACKAGE_STRING
"\n"
1621 bool fdname_is_valid(const char *s
) {
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.
1629 * Note that the empty string is explicitly allowed
1630 * here. However, we limit the length of the names to 255
1636 for (p
= s
; *p
; p
++) {
1648 bool oom_score_adjust_is_valid(int oa
) {
1649 return oa
>= OOM_SCORE_ADJ_MIN
&& oa
<= OOM_SCORE_ADJ_MAX
;