--- udev-098/udevstart.c.coldplug 2006-08-22 19:32:25.000000000 -0400 +++ udev-098/udevstart.c 2006-09-17 09:05:48.000000000 -0400 @@ -132,17 +132,23 @@ udev->dev = dev; strcpy(udev->action, "add"); + if (strncmp(udev->dev->devpath, "/devices/", 9) == 0) { + udev_rules_get_run(&rules, udev); + } else { if (strcmp(udev->dev->subsystem, "net") != 0) { + if (strcmp(udev->dev->subsystem, "input") != 0 || sysfs_attr_get_value(devpath, "dev")) { udev->devt = udev_device_get_devt(udev); if (major(udev->devt) == 0) return -1; + } } + udev_rules_get_name(&rules, udev); + } dbg("add '%s'", udev->dev->devpath); setenv("DEVPATH", udev->dev->devpath, 1); setenv("SUBSYSTEM", udev->dev->subsystem, 1); - udev_rules_get_name(&rules, udev); if (udev->ignore_device) { dbg("device event will be ignored"); goto exit; @@ -217,12 +223,12 @@ } } -static int has_devt(const char *path) +static int has_sysfs_key(const char *path, const char *key) { char filename[PATH_SIZE]; struct stat statbuf; - snprintf(filename, sizeof(filename), "%s/dev", path); + snprintf(filename, sizeof(filename), "%s/%s", path, key); filename[sizeof(filename)-1] = '\0'; if (stat(filename, &statbuf) == 0) @@ -231,6 +237,11 @@ return 0; } +static int has_devt(const char *path) +{ + return has_sysfs_key(path, "dev"); +} + static void udev_scan_block(struct list_head *device_list) { char base[PATH_SIZE]; @@ -312,7 +323,8 @@ snprintf(dirname2, sizeof(dirname2), "%s/%s", dirname, dent2->d_name); dirname2[sizeof(dirname2)-1] = '\0'; - if (has_devt(dirname2) || strcmp(dent->d_name, "net") == 0) + if (has_devt(dirname2) || strcmp(dent->d_name, "net") == 0 || + (strcmp(dent->d_name, "input") == 0 && has_sysfs_key(dirname2, "modalias"))) device_list_insert(dirname2, device_list); } closedir(dir2); @@ -322,6 +334,43 @@ } } +static void udev_scan_bus(struct list_head *device_list, char *bus, const char *sysfs_key) +{ + char base[PATH_SIZE]; + DIR *dir; + struct dirent *dent; + + snprintf(base, sizeof(base), "%s/bus/%s/devices", sysfs_path, bus); + base[sizeof(base)-1] = '\0'; + + dir = opendir(base); + if (dir != NULL) { + for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { + char linkname[PATH_SIZE]; + char dirname_short[PATH_SIZE]; + char *dirname = NULL; + + if (dent->d_name[0] == '.') + continue; + + snprintf(linkname, sizeof(linkname), "%s/%s", base, dent->d_name); + linkname[sizeof(linkname)-1] = '\0'; + + if (has_sysfs_key(linkname, sysfs_key)) { + int ret = readlink(linkname, dirname_short, PATH_SIZE); + if (ret > 8) { + dirname_short[ret] = '\0'; + /* replace ../../.. with /sys */ + dirname = dirname_short + 4; + memcpy(dirname, "/sys", 4); + device_list_insert(dirname, device_list); + } + } + } + closedir(dir); + } +} + static void asmlinkage sig_handler(int signum) { switch (signum) { @@ -367,6 +416,9 @@ udev_scan_class(&device_list); udev_scan_block(&device_list); + udev_scan_bus(&device_list, "pci", "modalias"); + udev_scan_bus(&device_list, "scsi", "type"); + udev_scan_bus(&device_list, "usb", "modalias"); exec_list(&device_list); udev_rules_cleanup(&rules);