From 988abb33a5c9d8023a8e1bd5535a75a16e5d9e46 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Mon, 12 May 2008 00:52:27 -0500 Subject: [PATCH] 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...) --- lib/dirtree.c | 6 ++++-- lib/lib.c | 5 +++++ lib/lib.h | 2 ++ toys/mdev.c | 69 +++++++++++++++++++++++++++-------------------------------- toys/toysh.c | 2 +- 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 + * Copyright 2005, 2008 Rob Landley * Copyright 2005 Frank Sorenson * * 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) -- 2.7.4