]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/util.c
Define FOREACH_DIRENT through FOREACH_DIRENT_ALL
[thirdparty/systemd.git] / src / basic / util.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
a7334b09 2
60918275 3#include <errno.h>
f6c2284a 4#include <fcntl.h>
87d2c1ff 5#include <sys/mman.h>
eef46c37 6
b5efdb8a 7#include "alloc-util.h"
3f6fd1ba 8#include "build.h"
cf0fbc49 9#include "dirent-util.h"
686d13b9 10#include "env-file.h"
0307ea49 11#include "env-util.h"
3ffd4af2 12#include "fd-util.h"
f6c2284a 13#include "fileio.h"
f6c2284a 14#include "hostname-util.h"
a9f5d454 15#include "log.h"
f6c2284a 16#include "macro.h"
6bedfcbb 17#include "parse-util.h"
cf0fbc49 18#include "stat-util.h"
07630cea 19#include "string-util.h"
4f5dd394 20#include "util.h"
9ce17593 21#include "virt.h"
56cf987f 22
9a0e6896
LP
23int saved_argc = 0;
24char **saved_argv = NULL;
dcd61450 25static int saved_in_initrd = -1;
9086e840 26
65457142 27bool kexec_loaded(void) {
c47f86e6
ZJS
28 _cleanup_free_ char *s = NULL;
29
30 if (read_one_line_file("/sys/kernel/kexec_loaded", &s) < 0)
31 return false;
32
33 return s[0] == '1';
65457142 34}
fb9de93d 35
87d2c1ff
LP
36int prot_from_flags(int flags) {
37
38 switch (flags & O_ACCMODE) {
39
40 case O_RDONLY:
41 return PROT_READ;
42
43 case O_WRONLY:
44 return PROT_WRITE;
45
46 case O_RDWR:
47 return PROT_READ|PROT_WRITE;
48
49 default:
50 return -EINVAL;
51 }
7c99e0c1 52}
689b9a22 53
9be346c9 54bool in_initrd(void) {
0307ea49 55 int r;
1f22621b
KS
56 const char *e;
57 bool lenient = false;
8f33b5b8 58
dcd61450
IS
59 if (saved_in_initrd >= 0)
60 return saved_in_initrd;
825c6fe5 61
1f22621b 62 /* We have two checks here:
825c6fe5
LP
63 *
64 * 1. the flag file /etc/initrd-release must exist
65 * 2. the root file system must be a memory file system
66 *
67 * The second check is extra paranoia, since misdetecting an
629ff674 68 * initrd can have bad consequences due the initrd
825c6fe5 69 * emptying when transititioning to the main systemd.
1f22621b
KS
70 *
71 * If env var $SYSTEMD_IN_INITRD is not set or set to "auto",
72 * both checks are used. If it's set to "lenient", only check
38f3e0a5 73 * 1 is used. If set to a boolean value, then the boolean
1f22621b 74 * value is returned.
825c6fe5
LP
75 */
76
1f22621b
KS
77 e = secure_getenv("SYSTEMD_IN_INITRD");
78 if (e) {
79 if (streq(e, "lenient"))
80 lenient = true;
81 else if (!streq(e, "auto")) {
82 r = parse_boolean(e);
83 if (r >= 0) {
84 saved_in_initrd = r > 0;
85 return saved_in_initrd;
86 }
87 log_debug_errno(r, "Failed to parse $SYSTEMD_IN_INITRD, ignoring: %m");
88 }
89 }
0307ea49 90
3b9b9169
KS
91 if (!lenient) {
92 r = path_is_temporary_fs("/");
93 if (r < 0)
94 log_debug_errno(r, "Couldn't determine if / is a temporary file system: %m");
95
96 saved_in_initrd = r > 0;
97 }
98
b562b9c6
KS
99 r = access("/etc/initrd-release", F_OK);
100 if (r >= 0) {
101 if (saved_in_initrd == 0)
102 log_debug("/etc/initrd-release exists, but it's not an initrd.");
103 else
104 saved_in_initrd = 1;
105 } else {
106 if (errno != ENOENT)
107 log_debug_errno(errno, "Failed to test if /etc/initrd-release exists: %m");
108 saved_in_initrd = 0;
109 }
9be346c9 110
dcd61450
IS
111 return saved_in_initrd;
112}
113
114void in_initrd_force(bool value) {
115 saved_in_initrd = value;
9be346c9 116}
069cfc85 117
240dbaa4
LP
118int on_ac_power(void) {
119 bool found_offline = false, found_online = false;
120 _cleanup_closedir_ DIR *d = NULL;
c19a51be 121 int r;
240dbaa4
LP
122
123 d = opendir("/sys/class/power_supply");
124 if (!d)
6d890034 125 return errno == ENOENT ? true : -errno;
240dbaa4 126
8fb3f009 127 FOREACH_DIRENT(de, d, return -errno) {
c19a51be
LP
128 _cleanup_close_ int device_fd = -1;
129 _cleanup_free_ char *contents = NULL;
130 unsigned v;
240dbaa4 131
c19a51be
LP
132 device_fd = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC);
133 if (device_fd < 0) {
3742095b 134 if (IN_SET(errno, ENOENT, ENOTDIR))
240dbaa4
LP
135 continue;
136
137 return -errno;
138 }
139
c19a51be
LP
140 r = read_virtual_file_at(device_fd, "type", SIZE_MAX, &contents, NULL);
141 if (r == -ENOENT)
142 continue;
143 if (r < 0)
144 return r;
240dbaa4 145
c19a51be 146 delete_trailing_chars(contents, NEWLINE);
240dbaa4 147
c19a51be
LP
148 /* We assume every power source is AC, except for batteries. See
149 * https://github.com/torvalds/linux/blob/4eef766b7d4d88f0b984781bc1bcb574a6eafdc7/include/linux/power_supply.h#L176
150 * for defined power source types. Also see:
151 * https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-power */
152 if (streq(contents, "Battery"))
240dbaa4
LP
153 continue;
154
c19a51be 155 contents = mfree(contents);
240dbaa4 156
c19a51be
LP
157 r = read_virtual_file_at(device_fd, "online", SIZE_MAX, &contents, NULL);
158 if (r == -ENOENT)
159 continue;
160 if (r < 0)
161 return r;
240dbaa4 162
c19a51be 163 delete_trailing_chars(contents, NEWLINE);
240dbaa4 164
c19a51be
LP
165 r = safe_atou(contents, &v);
166 if (r < 0)
167 return r;
168 if (v > 0) /* At least 1 and 2 are defined as different types of 'online' */
240dbaa4 169 found_online = true;
240dbaa4 170 else
c19a51be 171 found_offline = true;
240dbaa4
LP
172 }
173
174 return found_online || !found_offline;
175}
fabe5c0e 176
bc9fd78c
LP
177int container_get_leader(const char *machine, pid_t *pid) {
178 _cleanup_free_ char *s = NULL, *class = NULL;
179 const char *p;
180 pid_t leader;
181 int r;
182
183 assert(machine);
184 assert(pid);
185
1e5057b9
LP
186 if (streq(machine, ".host")) {
187 *pid = 1;
188 return 0;
189 }
190
52ef5dd7 191 if (!hostname_is_valid(machine, 0))
b9a8d250
LP
192 return -EINVAL;
193
63c372cb 194 p = strjoina("/run/systemd/machines/", machine);
13df9c39
LP
195 r = parse_env_file(NULL, p,
196 "LEADER", &s,
197 "CLASS", &class);
bc9fd78c
LP
198 if (r == -ENOENT)
199 return -EHOSTDOWN;
200 if (r < 0)
201 return r;
202 if (!s)
203 return -EIO;
204
205 if (!streq_ptr(class, "container"))
206 return -EIO;
207
208 r = parse_pid(s, &leader);
209 if (r < 0)
210 return r;
211 if (leader <= 1)
212 return -EIO;
213
214 *pid = leader;
215 return 0;
216}
217
3f6fd1ba 218int version(void) {
91b79ba8
ZJS
219 printf("systemd " STRINGIFY(PROJECT_VERSION) " (" GIT_VERSION ")\n%s\n",
220 systemd_features);
3f6fd1ba
LP
221 return 0;
222}
68c58c67 223
9ce17593 224/* Turn off core dumps but only if we're running outside of a container. */
e557b1a6
LP
225void disable_coredumps(void) {
226 int r;
227
228 if (detect_container() > 0)
229 return;
230
57512c89 231 r = write_string_file("/proc/sys/kernel/core_pattern", "|/bin/false", WRITE_STRING_FILE_DISABLE_BUFFER);
e557b1a6
LP
232 if (r < 0)
233 log_debug_errno(r, "Failed to turn off coredumps, ignoring: %m");
9ce17593 234}