diff options
author | Isaac Dunham <ibid.ag@gmail.com> | 2015-04-18 18:25:06 +0000 |
---|---|---|
committer | Rob Landley <rob@landley.net> | 2015-04-19 01:24:42 -0500 |
commit | 3cf9b08cc9ebeddc449638608f7a28c4c4ba20f9 (patch) | |
tree | 7c2ab09cf316b76f305db2c1b7a2b097aa0ead7a /toys/pending | |
parent | 957c3f7eaa4b56d6470ce8ef382b132c1aae9ca0 (diff) | |
download | toybox-3cf9b08cc9ebeddc449638608f7a28c4c4ba20f9.tar.gz |
mdev: implement hotplug support.
Use DEVPATH, DEVNAME, MAJOR, MINOR, and SUBSYSTEM instead of
checking the current path and reading .../dev.
While we're here, probe for partitions in block devices.
This uses a very lame check for ACTION (which can be add, remove,
or change): if it is "remove", then unlink the device.
Diffstat (limited to 'toys/pending')
-rw-r--r-- | toys/pending/mdev.c | 74 |
1 files changed, 52 insertions, 22 deletions
diff --git a/toys/pending/mdev.c b/toys/pending/mdev.c index 2d98c257..0c496336 100644 --- a/toys/pending/mdev.c +++ b/toys/pending/mdev.c @@ -31,34 +31,53 @@ config MDEV_CONF #include "toys.h" -// todo, open() block devices to trigger partition scanning. - // mknod in /dev based on a path like "/sys/block/hda/hda1" static void make_device(char *path) { - char *device_name, *s, *temp; + char *device_name = NULL, *s, *temp; int major, minor, type, len, fd; int mode = 0660; uid_t uid = 0; gid_t gid = 0; - // Try to read major/minor string - - temp = strrchr(path, '/'); - fd = open(path, O_RDONLY); - *temp=0; - temp = toybuf; - len = read(fd, temp, 64); - close(fd); - if (len<1) return; - temp[len] = 0; - - // Determine device name, type, major and minor - - device_name = strrchr(path, '/') + 1; - type = path[5]=='c' ? S_IFCHR : S_IFBLK; - major = minor = 0; - sscanf(temp, "%u:%u", &major, &minor); + if (path) { + // Try to read major/minor string + + temp = strrchr(path, '/'); + fd = open(path, O_RDONLY); + *temp=0; + temp = toybuf; + len = read(fd, temp, 64); + close(fd); + if (len<1) return; + temp[len] = 0; + + // Determine device type, major and minor + + type = path[5]=='c' ? S_IFCHR : S_IFBLK; + major = minor = 0; + sscanf(temp, "%u:%u", &major, &minor); + } else { + // if (!path), do hotplug + + if (!(temp = getenv("SUBSYSTEM"))) + return; + type = strcmp(temp, "block") ? S_IFCHR : S_IFBLK; + major = minor = 0; + if (!(temp = getenv("MAJOR"))) + return; + sscanf(temp, "%u", &major); + if (!(temp = getenv("MINOR"))) + return; + sscanf(temp, "%u", &minor); + path = getenv("DEVPATH"); + device_name = getenv("DEVNAME"); + if (!path) + return; + temp = toybuf; + } + if (!device_name) + device_name = strrchr(path, '/') + 1; // If we have a config file, look up permissions for this device @@ -167,9 +186,20 @@ found_device: } sprintf(temp, "/dev/%s", device_name); + + if (getenv("ACTION") && !strcmp(getenv("ACTION"), "remove")) { + unlink(temp); + return; + } + + if (strchr(device_name, '/')) + mkpathat(AT_FDCWD, temp, 0, 2); if (mknod(temp, mode | type, makedev(major, minor)) && errno != EEXIST) perror_exit("mknod %s failed", temp); + + if (type == S_IFBLK) close(open(temp, O_RDONLY)); // scan for partitions + if (CFG_MDEV_CONF) mode=chown(temp, uid, gid); } @@ -202,7 +232,7 @@ void mdev_main(void) if (toys.optflags) { dirtree_read("/sys/class", callback); dirtree_read("/sys/block", callback); + } else { // hotplug support + make_device(NULL); } - - // hotplug support goes here } |