X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=udev_sysfs.c;h=e8909f94f1f6166249fbcad8f571d7c0baa2b790;hp=7431dd6111692ec0afcd73ff2af56626a6b43747;hb=6e509e539b15ae882afd8ce3fafe1fbd33008509;hpb=66ec64e9adcba6e619a48729f50c992875ed6c88 diff --git a/udev_sysfs.c b/udev_sysfs.c index 7431dd611..e8909f94f 100644 --- a/udev_sysfs.c +++ b/udev_sysfs.c @@ -92,7 +92,6 @@ void sysfs_device_set_values(struct sysfs_device *dev, const char *devpath, pos = strrchr(dev->devpath, '/'); if (pos == NULL) return; - strlcpy(dev->kernel, &pos[1], sizeof(dev->kernel)); dbg("kernel='%s'", dev->kernel); @@ -156,9 +155,21 @@ struct sysfs_device *sysfs_device_get(const char *devpath) int len; char *pos; + /* we handle only these devpathes */ + if (devpath != NULL && + strncmp(devpath, "/devices/", 9) != 0 && + strncmp(devpath, "/subsystem/", 11) != 0 && + strncmp(devpath, "/module/", 8) != 0 && + strncmp(devpath, "/bus/", 5) != 0 && + strncmp(devpath, "/class/", 7) != 0 && + strncmp(devpath, "/block/", 7) != 0) + return NULL; + dbg("open '%s'", devpath); strlcpy(devpath_real, devpath, sizeof(devpath_real)); remove_trailing_chars(devpath_real, '/'); + if (devpath[0] == '\0' ) + return NULL; /* look for device already in cache (we never put an untranslated path in the cache) */ list_for_each_entry(dev_loop, &dev_list, node) { @@ -216,7 +227,7 @@ struct sysfs_device *sysfs_device_get(const char *devpath) if (pos != NULL) pos[0] = '\0'; else - dev->subsystem[0] = '\0'; + strlcpy(dev->subsystem, "subsystem", sizeof(dev->subsystem)); } else if (strncmp(dev->devpath, "/block/", 7) == 0) { strlcpy(dev->subsystem, "block", sizeof(dev->subsystem)); } else if (strncmp(dev->devpath, "/devices/", 9) == 0) { @@ -236,6 +247,14 @@ struct sysfs_device *sysfs_device_get(const char *devpath) strlcpy(dev->subsystem, "drivers", sizeof(dev->subsystem)); } else if (strncmp(dev->devpath, "/module/", 8) == 0) { strlcpy(dev->subsystem, "module", sizeof(dev->subsystem)); + } else if (strncmp(dev->devpath, "/subsystem/", 11) == 0) { + pos = strrchr(dev->devpath, '/'); + if (pos == &dev->devpath[10]) + strlcpy(dev->subsystem, "subsystem", sizeof(dev->subsystem)); + } else if (strncmp(dev->devpath, "/bus/", 5) == 0) { + pos = strrchr(dev->devpath, '/'); + if (pos == &dev->devpath[4]) + strlcpy(dev->subsystem, "subsystem", sizeof(dev->subsystem)); } /* get driver name */ @@ -268,13 +287,6 @@ struct sysfs_device *sysfs_device_get_parent(struct sysfs_device *dev) if (dev->parent != NULL) return dev->parent; - /* requesting a parent is only valid for devices */ - if ((strncmp(dev->devpath, "/devices/", 9) != 0) && - (strncmp(dev->devpath, "/subsystem/", 11) != 0) && - (strncmp(dev->devpath, "/class/", 7) != 0) && - (strncmp(dev->devpath, "/block/", 7) != 0)) - return NULL; - strlcpy(parent_devpath, dev->devpath, sizeof(parent_devpath)); dbg("'%s'", parent_devpath); @@ -284,20 +296,6 @@ struct sysfs_device *sysfs_device_get_parent(struct sysfs_device *dev) return NULL; pos[0] = '\0'; - /* are we at the top level of /devices */ - if (strcmp(parent_devpath, "/devices") == 0) { - dbg("/devices top level"); - return NULL; - } - - /* at the subsystems top level we want to follow the old-style "device" link */ - if (strncmp(parent_devpath, "/subsystem", 10) == 0) { - pos = strrchr(parent_devpath, '/'); - if (pos == &parent_devpath[10] || pos == parent_devpath || strcmp(pos, "/devices") == 0) { - dbg("/subsystem top level, look for device link"); - goto device_link; - } - } if (strncmp(parent_devpath, "/class", 6) == 0) { pos = strrchr(parent_devpath, '/'); if (pos == &parent_devpath[6] || pos == parent_devpath) { @@ -310,6 +308,11 @@ struct sysfs_device *sysfs_device_get_parent(struct sysfs_device *dev) goto device_link; } + /* are we at the top level? */ + pos = strrchr(parent_devpath, '/'); + if (pos == NULL || pos == parent_devpath) + return NULL; + /* get parent and remember it */ dev->parent = sysfs_device_get(parent_devpath); return dev->parent; @@ -352,6 +355,8 @@ char *sysfs_attr_get_value(const char *devpath, const char *attr_name) dbg("open '%s'/'%s'", devpath, attr_name); sysfs_len = strlcpy(path_full, sysfs_path, sizeof(path_full)); + if(sysfs_len >= sizeof(path_full)) + sysfs_len = sizeof(path_full) - 1; path = &path_full[sysfs_len]; strlcat(path_full, devpath, sizeof(path_full)); strlcat(path_full, "/", sizeof(path_full)); @@ -410,7 +415,7 @@ char *sysfs_attr_get_value(const char *devpath, const char *attr_name) /* read attribute value */ fd = open(path_full, O_RDONLY); if (fd < 0) { - dbg("attribute '%s' does not exist", path_full); + dbg("attribute '%s' can not be opened", path_full); goto out; } size = read(fd, value, sizeof(value)); @@ -430,3 +435,94 @@ 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, "/bus/", sizeof(path_full) - sysfs_len); + strlcat(path, id, sizeof(path_full) - sysfs_len); + if (stat(path_full, &statbuf) == 0) + goto found; + goto out; + + strlcpy(path, "/class/", sizeof(path_full) - sysfs_len); + strlcat(path, id, sizeof(path_full) - sysfs_len); + if (stat(path_full, &statbuf) == 0) + goto found; + } + + 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, "/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; + + 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; +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; +}