as suggested by Renaud Cerrato and Souf, switch over to recursive_action() for some...
authorMike Frysinger <vapier@gentoo.org>
Wed, 13 Jun 2007 09:24:50 +0000 (09:24 -0000)
committerMike Frysinger <vapier@gentoo.org>
Wed, 13 Jun 2007 09:24:50 +0000 (09:24 -0000)
util-linux/mdev.c

index 8e5b8a94b66bd5002226b153220ef29591e3769a..fca4fd0528fb3fdf5fd16fb485614ef9b4e7b897 100644 (file)
@@ -19,6 +19,8 @@ struct globals {
 #define root_major (G.root_major)
 #define root_minor (G.root_minor)
 
+#define MAX_SYSFS_DEPTH 3 /* prevent infinite loops in /sys symlinks */
+
 /* mknod in /dev based on a path like "/sys/block/hda/hda1" */
 static void make_device(char *path, int delete)
 {
@@ -191,39 +193,28 @@ static void make_device(char *path, int delete)
        if (delete) unlink(device_name);
 }
 
-/* Recursive search of /sys/block or /sys/class.  path must be a writeable
- * buffer of size PATH_MAX containing the directory string to start at. */
-
-static void find_dev(char *path)
+/* File callback for /sys/ traversal */
+static int fileAction(const char *fileName, struct stat *statbuf,
+                      void *userData, int depth)
 {
-       DIR *dir;
-       size_t len = strlen(path);
-       struct dirent *entry;
-
-       dir = opendir(path);
-       if (dir == NULL)
-               return;
-
-       while ((entry = readdir(dir)) != NULL) {
-               struct stat st;
-
-               /* Skip "." and ".." (also skips hidden files, which is ok) */
-
-               if (entry->d_name[0] == '.')
-                       continue;
+       size_t len = strlen(fileName) - 4;
+       char *scratch = userData;
 
-               // uClibc doesn't fill out entry->d_type reliably. so we use lstat().
+       if (strcmp(fileName + len, "/dev"))
+               return FALSE;
 
-               snprintf(path+len, PATH_MAX-len, "/%s", entry->d_name);
-               if (!lstat(path, &st) && S_ISDIR(st.st_mode)) find_dev(path);
-               path[len] = 0;
+       strcpy(scratch, fileName);
+       scratch[len] = 0;
+       make_device(scratch, 0);
 
-               /* If there's a dev entry, mknod it */
-
-               if (!strcmp(entry->d_name, "dev")) make_device(path, 0);
-       }
+       return TRUE;
+}
 
-       closedir(dir);
+/* Directory callback for /sys/ traversal */
+static int dirAction(const char *fileName, struct stat *statbuf,
+                      void *userData, int depth)
+{
+       return (depth >= MAX_SYSFS_DEPTH ? SKIP : TRUE);
 }
 
 /* For the full gory details, see linux/Documentation/firmware_class/README
@@ -308,10 +299,14 @@ int mdev_main(int argc, char **argv)
                xstat("/", &st);
                root_major = major(st.st_dev);
                root_minor = minor(st.st_dev);
-               strcpy(temp,"/sys/block");
-               find_dev(temp);
-               strcpy(temp,"/sys/class");
-               find_dev(temp);
+
+               recursive_action("/sys/block",
+                       ACTION_RECURSE | ACTION_FOLLOWLINKS,
+                       fileAction, dirAction, temp, 0);
+
+               recursive_action("/sys/class",
+                       ACTION_RECURSE | ACTION_FOLLOWLINKS,
+                       fileAction, dirAction, temp, 0);
 
        /* Hotplug */