]>
Commit | Line | Data |
---|---|---|
53e1b683 | 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
a7334b09 | 2 | |
11c3a366 | 3 | #include <alloca.h> |
60918275 | 4 | #include <errno.h> |
f6c2284a | 5 | #include <fcntl.h> |
f6c2284a LP |
6 | #include <sched.h> |
7 | #include <signal.h> | |
8 | #include <stdarg.h> | |
9 | #include <stdio.h> | |
10 | #include <stdlib.h> | |
11 | #include <string.h> | |
87d2c1ff | 12 | #include <sys/mman.h> |
f6c2284a | 13 | #include <sys/prctl.h> |
11c3a366 TA |
14 | #include <sys/statfs.h> |
15 | #include <sys/sysmacros.h> | |
f6c2284a | 16 | #include <sys/types.h> |
f6c2284a | 17 | #include <unistd.h> |
eef46c37 | 18 | |
b5efdb8a | 19 | #include "alloc-util.h" |
c43b2b9c | 20 | #include "btrfs-util.h" |
3f6fd1ba | 21 | #include "build.h" |
f6c2284a | 22 | #include "def.h" |
553e15f2 | 23 | #include "device-nodes.h" |
cf0fbc49 | 24 | #include "dirent-util.h" |
686d13b9 | 25 | #include "env-file.h" |
0307ea49 | 26 | #include "env-util.h" |
3ffd4af2 | 27 | #include "fd-util.h" |
f6c2284a | 28 | #include "fileio.h" |
f97b34a6 | 29 | #include "format-util.h" |
f6c2284a LP |
30 | #include "hashmap.h" |
31 | #include "hostname-util.h" | |
a9f5d454 | 32 | #include "log.h" |
f6c2284a LP |
33 | #include "macro.h" |
34 | #include "missing.h" | |
6bedfcbb | 35 | #include "parse-util.h" |
9eb977db | 36 | #include "path-util.h" |
0b452006 | 37 | #include "process-util.h" |
1e7da35b | 38 | #include "procfs-util.h" |
11c3a366 | 39 | #include "set.h" |
93cc7779 | 40 | #include "signal-util.h" |
cf0fbc49 | 41 | #include "stat-util.h" |
07630cea | 42 | #include "string-util.h" |
f6c2284a | 43 | #include "strv.h" |
93cc7779 | 44 | #include "time-util.h" |
8612da97 | 45 | #include "umask-util.h" |
b1d4f8e1 | 46 | #include "user-util.h" |
4f5dd394 | 47 | #include "util.h" |
9ce17593 | 48 | #include "virt.h" |
56cf987f | 49 | |
9a0e6896 LP |
50 | int saved_argc = 0; |
51 | char **saved_argv = NULL; | |
dcd61450 | 52 | static int saved_in_initrd = -1; |
9086e840 | 53 | |
a88c8750 TG |
54 | bool plymouth_running(void) { |
55 | return access("/run/plymouth/pid", F_OK) >= 0; | |
56 | } | |
57 | ||
4d6d6518 LP |
58 | bool display_is_local(const char *display) { |
59 | assert(display); | |
60 | ||
61 | return | |
62 | display[0] == ':' && | |
63 | display[1] >= '0' && | |
64 | display[1] <= '9'; | |
65 | } | |
66 | ||
65457142 | 67 | bool kexec_loaded(void) { |
c47f86e6 ZJS |
68 | _cleanup_free_ char *s = NULL; |
69 | ||
70 | if (read_one_line_file("/sys/kernel/kexec_loaded", &s) < 0) | |
71 | return false; | |
72 | ||
73 | return s[0] == '1'; | |
65457142 | 74 | } |
fb9de93d | 75 | |
87d2c1ff LP |
76 | int prot_from_flags(int flags) { |
77 | ||
78 | switch (flags & O_ACCMODE) { | |
79 | ||
80 | case O_RDONLY: | |
81 | return PROT_READ; | |
82 | ||
83 | case O_WRONLY: | |
84 | return PROT_WRITE; | |
85 | ||
86 | case O_RDWR: | |
87 | return PROT_READ|PROT_WRITE; | |
88 | ||
89 | default: | |
90 | return -EINVAL; | |
91 | } | |
7c99e0c1 | 92 | } |
689b9a22 | 93 | |
9be346c9 | 94 | bool in_initrd(void) { |
825c6fe5 | 95 | struct statfs s; |
0307ea49 | 96 | int r; |
8f33b5b8 | 97 | |
dcd61450 IS |
98 | if (saved_in_initrd >= 0) |
99 | return saved_in_initrd; | |
825c6fe5 LP |
100 | |
101 | /* We make two checks here: | |
102 | * | |
103 | * 1. the flag file /etc/initrd-release must exist | |
104 | * 2. the root file system must be a memory file system | |
105 | * | |
106 | * The second check is extra paranoia, since misdetecting an | |
629ff674 | 107 | * initrd can have bad consequences due the initrd |
825c6fe5 LP |
108 | * emptying when transititioning to the main systemd. |
109 | */ | |
110 | ||
0307ea49 ZJS |
111 | r = getenv_bool_secure("SYSTEMD_IN_INITRD"); |
112 | if (r < 0 && r != -ENXIO) | |
113 | log_debug_errno(r, "Failed to parse $SYSTEMD_IN_INITRD, ignoring: %m"); | |
114 | ||
115 | if (r >= 0) | |
116 | saved_in_initrd = r > 0; | |
117 | else | |
118 | saved_in_initrd = access("/etc/initrd-release", F_OK) >= 0 && | |
119 | statfs("/", &s) >= 0 && | |
120 | is_temporary_fs(&s); | |
9be346c9 | 121 | |
dcd61450 IS |
122 | return saved_in_initrd; |
123 | } | |
124 | ||
125 | void in_initrd_force(bool value) { | |
126 | saved_in_initrd = value; | |
9be346c9 | 127 | } |
069cfc85 | 128 | |
a9e12476 KS |
129 | /* hey glibc, APIs with callbacks without a user pointer are so useless */ |
130 | void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size, | |
f0f6d791 | 131 | __compar_d_fn_t compar, void *arg) { |
a9e12476 KS |
132 | size_t l, u, idx; |
133 | const void *p; | |
134 | int comparison; | |
135 | ||
2901f4b3 LP |
136 | assert(!size_multiply_overflow(nmemb, size)); |
137 | ||
a9e12476 KS |
138 | l = 0; |
139 | u = nmemb; | |
140 | while (l < u) { | |
141 | idx = (l + u) / 2; | |
2901f4b3 | 142 | p = (const uint8_t*) base + idx * size; |
a9e12476 KS |
143 | comparison = compar(key, p, arg); |
144 | if (comparison < 0) | |
145 | u = idx; | |
146 | else if (comparison > 0) | |
147 | l = idx + 1; | |
148 | else | |
149 | return (void *)p; | |
150 | } | |
151 | return NULL; | |
152 | } | |
09017585 | 153 | |
240dbaa4 LP |
154 | int on_ac_power(void) { |
155 | bool found_offline = false, found_online = false; | |
156 | _cleanup_closedir_ DIR *d = NULL; | |
8fb3f009 | 157 | struct dirent *de; |
240dbaa4 LP |
158 | |
159 | d = opendir("/sys/class/power_supply"); | |
160 | if (!d) | |
6d890034 | 161 | return errno == ENOENT ? true : -errno; |
240dbaa4 | 162 | |
8fb3f009 | 163 | FOREACH_DIRENT(de, d, return -errno) { |
240dbaa4 LP |
164 | _cleanup_close_ int fd = -1, device = -1; |
165 | char contents[6]; | |
166 | ssize_t n; | |
240dbaa4 | 167 | |
240dbaa4 LP |
168 | device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY); |
169 | if (device < 0) { | |
3742095b | 170 | if (IN_SET(errno, ENOENT, ENOTDIR)) |
240dbaa4 LP |
171 | continue; |
172 | ||
173 | return -errno; | |
174 | } | |
175 | ||
176 | fd = openat(device, "type", O_RDONLY|O_CLOEXEC|O_NOCTTY); | |
177 | if (fd < 0) { | |
178 | if (errno == ENOENT) | |
179 | continue; | |
180 | ||
181 | return -errno; | |
182 | } | |
183 | ||
184 | n = read(fd, contents, sizeof(contents)); | |
185 | if (n < 0) | |
186 | return -errno; | |
187 | ||
188 | if (n != 6 || memcmp(contents, "Mains\n", 6)) | |
189 | continue; | |
190 | ||
03e334a1 | 191 | safe_close(fd); |
240dbaa4 LP |
192 | fd = openat(device, "online", O_RDONLY|O_CLOEXEC|O_NOCTTY); |
193 | if (fd < 0) { | |
194 | if (errno == ENOENT) | |
195 | continue; | |
196 | ||
197 | return -errno; | |
198 | } | |
199 | ||
200 | n = read(fd, contents, sizeof(contents)); | |
201 | if (n < 0) | |
202 | return -errno; | |
203 | ||
204 | if (n != 2 || contents[1] != '\n') | |
205 | return -EIO; | |
206 | ||
207 | if (contents[0] == '1') { | |
208 | found_online = true; | |
209 | break; | |
210 | } else if (contents[0] == '0') | |
211 | found_offline = true; | |
212 | else | |
213 | return -EIO; | |
214 | } | |
215 | ||
216 | return found_online || !found_offline; | |
217 | } | |
fabe5c0e | 218 | |
bc9fd78c LP |
219 | int container_get_leader(const char *machine, pid_t *pid) { |
220 | _cleanup_free_ char *s = NULL, *class = NULL; | |
221 | const char *p; | |
222 | pid_t leader; | |
223 | int r; | |
224 | ||
225 | assert(machine); | |
226 | assert(pid); | |
227 | ||
1e5057b9 LP |
228 | if (streq(machine, ".host")) { |
229 | *pid = 1; | |
230 | return 0; | |
231 | } | |
232 | ||
b9a8d250 LP |
233 | if (!machine_name_is_valid(machine)) |
234 | return -EINVAL; | |
235 | ||
63c372cb | 236 | p = strjoina("/run/systemd/machines/", machine); |
13df9c39 LP |
237 | r = parse_env_file(NULL, p, |
238 | "LEADER", &s, | |
239 | "CLASS", &class); | |
bc9fd78c LP |
240 | if (r == -ENOENT) |
241 | return -EHOSTDOWN; | |
242 | if (r < 0) | |
243 | return r; | |
244 | if (!s) | |
245 | return -EIO; | |
246 | ||
247 | if (!streq_ptr(class, "container")) | |
248 | return -EIO; | |
249 | ||
250 | r = parse_pid(s, &leader); | |
251 | if (r < 0) | |
252 | return r; | |
253 | if (leader <= 1) | |
254 | return -EIO; | |
255 | ||
256 | *pid = leader; | |
257 | return 0; | |
258 | } | |
259 | ||
3f6fd1ba | 260 | int version(void) { |
f1028f57 | 261 | puts("systemd " STRINGIFY(PROJECT_VERSION) " (" GIT_VERSION ")\n" |
3f6fd1ba LP |
262 | SYSTEMD_FEATURES); |
263 | return 0; | |
264 | } | |
68c58c67 LP |
265 | |
266 | /* This is a direct translation of str_verscmp from boot.c */ | |
267 | static bool is_digit(int c) { | |
268 | return c >= '0' && c <= '9'; | |
269 | } | |
270 | ||
271 | static int c_order(int c) { | |
272 | if (c == 0 || is_digit(c)) | |
273 | return 0; | |
274 | ||
275 | if ((c >= 'a') && (c <= 'z')) | |
276 | return c; | |
277 | ||
278 | return c + 0x10000; | |
279 | } | |
280 | ||
281 | int str_verscmp(const char *s1, const char *s2) { | |
282 | const char *os1, *os2; | |
283 | ||
284 | assert(s1); | |
285 | assert(s2); | |
286 | ||
287 | os1 = s1; | |
288 | os2 = s2; | |
289 | ||
290 | while (*s1 || *s2) { | |
291 | int first; | |
292 | ||
293 | while ((*s1 && !is_digit(*s1)) || (*s2 && !is_digit(*s2))) { | |
294 | int order; | |
295 | ||
296 | order = c_order(*s1) - c_order(*s2); | |
297 | if (order != 0) | |
298 | return order; | |
299 | s1++; | |
300 | s2++; | |
301 | } | |
302 | ||
303 | while (*s1 == '0') | |
304 | s1++; | |
305 | while (*s2 == '0') | |
306 | s2++; | |
307 | ||
308 | first = 0; | |
309 | while (is_digit(*s1) && is_digit(*s2)) { | |
310 | if (first == 0) | |
311 | first = *s1 - *s2; | |
312 | s1++; | |
313 | s2++; | |
314 | } | |
315 | ||
316 | if (is_digit(*s1)) | |
317 | return 1; | |
318 | if (is_digit(*s2)) | |
319 | return -1; | |
320 | ||
321 | if (first != 0) | |
322 | return first; | |
323 | } | |
324 | ||
325 | return strcmp(os1, os2); | |
326 | } | |
9ce17593 JK |
327 | |
328 | /* Turn off core dumps but only if we're running outside of a container. */ | |
e557b1a6 LP |
329 | void disable_coredumps(void) { |
330 | int r; | |
331 | ||
332 | if (detect_container() > 0) | |
333 | return; | |
334 | ||
57512c89 | 335 | r = write_string_file("/proc/sys/kernel/core_pattern", "|/bin/false", WRITE_STRING_FILE_DISABLE_BUFFER); |
e557b1a6 LP |
336 | if (r < 0) |
337 | log_debug_errno(r, "Failed to turn off coredumps, ignoring: %m"); | |
9ce17593 | 338 | } |