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

    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))) {
      len = fdlength(fd);
      conf = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
      if (conf) {
        int line = 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, 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);
  }
}
