1 /* SPDX-License-Identifier: LGPL-2.1+ */
13 #include <sys/prctl.h>
14 #include <sys/statfs.h>
15 #include <sys/sysmacros.h>
16 #include <sys/types.h>
19 #include "alloc-util.h"
20 #include "btrfs-util.h"
23 #include "device-nodes.h"
24 #include "dirent-util.h"
29 #include "format-util.h"
31 #include "hostname-util.h"
35 #include "parse-util.h"
36 #include "path-util.h"
37 #include "process-util.h"
38 #include "procfs-util.h"
40 #include "signal-util.h"
41 #include "stat-util.h"
42 #include "string-util.h"
44 #include "time-util.h"
45 #include "umask-util.h"
46 #include "user-util.h"
51 char **saved_argv
= NULL
;
52 static int saved_in_initrd
= -1;
54 bool kexec_loaded(void) {
55 _cleanup_free_
char *s
= NULL
;
57 if (read_one_line_file("/sys/kernel/kexec_loaded", &s
) < 0)
63 int prot_from_flags(int flags
) {
65 switch (flags
& O_ACCMODE
) {
74 return PROT_READ
|PROT_WRITE
;
81 bool in_initrd(void) {
85 if (saved_in_initrd
>= 0)
86 return saved_in_initrd
;
88 /* We make two checks here:
90 * 1. the flag file /etc/initrd-release must exist
91 * 2. the root file system must be a memory file system
93 * The second check is extra paranoia, since misdetecting an
94 * initrd can have bad consequences due the initrd
95 * emptying when transititioning to the main systemd.
98 r
= getenv_bool_secure("SYSTEMD_IN_INITRD");
99 if (r
< 0 && r
!= -ENXIO
)
100 log_debug_errno(r
, "Failed to parse $SYSTEMD_IN_INITRD, ignoring: %m");
103 saved_in_initrd
= r
> 0;
105 saved_in_initrd
= access("/etc/initrd-release", F_OK
) >= 0 &&
106 statfs("/", &s
) >= 0 &&
109 return saved_in_initrd
;
112 void in_initrd_force(bool value
) {
113 saved_in_initrd
= value
;
116 int on_ac_power(void) {
117 bool found_offline
= false, found_online
= false;
118 _cleanup_closedir_
DIR *d
= NULL
;
121 d
= opendir("/sys/class/power_supply");
123 return errno
== ENOENT
? true : -errno
;
125 FOREACH_DIRENT(de
, d
, return -errno
) {
126 _cleanup_close_
int fd
= -1, device
= -1;
130 device
= openat(dirfd(d
), de
->d_name
, O_DIRECTORY
|O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
132 if (IN_SET(errno
, ENOENT
, ENOTDIR
))
138 fd
= openat(device
, "type", O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
146 n
= read(fd
, contents
, sizeof(contents
));
150 if (n
!= 6 || memcmp(contents
, "Mains\n", 6))
154 fd
= openat(device
, "online", O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
162 n
= read(fd
, contents
, sizeof(contents
));
166 if (n
!= 2 || contents
[1] != '\n')
169 if (contents
[0] == '1') {
172 } else if (contents
[0] == '0')
173 found_offline
= true;
178 return found_online
|| !found_offline
;
181 int container_get_leader(const char *machine
, pid_t
*pid
) {
182 _cleanup_free_
char *s
= NULL
, *class = NULL
;
190 if (streq(machine
, ".host")) {
195 if (!machine_name_is_valid(machine
))
198 p
= strjoina("/run/systemd/machines/", machine
);
199 r
= parse_env_file(NULL
, p
,
209 if (!streq_ptr(class, "container"))
212 r
= parse_pid(s
, &leader
);
223 puts("systemd " STRINGIFY(PROJECT_VERSION
) " (" GIT_VERSION
")\n"
228 /* This is a direct translation of str_verscmp from boot.c */
229 static bool is_digit(int c
) {
230 return c
>= '0' && c
<= '9';
233 static int c_order(int c
) {
234 if (c
== 0 || is_digit(c
))
237 if ((c
>= 'a') && (c
<= 'z'))
243 int str_verscmp(const char *s1
, const char *s2
) {
244 const char *os1
, *os2
;
255 while ((*s1
&& !is_digit(*s1
)) || (*s2
&& !is_digit(*s2
))) {
258 order
= c_order(*s1
) - c_order(*s2
);
271 while (is_digit(*s1
) && is_digit(*s2
)) {
287 return strcmp(os1
, os2
);
290 /* Turn off core dumps but only if we're running outside of a container. */
291 void disable_coredumps(void) {
294 if (detect_container() > 0)
297 r
= write_string_file("/proc/sys/kernel/core_pattern", "|/bin/false", WRITE_STRING_FILE_DISABLE_BUFFER
);
299 log_debug_errno(r
, "Failed to turn off coredumps, ignoring: %m");