aboutsummaryrefslogtreecommitdiff
path: root/toys/pending/mdev.c
diff options
context:
space:
mode:
authorIsaac Dunham <ibid.ag@gmail.com>2015-04-18 18:25:06 +0000
committerRob Landley <rob@landley.net>2015-04-19 01:24:42 -0500
commit3cf9b08cc9ebeddc449638608f7a28c4c4ba20f9 (patch)
tree7c2ab09cf316b76f305db2c1b7a2b097aa0ead7a /toys/pending/mdev.c
parent957c3f7eaa4b56d6470ce8ef382b132c1aae9ca0 (diff)
downloadtoybox-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/mdev.c')
-rw-r--r--toys/pending/mdev.c74
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
}