X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=udev%2Flib%2Flibudev-device.c;h=0cb59212815459924f7319187ff7e5b0d81e9f21;hb=61ee8cc92d5298da4fd4f46016991369a933ef7f;hp=eda3f5d97e26d8e3176849cc2432ca9f8b0cc2f0;hpb=77b852f3334311575b9c19ffb29d4a77a21b4bb2;p=elogind.git diff --git a/udev/lib/libudev-device.c b/udev/lib/libudev-device.c index eda3f5d97..0cb592128 100644 --- a/udev/lib/libudev-device.c +++ b/udev/lib/libudev-device.c @@ -40,6 +40,7 @@ struct udev_device { const char *sysnum; char *devnode; char *subsystem; + char *devtype; char *driver; char *action; char *devpath_old; @@ -59,6 +60,7 @@ struct udev_device { dev_t devnum; unsigned int parent_set:1; unsigned int subsystem_set:1; + unsigned int devtype_set:1; unsigned int devlinks_uptodate:1; unsigned int envp_uptodate:1; unsigned int driver_set:1; @@ -204,7 +206,9 @@ int udev_device_read_uevent_file(struct udev_device *udev_device) continue; pos[0] = '\0'; - if (strncmp(line, "MAJOR=", 6) == 0) + if (strncmp(line, "DEVTYPE=", 8) == 0) + udev_device_set_devtype(udev_device, &line[8]); + else if (strncmp(line, "MAJOR=", 6) == 0) maj = strtoull(&line[6], NULL, 10); else if (strncmp(line, "MINOR=", 6) == 0) min = strtoull(&line[6], NULL, 10); @@ -501,9 +505,11 @@ static struct udev_device *device_new_from_parent(struct udev_device *udev_devic strncmp(udev_device->devpath, "/block/", 7) == 0) { util_strlcpy(path, udev_device->syspath, sizeof(path)); util_strlcat(path, "/device", sizeof(path)); - if (util_resolve_sys_link(udev_device->udev, path, sizeof(path)) == 0) + if (util_resolve_sys_link(udev_device->udev, path, sizeof(path)) == 0) { udev_device_parent = udev_device_new_from_syspath(udev_device->udev, path); - return udev_device_parent; + if (udev_device_parent != NULL) + return udev_device_parent; + } } util_strlcpy(path, udev_device->syspath, sizeof(path)); @@ -535,17 +541,26 @@ struct udev_device *udev_device_get_parent(struct udev_device *udev_device) return udev_device->parent_device; } -struct udev_device *udev_device_get_parent_with_subsystem(struct udev_device *udev_device, const char *subsystem) +struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_device *udev_device, const char *subsystem, const char *devtype) { struct udev_device *parent; + if (subsystem == NULL) + return NULL; + parent = udev_device_get_parent(udev_device); while (parent != NULL) { const char *parent_subsystem; + const char *parent_devtype; parent_subsystem = udev_device_get_subsystem(parent); - if (parent_subsystem != NULL && strcmp(parent_subsystem, subsystem) == 0) - break; + if (parent_subsystem != NULL && strcmp(parent_subsystem, subsystem) == 0) { + if (devtype == NULL) + break; + parent_devtype = udev_device_get_devtype(parent); + if (parent_devtype != NULL && strcmp(parent_devtype, devtype) == 0) + break; + } parent = udev_device_get_parent(parent); } return parent; @@ -603,6 +618,7 @@ void udev_device_unref(struct udev_device *udev_device) free(udev_device->sysname); free(udev_device->devnode); free(udev_device->subsystem); + free(udev_device->devtype); udev_list_cleanup_entries(udev_device->udev, &udev_device->devlinks_list); udev_list_cleanup_entries(udev_device->udev, &udev_device->properties_list); free(udev_device->action); @@ -721,6 +737,26 @@ const char *udev_device_get_subsystem(struct udev_device *udev_device) return udev_device->subsystem; } +/** + * udev_device_get_devtype: + * @udev_device: udev device + * + * Retrieve the devtype string of the udev device. + * + * Returns: the devtype name of the udev device, or #NULL if it can not be determined + **/ +const char *udev_device_get_devtype(struct udev_device *udev_device) +{ + if (udev_device == NULL) + return NULL; + if (!udev_device->devtype_set) { + udev_device->devtype_set = 1; + if (!udev_device->info_loaded) + udev_device_read_uevent_file(udev_device); + } + return udev_device->devtype; +} + /** * udev_device_get_devlinks_list_entry: * @udev_device: udev device @@ -857,11 +893,16 @@ const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const } if (S_ISLNK(statbuf.st_mode)) { - /* links return the last element of the target path */ char target[UTIL_NAME_SIZE]; int len; char *pos; + /* some core links return the last element of the target path */ + if (strcmp(sysattr, "driver") != 0 && + strcmp(sysattr, "subsystem") != 0 && + strcmp(sysattr, "module") != 0) + goto out; + len = readlink(path, target, sizeof(target)); if (len > 0) { target[len] = '\0'; @@ -956,6 +997,17 @@ int udev_device_set_subsystem(struct udev_device *udev_device, const char *subsy return 0; } +int udev_device_set_devtype(struct udev_device *udev_device, const char *devtype) +{ + free(udev_device->devtype); + udev_device->devtype = strdup(devtype); + if (udev_device->devtype == NULL) + return -ENOMEM; + udev_device->devtype_set = 1; + udev_device_add_property(udev_device, "DEVTYPE", udev_device->devtype); + return 0; +} + int udev_device_set_devnode(struct udev_device *udev_device, const char *devnode) { free(udev_device->devnode);