sd-device: device_id - set correctly for 'drivers'
The 'drivers' pseudo-subsystem needs special treatment. These pseudo-devices are found under /sys/bus/drivers/, so needs the real subsystem encoded in the device_id in order to be resolved. The reader side already assumed this to be the case.
This commit is contained in:
@@ -76,6 +76,8 @@ struct sd_device {
|
||||
|
||||
char *subsystem;
|
||||
bool subsystem_set; /* don't reread subsystem */
|
||||
char *driver_subsystem; /* only set for the 'drivers' subsystem */
|
||||
bool driver_subsystem_set; /* don't reread subsystem */
|
||||
char *driver;
|
||||
bool driver_set; /* don't reread driver */
|
||||
|
||||
|
||||
@@ -75,6 +75,7 @@ _public_ sd_device *sd_device_unref(sd_device *device) {
|
||||
free(device->devtype);
|
||||
free(device->devname);
|
||||
free(device->subsystem);
|
||||
free(device->driver_subsystem);
|
||||
free(device->driver);
|
||||
free(device->id_filename);
|
||||
free(device->properties_strv);
|
||||
@@ -766,21 +767,45 @@ int device_set_subsystem(sd_device *device, const char *_subsystem) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int device_set_drivers_subsystem(sd_device *device, const char *_subsystem) {
|
||||
_cleanup_free_ char *subsystem = NULL;
|
||||
int r;
|
||||
|
||||
assert(device);
|
||||
assert(_subsystem);
|
||||
assert(*_subsystem);
|
||||
|
||||
subsystem = strdup(_subsystem);
|
||||
if (!subsystem)
|
||||
return -ENOMEM;
|
||||
|
||||
r = device_set_subsystem(device, "drivers");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
free(device->driver_subsystem);
|
||||
device->driver_subsystem = subsystem;
|
||||
subsystem = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
_public_ int sd_device_get_subsystem(sd_device *device, const char **ret) {
|
||||
const char *syspath, *drivers = NULL;
|
||||
int r;
|
||||
|
||||
assert_return(ret, -EINVAL);
|
||||
assert_return(device, -EINVAL);
|
||||
|
||||
r = sd_device_get_syspath(device, &syspath);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!device->subsystem_set) {
|
||||
_cleanup_free_ char *subsystem = NULL;
|
||||
const char *syspath;
|
||||
char *path;
|
||||
int r;
|
||||
|
||||
/* read 'subsystem' link */
|
||||
r = sd_device_get_syspath(device, &syspath);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
path = strjoina(syspath, "/subsystem");
|
||||
r = readlink_value(path, &subsystem);
|
||||
if (r >= 0)
|
||||
@@ -788,16 +813,39 @@ _public_ int sd_device_get_subsystem(sd_device *device, const char **ret) {
|
||||
/* use implicit names */
|
||||
else if (path_startswith(device->devpath, "/module/"))
|
||||
r = device_set_subsystem(device, "module");
|
||||
else if (strstr(device->devpath, "/drivers/"))
|
||||
r = device_set_subsystem(device, "drivers");
|
||||
else if (path_startswith(device->devpath, "/subsystem/") ||
|
||||
path_startswith(device->devpath, "/class/") ||
|
||||
path_startswith(device->devpath, "/bus/"))
|
||||
else if (!(drivers = strstr(syspath, "/drivers/")) &&
|
||||
(path_startswith(device->devpath, "/subsystem/") ||
|
||||
path_startswith(device->devpath, "/class/") ||
|
||||
path_startswith(device->devpath, "/bus/")))
|
||||
r = device_set_subsystem(device, "subsystem");
|
||||
if (r < 0 && r != -ENOENT)
|
||||
return log_debug_errno(r, "sd-device: could not set subsystem for %s: %m", device->devpath);
|
||||
|
||||
device->subsystem_set = true;
|
||||
} else if (!device->driver_subsystem_set)
|
||||
drivers = strstr(syspath, "/drivers/");
|
||||
|
||||
if (!device->driver_subsystem_set) {
|
||||
if (drivers) {
|
||||
_cleanup_free_ char *subpath = NULL;
|
||||
|
||||
subpath = strndup(syspath, drivers - syspath);
|
||||
if (!subpath)
|
||||
r = -ENOMEM;
|
||||
else {
|
||||
const char *subsys;
|
||||
|
||||
subsys = strrchr(subpath, '/');
|
||||
if (!subsys)
|
||||
r = -EINVAL;
|
||||
else
|
||||
r = device_set_drivers_subsystem(device, subsys + 1);
|
||||
}
|
||||
if (r < 0 && r != -ENOENT)
|
||||
return log_debug_errno(r, "sd-device: could not set subsystem for driver %s: %m", device->devpath);
|
||||
}
|
||||
|
||||
device->driver_subsystem_set = true;
|
||||
}
|
||||
|
||||
if (!device->subsystem)
|
||||
@@ -1234,9 +1282,17 @@ int device_get_id_filename(sd_device *device, const char **ret) {
|
||||
if (!subsystem)
|
||||
return -EINVAL;
|
||||
|
||||
r = asprintf(&id, "+%s:%s", subsystem, sysname);
|
||||
if (r < 0)
|
||||
return -ENOMEM;
|
||||
if (streq(subsystem, "drivers")) {
|
||||
/* the 'drivers' pseudo-subsystem is special, and needs the real subsystem
|
||||
* encoded as well */
|
||||
r = asprintf(&id, "+drivers:%s:%s", device->driver_subsystem, sysname);
|
||||
if (r < 0)
|
||||
return -ENOMEM;
|
||||
} else {
|
||||
r = asprintf(&id, "+%s:%s", subsystem, sysname);
|
||||
if (r < 0)
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
device->id_filename = id;
|
||||
|
||||
Reference in New Issue
Block a user