OSDN Git Service

am 7e612cb8: (-s ours) am f41c7e0b: Merge remote-tracking branch \'toybox/master...
[android-x86/external-toybox.git] / toys / pending / mdev.c
index 2d98c25..a13a53d 100644 (file)
@@ -31,34 +31,54 @@ 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;
-  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
 
@@ -166,11 +186,22 @@ found_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)
@@ -202,7 +233,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
 }