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_new(&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; }
/** * udev_device_get_is_initialized: * @udev_device: udev device * * Check if udev has already handled the device and has set up * device node permissions and context, or has renamed a network * device. * * This is only implemented for devices with a device node * or network interfaces. All other devices return 1 here. * * Returns: 1 if the device is set up. 0 otherwise. **/ _public_ int udev_device_get_is_initialized(struct udev_device *udev_device) { int r, initialized; assert_return(udev_device, -EINVAL); r = sd_device_get_is_initialized(udev_device->device, &initialized); if (r < 0) { errno = -r; return 0; } return initialized; }