int device_shallow_clone(sd_device *old_device, sd_device **new_device) {
_cleanup_(sd_device_unrefp) sd_device *ret = NULL;
- const char *subsystem;
+ const char *val;
int r;
assert(old_device);
if (r < 0)
return r;
- if (sd_device_get_subsystem(old_device, &subsystem) >= 0) {
- r = device_set_subsystem(ret, subsystem);
+ if (sd_device_get_subsystem(old_device, &val) >= 0) {
+ r = device_set_subsystem(ret, val);
if (r < 0)
return r;
+
+ if (streq(val, "drivers")) {
+ ret->driver_subsystem = strdup(old_device->driver_subsystem);
+ if (!ret->driver_subsystem)
+ return -ENOMEM;
+ }
} else
ret->subsystem_set = true;
- ret->devnum = old_device->devnum;
+ /* The device may be already removed. Let's copy minimal set of information to make
+ * device_get_device_id() work without uevent file. */
- *new_device = TAKE_PTR(ret);
+ if (sd_device_get_property_value(old_device, "IFINDEX", &val) >= 0) {
+ r = device_set_ifindex(ret, val);
+ if (r < 0)
+ return r;
+ }
+
+ if (sd_device_get_property_value(old_device, "MAJOR", &val) >= 0) {
+ const char *minor = NULL;
+ (void) sd_device_get_property_value(old_device, "MINOR", &minor);
+ r = device_set_devnum(ret, val, minor);
+ if (r < 0)
+ return r;
+ }
+
+ /* And then read uevent file, but ignore errors, as some devices seem to return a spurious
+ * error on read, e.g. -ENODEV, and even if ifindex or devnum is set in the above,
+ * sd_device_get_ifindex() or sd_device_get_devnum() fails. See. #19788. */
+ (void) device_read_uevent_file(ret);
+
+ *new_device = TAKE_PTR(ret);
return 0;
}