#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;
- int major, minor, type, len, fd;
+ char *device_name = NULL, *s, *temp;
+ int major = 0, minor = 0, 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
+ if (path) {
+ // Try to read major/minor string
+
+ temp = strrchr(path, '/');
+ fd = open(path, O_RDONLY);
+ *temp=0;
+ len = read(fd, toybuf, 64);
+ close(fd);
+ if (len<1) return;
+ toybuf[len] = 0;
+
+ // Determine device type, major and minor
+
+ type = path[5]=='c' ? S_IFCHR : S_IFBLK;
+ sscanf(toybuf, "%u:%u", &major, &minor);
+ } else {
+ // if (!path), do hotplug
+
+ if (!(temp = getenv("SUBSYSTEM")))
+ return;
+ type = strcmp(temp, "block") ? S_IFCHR : S_IFBLK;
+ 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;
+ }
+ if (!device_name)
+ device_name = strrchr(path, '/') + 1;
- device_name = strrchr(path, '/') + 1;
- type = path[5]=='c' ? S_IFCHR : S_IFBLK;
- major = minor = 0;
- sscanf(temp, "%u:%u", &major, &minor);
+ // as in linux/drivers/base/core.c, device_get_devnode()
+ while ((temp = strchr(device_name, '!'))) {
+ *temp = '/';
+ }
// If we have a config file, look up permissions for this device
}
}
- sprintf(temp, "/dev/%s", device_name);
- if (mknod(temp, mode | type, makedev(major, minor)) && errno != EEXIST)
- perror_exit("mknod %s failed", temp);
+ sprintf(toybuf, "/dev/%s", device_name);
- if (CFG_MDEV_CONF) mode=chown(temp, uid, gid);
+ if ((temp=getenv("ACTION")) && !strcmp(temp, "remove")) {
+ unlink(toybuf);
+ return;
+ }
+
+ if (strchr(device_name, '/'))
+ mkpathat(AT_FDCWD, toybuf, 0, 2);
+ if (mknod(toybuf, mode | type, makedev(major, minor)) && errno != EEXIST)
+ perror_exit("mknod %s failed", toybuf);
+
+
+ if (type == S_IFBLK) close(open(toybuf, O_RDONLY)); // scan for partitions
+
+ if (CFG_MDEV_CONF) mode=chown(toybuf, uid, gid);
}
static int callback(struct dirtree *node)
if (toys.optflags) {
dirtree_read("/sys/class", callback);
dirtree_read("/sys/block", callback);
+ } else { // hotplug support
+ make_device(NULL);
}
-
- // hotplug support goes here
}