File: | build-scan/../src/basic/exec-util.c |
Warning: | line 211, column 9 Value stored to 'fd' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
2 | |
3 | #include <dirent.h> |
4 | #include <errno(*__errno_location ()).h> |
5 | #include <sys/prctl.h> |
6 | #include <sys/types.h> |
7 | #include <unistd.h> |
8 | #include <stdio.h> |
9 | |
10 | #include "alloc-util.h" |
11 | #include "conf-files.h" |
12 | #include "env-util.h" |
13 | #include "exec-util.h" |
14 | #include "fd-util.h" |
15 | #include "fileio.h" |
16 | #include "hashmap.h" |
17 | #include "macro.h" |
18 | #include "process-util.h" |
19 | #include "set.h" |
20 | #include "signal-util.h" |
21 | #include "stat-util.h" |
22 | #include "string-util.h" |
23 | #include "strv.h" |
24 | #include "terminal-util.h" |
25 | #include "util.h" |
26 | |
27 | /* Put this test here for a lack of better place */ |
28 | assert_cc(EAGAIN == EWOULDBLOCK)GCC diagnostic push
; GCC diagnostic ignored "-Wdeclaration-after-statement" ; struct _assert_struct_7 { char x[(11 == 11) ? 0 : -1]; }; GCC diagnostic pop ; |
29 | |
30 | static int do_spawn(const char *path, char *argv[], int stdout_fd, pid_t *pid) { |
31 | |
32 | pid_t _pid; |
33 | int r; |
34 | |
35 | if (null_or_empty_path(path)) { |
36 | log_debug("%s is empty (a mask).", path)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/basic/exec-util.c", 36, __func__, "%s is empty (a mask)." , path) : -abs(_e); }); |
37 | return 0; |
38 | } |
39 | |
40 | r = safe_fork("(direxec)", FORK_DEATHSIG|FORK_LOG, &_pid); |
41 | if (r < 0) |
42 | return r; |
43 | if (r == 0) { |
44 | char *_argv[2]; |
45 | |
46 | if (stdout_fd >= 0) { |
47 | r = rearrange_stdio(STDIN_FILENO0, stdout_fd, STDERR_FILENO2); |
48 | if (r < 0) |
49 | _exit(EXIT_FAILURE1); |
50 | } |
51 | |
52 | if (!argv) { |
53 | _argv[0] = (char*) path; |
54 | _argv[1] = NULL((void*)0); |
55 | argv = _argv; |
56 | } else |
57 | argv[0] = (char*) path; |
58 | |
59 | execv(path, argv); |
60 | log_error_errno(errno, "Failed to execute %s: %m", path)({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/basic/exec-util.c", 60, __func__ , "Failed to execute %s: %m", path) : -abs(_e); }); |
61 | _exit(EXIT_FAILURE1); |
62 | } |
63 | |
64 | *pid = _pid; |
65 | return 1; |
66 | } |
67 | |
68 | static int do_execute( |
69 | char **directories, |
70 | usec_t timeout, |
71 | gather_stdout_callback_t const callbacks[_STDOUT_CONSUME_MAX], |
72 | void* const callback_args[_STDOUT_CONSUME_MAX], |
73 | int output_fd, |
74 | char *argv[]) { |
75 | |
76 | _cleanup_hashmap_free_free___attribute__((cleanup(hashmap_free_freep))) Hashmap *pids = NULL((void*)0); |
77 | _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **paths = NULL((void*)0); |
78 | char **path; |
79 | int r; |
80 | |
81 | /* We fork this all off from a child process so that we can somewhat cleanly make |
82 | * use of SIGALRM to set a time limit. |
83 | * |
84 | * If callbacks is nonnull, execution is serial. Otherwise, we default to parallel. |
85 | */ |
86 | |
87 | r = conf_files_list_strv(&paths, NULL((void*)0), NULL((void*)0), CONF_FILES_EXECUTABLE|CONF_FILES_REGULAR|CONF_FILES_FILTER_MASKED, (const char* const*) directories); |
88 | if (r < 0) |
89 | return r; |
90 | |
91 | if (!callbacks) { |
92 | pids = hashmap_new(NULL)internal_hashmap_new(((void*)0) ); |
93 | if (!pids) |
94 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/basic/exec-util.c" , 94, __func__); |
95 | } |
96 | |
97 | /* Abort execution of this process after the timout. We simply rely on SIGALRM as |
98 | * default action terminating the process, and turn on alarm(). */ |
99 | |
100 | if (timeout != USEC_INFINITY((usec_t) -1)) |
101 | alarm(DIV_ROUND_UP(timeout, USEC_PER_SEC)({ const typeof((timeout)) __unique_prefix_X8 = ((timeout)); const typeof((((usec_t) 1000000ULL))) __unique_prefix_Y9 = ((((usec_t ) 1000000ULL))); (__unique_prefix_X8 / __unique_prefix_Y9 + ! !(__unique_prefix_X8 % __unique_prefix_Y9)); })); |
102 | |
103 | STRV_FOREACH(path, paths)for ((path) = (paths); (path) && *(path); (path)++) { |
104 | _cleanup_free___attribute__((cleanup(freep))) char *t = NULL((void*)0); |
105 | _cleanup_close___attribute__((cleanup(closep))) int fd = -1; |
106 | pid_t pid; |
107 | |
108 | t = strdup(*path); |
109 | if (!t) |
110 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/basic/exec-util.c" , 110, __func__); |
111 | |
112 | if (callbacks) { |
113 | fd = open_serialization_fd(basename(*path)); |
114 | if (fd < 0) |
115 | return log_error_errno(fd, "Failed to open serialization file: %m")({ int _level = ((3)), _e = ((fd)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/basic/exec-util.c", 115, __func__, "Failed to open serialization file: %m" ) : -abs(_e); }); |
116 | } |
117 | |
118 | r = do_spawn(t, argv, fd, &pid); |
119 | if (r <= 0) |
120 | continue; |
121 | |
122 | if (pids) { |
123 | r = hashmap_put(pids, PID_TO_PTR(pid), t); |
124 | if (r < 0) |
125 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/basic/exec-util.c" , 125, __func__); |
126 | t = NULL((void*)0); |
127 | } else { |
128 | r = wait_for_terminate_and_check(t, pid, WAIT_LOG); |
129 | if (r < 0) |
130 | continue; |
131 | |
132 | if (lseek(fd, 0, SEEK_SET0) < 0) |
133 | return log_error_errno(errno, "Failed to seek on serialization fd: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/basic/exec-util.c", 133, __func__ , "Failed to seek on serialization fd: %m") : -abs(_e); }); |
134 | |
135 | r = callbacks[STDOUT_GENERATE](fd, callback_args[STDOUT_GENERATE]); |
136 | fd = -1; |
137 | if (r < 0) |
138 | return log_error_errno(r, "Failed to process output from %s: %m", *path)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/basic/exec-util.c", 138, __func__, "Failed to process output from %s: %m" , *path) : -abs(_e); }); |
139 | } |
140 | } |
141 | |
142 | if (callbacks) { |
143 | r = callbacks[STDOUT_COLLECT](output_fd, callback_args[STDOUT_COLLECT]); |
144 | if (r < 0) |
145 | return log_error_errno(r, "Callback two failed: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/basic/exec-util.c", 145, __func__, "Callback two failed: %m" ) : -abs(_e); }); |
146 | } |
147 | |
148 | while (!hashmap_isempty(pids)) { |
149 | _cleanup_free___attribute__((cleanup(freep))) char *t = NULL((void*)0); |
150 | pid_t pid; |
151 | |
152 | pid = PTR_TO_PID(hashmap_first_key(pids)); |
153 | assert(pid > 0)do { if ((__builtin_expect(!!(!(pid > 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("pid > 0"), "../src/basic/exec-util.c" , 153, __PRETTY_FUNCTION__); } while (0); |
154 | |
155 | t = hashmap_remove(pids, PID_TO_PTR(pid)); |
156 | assert(t)do { if ((__builtin_expect(!!(!(t)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("t"), "../src/basic/exec-util.c", 156, __PRETTY_FUNCTION__ ); } while (0); |
157 | |
158 | (void) wait_for_terminate_and_check(t, pid, WAIT_LOG); |
159 | } |
160 | |
161 | return 0; |
162 | } |
163 | |
164 | int execute_directories( |
165 | const char* const* directories, |
166 | usec_t timeout, |
167 | gather_stdout_callback_t const callbacks[_STDOUT_CONSUME_MAX], |
168 | void* const callback_args[_STDOUT_CONSUME_MAX], |
169 | char *argv[]) { |
170 | |
171 | char **dirs = (char**) directories; |
172 | _cleanup_close___attribute__((cleanup(closep))) int fd = -1; |
173 | char *name; |
174 | int r; |
175 | |
176 | assert(!strv_isempty(dirs))do { if ((__builtin_expect(!!(!(!strv_isempty(dirs))),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("!strv_isempty(dirs)"), "../src/basic/exec-util.c" , 176, __PRETTY_FUNCTION__); } while (0); |
177 | |
178 | name = basename(dirs[0]); |
179 | assert(!isempty(name))do { if ((__builtin_expect(!!(!(!isempty(name))),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("!isempty(name)"), "../src/basic/exec-util.c" , 179, __PRETTY_FUNCTION__); } while (0); |
180 | |
181 | if (callbacks) { |
182 | assert(callback_args)do { if ((__builtin_expect(!!(!(callback_args)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("callback_args"), "../src/basic/exec-util.c" , 182, __PRETTY_FUNCTION__); } while (0); |
183 | assert(callbacks[STDOUT_GENERATE])do { if ((__builtin_expect(!!(!(callbacks[STDOUT_GENERATE])), 0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("callbacks[STDOUT_GENERATE]" ), "../src/basic/exec-util.c", 183, __PRETTY_FUNCTION__); } while (0); |
184 | assert(callbacks[STDOUT_COLLECT])do { if ((__builtin_expect(!!(!(callbacks[STDOUT_COLLECT])),0 ))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("callbacks[STDOUT_COLLECT]" ), "../src/basic/exec-util.c", 184, __PRETTY_FUNCTION__); } while (0); |
185 | assert(callbacks[STDOUT_CONSUME])do { if ((__builtin_expect(!!(!(callbacks[STDOUT_CONSUME])),0 ))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("callbacks[STDOUT_CONSUME]" ), "../src/basic/exec-util.c", 185, __PRETTY_FUNCTION__); } while (0); |
186 | |
187 | fd = open_serialization_fd(name); |
188 | if (fd < 0) |
189 | return log_error_errno(fd, "Failed to open serialization file: %m")({ int _level = ((3)), _e = ((fd)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/basic/exec-util.c", 189, __func__, "Failed to open serialization file: %m" ) : -abs(_e); }); |
190 | } |
191 | |
192 | /* Executes all binaries in the directories serially or in parallel and waits for |
193 | * them to finish. Optionally a timeout is applied. If a file with the same name |
194 | * exists in more than one directory, the earliest one wins. */ |
195 | |
196 | r = safe_fork("(sd-executor)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL((void*)0)); |
197 | if (r < 0) |
198 | return r; |
199 | if (r == 0) { |
200 | r = do_execute(dirs, timeout, callbacks, callback_args, fd, argv); |
201 | _exit(r < 0 ? EXIT_FAILURE1 : EXIT_SUCCESS0); |
202 | } |
203 | |
204 | if (!callbacks) |
205 | return 0; |
206 | |
207 | if (lseek(fd, 0, SEEK_SET0) < 0) |
208 | return log_error_errno(errno, "Failed to rewind serialization fd: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/basic/exec-util.c", 208, __func__ , "Failed to rewind serialization fd: %m") : -abs(_e); }); |
209 | |
210 | r = callbacks[STDOUT_CONSUME](fd, callback_args[STDOUT_CONSUME]); |
211 | fd = -1; |
Value stored to 'fd' is never read | |
212 | if (r < 0) |
213 | return log_error_errno(r, "Failed to parse returned data: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/basic/exec-util.c", 213, __func__, "Failed to parse returned data: %m" ) : -abs(_e); }); |
214 | return 0; |
215 | } |
216 | |
217 | static int gather_environment_generate(int fd, void *arg) { |
218 | char ***env = arg, **x, **y; |
219 | _cleanup_fclose___attribute__((cleanup(fclosep))) FILE *f = NULL((void*)0); |
220 | _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **new = NULL((void*)0); |
221 | int r; |
222 | |
223 | /* Read a series of VAR=value assignments from fd, use them to update the list of |
224 | * variables in env. Also update the exported environment. |
225 | * |
226 | * fd is always consumed, even on error. |
227 | */ |
228 | |
229 | assert(env)do { if ((__builtin_expect(!!(!(env)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("env"), "../src/basic/exec-util.c", 229, __PRETTY_FUNCTION__); } while (0); |
230 | |
231 | f = fdopen(fd, "r"); |
232 | if (!f) { |
233 | safe_close(fd); |
234 | return -errno(*__errno_location ()); |
235 | } |
236 | |
237 | r = load_env_file_pairs(f, NULL((void*)0), NULL((void*)0), &new); |
238 | if (r < 0) |
239 | return r; |
240 | |
241 | STRV_FOREACH_PAIR(x, y, new)for ((x) = (new), (y) = (x+1); (x) && *(x) && *(y); (x) += 2, (y) = (x + 1)) { |
242 | char *p; |
243 | |
244 | if (!env_name_is_valid(*x)) { |
245 | log_warning("Invalid variable assignment \"%s=...\", ignoring.", *x)({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/basic/exec-util.c", 245, __func__, "Invalid variable assignment \"%s=...\", ignoring." , *x) : -abs(_e); }); |
246 | continue; |
247 | } |
248 | |
249 | p = strjoin(*x, "=", *y)strjoin_real((*x), "=", *y, ((void*)0)); |
250 | if (!p) |
251 | return -ENOMEM12; |
252 | |
253 | r = strv_env_replace(env, p); |
254 | if (r < 0) |
255 | return r; |
256 | |
257 | if (setenv(*x, *y, true1) < 0) |
258 | return -errno(*__errno_location ()); |
259 | } |
260 | |
261 | return r; |
262 | } |
263 | |
264 | static int gather_environment_collect(int fd, void *arg) { |
265 | char ***env = arg; |
266 | _cleanup_fclose___attribute__((cleanup(fclosep))) FILE *f = NULL((void*)0); |
267 | int r; |
268 | |
269 | /* Write out a series of env=cescape(VAR=value) assignments to fd. */ |
270 | |
271 | assert(env)do { if ((__builtin_expect(!!(!(env)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("env"), "../src/basic/exec-util.c", 271, __PRETTY_FUNCTION__); } while (0); |
272 | |
273 | f = fdopen(fd, "w"); |
274 | if (!f) { |
275 | safe_close(fd); |
276 | return -errno(*__errno_location ()); |
277 | } |
278 | |
279 | r = serialize_environment(f, *env); |
280 | if (r < 0) |
281 | return r; |
282 | |
283 | if (ferror(f)) |
284 | return errno(*__errno_location ()) > 0 ? -errno(*__errno_location ()) : -EIO5; |
285 | |
286 | return 0; |
287 | } |
288 | |
289 | static int gather_environment_consume(int fd, void *arg) { |
290 | char ***env = arg; |
291 | _cleanup_fclose___attribute__((cleanup(fclosep))) FILE *f = NULL((void*)0); |
292 | char line[LINE_MAX2048]; |
293 | int r = 0, k; |
294 | |
295 | /* Read a series of env=cescape(VAR=value) assignments from fd into env. */ |
296 | |
297 | assert(env)do { if ((__builtin_expect(!!(!(env)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("env"), "../src/basic/exec-util.c", 297, __PRETTY_FUNCTION__); } while (0); |
298 | |
299 | f = fdopen(fd, "r"); |
300 | if (!f) { |
301 | safe_close(fd); |
302 | return -errno(*__errno_location ()); |
303 | } |
304 | |
305 | FOREACH_LINE(line, f, return -EIO)for (;;) if (!fgets(line, sizeof(line), f)) { if (ferror(f)) { return -5; } break; } else { |
306 | truncate_nl(line); |
307 | |
308 | k = deserialize_environment(env, line); |
309 | if (k < 0) |
310 | log_error_errno(k, "Invalid line \"%s\": %m", line)({ int _level = ((3)), _e = ((k)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/basic/exec-util.c", 310, __func__, "Invalid line \"%s\": %m" , line) : -abs(_e); }); |
311 | if (k < 0 && r == 0) |
312 | r = k; |
313 | } |
314 | |
315 | return r; |
316 | } |
317 | |
318 | const gather_stdout_callback_t gather_environment[] = { |
319 | gather_environment_generate, |
320 | gather_environment_collect, |
321 | gather_environment_consume, |
322 | }; |