1 /* SPDX-License-Identifier: LGPL-2.1+ */
5 #include "alloc-util.h"
6 #include "device-util.h"
9 #include "parse-util.h"
10 #include "signal-util.h"
11 #include "string-table.h"
12 #include "string-util.h"
13 #include "udev-util.h"
15 static const char* const resolve_name_timing_table
[_RESOLVE_NAME_TIMING_MAX
] = {
16 [RESOLVE_NAME_NEVER
] = "never",
17 [RESOLVE_NAME_LATE
] = "late",
18 [RESOLVE_NAME_EARLY
] = "early",
21 DEFINE_STRING_TABLE_LOOKUP(resolve_name_timing
, ResolveNameTiming
);
23 int udev_parse_config_full(
24 unsigned *ret_children_max
,
25 usec_t
*ret_exec_delay_usec
,
26 usec_t
*ret_event_timeout_usec
,
27 ResolveNameTiming
*ret_resolve_name_timing
,
28 int *ret_timeout_signal
) {
30 _cleanup_free_
char *log_val
= NULL
, *children_max
= NULL
, *exec_delay
= NULL
, *event_timeout
= NULL
, *resolve_names
= NULL
, *timeout_signal
= NULL
;
33 r
= parse_env_file(NULL
, "/etc/udev/udev.conf",
35 "children_max", &children_max
,
36 "exec_delay", &exec_delay
,
37 "event_timeout", &event_timeout
,
38 "resolve_names", &resolve_names
,
39 "timeout_signal", &timeout_signal
);
52 ((log_val
[0] == '"' && log_val
[n
-1] == '"') ||
53 (log_val
[0] == '\'' && log_val
[n
-1] == '\''))) {
54 log_val
[n
- 1] = '\0';
59 /* we set the udev log level here explicitly, this is supposed
60 * to regulate the code in libudev/ and udev/. */
61 r
= log_set_max_level_from_string_realm(LOG_REALM_UDEV
, log
);
63 log_syntax(NULL
, LOG_WARNING
, "/etc/udev/udev.conf", 0, r
,
64 "failed to set udev log level '%s', ignoring: %m", log
);
67 if (ret_children_max
&& children_max
) {
68 r
= safe_atou(children_max
, ret_children_max
);
70 log_syntax(NULL
, LOG_WARNING
, "/etc/udev/udev.conf", 0, r
,
71 "failed to parse children_max=%s, ignoring: %m", children_max
);
74 if (ret_exec_delay_usec
&& exec_delay
) {
75 r
= parse_sec(exec_delay
, ret_exec_delay_usec
);
77 log_syntax(NULL
, LOG_WARNING
, "/etc/udev/udev.conf", 0, r
,
78 "failed to parse exec_delay=%s, ignoring: %m", exec_delay
);
81 if (ret_event_timeout_usec
&& event_timeout
) {
82 r
= parse_sec(event_timeout
, ret_event_timeout_usec
);
84 log_syntax(NULL
, LOG_WARNING
, "/etc/udev/udev.conf", 0, r
,
85 "failed to parse event_timeout=%s, ignoring: %m", event_timeout
);
88 if (ret_resolve_name_timing
&& resolve_names
) {
91 t
= resolve_name_timing_from_string(resolve_names
);
93 log_syntax(NULL
, LOG_WARNING
, "/etc/udev/udev.conf", 0, r
,
94 "failed to parse resolve_names=%s, ignoring.", resolve_names
);
96 *ret_resolve_name_timing
= t
;
99 if (ret_timeout_signal
&& timeout_signal
) {
100 r
= signal_from_string(timeout_signal
);
102 log_syntax(NULL
, LOG_WARNING
, "/etc/udev/udev.conf", 0, r
,
103 "failed to parse timeout_signal=%s, ignoring: %m", timeout_signal
);
105 *ret_timeout_signal
= r
;
111 struct DeviceMonitorData
{
116 static int device_monitor_handler(sd_device_monitor
*monitor
, sd_device
*device
, void *userdata
) {
117 struct DeviceMonitorData
*data
= userdata
;
122 assert(data
->sysname
);
123 assert(!data
->device
);
125 if (sd_device_get_sysname(device
, &sysname
) >= 0 && streq(sysname
, data
->sysname
)) {
126 data
->device
= sd_device_ref(device
);
127 return sd_event_exit(sd_device_monitor_get_event(monitor
), 0);
133 static int device_timeout_handler(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
134 return sd_event_exit(sd_event_source_get_event(s
), -ETIMEDOUT
);
137 int device_wait_for_initialization(sd_device
*device
, const char *subsystem
, usec_t timeout
, sd_device
**ret
) {
138 _cleanup_(sd_device_monitor_unrefp
) sd_device_monitor
*monitor
= NULL
;
139 _cleanup_(sd_event_source_unrefp
) sd_event_source
*timeout_source
= NULL
;
140 _cleanup_(sd_event_unrefp
) sd_event
*event
= NULL
;
141 struct DeviceMonitorData data
= {};
146 if (sd_device_get_is_initialized(device
) > 0) {
148 *ret
= sd_device_ref(device
);
152 assert_se(sd_device_get_sysname(device
, &data
.sysname
) >= 0);
154 /* Wait until the device is initialized, so that we can get access to the ID_PATH property */
156 r
= sd_event_new(&event
);
158 return log_error_errno(r
, "Failed to get default event: %m");
160 r
= sd_device_monitor_new(&monitor
);
162 return log_error_errno(r
, "Failed to acquire monitor: %m");
165 r
= sd_device_get_subsystem(device
, &subsystem
);
166 if (r
< 0 && r
!= -ENOENT
)
167 return log_device_error_errno(device
, r
, "Failed to get subsystem: %m");
171 r
= sd_device_monitor_filter_add_match_subsystem_devtype(monitor
, subsystem
, NULL
);
173 return log_error_errno(r
, "Failed to add %s subsystem match to monitor: %m", subsystem
);
176 r
= sd_device_monitor_attach_event(monitor
, event
);
178 return log_error_errno(r
, "Failed to attach event to device monitor: %m");
180 r
= sd_device_monitor_start(monitor
, device_monitor_handler
, &data
);
182 return log_error_errno(r
, "Failed to start device monitor: %m");
184 if (timeout
!= USEC_INFINITY
) {
185 r
= sd_event_add_time_relative(
186 event
, &timeout_source
,
187 CLOCK_MONOTONIC
, timeout
, 0,
188 device_timeout_handler
, NULL
);
190 return log_error_errno(r
, "Failed to add timeout event source: %m");
193 /* Check again, maybe things changed. Udev will re-read the db if the device wasn't initialized
195 if (sd_device_get_is_initialized(device
) > 0) {
197 *ret
= sd_device_ref(device
);
201 r
= sd_event_loop(event
);
203 return log_error_errno(r
, "Failed to wait for device to be initialized: %m");
206 *ret
= TAKE_PTR(data
.device
);
210 int device_is_renaming(sd_device
*dev
) {
215 r
= sd_device_get_property_value(dev
, "ID_RENAMING", NULL
);
216 if (r
< 0 && r
!= -ENOENT
)
222 bool device_for_action(sd_device
*dev
, DeviceAction action
) {
227 if (device_get_action(dev
, &a
) < 0)