Bug Summary

File:build-scan/../src/udev/udev-event.c
Warning:line 168, column 25
Value stored to 'l' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name udev-event.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fdenormal-fp-math=preserve-sign,preserve-sign -ffp-contract=fast -fno-rounding-math -ffast-math -ffinite-math-only -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -include config.h -I src/udev/libudev-core.a.p -I src/udev -I ../src/udev -I src/basic -I ../src/basic -I src/shared -I ../src/shared -I src/systemd -I ../src/systemd -I src/journal -I ../src/journal -I src/journal-remote -I ../src/journal-remote -I src/nspawn -I ../src/nspawn -I src/resolve -I ../src/resolve -I src/timesync -I ../src/timesync -I ../src/time-wait-sync -I src/login -I ../src/login -I src/libudev -I ../src/libudev -I src/core -I ../src/core -I ../src/libsystemd/sd-bus -I ../src/libsystemd/sd-device -I ../src/libsystemd/sd-hwdb -I ../src/libsystemd/sd-id128 -I ../src/libsystemd/sd-netlink -I ../src/libsystemd/sd-network -I src/libsystemd-network -I ../src/libsystemd-network -I . -I .. -I ../src/udev/net -I /usr/include/blkid -D _FILE_OFFSET_BITS=64 -D LOG_REALM=LOG_REALM_UDEV -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wwrite-strings -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-result -Wno-format-signedness -Wno-error=nonnull -std=gnu99 -fconst-strings -fdebug-compilation-dir /home/mrc0mmand/repos/@redhat-plumbers/systemd-rhel8/build-scan -ferror-limit 19 -fvisibility hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-07-16-221226-1465241-1 -x c ../src/udev/udev-event.c
1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 *
4 */
5
6#include <ctype.h>
7#include <errno(*__errno_location ()).h>
8#include <fcntl.h>
9#include <net/if.h>
10#include <poll.h>
11#include <stddef.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15#include <sys/epoll.h>
16#include <sys/prctl.h>
17#include <sys/signalfd.h>
18#include <sys/wait.h>
19#include <unistd.h>
20
21#include "alloc-util.h"
22#include "fd-util.h"
23#include "format-util.h"
24#include "netlink-util.h"
25#include "process-util.h"
26#include "signal-util.h"
27#include "string-util.h"
28#include "udev.h"
29
30typedef struct Spawn {
31 const char *cmd;
32 pid_t pid;
33 usec_t timeout_warn;
34 usec_t timeout;
35 bool_Bool accept_failure;
36} Spawn;
37
38struct udev_event *udev_event_new(struct udev_device *dev) {
39 struct udev *udev = udev_device_get_udev(dev);
40 struct udev_event *event;
41
42 event = new0(struct udev_event, 1)((struct udev_event*) calloc((1), sizeof(struct udev_event)));
43 if (event == NULL((void*)0))
44 return NULL((void*)0);
45 event->dev = dev;
46 event->udev = udev;
47 udev_list_init(udev, &event->run_list, false0);
48 udev_list_init(udev, &event->seclabel_list, false0);
49 event->birth_usec = now(CLOCK_MONOTONIC1);
50 return event;
51}
52
53void udev_event_unref(struct udev_event *event) {
54 if (event == NULL((void*)0))
55 return;
56 sd_netlink_unref(event->rtnl);
57 udev_list_cleanup(&event->run_list);
58 udev_list_cleanup(&event->seclabel_list);
59 free(event->program_result);
60 free(event->name);
61 free(event);
62}
63
64enum subst_type {
65 SUBST_UNKNOWN,
66 SUBST_DEVNODE,
67 SUBST_ATTR,
68 SUBST_ENV,
69 SUBST_KERNEL,
70 SUBST_KERNEL_NUMBER,
71 SUBST_DRIVER,
72 SUBST_DEVPATH,
73 SUBST_ID,
74 SUBST_MAJOR,
75 SUBST_MINOR,
76 SUBST_RESULT,
77 SUBST_PARENT,
78 SUBST_NAME,
79 SUBST_LINKS,
80 SUBST_ROOT,
81 SUBST_SYS,
82};
83
84static size_t subst_format_var(struct udev_event *event, struct udev_device *dev,
85 enum subst_type type, char *attr,
86 char *dest, size_t l) {
87 char *s = dest;
88
89 switch (type) {
90 case SUBST_DEVPATH:
91 l = strpcpy(&s, l, udev_device_get_devpath(dev));
92 break;
93 case SUBST_KERNEL:
94 l = strpcpy(&s, l, udev_device_get_sysname(dev));
95 break;
96 case SUBST_KERNEL_NUMBER:
97 if (udev_device_get_sysnum(dev) == NULL((void*)0))
98 break;
99 l = strpcpy(&s, l, udev_device_get_sysnum(dev));
100 break;
101 case SUBST_ID:
102 if (event->dev_parent == NULL((void*)0))
103 break;
104 l = strpcpy(&s, l, udev_device_get_sysname(event->dev_parent));
105 break;
106 case SUBST_DRIVER: {
107 const char *driver;
108
109 if (event->dev_parent == NULL((void*)0))
110 break;
111
112 driver = udev_device_get_driver(event->dev_parent);
113 if (driver == NULL((void*)0))
114 break;
115 l = strpcpy(&s, l, driver);
116 break;
117 }
118 case SUBST_MAJOR: {
119 char num[UTIL_PATH_SIZE1024];
120
121 sprintf(num, "%u", major(udev_device_get_devnum(dev))gnu_dev_major (udev_device_get_devnum(dev)));
122 l = strpcpy(&s, l, num);
123 break;
124 }
125 case SUBST_MINOR: {
126 char num[UTIL_PATH_SIZE1024];
127
128 sprintf(num, "%u", minor(udev_device_get_devnum(dev))gnu_dev_minor (udev_device_get_devnum(dev)));
129 l = strpcpy(&s, l, num);
130 break;
131 }
132 case SUBST_RESULT: {
133 char *rest;
134 int i;
135
136 if (event->program_result == NULL((void*)0))
137 break;
138 /* get part of the result string */
139 i = 0;
140 if (attr != NULL((void*)0))
141 i = strtoul(attr, &rest, 10);
142 if (i > 0) {
143 char result[UTIL_PATH_SIZE1024];
144 char tmp[UTIL_PATH_SIZE1024];
145 char *cpos;
146
147 strscpy(result, sizeof(result), event->program_result);
148 cpos = result;
149 while (--i) {
150 while (cpos[0] != '\0' && !isspace(cpos[0])((*__ctype_b_loc ())[(int) ((cpos[0]))] & (unsigned short
int) _ISspace)
)
151 cpos++;
152 while (isspace(cpos[0])((*__ctype_b_loc ())[(int) ((cpos[0]))] & (unsigned short
int) _ISspace)
)
153 cpos++;
154 if (cpos[0] == '\0')
155 break;
156 }
157 if (i > 0) {
158 log_error("requested part of result string not found")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_UDEV
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/udev/udev-event.c", 158, __func__, "requested part of result string not found"
) : -abs(_e); })
;
159 break;
160 }
161 strscpy(tmp, sizeof(tmp), cpos);
162 /* %{2+}c copies the whole string from the second part on */
163 if (rest[0] != '+') {
164 cpos = strchr(tmp, ' ');
165 if (cpos)
166 cpos[0] = '\0';
167 }
168 l = strpcpy(&s, l, tmp);
Value stored to 'l' is never read
169 } else {
170 l = strpcpy(&s, l, event->program_result);
171 }
172 break;
173 }
174 case SUBST_ATTR: {
175 const char *value = NULL((void*)0);
176 char vbuf[UTIL_NAME_SIZE512];
177 size_t len;
178 int count;
179
180 if (attr == NULL((void*)0)) {
181 log_error("missing file parameter for attr")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_UDEV
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/udev/udev-event.c", 181, __func__, "missing file parameter for attr"
) : -abs(_e); })
;
182 break;
183 }
184
185 /* try to read the value specified by "[dmi/id]product_name" */
186 if (util_resolve_subsys_kernel(event->udev, attr, vbuf, sizeof(vbuf), 1) == 0)
187 value = vbuf;
188
189 /* try to read the attribute the device */
190 if (value == NULL((void*)0))
191 value = udev_device_get_sysattr_value(event->dev, attr);
192
193 /* try to read the attribute of the parent device, other matches have selected */
194 if (value == NULL((void*)0) && event->dev_parent != NULL((void*)0) && event->dev_parent != event->dev)
195 value = udev_device_get_sysattr_value(event->dev_parent, attr);
196
197 if (value == NULL((void*)0))
198 break;
199
200 /* strip trailing whitespace, and replace unwanted characters */
201 if (value != vbuf)
202 strscpy(vbuf, sizeof(vbuf), value);
203 len = strlen(vbuf);
204 while (len > 0 && isspace(vbuf[--len])((*__ctype_b_loc ())[(int) ((vbuf[--len]))] & (unsigned short
int) _ISspace)
)
205 vbuf[len] = '\0';
206 count = util_replace_chars(vbuf, UDEV_ALLOWED_CHARS_INPUT"/ $%?,");
207 if (count > 0)
208 log_debug("%i character(s) replaced" , count)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/udev/udev-event.c", 208, __func__, "%i character(s) replaced"
, count) : -abs(_e); })
;
209 l = strpcpy(&s, l, vbuf);
210 break;
211 }
212 case SUBST_PARENT: {
213 struct udev_device *dev_parent;
214 const char *devnode;
215
216 dev_parent = udev_device_get_parent(event->dev);
217 if (dev_parent == NULL((void*)0))
218 break;
219 devnode = udev_device_get_devnode(dev_parent);
220 if (devnode != NULL((void*)0))
221 l = strpcpy(&s, l, devnode + STRLEN("/dev/")(sizeof("""/dev/""") - 1));
222 break;
223 }
224 case SUBST_DEVNODE:
225 if (udev_device_get_devnode(dev) != NULL((void*)0))
226 l = strpcpy(&s, l, udev_device_get_devnode(dev));
227 break;
228 case SUBST_NAME:
229 if (event->name != NULL((void*)0))
230 l = strpcpy(&s, l, event->name);
231 else if (udev_device_get_devnode(dev) != NULL((void*)0))
232 l = strpcpy(&s, l,
233 udev_device_get_devnode(dev) + STRLEN("/dev/")(sizeof("""/dev/""") - 1));
234 else
235 l = strpcpy(&s, l, udev_device_get_sysname(dev));
236 break;
237 case SUBST_LINKS: {
238 struct udev_list_entry *list_entry;
239
240 list_entry = udev_device_get_devlinks_list_entry(dev);
241 if (list_entry == NULL((void*)0))
242 break;
243 l = strpcpy(&s, l,
244 udev_list_entry_get_name(list_entry) + STRLEN("/dev/")(sizeof("""/dev/""") - 1));
245 udev_list_entry_foreach(list_entry, udev_list_entry_get_next(list_entry))for (list_entry = udev_list_entry_get_next(list_entry); list_entry
!= ((void*)0); list_entry = udev_list_entry_get_next(list_entry
))
246 l = strpcpyl(&s, l, " ",
247 udev_list_entry_get_name(list_entry) + STRLEN("/dev/")(sizeof("""/dev/""") - 1),
248 NULL((void*)0));
249 break;
250 }
251 case SUBST_ROOT:
252 l = strpcpy(&s, l, "/dev");
253 break;
254 case SUBST_SYS:
255 l = strpcpy(&s, l, "/sys");
256 break;
257 case SUBST_ENV:
258 if (attr == NULL((void*)0)) {
259 break;
260 } else {
261 const char *value;
262
263 value = udev_device_get_property_value(event->dev, attr);
264 if (value == NULL((void*)0))
265 break;
266 l = strpcpy(&s, l, value);
267 break;
268 }
269 default:
270 log_error("unknown substitution type=%i", type)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_UDEV
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/udev/udev-event.c", 270, __func__, "unknown substitution type=%i"
, type) : -abs(_e); })
;
271 break;
272 }
273
274 return s - dest;
275}
276
277size_t udev_event_apply_format(struct udev_event *event,
278 const char *src, char *dest, size_t size,
279 bool_Bool replace_whitespace) {
280 struct udev_device *dev = event->dev;
281 static const struct subst_map {
282 const char *name;
283 const char fmt;
284 enum subst_type type;
285 } map[] = {
286 { .name = "devnode", .fmt = 'N', .type = SUBST_DEVNODE },
287 { .name = "tempnode", .fmt = 'N', .type = SUBST_DEVNODE },
288 { .name = "attr", .fmt = 's', .type = SUBST_ATTR },
289 { .name = "sysfs", .fmt = 's', .type = SUBST_ATTR },
290 { .name = "env", .fmt = 'E', .type = SUBST_ENV },
291 { .name = "kernel", .fmt = 'k', .type = SUBST_KERNEL },
292 { .name = "number", .fmt = 'n', .type = SUBST_KERNEL_NUMBER },
293 { .name = "driver", .fmt = 'd', .type = SUBST_DRIVER },
294 { .name = "devpath", .fmt = 'p', .type = SUBST_DEVPATH },
295 { .name = "id", .fmt = 'b', .type = SUBST_ID },
296 { .name = "major", .fmt = 'M', .type = SUBST_MAJOR },
297 { .name = "minor", .fmt = 'm', .type = SUBST_MINOR },
298 { .name = "result", .fmt = 'c', .type = SUBST_RESULT },
299 { .name = "parent", .fmt = 'P', .type = SUBST_PARENT },
300 { .name = "name", .fmt = 'D', .type = SUBST_NAME },
301 { .name = "links", .fmt = 'L', .type = SUBST_LINKS },
302 { .name = "root", .fmt = 'r', .type = SUBST_ROOT },
303 { .name = "sys", .fmt = 'S', .type = SUBST_SYS },
304 };
305 const char *from;
306 char *s;
307 size_t l;
308
309 assert(dev)do { if ((__builtin_expect(!!(!(dev)),0))) log_assert_failed_realm
(LOG_REALM_UDEV, ("dev"), "../src/udev/udev-event.c", 309, __PRETTY_FUNCTION__
); } while (0)
;
310
311 from = src;
312 s = dest;
313 l = size;
314
315 for (;;) {
316 enum subst_type type = SUBST_UNKNOWN;
317 char attrbuf[UTIL_PATH_SIZE1024];
318 char *attr = NULL((void*)0);
319 size_t subst_len;
320
321 while (from[0] != '\0') {
322 if (from[0] == '$') {
323 /* substitute named variable */
324 unsigned int i;
325
326 if (from[1] == '$') {
327 from++;
328 goto copy;
329 }
330
331 for (i = 0; i < ELEMENTSOF(map)__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(map), typeof(&*(map))), sizeof(map)/sizeof((map)[
0]), ((void)0)))
; i++) {
332 if (startswith(&from[1], map[i].name)) {
333 type = map[i].type;
334 from += strlen(map[i].name)+1;
335 goto subst;
336 }
337 }
338 } else if (from[0] == '%') {
339 /* substitute format char */
340 unsigned int i;
341
342 if (from[1] == '%') {
343 from++;
344 goto copy;
345 }
346
347 for (i = 0; i < ELEMENTSOF(map)__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(map), typeof(&*(map))), sizeof(map)/sizeof((map)[
0]), ((void)0)))
; i++) {
348 if (from[1] == map[i].fmt) {
349 type = map[i].type;
350 from += 2;
351 goto subst;
352 }
353 }
354 }
355copy:
356 /* copy char */
357 if (l < 2) /* need space for this char and the terminating NUL */
358 goto out;
359 s[0] = from[0];
360 from++;
361 s++;
362 l--;
363 }
364
365 goto out;
366subst:
367 /* extract possible $format{attr} */
368 if (from[0] == '{') {
369 unsigned int i;
370
371 from++;
372 for (i = 0; from[i] != '}'; i++)
373 if (from[i] == '\0') {
374 log_error("missing closing brace for format '%s'", src)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_UDEV
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/udev/udev-event.c", 374, __func__, "missing closing brace for format '%s'"
, src) : -abs(_e); })
;
375 goto out;
376 }
377
378 if (i >= sizeof(attrbuf))
379 goto out;
380 memcpy(attrbuf, from, i);
381 attrbuf[i] = '\0';
382 from += i+1;
383 attr = attrbuf;
384 } else {
385 attr = NULL((void*)0);
386 }
387
388 subst_len = subst_format_var(event, dev, type, attr, s, l);
389
390 /* SUBST_RESULT handles spaces itself */
391 if (replace_whitespace && type != SUBST_RESULT)
392 /* util_replace_whitespace can replace in-place,
393 * and does nothing if subst_len == 0
394 */
395 subst_len = util_replace_whitespace(s, s, subst_len);
396
397 s += subst_len;
398 l -= subst_len;
399 }
400
401out:
402 assert(l >= 1)do { if ((__builtin_expect(!!(!(l >= 1)),0))) log_assert_failed_realm
(LOG_REALM_UDEV, ("l >= 1"), "../src/udev/udev-event.c", 402
, __PRETTY_FUNCTION__); } while (0)
;
403 s[0] = '\0';
404 return l;
405}
406
407static int spawn_exec(struct udev_event *event,
408 const char *cmd, char *const argv[], char **envp,
409 int fd_stdout, int fd_stderr) {
410 _cleanup_close___attribute__((cleanup(closep))) int fd = -1;
411 int r;
412
413 /* discard child output or connect to pipe */
414 fd = open("/dev/null", O_RDWR02);
415 if (fd >= 0) {
416 r = dup2(fd, STDIN_FILENO0);
417 if (r < 0)
418 log_warning_errno(errno, "redirecting stdin failed: %m")({ int _level = ((4)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_UDEV); (log_get_max_level_realm(_realm) >= (
(_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/udev/udev-event.c", 418, __func__
, "redirecting stdin failed: %m") : -abs(_e); })
;
419
420 if (fd_stdout < 0) {
421 r = dup2(fd, STDOUT_FILENO1);
422 if (r < 0)
423 log_warning_errno(errno, "redirecting stdout failed: %m")({ int _level = ((4)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_UDEV); (log_get_max_level_realm(_realm) >= (
(_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/udev/udev-event.c", 423, __func__
, "redirecting stdout failed: %m") : -abs(_e); })
;
424 }
425
426 if (fd_stderr < 0) {
427 r = dup2(fd, STDERR_FILENO2);
428 if (r < 0)
429 log_warning_errno(errno, "redirecting stderr failed: %m")({ int _level = ((4)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_UDEV); (log_get_max_level_realm(_realm) >= (
(_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/udev/udev-event.c", 429, __func__
, "redirecting stderr failed: %m") : -abs(_e); })
;
430 }
431 } else
432 log_warning_errno(errno, "open /dev/null failed: %m")({ int _level = ((4)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_UDEV); (log_get_max_level_realm(_realm) >= (
(_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/udev/udev-event.c", 432, __func__
, "open /dev/null failed: %m") : -abs(_e); })
;
433
434 /* connect pipes to std{out,err} */
435 if (fd_stdout >= 0) {
436 r = dup2(fd_stdout, STDOUT_FILENO1);
437 if (r < 0)
438 log_warning_errno(errno, "redirecting stdout failed: %m")({ int _level = ((4)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_UDEV); (log_get_max_level_realm(_realm) >= (
(_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/udev/udev-event.c", 438, __func__
, "redirecting stdout failed: %m") : -abs(_e); })
;
439
440 fd_stdout = safe_close(fd_stdout);
441 }
442
443 if (fd_stderr >= 0) {
444 r = dup2(fd_stderr, STDERR_FILENO2);
445 if (r < 0)
446 log_warning_errno(errno, "redirecting stdout failed: %m")({ int _level = ((4)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_UDEV); (log_get_max_level_realm(_realm) >= (
(_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/udev/udev-event.c", 446, __func__
, "redirecting stdout failed: %m") : -abs(_e); })
;
447
448 fd_stderr = safe_close(fd_stderr);
449 }
450
451 /* terminate child in case parent goes away */
452 prctl(PR_SET_PDEATHSIG1, SIGTERM15);
453
454 /* restore sigmask before exec */
455 (void) reset_signal_mask();
456
457 execve(argv[0], argv, envp);
458
459 /* exec failed */
460 return log_error_errno(errno, "failed to execute '%s' '%s': %m", argv[0], cmd)({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_UDEV); (log_get_max_level_realm(_realm) >= (
(_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/udev/udev-event.c", 460, __func__
, "failed to execute '%s' '%s': %m", argv[0], cmd) : -abs(_e)
; })
;
461}
462
463static void spawn_read(struct udev_event *event,
464 usec_t timeout_usec,
465 const char *cmd,
466 int fd_stdout, int fd_stderr,
467 char *result, size_t ressize) {
468 _cleanup_close___attribute__((cleanup(closep))) int fd_ep = -1;
469 struct epoll_event ep_outpipe = {
470 .events = EPOLLINEPOLLIN,
471 .data.ptr = &fd_stdout,
472 };
473 struct epoll_event ep_errpipe = {
474 .events = EPOLLINEPOLLIN,
475 .data.ptr = &fd_stderr,
476 };
477 size_t respos = 0;
478 int r;
479
480 /* read from child if requested */
481 if (fd_stdout < 0 && fd_stderr < 0)
482 return;
483
484 fd_ep = epoll_create1(EPOLL_CLOEXECEPOLL_CLOEXEC);
485 if (fd_ep < 0) {
486 log_error_errno(errno, "error creating epoll fd: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_UDEV); (log_get_max_level_realm(_realm) >= (
(_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/udev/udev-event.c", 486, __func__
, "error creating epoll fd: %m") : -abs(_e); })
;
487 return;
488 }
489
490 if (fd_stdout >= 0) {
491 r = epoll_ctl(fd_ep, EPOLL_CTL_ADD1, fd_stdout, &ep_outpipe);
492 if (r < 0) {
493 log_error_errno(errno, "fail to add stdout fd to epoll: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_UDEV); (log_get_max_level_realm(_realm) >= (
(_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/udev/udev-event.c", 493, __func__
, "fail to add stdout fd to epoll: %m") : -abs(_e); })
;
494 return;
495 }
496 }
497
498 if (fd_stderr >= 0) {
499 r = epoll_ctl(fd_ep, EPOLL_CTL_ADD1, fd_stderr, &ep_errpipe);
500 if (r < 0) {
501 log_error_errno(errno, "fail to add stderr fd to epoll: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_UDEV); (log_get_max_level_realm(_realm) >= (
(_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/udev/udev-event.c", 501, __func__
, "fail to add stderr fd to epoll: %m") : -abs(_e); })
;
502 return;
503 }
504 }
505
506 /* read child output */
507 while (fd_stdout >= 0 || fd_stderr >= 0) {
508 int timeout;
509 int fdcount;
510 struct epoll_event ev[4];
511 int i;
512
513 if (timeout_usec > 0) {
514 usec_t age_usec;
515
516 age_usec = now(CLOCK_MONOTONIC1) - event->birth_usec;
517 if (age_usec >= timeout_usec) {
518 log_error("timeout '%s'", cmd)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_UDEV
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/udev/udev-event.c", 518, __func__, "timeout '%s'", cmd
) : -abs(_e); })
;
519 return;
520 }
521 timeout = ((timeout_usec - age_usec) / USEC_PER_MSEC((usec_t) 1000ULL)) + MSEC_PER_SEC1000ULL;
522 } else {
523 timeout = -1;
524 }
525
526 fdcount = epoll_wait(fd_ep, ev, ELEMENTSOF(ev)__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(ev), typeof(&*(ev))), sizeof(ev)/sizeof((ev)[0]),
((void)0)))
, timeout);
527 if (fdcount < 0) {
528 if (errno(*__errno_location ()) == EINTR4)
529 continue;
530 log_error_errno(errno, "failed to poll: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_UDEV); (log_get_max_level_realm(_realm) >= (
(_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/udev/udev-event.c", 530, __func__
, "failed to poll: %m") : -abs(_e); })
;
531 return;
532 } else if (fdcount == 0) {
533 log_error("timeout '%s'", cmd)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_UDEV
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/udev/udev-event.c", 533, __func__, "timeout '%s'", cmd
) : -abs(_e); })
;
534 return;
535 }
536
537 for (i = 0; i < fdcount; i++) {
538 int *fd = (int *)ev[i].data.ptr;
539
540 if (*fd < 0)
541 continue;
542
543 if (ev[i].events & EPOLLINEPOLLIN) {
544 ssize_t count;
545 char buf[4096];
546
547 count = read(*fd, buf, sizeof(buf)-1);
548 if (count <= 0)
549 continue;
550 buf[count] = '\0';
551
552 /* store stdout result */
553 if (result != NULL((void*)0) && *fd == fd_stdout) {
554 if (respos + count < ressize) {
555 memcpy(&result[respos], buf, count);
556 respos += count;
557 } else {
558 log_error("'%s' ressize %zu too short", cmd, ressize)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_UDEV
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/udev/udev-event.c", 558, __func__, "'%s' ressize %zu too short"
, cmd, ressize) : -abs(_e); })
;
559 }
560 }
561
562 /* log debug output only if we watch stderr */
563 if (fd_stderr >= 0) {
564 char *pos;
565 char *line;
566
567 pos = buf;
568 while ((line = strsep(&pos, "\n"))) {
569 if (pos != NULL((void*)0) || line[0] != '\0')
570 log_debug("'%s'(%s) '%s'", cmd, *fd == fd_stdout ? "out" : "err" , line)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/udev/udev-event.c", 570, __func__, "'%s'(%s) '%s'",
cmd, *fd == fd_stdout ? "out" : "err" , line) : -abs(_e); })
;
571 }
572 }
573 } else if (ev[i].events & EPOLLHUPEPOLLHUP) {
574 r = epoll_ctl(fd_ep, EPOLL_CTL_DEL2, *fd, NULL((void*)0));
575 if (r < 0) {
576 log_error_errno(errno, "failed to remove fd from epoll: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_UDEV); (log_get_max_level_realm(_realm) >= (
(_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/udev/udev-event.c", 576, __func__
, "failed to remove fd from epoll: %m") : -abs(_e); })
;
577 return;
578 }
579 *fd = -1;
580 }
581 }
582 }
583
584 /* return the child's stdout string */
585 if (result != NULL((void*)0))
586 result[respos] = '\0';
587}
588
589static int on_spawn_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
590 Spawn *spawn = userdata;
591 char timeout[FORMAT_TIMESTAMP_RELATIVE_MAX256];
592
593 assert(spawn)do { if ((__builtin_expect(!!(!(spawn)),0))) log_assert_failed_realm
(LOG_REALM_UDEV, ("spawn"), "../src/udev/udev-event.c", 593, __PRETTY_FUNCTION__
); } while (0)
;
594
595 kill_and_sigcont(spawn->pid, SIGKILL9);
596
597 log_error("spawned process '%s' ["PID_FMT"] timed out after %s, killing", spawn->cmd, spawn->pid,({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_UDEV
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/udev/udev-event.c", 598, __func__, "spawned process '%s' ["
"%" "i""] timed out after %s, killing", spawn->cmd, spawn->
pid, format_timestamp_relative(timeout, sizeof(timeout), spawn
->timeout)) : -abs(_e); })
598 format_timestamp_relative(timeout, sizeof(timeout), spawn->timeout))({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_UDEV
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/udev/udev-event.c", 598, __func__, "spawned process '%s' ["
"%" "i""] timed out after %s, killing", spawn->cmd, spawn->
pid, format_timestamp_relative(timeout, sizeof(timeout), spawn
->timeout)) : -abs(_e); })
;
599
600 return 1;
601}
602
603static int on_spawn_timeout_warning(sd_event_source *s, uint64_t usec, void *userdata) {
604 Spawn *spawn = userdata;
605 char timeout[FORMAT_TIMESTAMP_RELATIVE_MAX256];
606
607 assert(spawn)do { if ((__builtin_expect(!!(!(spawn)),0))) log_assert_failed_realm
(LOG_REALM_UDEV, ("spawn"), "../src/udev/udev-event.c", 607, __PRETTY_FUNCTION__
); } while (0)
;
608
609 log_warning("spawned process '%s' ["PID_FMT"] is taking longer than %s to complete", spawn->cmd, spawn->pid,({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_UDEV
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/udev/udev-event.c", 610, __func__, "spawned process '%s' ["
"%" "i""] is taking longer than %s to complete", spawn->cmd
, spawn->pid, format_timestamp_relative(timeout, sizeof(timeout
), spawn->timeout)) : -abs(_e); })
610 format_timestamp_relative(timeout, sizeof(timeout), spawn->timeout))({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_UDEV
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/udev/udev-event.c", 610, __func__, "spawned process '%s' ["
"%" "i""] is taking longer than %s to complete", spawn->cmd
, spawn->pid, format_timestamp_relative(timeout, sizeof(timeout
), spawn->timeout)) : -abs(_e); })
;
611
612 return 1;
613}
614
615static int on_spawn_sigchld(sd_event_source *s, const siginfo_t *si, void *userdata) {
616 Spawn *spawn = userdata;
617
618 assert(spawn)do { if ((__builtin_expect(!!(!(spawn)),0))) log_assert_failed_realm
(LOG_REALM_UDEV, ("spawn"), "../src/udev/udev-event.c", 618, __PRETTY_FUNCTION__
); } while (0)
;
619
620 switch (si->si_code) {
621 case CLD_EXITEDCLD_EXITED:
622 if (si->si_status_sifields._sigchld.si_status == 0) {
623 log_debug("Process '%s' succeeded.", spawn->cmd)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/udev/udev-event.c", 623, __func__, "Process '%s' succeeded."
, spawn->cmd) : -abs(_e); })
;
624 sd_event_exit(sd_event_source_get_event(s), 0);
625
626 return 1;
627 } else if (spawn->accept_failure)
628 log_debug("Process '%s' failed with exit code %i.", spawn->cmd, si->si_status)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/udev/udev-event.c", 628, __func__, "Process '%s' failed with exit code %i."
, spawn->cmd, si->_sifields._sigchld.si_status) : -abs(
_e); })
;
629 else
630 log_warning("Process '%s' failed with exit code %i.", spawn->cmd, si->si_status)({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_UDEV
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/udev/udev-event.c", 630, __func__, "Process '%s' failed with exit code %i."
, spawn->cmd, si->_sifields._sigchld.si_status) : -abs(
_e); })
;
631
632 break;
633 case CLD_KILLEDCLD_KILLED:
634 case CLD_DUMPEDCLD_DUMPED:
635 log_warning("Process '%s' terminated by signal %s.", spawn->cmd, signal_to_string(si->si_status))({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_UDEV
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/udev/udev-event.c", 635, __func__, "Process '%s' terminated by signal %s."
, spawn->cmd, signal_to_string(si->_sifields._sigchld.si_status
)) : -abs(_e); })
;
636
637 break;
638 default:
639 log_error("Process '%s' failed due to unknown reason.", spawn->cmd)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_UDEV
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/udev/udev-event.c", 639, __func__, "Process '%s' failed due to unknown reason."
, spawn->cmd) : -abs(_e); })
;
640 }
641
642 sd_event_exit(sd_event_source_get_event(s), -EIO5);
643
644 return 1;
645}
646
647static int spawn_wait(struct udev_event *event,
648 usec_t timeout_usec,
649 usec_t timeout_warn_usec,
650 const char *cmd, pid_t pid,
651 bool_Bool accept_failure) {
652 Spawn spawn = {
653 .cmd = cmd,
654 .pid = pid,
655 .accept_failure = accept_failure,
656 };
657 _cleanup_(sd_event_unrefp)__attribute__((cleanup(sd_event_unrefp))) sd_event *e = NULL((void*)0);
658 int r, ret;
659
660 r = sd_event_new(&e);
661 if (r < 0)
662 return r;
663
664 if (timeout_usec > 0) {
665 usec_t usec, age_usec;
666
667 usec = now(CLOCK_MONOTONIC1);
668 age_usec = usec - event->birth_usec;
669 if (age_usec < timeout_usec) {
670 if (timeout_warn_usec > 0 && timeout_warn_usec < timeout_usec && age_usec < timeout_warn_usec) {
671 spawn.timeout_warn = timeout_warn_usec - age_usec;
672
673 r = sd_event_add_time(e, NULL((void*)0), CLOCK_MONOTONIC1,
674 usec + spawn.timeout_warn, USEC_PER_SEC((usec_t) 1000000ULL),
675 on_spawn_timeout_warning, &spawn);
676 if (r < 0)
677 return r;
678 }
679
680 spawn.timeout = timeout_usec - age_usec;
681
682 r = sd_event_add_time(e, NULL((void*)0), CLOCK_MONOTONIC1,
683 usec + spawn.timeout, USEC_PER_SEC((usec_t) 1000000ULL), on_spawn_timeout, &spawn);
684 if (r < 0)
685 return r;
686 }
687 }
688
689 r = sd_event_add_child(e, NULL((void*)0), pid, WEXITED4, on_spawn_sigchld, &spawn);
690 if (r < 0)
691 return r;
692
693 r = sd_event_loop(e);
694 if (r < 0)
695 return r;
696
697 r = sd_event_get_exit_code(e, &ret);
698 if (r < 0)
699 return r;
700
701 return ret;
702}
703
704int udev_build_argv(struct udev *udev, char *cmd, int *argc, char *argv[]) {
705 int i = 0;
706 char *pos;
707
708 if (strchr(cmd, ' ') == NULL((void*)0)) {
709 argv[i++] = cmd;
710 goto out;
711 }
712
713 pos = cmd;
714 while (pos != NULL((void*)0) && pos[0] != '\0') {
715 if (IN_SET(pos[0], '\'', '"')({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){'\'', '"'})/sizeof(int)]; switch(pos[0])
{ case '\'': case '"': _found = 1; break; default: break; } _found
; })
) {
716 /* do not separate quotes or double quotes */
717 char delim[2] = { pos[0], '\0' };
718
719 pos++;
720 argv[i] = strsep(&pos, delim);
721 if (pos != NULL((void*)0))
722 while (pos[0] == ' ')
723 pos++;
724 } else {
725 argv[i] = strsep(&pos, " ");
726 if (pos != NULL((void*)0))
727 while (pos[0] == ' ')
728 pos++;
729 }
730 i++;
731 }
732out:
733 argv[i] = NULL((void*)0);
734 if (argc)
735 *argc = i;
736 return 0;
737}
738
739int udev_event_spawn(struct udev_event *event,
740 usec_t timeout_usec,
741 usec_t timeout_warn_usec,
742 bool_Bool accept_failure,
743 const char *cmd,
744 char *result, size_t ressize) {
745 int outpipe[2] = {-1, -1};
746 int errpipe[2] = {-1, -1};
747 pid_t pid;
748 int err = 0;
749
750 /* pipes from child to parent */
751 if (result != NULL((void*)0) || log_get_max_level()log_get_max_level_realm(LOG_REALM_UDEV) >= LOG_INFO6) {
752 if (pipe2(outpipe, O_NONBLOCK04000) != 0) {
753 err = log_error_errno(errno, "pipe failed: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_UDEV); (log_get_max_level_realm(_realm) >= (
(_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/udev/udev-event.c", 753, __func__
, "pipe failed: %m") : -abs(_e); })
;
754 goto out;
755 }
756 }
757 if (log_get_max_level()log_get_max_level_realm(LOG_REALM_UDEV) >= LOG_INFO6) {
758 if (pipe2(errpipe, O_NONBLOCK04000) != 0) {
759 err = log_error_errno(errno, "pipe failed: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_UDEV); (log_get_max_level_realm(_realm) >= (
(_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/udev/udev-event.c", 759, __func__
, "pipe failed: %m") : -abs(_e); })
;
760 goto out;
761 }
762 }
763
764 err = safe_fork("(spawn)", FORK_RESET_SIGNALS|FORK_LOG, &pid);
765 if (err < 0)
766 goto out;
767 if (err == 0) {
768 char arg[UTIL_PATH_SIZE1024];
769 char *argv[128];
770 char program[UTIL_PATH_SIZE1024];
771
772 /* child closes parent's ends of pipes */
773 outpipe[READ_END0] = safe_close(outpipe[READ_END0]);
774 errpipe[READ_END0] = safe_close(errpipe[READ_END0]);
775
776 strscpy(arg, sizeof(arg), cmd);
777 udev_build_argv(event->udev, arg, NULL((void*)0), argv);
778
779 /* allow programs in /usr/lib/udev/ to be called without the path */
780 if (argv[0][0] != '/') {
781 strscpyl(program, sizeof(program), UDEVLIBEXECDIR"/usr/lib/udev" "/", argv[0], NULL((void*)0));
782 argv[0] = program;
783 }
784
785 log_debug("starting '%s'", cmd)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/udev/udev-event.c", 785, __func__, "starting '%s'",
cmd) : -abs(_e); })
;
786
787 spawn_exec(event, cmd, argv, udev_device_get_properties_envp(event->dev),
788 outpipe[WRITE_END1], errpipe[WRITE_END1]);
789
790 _exit(2);
791 }
792
793 /* parent closed child's ends of pipes */
794 outpipe[WRITE_END1] = safe_close(outpipe[WRITE_END1]);
795 errpipe[WRITE_END1] = safe_close(errpipe[WRITE_END1]);
796
797 spawn_read(event,
798 timeout_usec,
799 cmd,
800 outpipe[READ_END0], errpipe[READ_END0],
801 result, ressize);
802
803 err = spawn_wait(event, timeout_usec, timeout_warn_usec, cmd, pid, accept_failure);
804
805out:
806 if (outpipe[READ_END0] >= 0)
807 close(outpipe[READ_END0]);
808 if (outpipe[WRITE_END1] >= 0)
809 close(outpipe[WRITE_END1]);
810 if (errpipe[READ_END0] >= 0)
811 close(errpipe[READ_END0]);
812 if (errpipe[WRITE_END1] >= 0)
813 close(errpipe[WRITE_END1]);
814 return err;
815}
816
817static int rename_netif(struct udev_event *event) {
818 struct udev_device *dev = event->dev;
819 char name[IFNAMSIZ16];
820 const char *oldname;
821 int r;
822
823 oldname = udev_device_get_sysname(dev);
824
825 strscpy(name, IFNAMSIZ16, event->name);
826
827 r = rtnl_set_link_name(&event->rtnl, udev_device_get_ifindex(dev), name);
828 if (r < 0)
829 return log_error_errno(r, "Error changing net interface name '%s' to '%s': %m", oldname, name)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_UDEV);
(log_get_max_level_realm(_realm) >= ((_level) & 0x07)
) ? log_internal_realm(((_realm) << 10 | (_level)), _e,
"../src/udev/udev-event.c", 829, __func__, "Error changing net interface name '%s' to '%s': %m"
, oldname, name) : -abs(_e); })
;
830
831 log_debug("renamed network interface '%s' to '%s'", oldname, name)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/udev/udev-event.c", 831, __func__, "renamed network interface '%s' to '%s'"
, oldname, name) : -abs(_e); })
;
832
833 return 0;
834}
835
836void udev_event_execute_rules(struct udev_event *event,
837 usec_t timeout_usec, usec_t timeout_warn_usec,
838 struct udev_list *properties_list,
839 struct udev_rules *rules) {
840 struct udev_device *dev = event->dev;
841
842 if (udev_device_get_subsystem(dev) == NULL((void*)0))
843 return;
844
845 if (streq(udev_device_get_action(dev), "remove")(strcmp((udev_device_get_action(dev)),("remove")) == 0)) {
846 udev_device_read_db(dev);
847 udev_device_tag_index(dev, NULL((void*)0), false0);
848 udev_device_delete_db(dev);
849
850 if (major(udev_device_get_devnum(dev))gnu_dev_major (udev_device_get_devnum(dev)) != 0)
851 udev_watch_end(event->udev, dev);
852
853 udev_rules_apply_to_event(rules, event,
854 timeout_usec, timeout_warn_usec,
855 properties_list);
856
857 if (major(udev_device_get_devnum(dev))gnu_dev_major (udev_device_get_devnum(dev)) != 0)
858 udev_node_remove(dev);
859 } else {
860 event->dev_db = udev_device_clone_with_db(dev);
861 if (event->dev_db != NULL((void*)0)) {
862 /* disable watch during event processing */
863 if (major(udev_device_get_devnum(dev))gnu_dev_major (udev_device_get_devnum(dev)) != 0)
864 udev_watch_end(event->udev, event->dev_db);
865
866 if (major(udev_device_get_devnum(dev))gnu_dev_major (udev_device_get_devnum(dev)) == 0 &&
867 streq(udev_device_get_action(dev), "move")(strcmp((udev_device_get_action(dev)),("move")) == 0))
868 udev_device_copy_properties(dev, event->dev_db);
869 }
870
871 udev_rules_apply_to_event(rules, event,
872 timeout_usec, timeout_warn_usec,
873 properties_list);
874
875 /* rename a new network interface, if needed */
876 if (udev_device_get_ifindex(dev) > 0 && streq(udev_device_get_action(dev), "add")(strcmp((udev_device_get_action(dev)),("add")) == 0) &&
877 event->name != NULL((void*)0) && !streq(event->name, udev_device_get_sysname(dev))(strcmp((event->name),(udev_device_get_sysname(dev))) == 0
)
) {
878 int r;
879
880 r = rename_netif(event);
881 if (r < 0)
882 log_warning_errno(r, "could not rename interface '%d' from '%s' to '%s': %m", udev_device_get_ifindex(dev),({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_UDEV);
(log_get_max_level_realm(_realm) >= ((_level) & 0x07)
) ? log_internal_realm(((_realm) << 10 | (_level)), _e,
"../src/udev/udev-event.c", 883, __func__, "could not rename interface '%d' from '%s' to '%s': %m"
, udev_device_get_ifindex(dev), udev_device_get_sysname(dev),
event->name) : -abs(_e); })
883 udev_device_get_sysname(dev), event->name)({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_UDEV);
(log_get_max_level_realm(_realm) >= ((_level) & 0x07)
) ? log_internal_realm(((_realm) << 10 | (_level)), _e,
"../src/udev/udev-event.c", 883, __func__, "could not rename interface '%d' from '%s' to '%s': %m"
, udev_device_get_ifindex(dev), udev_device_get_sysname(dev),
event->name) : -abs(_e); })
;
884 else {
885 r = udev_device_rename(dev, event->name);
886 if (r < 0)
887 log_warning_errno(r, "renamed interface '%d' from '%s' to '%s', but could not update udev_device: %m",({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_UDEV);
(log_get_max_level_realm(_realm) >= ((_level) & 0x07)
) ? log_internal_realm(((_realm) << 10 | (_level)), _e,
"../src/udev/udev-event.c", 888, __func__, "renamed interface '%d' from '%s' to '%s', but could not update udev_device: %m"
, udev_device_get_ifindex(dev), udev_device_get_sysname(dev),
event->name) : -abs(_e); })
888 udev_device_get_ifindex(dev), udev_device_get_sysname(dev), event->name)({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_UDEV);
(log_get_max_level_realm(_realm) >= ((_level) & 0x07)
) ? log_internal_realm(((_realm) << 10 | (_level)), _e,
"../src/udev/udev-event.c", 888, __func__, "renamed interface '%d' from '%s' to '%s', but could not update udev_device: %m"
, udev_device_get_ifindex(dev), udev_device_get_sysname(dev),
event->name) : -abs(_e); })
;
889 else
890 log_debug("changed devpath to '%s'", udev_device_get_devpath(dev))({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/udev/udev-event.c", 890, __func__, "changed devpath to '%s'"
, udev_device_get_devpath(dev)) : -abs(_e); })
;
891 }
892 }
893
894 if (major(udev_device_get_devnum(dev))gnu_dev_major (udev_device_get_devnum(dev)) > 0) {
895 bool_Bool apply;
896
897 /* remove/update possible left-over symlinks from old database entry */
898 if (event->dev_db != NULL((void*)0))
899 udev_node_update_old_links(dev, event->dev_db);
900
901 if (!event->owner_set)
902 event->uid = udev_device_get_devnode_uid(dev);
903
904 if (!event->group_set)
905 event->gid = udev_device_get_devnode_gid(dev);
906
907 if (!event->mode_set) {
908 if (udev_device_get_devnode_mode(dev) > 0) {
909 /* kernel supplied value */
910 event->mode = udev_device_get_devnode_mode(dev);
911 } else if (event->gid > 0) {
912 /* default 0660 if a group is assigned */
913 event->mode = 0660;
914 } else {
915 /* default 0600 */
916 event->mode = 0600;
917 }
918 }
919
920 apply = streq(udev_device_get_action(dev), "add")(strcmp((udev_device_get_action(dev)),("add")) == 0) || event->owner_set || event->group_set || event->mode_set;
921 udev_node_add(dev, apply, event->mode, event->uid, event->gid, &event->seclabel_list);
922 }
923
924 /* preserve old, or get new initialization timestamp */
925 udev_device_ensure_usec_initialized(event->dev, event->dev_db);
926
927 /* (re)write database file */
928 udev_device_tag_index(dev, event->dev_db, true1);
929 udev_device_update_db(dev);
930 udev_device_set_is_initialized(dev);
931
932 event->dev_db = udev_device_unref(event->dev_db);
933 }
934}
935
936void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec) {
937 struct udev_list_entry *list_entry;
938
939 udev_list_entry_foreach(list_entry, udev_list_get_entry(&event->run_list))for (list_entry = udev_list_get_entry(&event->run_list
); list_entry != ((void*)0); list_entry = udev_list_entry_get_next
(list_entry))
{
940 char command[UTIL_PATH_SIZE1024];
941 const char *cmd = udev_list_entry_get_name(list_entry);
942 enum udev_builtin_cmd builtin_cmd = udev_list_entry_get_num(list_entry);
943
944 udev_event_apply_format(event, cmd, command, sizeof(command), false0);
945
946 if (builtin_cmd < UDEV_BUILTIN_MAX)
947 udev_builtin_run(event->dev, builtin_cmd, command, false0);
948 else {
949 if (event->exec_delay > 0) {
950 log_debug("delay execution of '%s'", command)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/udev/udev-event.c", 950, __func__, "delay execution of '%s'"
, command) : -abs(_e); })
;
951 sleep(event->exec_delay);
952 }
953
954 udev_event_spawn(event, timeout_usec, timeout_warn_usec, false0, command, NULL((void*)0), 0);
955 }
956 }
957}