/* mdev.c - Populate /dev directory and handle hotplug events
 *
 * Copyright 2005, 2008 Rob Landley <rob@landley.net>
 * Copyright 2005 Frank Sorenson <frank@tuxrocks.com>

USE_MDEV(NEWTOY(mdev, "s", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_UMASK))

config MDEV
  bool "mdev"
  default n
  help
    usage: mdev [-s]

    Create devices in /dev using information from /sys.

    -s	Scan all entries in /sys to populate /dev

config MDEV_CONF
  bool "Configuration file for mdev"
  default y
  depends on MDEV
  help
    The mdev config file (/etc/mdev.conf) contains lines that look like:
    hd[a-z][0-9]* 0:3 660

    Each line must contain three whitespace separated fields. The first
    field is a regular expression matching one or more device names,
    the second and third fields are uid:gid and file permissions for
    matching devies.
*/

#include "toys.h"

// mknod in /dev based on a path like "/sys/block/hda/hda1"
static void make_device(char *path)
{
  char *device_name = 0, *s, *temp;
  int major = 0, minor = 0, type, len, fd, mode = 0660;
  uid_t uid = 0;
  gid_t gid = 0;

  if (path) {

    // Try to read major/minor string, returning if we can't
    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("MODALIAS"))) xrun((char *[]){"modprobe", temp, 0});
    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);
    if (!(path = getenv("DEVPATH"))) return;
    device_name = getenv("DEVNAME");
  }
  if (!device_name)
    device_name = strrchr(path, '/') + 1;

  // 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

  if (CFG_MDEV_CONF) {
    char *conf, *pos, *end;

    // mmap the config file
    if (-1!=(fd = open("/etc/mdev.conf", O_RDONLY))) {
      int line = 0;

      len = fdlength(fd);
      conf = xmmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);

      // Loop through lines in mmaped file
      for (pos = conf; pos-conf<len;) {
        int field;
        char *end2;

        line++;
        // find end of this line
        for(end = pos; end-conf<len && *end!='\n'; end++);

        // Three fields: regex, uid:gid, mode
        for (field = 3; field; field--) {
          // Skip whitespace
          while (pos<end && isspace(*pos)) pos++;
          if (pos==end || *pos=='#') break;
          for (end2 = pos;
            end2<end && !isspace(*end2) && *end2!='#'; end2++);
          switch(field) {
            // Regex to match this device
            case 3:
            {
              char *regex = strndup(pos, end2-pos);
              regex_t match;
              regmatch_t off;
              int result;

              // Is this it?
              xregcomp(&match, regex, REG_EXTENDED);
              result=regexec(&match, device_name, 1, &off, 0);
              regfree(&match);
              free(regex);

              // If not this device, skip rest of line
              if (result || off.rm_so
                || off.rm_eo!=strlen(device_name))
                  goto end_line;

              break;
            }
            // uid:gid
            case 2:
            {
              char *s2;

              // Find :
              for(s = pos; s<end2 && *s!=':'; s++);
              if (s==end2) goto end_line;

              // Parse UID
              uid = strtoul(pos,&s2,10);
              if (s!=s2) {
                struct passwd *pass;
                char *str = strndup(pos, s-pos);
                pass = getpwnam(str);
                free(str);
                if (!pass) goto end_line;
                uid = pass->pw_uid;
              }
              s++;
              // parse GID
              gid = strtoul(s,&s2,10);
              if (end2!=s2) {
                struct group *grp;
                char *str = strndup(s, end2-s);
                grp = getgrnam(str);
                free(str);
                if (!grp) goto end_line;
                gid = grp->gr_gid;
              }
              break;
            }
            // mode
            case 1:
            {
              mode = strtoul(pos, &pos, 8);
              if (pos!=end2) goto end_line;
              goto found_device;
            }
          }
          pos=end2;
        }
end_line:
        // Did everything parse happily?
        if (field && field!=3) error_exit("Bad line %d", line);

        // Next line
        pos = ++end;
      }
found_device:
      munmap(conf, len);
    }
    close(fd);
  }

  sprintf(toybuf, "/dev/%s", device_name);

  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, dev_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)
{
  // Entries in /sys/class/block aren't char devices, so skip 'em.  (We'll
  // get block devices out of /sys/block.)
  if(!strcmp(node->name, "block")) return 0;

  // Does this directory have a "dev" entry in it?
  // This is path based because the hotplug callbacks are
  if (S_ISDIR(node->st.st_mode) || S_ISLNK(node->st.st_mode)) {
    int len=4;
    char *dev = dirtree_path(node, &len);
    strcpy(dev+len, "/dev");
    if (!access(dev, R_OK)) make_device(dev);
    free(dev);
  }

  // Circa 2.6.25 the entries more than 2 deep are all either redundant
  // (mouse#, event#) or unnamed (every usb_* entry is called "device").

  return (node->parent && node->parent->parent) ? 0 : DIRTREE_RECURSE;
}

void mdev_main(void)
{
  // Handle -s

  if (toys.optflags) {
    dirtree_read("/sys/class", callback);
    dirtree_read("/sys/block", callback);
  } else { // hotplug support
    make_device(NULL);
  }
}
