Re: An idea on devfs vs. udev

From: Frank Sorenson
Date: Mon Oct 31 2005 - 04:21:35 EST


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Rob Landley wrote:
> I'm pondering adding a micro-udev to busybox (it's fairly far down on the todo
> list).

snip

> function makedev
> {
> j=`echo "$1" | sed 's .*/\(.*\)/dev \1 '`
> minor=`cat "$1" | sed 's .*: '`
> major=`cat "$1" | sed 's :.* '`
> mknod tmpdir/"$j" $2 $major $minor
> }
>
> for i in `find /sys/block -name "dev"`
> do
> makedev -m 700 $i b $major $minor
> echo -n b
> done
>
> for i in `find /sys/class -name "dev"`
> do
> makedev -m 700 $i c $major $minor
> echo -n c
> done
>
> You think implementing that in C would take more than 4k?

I'm certain that someone can do better than this, but here's a C version
that does it in 4684 bytes (stripped). It's simple, and runs fast. I'm
sure that someone could optimize this much further.

Frank
- --
Frank Sorenson - KD7TZK
Systems Manager, Computer Science Department
Brigham Young University
frank@xxxxxxxxxxxx
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org

iD8DBQFDZeIWaI0dwg4A47wRAiWgAJ9LzBcNhfrW5KHP9f8qg+spfGUSKwCdFTlw
grK0kedpIQ/JRDN2yMqLG4U=
=K4vE
-----END PGP SIGNATURE-----
/*
* miniudev - implement a small udev that can run at bootup
* Copyright Frank Sorenson <frank@xxxxxxxxxxxx> 2005
*
* Permission is hereby granted to copy, modify and redistribute this code
* in terms of the GNU Library General Public License, Version 2 or later,
* at your option.
*
*/

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/sysmacros.h>

#define DEV_PATH "/dev"
#define DEV_MODE 0700

int get_device_info(const char *path, int *major, int *minor)
{
char buf[512];
int fd;
int ret;
char *chr;
char got_colon = 0;
int tempval = 0;

sprintf(buf, "%s/dev", path);
fd = open(buf, O_RDONLY);
ret = read(fd, buf, 1024);
buf[ret - 1] = '\0';
if (ret == 0)
return -1;
close(fd);

chr = buf;
while (*chr != '\0') {
if (*chr == ':') {
*major = tempval;
tempval = 0;
got_colon ++;
} else {
tempval *= 10;
tempval += (*chr - '0');
}
chr ++;
}
*minor = tempval;

return 0;
}

int make_device(const char *path, int type)
{
char buf[512];
const char *device_name;
int major;
int minor;
int ret;
int local_errno;

device_name = path;
while (*device_name != '\0')
device_name ++;
while ((*(device_name - 1) != '/') && (device_name > path)) {
device_name --;
}
get_device_info(path, &major, &minor);
printf("%s: %d %d\n", device_name, major, minor);

sprintf(buf, "%s/%s", DEV_PATH, device_name);
ret = mknod(buf, DEV_MODE | type, makedev(major, minor));
if (ret != 0) {
local_errno = errno;
printf("Could not create device node %s: error %d\n", buf, local_errno);
}

return 0;
}

char cmp(const char *s1, const char *s2)
{
int n = 0;

while (s1[n] == s2[n]) {
if (s1[n] == '\0')
return 1;
n++;
}
return 0;
}

int find_dev(const char *path, int type)
{
DIR *dir;
struct dirent *entry;
char temp_path[512];
int local_errno;

dir = opendir(path);
if (dir == NULL) {
printf("Could not open path %s: error %d\n", path, local_errno);
exit(-1);
}

do {
entry = readdir(dir);
if (entry == NULL)
break;
if (cmp(entry->d_name, "."))
continue;
if (cmp(entry->d_name, ".."))
continue;
if (entry->d_type == DT_DIR) {
sprintf(temp_path, "%s/%s", path, entry->d_name);
find_dev(temp_path, type);
}
if (cmp(entry->d_name, "dev")) {
make_device(path, type);
}
} while (entry != NULL);
closedir(dir);

return 0;
}


int main(int argc, char *argv[])
{
find_dev("/sys/block", S_IFBLK);
find_dev("/sys/class", S_IFCHR);

return 0;
}