1 /* SPDX-License-Identifier: LGPL-2.1+ */
7 #include "alloc-util.h"
9 #include "dirent-util.h"
14 #include "hostname-util.h"
17 #include "parse-util.h"
18 #include "stat-util.h"
19 #include "string-util.h"
24 char **saved_argv
= NULL
;
25 static int saved_in_initrd
= -1;
27 bool kexec_loaded(void) {
28 _cleanup_free_
char *s
= NULL
;
30 if (read_one_line_file("/sys/kernel/kexec_loaded", &s
) < 0)
36 int prot_from_flags(int flags
) {
38 switch (flags
& O_ACCMODE
) {
47 return PROT_READ
|PROT_WRITE
;
54 bool in_initrd(void) {
58 if (saved_in_initrd
>= 0)
59 return saved_in_initrd
;
61 /* We make two checks here:
63 * 1. the flag file /etc/initrd-release must exist
64 * 2. the root file system must be a memory file system
66 * The second check is extra paranoia, since misdetecting an
67 * initrd can have bad consequences due the initrd
68 * emptying when transititioning to the main systemd.
71 r
= getenv_bool_secure("SYSTEMD_IN_INITRD");
72 if (r
< 0 && r
!= -ENXIO
)
73 log_debug_errno(r
, "Failed to parse $SYSTEMD_IN_INITRD, ignoring: %m");
76 saved_in_initrd
= r
> 0;
78 saved_in_initrd
= access("/etc/initrd-release", F_OK
) >= 0 &&
79 statfs("/", &s
) >= 0 &&
82 return saved_in_initrd
;
85 void in_initrd_force(bool value
) {
86 saved_in_initrd
= value
;
89 int on_ac_power(void) {
90 bool found_offline
= false, found_online
= false;
91 _cleanup_closedir_
DIR *d
= NULL
;
94 d
= opendir("/sys/class/power_supply");
96 return errno
== ENOENT
? true : -errno
;
98 FOREACH_DIRENT(de
, d
, return -errno
) {
99 _cleanup_close_
int fd
= -1, device
= -1;
103 device
= openat(dirfd(d
), de
->d_name
, O_DIRECTORY
|O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
105 if (IN_SET(errno
, ENOENT
, ENOTDIR
))
111 fd
= openat(device
, "type", O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
119 n
= read(fd
, contents
, sizeof(contents
));
123 if (n
!= 6 || memcmp(contents
, "Mains\n", 6))
127 fd
= openat(device
, "online", O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
135 n
= read(fd
, contents
, sizeof(contents
));
139 if (n
!= 2 || contents
[1] != '\n')
142 if (contents
[0] == '1') {
145 } else if (contents
[0] == '0')
146 found_offline
= true;
151 return found_online
|| !found_offline
;
154 int container_get_leader(const char *machine
, pid_t
*pid
) {
155 _cleanup_free_
char *s
= NULL
, *class = NULL
;
163 if (streq(machine
, ".host")) {
168 if (!machine_name_is_valid(machine
))
171 p
= strjoina("/run/systemd/machines/", machine
);
172 r
= parse_env_file(NULL
, p
,
182 if (!streq_ptr(class, "container"))
185 r
= parse_pid(s
, &leader
);
196 puts("systemd " STRINGIFY(PROJECT_VERSION
) " (" GIT_VERSION
")\n"
201 /* This is a direct translation of str_verscmp from boot.c */
202 static bool is_digit(int c
) {
203 return c
>= '0' && c
<= '9';
206 static int c_order(int c
) {
207 if (c
== 0 || is_digit(c
))
210 if ((c
>= 'a') && (c
<= 'z'))
216 int str_verscmp(const char *s1
, const char *s2
) {
217 const char *os1
, *os2
;
228 while ((*s1
&& !is_digit(*s1
)) || (*s2
&& !is_digit(*s2
))) {
231 order
= c_order(*s1
) - c_order(*s2
);
244 while (is_digit(*s1
) && is_digit(*s2
)) {
260 return strcmp(os1
, os2
);
263 /* Turn off core dumps but only if we're running outside of a container. */
264 void disable_coredumps(void) {
267 if (detect_container() > 0)
270 r
= write_string_file("/proc/sys/kernel/core_pattern", "|/bin/false", WRITE_STRING_FILE_DISABLE_BUFFER
);
272 log_debug_errno(r
, "Failed to turn off coredumps, ignoring: %m");