diff --git a/src/rfkill/rfkill.c b/src/rfkill/rfkill.c index 1cc887df12..ac21dc064c 100644 --- a/src/rfkill/rfkill.c +++ b/src/rfkill/rfkill.c @@ -18,6 +18,7 @@ #include "proc-cmdline.h" #include "string-table.h" #include "string-util.h" +#include "udev-util.h" #include "util.h" #include "list.h" @@ -88,89 +89,6 @@ static int find_device( return 0; } -struct DeviceMonitorData { - const char *sysname; - sd_device *device; -}; - -static int device_monitor_handler(sd_device_monitor *monitor, sd_device *device, void *userdata) { - struct DeviceMonitorData *data = userdata; - const char *sysname; - - assert(device); - assert(data); - assert(data->sysname); - - if (sd_device_get_sysname(device, &sysname) >= 0 && streq(sysname, data->sysname)) { - data->device = sd_device_ref(device); - return sd_event_exit(sd_device_monitor_get_event(monitor), 0); - } - - return 0; -} - -static int wait_for_initialized( - sd_device *device, - sd_device **ret) { - - _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor = NULL; - _cleanup_(sd_event_unrefp) sd_event *event = NULL; - _cleanup_(sd_device_unrefp) sd_device *d = NULL; - struct DeviceMonitorData data = {}; - int r; - - assert(device); - assert(ret); - - if (sd_device_get_is_initialized(device) > 0) { - *ret = sd_device_ref(device); - return 0; - } - - assert_se(sd_device_get_sysname(device, &data.sysname) >= 0); - - /* Wait until the device is initialized, so that we can get - * access to the ID_PATH property */ - - r = sd_event_default(&event); - if (r < 0) - return log_error_errno(r, "Failed to get default event: %m"); - - r = sd_device_monitor_new(&monitor); - if (r < 0) - return log_error_errno(r, "Failed to acquire monitor: %m"); - - r = sd_device_monitor_filter_add_match_subsystem_devtype(monitor, "rfkill", NULL); - if (r < 0) - return log_error_errno(r, "Failed to add rfkill device match to monitor: %m"); - - r = sd_device_monitor_attach_event(monitor, event); - if (r < 0) - return log_error_errno(r, "Failed to attach event to device monitor: %m"); - - r = sd_device_monitor_start(monitor, device_monitor_handler, &data); - if (r < 0) - return log_error_errno(r, "Failed to start device monitor: %m"); - - /* Check again, maybe things changed */ - r = sd_device_new_from_subsystem_sysname(&d, "rfkill", data.sysname); - if (r < 0) - return log_full_errno(IN_SET(r, -ENOENT, -ENXIO, -ENODEV) ? LOG_DEBUG : LOG_ERR, r, - "Failed to open device '%s': %m", data.sysname); - - if (sd_device_get_is_initialized(d) > 0) { - *ret = TAKE_PTR(d); - return 0; - } - - r = sd_event_loop(event); - if (r < 0) - return log_error_errno(r, "Event loop failed: %m"); - - *ret = TAKE_PTR(data.device); - return 0; -} - static int determine_state_file( const struct rfkill_event *event, char **ret) { @@ -187,7 +105,7 @@ static int determine_state_file( if (r < 0) return r; - r = wait_for_initialized(d, &device); + r = device_wait_for_initialization(d, "rfkill", &device); if (r < 0) return r; diff --git a/src/shared/udev-util.c b/src/shared/udev-util.c index fdeaf8f613..4200032b3b 100644 --- a/src/shared/udev-util.c +++ b/src/shared/udev-util.c @@ -91,3 +91,81 @@ int udev_parse_config_full( return 0; } + +struct DeviceMonitorData { + const char *sysname; + sd_device *device; +}; + +static int device_monitor_handler(sd_device_monitor *monitor, sd_device *device, void *userdata) { + struct DeviceMonitorData *data = userdata; + const char *sysname; + + assert(device); + assert(data); + assert(data->sysname); + assert(!data->device); + + if (sd_device_get_sysname(device, &sysname) >= 0 && streq(sysname, data->sysname)) { + data->device = sd_device_ref(device); + return sd_event_exit(sd_device_monitor_get_event(monitor), 0); + } + + return 0; +} + +int device_wait_for_initialization(sd_device *device, const char *subsystem, sd_device **ret) { + _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor = NULL; + _cleanup_(sd_event_unrefp) sd_event *event = NULL; + struct DeviceMonitorData data = {}; + int r; + + assert(device); + assert(subsystem); + + if (sd_device_get_is_initialized(device) > 0) { + if (ret) + *ret = sd_device_ref(device); + return 0; + } + + assert_se(sd_device_get_sysname(device, &data.sysname) >= 0); + + /* Wait until the device is initialized, so that we can get access to the ID_PATH property */ + + r = sd_event_default(&event); + if (r < 0) + return log_error_errno(r, "Failed to get default event: %m"); + + r = sd_device_monitor_new(&monitor); + if (r < 0) + return log_error_errno(r, "Failed to acquire monitor: %m"); + + r = sd_device_monitor_filter_add_match_subsystem_devtype(monitor, subsystem, NULL); + if (r < 0) + return log_error_errno(r, "Failed to add %s subsystem match to monitor: %m", subsystem); + + r = sd_device_monitor_attach_event(monitor, event); + if (r < 0) + return log_error_errno(r, "Failed to attach event to device monitor: %m"); + + r = sd_device_monitor_start(monitor, device_monitor_handler, &data); + if (r < 0) + return log_error_errno(r, "Failed to start device monitor: %m"); + + /* Check again, maybe things changed. Udev will re-read the db if the device wasn't initialized + * yet. */ + if (sd_device_get_is_initialized(device) > 0) { + if (ret) + *ret = sd_device_ref(device); + return 0; + } + + r = sd_event_loop(event); + if (r < 0) + return log_error_errno(r, "Event loop failed: %m"); + + if (ret) + *ret = TAKE_PTR(data.device); + return 0; +} diff --git a/src/shared/udev-util.h b/src/shared/udev-util.h index be08fe1ff8..932c4a9cd5 100644 --- a/src/shared/udev-util.h +++ b/src/shared/udev-util.h @@ -1,6 +1,8 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once +#include "sd-device.h" + #include "time-util.h" typedef enum ResolveNameTiming { @@ -23,3 +25,5 @@ int udev_parse_config_full( static inline int udev_parse_config(void) { return udev_parse_config_full(NULL, NULL, NULL, NULL); } + +int device_wait_for_initialization(sd_device *device, const char *subsystem, sd_device **ret);