diff options
Diffstat (limited to 'util-linux/mdev.c')
| -rw-r--r-- | util-linux/mdev.c | 59 |
1 files changed, 27 insertions, 32 deletions
diff --git a/util-linux/mdev.c b/util-linux/mdev.c index 8e5b8a94b..fca4fd052 100644 --- a/util-linux/mdev.c +++ b/util-linux/mdev.c | |||
| @@ -19,6 +19,8 @@ struct globals { | |||
| 19 | #define root_major (G.root_major) | 19 | #define root_major (G.root_major) |
| 20 | #define root_minor (G.root_minor) | 20 | #define root_minor (G.root_minor) |
| 21 | 21 | ||
| 22 | #define MAX_SYSFS_DEPTH 3 /* prevent infinite loops in /sys symlinks */ | ||
| 23 | |||
| 22 | /* mknod in /dev based on a path like "/sys/block/hda/hda1" */ | 24 | /* mknod in /dev based on a path like "/sys/block/hda/hda1" */ |
| 23 | static void make_device(char *path, int delete) | 25 | static void make_device(char *path, int delete) |
| 24 | { | 26 | { |
| @@ -191,39 +193,28 @@ static void make_device(char *path, int delete) | |||
| 191 | if (delete) unlink(device_name); | 193 | if (delete) unlink(device_name); |
| 192 | } | 194 | } |
| 193 | 195 | ||
| 194 | /* Recursive search of /sys/block or /sys/class. path must be a writeable | 196 | /* File callback for /sys/ traversal */ |
| 195 | * buffer of size PATH_MAX containing the directory string to start at. */ | 197 | static int fileAction(const char *fileName, struct stat *statbuf, |
| 196 | 198 | void *userData, int depth) | |
| 197 | static void find_dev(char *path) | ||
| 198 | { | 199 | { |
| 199 | DIR *dir; | 200 | size_t len = strlen(fileName) - 4; |
| 200 | size_t len = strlen(path); | 201 | char *scratch = userData; |
| 201 | struct dirent *entry; | ||
| 202 | |||
| 203 | dir = opendir(path); | ||
| 204 | if (dir == NULL) | ||
| 205 | return; | ||
| 206 | |||
| 207 | while ((entry = readdir(dir)) != NULL) { | ||
| 208 | struct stat st; | ||
| 209 | |||
| 210 | /* Skip "." and ".." (also skips hidden files, which is ok) */ | ||
| 211 | |||
| 212 | if (entry->d_name[0] == '.') | ||
| 213 | continue; | ||
| 214 | 202 | ||
| 215 | // uClibc doesn't fill out entry->d_type reliably. so we use lstat(). | 203 | if (strcmp(fileName + len, "/dev")) |
| 204 | return FALSE; | ||
| 216 | 205 | ||
| 217 | snprintf(path+len, PATH_MAX-len, "/%s", entry->d_name); | 206 | strcpy(scratch, fileName); |
| 218 | if (!lstat(path, &st) && S_ISDIR(st.st_mode)) find_dev(path); | 207 | scratch[len] = 0; |
| 219 | path[len] = 0; | 208 | make_device(scratch, 0); |
| 220 | 209 | ||
| 221 | /* If there's a dev entry, mknod it */ | 210 | return TRUE; |
| 222 | 211 | } | |
| 223 | if (!strcmp(entry->d_name, "dev")) make_device(path, 0); | ||
| 224 | } | ||
| 225 | 212 | ||
| 226 | closedir(dir); | 213 | /* Directory callback for /sys/ traversal */ |
| 214 | static int dirAction(const char *fileName, struct stat *statbuf, | ||
| 215 | void *userData, int depth) | ||
| 216 | { | ||
| 217 | return (depth >= MAX_SYSFS_DEPTH ? SKIP : TRUE); | ||
| 227 | } | 218 | } |
| 228 | 219 | ||
| 229 | /* For the full gory details, see linux/Documentation/firmware_class/README | 220 | /* For the full gory details, see linux/Documentation/firmware_class/README |
| @@ -308,10 +299,14 @@ int mdev_main(int argc, char **argv) | |||
| 308 | xstat("/", &st); | 299 | xstat("/", &st); |
| 309 | root_major = major(st.st_dev); | 300 | root_major = major(st.st_dev); |
| 310 | root_minor = minor(st.st_dev); | 301 | root_minor = minor(st.st_dev); |
| 311 | strcpy(temp,"/sys/block"); | 302 | |
| 312 | find_dev(temp); | 303 | recursive_action("/sys/block", |
| 313 | strcpy(temp,"/sys/class"); | 304 | ACTION_RECURSE | ACTION_FOLLOWLINKS, |
| 314 | find_dev(temp); | 305 | fileAction, dirAction, temp, 0); |
| 306 | |||
| 307 | recursive_action("/sys/class", | ||
| 308 | ACTION_RECURSE | ACTION_FOLLOWLINKS, | ||
| 309 | fileAction, dirAction, temp, 0); | ||
| 315 | 310 | ||
| 316 | /* Hotplug */ | 311 | /* Hotplug */ |
| 317 | 312 | ||
