chiark / gitweb /
[PATCH] udevstart: simplify "dev" file searching
authorkay.sievers@vrfy.org <kay.sievers@vrfy.org>
Thu, 10 Feb 2005 17:26:09 +0000 (18:26 +0100)
committerGreg KH <gregkh@suse.de>
Wed, 27 Apr 2005 06:31:07 +0000 (23:31 -0700)
Just stat() the "dev" file in the device directory instead of
opening the directory and iterating over all entries.

Make udevstart work with the settings in with udev.conf so we can
run a test program.

Add a test for udevstart.

Remove changelog stuff from code. We should never start with this
silly thing.

test/udev-test.pl
test/udevstart-test.pl [new file with mode: 0644]
udev_start.c

index 5a519ef..992fc00 100644 (file)
 # After creation and removal the result is checked against the
 # expected value and the result is printed.
 #
-# happy testing,
 # Kay Sievers <kay.sievers@vrfy.org>, 2003
-#
-# Modified April 9, 2004 by Leann Ogasawara <ogasawara@osdl.org>
-#  - expanded @tests array to add more symlinks and permissions tests
-#  - some of the symlinks tests also test lack of node creation
-#  - added symlink_test() function
-#  - moved permissions and major_minor tests into their own functions
+# Leann Ogasawara <ogasawara@osdl.org>, 2004
 
 use warnings;
 use strict;
diff --git a/test/udevstart-test.pl b/test/udevstart-test.pl
new file mode 100644 (file)
index 0000000..b6f85bb
--- /dev/null
@@ -0,0 +1,58 @@
+#!/usr/bin/perl
+
+# udevstart-test
+#
+# runs udevstart in a temporary directory with our test sysfs-tree
+# and counts the created nodes to compare it with the expected numbers.
+#
+# Kay Sievers <kay.sievers@vrfy.org>, 2005
+#
+
+use warnings;
+use strict;
+
+my $PWD = $ENV{PWD};
+my $sysfs     = "sys/";
+my $udev_bin  = "../udev";
+my $udev_root = "udev-root/"; # !!! directory will be removed !!!
+my $udev_db   = ".udevdb";
+my $main_conf = "udev-test.conf";
+my $conf_tmp  = "udev-test.rules";
+
+# set env
+$ENV{UDEV_TEST} = "yes";
+$ENV{SYSFS_PATH} = $sysfs;
+$ENV{UDEV_CONFIG_FILE} = $main_conf;
+$ENV{UDEV_NO_DEVD} = "yes";
+$ENV{UDEV_NO_HOTPLUGD} = "yes";
+
+# due to mknod restrictions
+if (!($<==0)) {
+       print "Must have root permissions to run properly.\n";
+       exit;
+}
+
+# prepare
+system("rm -rf $udev_root");
+mkdir($udev_root) || die "unable to create udev_root: $udev_root\n";
+
+# create initial config file
+open CONF, ">$main_conf" || die "unable to create config file: $main_conf";
+print CONF "udev_root=\"$udev_root\"\n";
+print CONF "udev_db=\"$udev_db\"\n";
+print CONF "udev_rules=\"$conf_tmp\"\n";
+close CONF;
+
+system("$udev_bin udevstart");
+my $block = int( `find $udev_root -type b -print | wc -l`);
+my $char  = int( `find $udev_root -type c -print | wc -l`);
+
+print "block devices: $block/10\n";
+print "char devices: $char/91\n";
+
+# cleanup
+system("rm -rf $udev_db");
+system("rm -rf $udev_root");
+unlink($conf_tmp);
+unlink($main_conf);
+
index 8c7a06b..dcb4293 100644 (file)
@@ -30,6 +30,7 @@
 #include <ctype.h>
 #include <dirent.h>
 #include <sys/wait.h>
+#include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
 
 #include "udev.h"
 
 
-#define MAX_PATHLEN            1024
-#define SYSBLOCK               "/sys/block"
-#define SYSCLASS               "/sys/class"
+#define MAX_PATH_SIZE          512
 
 struct device {
        struct list_head list;
-       char path[MAX_PATHLEN];
-       char subsys[MAX_PATHLEN];
+       char path[MAX_PATH_SIZE];
+       char subsys[MAX_PATH_SIZE];
 };
 
 /* sort files in lexical order */
-static int device_list_insert(char *path, char *subsystem, struct list_head *device_list)
+static int device_list_insert(const char *path, char *subsystem, struct list_head *device_list)
 {
        struct device *loop_device;
        struct device *new_device;
 
+       dbg("insert: '%s'\n", path);
+
        list_for_each_entry(loop_device, device_list, list) {
                if (strcmp(loop_device->path, path) > 0) {
                        break;
@@ -87,18 +88,20 @@ static char *first_list[] = {
        NULL,
 };
 
-static int add_device(char *devpath, char *subsystem)
+static int add_device(const char *path, const char *subsystem)
 {
        struct udevice udev;
-       char path[SYSFS_PATH_MAX];
        struct sysfs_class_device *class_dev;
+       const char *devpath;
+
+       devpath = &path[strlen(sysfs_path)];
 
        /* set environment for callouts and dev.d/ */
        setenv("DEVPATH", devpath, 1);
        setenv("SUBSYSTEM", subsystem, 1);
 
-       snprintf(path, SYSFS_PATH_MAX, "%s%s", sysfs_path, devpath);
-       path[SYSFS_PATH_MAX-1] = '\0';
+       dbg("exec  : '%s' (%s)\n", devpath, path);
+
        class_dev = sysfs_open_class_device_path(path);
        if (class_dev == NULL) {
                dbg ("sysfs_open_class_device_path failed");
@@ -127,7 +130,7 @@ static void exec_list(struct list_head *device_list)
 
        /* handle the "first" type devices first */
        list_for_each_entry_safe(loop_device, tmp_device, device_list, list) {
-               for (i=0; first_list[i] != NULL; i++) {
+               for (i = 0; first_list[i] != NULL; i++) {
                        if (strncmp(loop_device->path, first_list[i], strlen(first_list[i])) == 0) {
                                add_device(loop_device->path, loop_device->subsys);
                                list_del(&loop_device->list);
@@ -140,7 +143,7 @@ static void exec_list(struct list_head *device_list)
        /* handle the devices we are allowed to, excluding the "last" type devices */
        list_for_each_entry_safe(loop_device, tmp_device, device_list, list) {
                int found = 0;
-               for (i=0; last_list[i] != NULL; i++) {
+               for (i = 0; last_list[i] != NULL; i++) {
                        if (strncmp(loop_device->path, last_list[i], strlen(last_list[i])) == 0) {
                                found = 1;
                                break;
@@ -162,56 +165,61 @@ static void exec_list(struct list_head *device_list)
        }
 }
 
+static int has_devt(const char *directory)
+{
+       char filename[MAX_PATH_SIZE];
+       struct stat statbuf;
+
+       snprintf(filename, MAX_PATH_SIZE, "%s/dev", directory);
+       filename[MAX_PATH_SIZE-1] = '\0';
+
+       if (stat(filename, &statbuf) == 0)
+               return 1;
+
+       return 0;
+}
+
 static void udev_scan_block(void)
 {
+       char base[MAX_PATH_SIZE];
        DIR *dir;
        struct dirent *dent;
        LIST_HEAD(device_list);
 
-       dir = opendir(SYSBLOCK);
+       snprintf(base, MAX_PATH_SIZE, "%s/block", sysfs_path);
+       base[MAX_PATH_SIZE-1] = '\0';
+
+       dir = opendir(base);
        if (dir != NULL) {
                for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
-                       char dirname[MAX_PATHLEN];
+                       char dirname[MAX_PATH_SIZE];
                        DIR *dir2;
                        struct dirent *dent2;
 
-                       if ((strcmp(dent->d_name, ".") == 0) ||
-                           (strcmp(dent->d_name, "..") == 0))
+                       if (dent->d_name[0] == '.')
                                continue;
 
-                       snprintf(dirname, MAX_PATHLEN, "/block/%s", dent->d_name);
-                       dirname[MAX_PATHLEN-1] = '\0';
-                       device_list_insert(dirname, "block", &device_list);
+                       snprintf(dirname, MAX_PATH_SIZE, "%s/%s", base, dent->d_name);
+                       dirname[MAX_PATH_SIZE-1] = '\0';
+                       if (has_devt(dirname))
+                               device_list_insert(dirname, "block", &device_list);
+                       else
+                               continue;
 
-                       snprintf(dirname, MAX_PATHLEN, "%s/%s", SYSBLOCK, dent->d_name);
+                       snprintf(dirname, MAX_PATH_SIZE, "%s/%s", base, dent->d_name);
                        dir2 = opendir(dirname);
                        if (dir2 != NULL) {
                                for (dent2 = readdir(dir2); dent2 != NULL; dent2 = readdir(dir2)) {
-                                       char dirname2[MAX_PATHLEN];
-                                       DIR *dir3;
-                                       struct dirent *dent3;
+                                       char dirname2[MAX_PATH_SIZE];
 
-                                       if ((strcmp(dent2->d_name, ".") == 0) ||
-                                           (strcmp(dent2->d_name, "..") == 0))
+                                       if (dent2->d_name[0] == '.')
                                                continue;
 
-                                       snprintf(dirname2, MAX_PATHLEN, "%s/%s", dirname, dent2->d_name);
-                                       dirname2[MAX_PATHLEN-1] = '\0';
-
-                                       dir3 = opendir(dirname2);
-                                       if (dir3 != NULL) {
-                                               for (dent3 = readdir(dir3); dent3 != NULL; dent3 = readdir(dir3)) {
-                                                       char filename[MAX_PATHLEN];
-
-                                                       if (strcmp(dent3->d_name, "dev") == 0) {
-                                                               snprintf(filename, MAX_PATHLEN, "/block/%s/%s",
-                                                                        dent->d_name, dent2->d_name);
-                                                               filename[MAX_PATHLEN-1] = '\0';
-                                                               device_list_insert(filename, "block", &device_list);
-                                                       }
-                                               }
-                                               closedir(dir3);
-                                       }
+                                       snprintf(dirname2, MAX_PATH_SIZE, "%s/%s", dirname, dent2->d_name);
+                                       dirname2[MAX_PATH_SIZE-1] = '\0';
+
+                                       if (has_devt(dirname2))
+                                               device_list_insert(dirname2, "block", &device_list);
                                }
                                closedir(dir2);
                        }
@@ -224,59 +232,42 @@ static void udev_scan_block(void)
 
 static void udev_scan_class(void)
 {
+       char base[MAX_PATH_SIZE];
        DIR *dir;
        struct dirent *dent;
        LIST_HEAD(device_list);
 
-       dir = opendir(SYSCLASS);
+       snprintf(base, MAX_PATH_SIZE, "%s/class", sysfs_path);
+       base[MAX_PATH_SIZE-1] = '\0';
+
+       dir = opendir(base);
        if (dir != NULL) {
                for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
-                       char dirname[MAX_PATHLEN];
+                       char dirname[MAX_PATH_SIZE];
                        DIR *dir2;
                        struct dirent *dent2;
 
-                       if ((strcmp(dent->d_name, ".") == 0) ||
-                           (strcmp(dent->d_name, "..") == 0))
+                       if (dent->d_name[0] == '.')
                                continue;
 
-                       snprintf(dirname, MAX_PATHLEN, "%s/%s", SYSCLASS, dent->d_name);
-                       dirname[MAX_PATHLEN-1] = '\0';
+                       snprintf(dirname, MAX_PATH_SIZE, "%s/%s", base, dent->d_name);
+                       dirname[MAX_PATH_SIZE-1] = '\0';
                        dir2 = opendir(dirname);
                        if (dir2 != NULL) {
                                for (dent2 = readdir(dir2); dent2 != NULL; dent2 = readdir(dir2)) {
-                                       char dirname2[MAX_PATHLEN];
-                                       DIR *dir3;
-                                       struct dirent *dent3;
+                                       char dirname2[MAX_PATH_SIZE];
 
-                                       if ((strcmp(dent2->d_name, ".") == 0) ||
-                                           (strcmp(dent2->d_name, "..") == 0))
+                                       if (dent2->d_name[0] == '.')
                                                continue;
 
+                                       snprintf(dirname2, MAX_PATH_SIZE, "%s/%s", dirname, dent2->d_name);
+                                       dirname2[MAX_PATH_SIZE-1] = '\0';
+
                                        /* pass the net class as it is */
-                                       if (strcmp(dent->d_name, "net") == 0) {
-                                               snprintf(dirname2, MAX_PATHLEN, "/class/net/%s", dent2->d_name);
+                                       if (strcmp(dent->d_name, "net") == 0)
                                                device_list_insert(dirname2, "net", &device_list);
-                                               continue;
-                                       }
-
-                                       snprintf(dirname2, MAX_PATHLEN, "%s/%s", dirname, dent2->d_name);
-                                       dirname2[MAX_PATHLEN-1] = '\0';
-                                       dir3 = opendir(dirname2);
-                                       if (dir3 != NULL) {
-                                               for (dent3 = readdir(dir3); dent3 != NULL; dent3 = readdir(dir3)) {
-                                                       char filename[MAX_PATHLEN];
-
-                                                       /* pass devices with a "dev" file */
-                                                       if (strcmp(dent3->d_name, "dev") == 0) {
-                                                               snprintf(filename, MAX_PATHLEN, "/class/%s/%s",
-                                                                        dent->d_name, dent2->d_name);
-                                                               filename[MAX_PATHLEN-1] = '\0';
-                                                               device_list_insert(filename, dent->d_name, &device_list);
-                                                               break;
-                                                       }
-                                               }
-                                               closedir(dir3);
-                                       }
+                                       else if (has_devt(dirname2))
+                                               device_list_insert(dirname2, dent->d_name, &device_list);
                                }
                                closedir(dir2);
                        }