]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/util.c
fileio: add read_virtual_file_at() flavour that takes dir_fd/path pair
[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;
8fb3f009 121 struct dirent *de;
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) {
240dbaa4
LP
128 _cleanup_close_ int fd = -1, device = -1;
129 char contents[6];
130 ssize_t n;
240dbaa4 131
240dbaa4
LP
132 device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY);
133 if (device < 0) {
3742095b 134 if (IN_SET(errno, ENOENT, ENOTDIR))
240dbaa4
LP
135 continue;
136
137 return -errno;
138 }
139
140 fd = openat(device, "type", O_RDONLY|O_CLOEXEC|O_NOCTTY);
141 if (fd < 0) {
142 if (errno == ENOENT)
143 continue;
144
145 return -errno;
146 }
147
148 n = read(fd, contents, sizeof(contents));
149 if (n < 0)
150 return -errno;
151
152 if (n != 6 || memcmp(contents, "Mains\n", 6))
153 continue;
154
03e334a1 155 safe_close(fd);
240dbaa4
LP
156 fd = openat(device, "online", O_RDONLY|O_CLOEXEC|O_NOCTTY);
157 if (fd < 0) {
158 if (errno == ENOENT)
159 continue;
160
161 return -errno;
162 }
163
164 n = read(fd, contents, sizeof(contents));
165 if (n < 0)
166 return -errno;
167
168 if (n != 2 || contents[1] != '\n')
169 return -EIO;
170
171 if (contents[0] == '1') {
172 found_online = true;
173 break;
174 } else if (contents[0] == '0')
175 found_offline = true;
176 else
177 return -EIO;
178 }
179
180 return found_online || !found_offline;
181}
fabe5c0e 182
bc9fd78c
LP
183int container_get_leader(const char *machine, pid_t *pid) {
184 _cleanup_free_ char *s = NULL, *class = NULL;
185 const char *p;
186 pid_t leader;
187 int r;
188
189 assert(machine);
190 assert(pid);
191
1e5057b9
LP
192 if (streq(machine, ".host")) {
193 *pid = 1;
194 return 0;
195 }
196
52ef5dd7 197 if (!hostname_is_valid(machine, 0))
b9a8d250
LP
198 return -EINVAL;
199
63c372cb 200 p = strjoina("/run/systemd/machines/", machine);
13df9c39
LP
201 r = parse_env_file(NULL, p,
202 "LEADER", &s,
203 "CLASS", &class);
bc9fd78c
LP
204 if (r == -ENOENT)
205 return -EHOSTDOWN;
206 if (r < 0)
207 return r;
208 if (!s)
209 return -EIO;
210
211 if (!streq_ptr(class, "container"))
212 return -EIO;
213
214 r = parse_pid(s, &leader);
215 if (r < 0)
216 return r;
217 if (leader <= 1)
218 return -EIO;
219
220 *pid = leader;
221 return 0;
222}
223
3f6fd1ba 224int version(void) {
91b79ba8
ZJS
225 printf("systemd " STRINGIFY(PROJECT_VERSION) " (" GIT_VERSION ")\n%s\n",
226 systemd_features);
3f6fd1ba
LP
227 return 0;
228}
68c58c67 229
9ce17593 230/* Turn off core dumps but only if we're running outside of a container. */
e557b1a6
LP
231void disable_coredumps(void) {
232 int r;
233
234 if (detect_container() > 0)
235 return;
236
57512c89 237 r = write_string_file("/proc/sys/kernel/core_pattern", "|/bin/false", WRITE_STRING_FILE_DISABLE_BUFFER);
e557b1a6
LP
238 if (r < 0)
239 log_debug_errno(r, "Failed to turn off coredumps, ignoring: %m");
9ce17593 240}