summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2008-05-12 00:52:27 -0500
committerRob Landley <rob@landley.net>2008-05-12 00:52:27 -0500
commit988abb33a5c9d8023a8e1bd5535a75a16e5d9e46 (patch)
treee79fe82472c84fe3e6675650e49770c8c0e23733
parente156d44eb2e9954d37ed0dfa326f263c3ed4c3d7 (diff)
downloadtoybox-988abb33a5c9d8023a8e1bd5535a75a16e5d9e46.tar.gz
toybox-988abb33a5c9d8023a8e1bd5535a75a16e5d9e46.tar.bz2
toybox-988abb33a5c9d8023a8e1bd5535a75a16e5d9e46.zip
Update mdev to work around the newest sysfs api breakage in the 2.6.25 kernel.
(Yeah, I know sysfs hasn't actually got an API, but I like to pretend...)
-rw-r--r--lib/dirtree.c6
-rw-r--r--lib/lib.c5
-rw-r--r--lib/lib.h2
-rw-r--r--toys/mdev.c69
-rw-r--r--toys/toysh.c2
5 files changed, 43 insertions, 41 deletions
diff --git a/lib/dirtree.c b/lib/dirtree.c
index 45ee139..a695bb3 100644
--- a/lib/dirtree.c
+++ b/lib/dirtree.c
@@ -58,6 +58,7 @@ struct dirtree *dirtree_read(char *path, struct dirtree *parent,
if (!(dir = opendir(path))) perror_msg("No %s", path);
else for (;;) {
+ int norecurse = 0;
struct dirent *entry = readdir(dir);
if (!entry) {
closedir(dir);
@@ -74,8 +75,9 @@ struct dirtree *dirtree_read(char *path, struct dirtree *parent,
*ddt = dirtree_add_node(path);
if (!*ddt) continue;
(*ddt)->parent = parent;
- if (callback) callback(path, *ddt);
- if (entry->d_type == DT_DIR)
+ (*ddt)->depth = parent ? parent->depth + 1 : 1;
+ if (callback) norecurse = callback(path, *ddt);
+ if (!norecurse && entry->d_type == DT_DIR)
(*ddt)->child = dirtree_read(path, *ddt, callback);
if (callback) free(*ddt);
else ddt = &((*ddt)->next);
diff --git a/lib/lib.c b/lib/lib.c
index 6102e1b..0e3fe02 100644
--- a/lib/lib.c
+++ b/lib/lib.c
@@ -326,6 +326,11 @@ char *xabspath(char *path)
return path;
}
+void xchdir(char *path)
+{
+ if (chdir(path)) error_exit("chdir '%s'");
+}
+
// Ensure entire path exists.
// If mode != -1 set permissions on newly created dirs.
// Requires that path string be writable (for temporary null terminators).
diff --git a/lib/lib.h b/lib/lib.h
index 8ffd103..f8f52e6 100644
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -36,6 +36,7 @@ void get_optflags(void);
struct dirtree {
struct dirtree *next, *child, *parent;
struct stat st;
+ int depth;
char name[];
};
@@ -75,6 +76,7 @@ void xwrite(int fd, void *buf, size_t len);
char *xgetcwd(void);
void xstat(char *path, struct stat *st);
char *xabspath(char *path);
+void xchdir(char *path);
void xmkpath(char *path, int mode);
struct string_list *find_in_path(char *path, char *filename);
void utoa_to_buf(unsigned n, char *buf, unsigned buflen);
diff --git a/toys/mdev.c b/toys/mdev.c
index 6e69a77..63c5082 100644
--- a/toys/mdev.c
+++ b/toys/mdev.c
@@ -2,7 +2,7 @@
*
* mdev - Mini udev for busybox
*
- * Copyright 2005, 2007 Rob Landley <rob@landley.net>
+ * Copyright 2005, 2008 Rob Landley <rob@landley.net>
* Copyright 2005 Frank Sorenson <frank@tuxrocks.com>
*
* Not in SUSv3.
@@ -11,7 +11,7 @@ USE_MDEV(NEWTOY(mdev, "s", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_UMASK))
config MDEV
bool "mdev"
- default n
+ default y
help
usage: mdev [-s]
@@ -21,7 +21,7 @@ config MDEV
config MDEV_CONF
bool "Configuration file for mdev"
- default n
+ default y
depends on MDEV
help
The mdev config file (/etc/mdev.conf) contains lines that look like:
@@ -47,8 +47,7 @@ static void make_device(char *path)
// Try to read major/minor string
- temp = path+strlen(path);
- strcpy(temp, "/dev");
+ temp = strrchr(path, '/');
fd = open(path, O_RDONLY);
*temp=0;
temp++;
@@ -172,49 +171,43 @@ found_device:
if (CFG_MDEV_CONF) chown(temp, uid, gid);
}
-// 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)
+static int callback(char *path, struct dirtree *node)
{
- DIR *dir;
- int len=strlen(path);
-
- if (!(dir = opendir(path)))
- perror_exit("No %s",path);
-
- for (;;) {
- struct dirent *entry = readdir(dir);
-
- if (!entry) break;
-
- // Skip "." and ".." (also skips hidden files, which is ok)
-
- if (entry->d_name[0]=='.') continue;
-
- if (entry->d_type == DT_DIR) {
- snprintf(path+len, sizeof(toybuf)-len, "/%s", entry->d_name);
- find_dev(path);
- path[len] = 0;
- }
-
- // If there's a dev entry, mknod it
-
- if (strcmp(entry->d_name, "dev")) make_device(path);
+ // Entries in /sys/class/block aren't char devices, so skip 'em. (We'll
+ // get block devices out of /sys/block.)
+ if(!strcmp(node->name, "block")) return 1;
+
+ // Does this directory have a "dev" entry in it?
+ if (S_ISDIR(node->st.st_mode) || S_ISLNK(node->st.st_mode)) {
+ char *dest = path+strlen(path);
+ strcpy(dest, "/dev");
+ if (!access(path, R_OK)) make_device(path);
+ *dest = 0;
}
- closedir(dir);
+ // Circa 2.6.25 the entries more than 2 deep are all either redundant
+ // (mouse#, event#) or unnamed (every usb_* entry is called "device").
+ return node->depth>1;
}
void mdev_main(void)
{
+ // Handle -s
+
if (toys.optflags) {
- strcpy(toybuf, "/sys/block");
- find_dev(toybuf);
+ xchdir("/sys/class");
strcpy(toybuf, "/sys/class");
- find_dev(toybuf);
- return;
+ dirtree_read(toybuf, NULL, callback);
+ strcpy(toybuf+5, "block");
+ dirtree_read(toybuf, NULL, callback);
}
+// if (toys.optflags) {
+// strcpy(toybuf, "/sys/block");
+// find_dev(toybuf);
+// strcpy(toybuf, "/sys/class");
+// find_dev(toybuf);
+// return;
+// }
// hotplug support goes here
}
diff --git a/toys/toysh.c b/toys/toysh.c
index 17467fa..d1ef683 100644
--- a/toys/toysh.c
+++ b/toys/toysh.c
@@ -349,7 +349,7 @@ static void handle(char *command)
void cd_main(void)
{
char *dest = *toys.optargs ? *toys.optargs : getenv("HOME");
- if (chdir(dest)) error_exit("chdir %s",dest);
+ xchdir(dest);
}
void exit_main(void)