diff options
Diffstat (limited to 'udev_sysfs.c')
-rw-r--r-- | udev_sysfs.c | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/udev_sysfs.c b/udev_sysfs.c index 1846a42f6a..8525620a09 100644 --- a/udev_sysfs.c +++ b/udev_sysfs.c @@ -429,3 +429,95 @@ char *sysfs_attr_get_value(const char *devpath, const char *attr_name) out: return attr->value; } + +int sysfs_lookup_devpath_by_subsys_id(char *devpath_full, size_t len, const char *subsystem, const char *id) +{ + size_t sysfs_len; + char path_full[PATH_SIZE]; + char *path; + struct stat statbuf; + + sysfs_len = strlcpy(path_full, sysfs_path, sizeof(path_full)); + path = &path_full[sysfs_len]; + + if (strcmp(subsystem, "subsystem") == 0) { + strlcpy(path, "/subsystem/", sizeof(path_full) - sysfs_len); + strlcat(path, id, sizeof(path_full) - sysfs_len); + if (stat(path_full, &statbuf) == 0) + goto found; + + strlcpy(path, "/class/", sizeof(path_full) - sysfs_len); + strlcat(path, id, sizeof(path_full) - sysfs_len); + if (stat(path_full, &statbuf) == 0) + goto found; + + strlcpy(path, "/bus/", sizeof(path_full) - sysfs_len); + strlcat(path, id, sizeof(path_full) - sysfs_len); + if (stat(path_full, &statbuf) == 0) + goto found; + goto out; + } + + if (strcmp(subsystem, "module") == 0) { + strlcpy(path, "/module/", sizeof(path_full) - sysfs_len); + strlcat(path, id, sizeof(path_full) - sysfs_len); + if (stat(path_full, &statbuf) == 0) + goto found; + goto out; + } + + if (strcmp(subsystem, "drivers") == 0) { + char subsys[NAME_SIZE]; + char *driver; + + strlcpy(subsys, id, sizeof(subsys)); + driver = strchr(subsys, ':'); + if (driver != NULL) { + driver[0] = '\0'; + driver = &driver[1]; + strlcpy(path, "/subsystem/", sizeof(path_full) - sysfs_len); + strlcat(path, subsys, sizeof(path_full) - sysfs_len); + strlcat(path, "/drivers/", sizeof(path_full) - sysfs_len); + strlcat(path, driver, sizeof(path_full) - sysfs_len); + if (stat(path_full, &statbuf) == 0) + goto found; + + strlcpy(path, "/bus/", sizeof(path_full) - sysfs_len); + strlcat(path, subsys, sizeof(path_full) - sysfs_len); + strlcat(path, "/drivers/", sizeof(path_full) - sysfs_len); + strlcat(path, driver, sizeof(path_full) - sysfs_len); + if (stat(path_full, &statbuf) == 0) + goto found; + } + goto out; + } + + strlcpy(path, "/subsystem/", sizeof(path_full) - sysfs_len); + strlcat(path, subsystem, sizeof(path_full) - sysfs_len); + strlcat(path, "/devices/", sizeof(path_full) - sysfs_len); + strlcat(path, id, sizeof(path_full) - sysfs_len); + if (stat(path_full, &statbuf) == 0) + goto found; + + strlcpy(path, "/class/", sizeof(path_full) - sysfs_len); + strlcat(path, subsystem, sizeof(path_full) - sysfs_len); + strlcat(path, "/", sizeof(path_full) - sysfs_len); + strlcat(path, id, sizeof(path_full) - sysfs_len); + if (stat(path_full, &statbuf) == 0) + goto found; + + strlcpy(path, "/bus/", sizeof(path_full) - sysfs_len); + strlcat(path, subsystem, sizeof(path_full) - sysfs_len); + strlcat(path, "/devices/", sizeof(path_full) - sysfs_len); + strlcat(path, id, sizeof(path_full) - sysfs_len); + if (stat(path_full, &statbuf) == 0) + goto found; +out: + return 0; + +found: + if (S_ISLNK(statbuf.st_mode)) + sysfs_resolve_link(path, sizeof(path_full) - sysfs_len); + strlcpy(devpath_full, path, len); + return 1; +} |