Revert last mdev commit because it copied code out of a GPLv2 program.
authorRob Landley <rob@landley.net>
Wed, 8 Apr 2015 09:20:31 +0000 (04:20 -0500)
committerRob Landley <rob@landley.net>
Wed, 8 Apr 2015 09:20:31 +0000 (04:20 -0500)
Guys, you CANNOT COPY CODE FROM BUSYBOX. I don't care if I was the initial
author of that file, other people have touched it since.

I know I added "pending" because I couldn't keep up with code review in
realtime and stuff was getting lost, so we needed a place to park things
before they underwent the full dorodango process. I also know none of the
binaries I distribute has anything in pending enabled. But dude, if I'm going
to find stuff like this I have to start reviewing the code BEFORE applying
it to pending, and we all know where that leads.

Please don't do this again.

toys/pending/mdev.c

index 2aa09bc..2d98c25 100644 (file)
@@ -29,23 +29,16 @@ config MDEV_CONF
     matching devies.
 */
 
-#define FOR_mdev
 #include "toys.h"
 
 // todo, open() block devices to trigger partition scanning.
 
-GLOBALS(
-  char *devname;
-  int root_maj, root_min, verbose;
-)
-
-
 // mknod in /dev based on a path like "/sys/block/hda/hda1"
-static void make_device(char *path, char *operation)
+static void make_device(char *path)
 {
-  char *device_name, *s, *temp, *alias = NULL, *cmd = NULL, buf[PATH_MAX];
-  char sign = 0, op_pref = 0, *str2 = NULL, *ln = NULL;
-  int major, minor, type, len, fd, ufd, mode = 0660;
+  char *device_name, *s, *temp;
+  int major, minor, type, len, fd;
+  int mode = 0660;
   uid_t uid = 0;
   gid_t gid = 0;
 
@@ -53,32 +46,19 @@ static void make_device(char *path, char *operation)
 
   temp = strrchr(path, '/');
   fd = open(path, O_RDONLY);
-  *temp = 0;
+  *temp=0;
   temp = toybuf;
   len = read(fd, temp, 64);
   close(fd);
-  if (!strcmp(operation, "add") && len < 1) return;
+  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;
-  if (sscanf(temp, "%u:%u", &major, &minor) != 2) major = -1;
-
-  memset(buf, 0, sizeof(buf));
-  device_name = TT.devname;
-  if (!device_name) {
-    sprintf(buf,"%s/uevent", path);
-    if ((ufd = open(buf, O_RDONLY)) >= 0) {
-      for (; (ln = get_line(ufd)); free(ln)) {
-        if (strstr(ln, "DEVNAME=")) {
-          device_name = ln + strlen("DEVNAME=") ;
-          break;
-        }  
-      }
-      close(ufd);
-    }
-  }
-  if (!device_name) device_name = strrchr(path, '/') + 1;
-  type = S_IFCHR;
-  if (strstr(path, "/block/")) type =  S_IFBLK;
+  sscanf(temp, "%u:%u", &major, &minor);
 
   // If we have a config file, look up permissions for this device
 
@@ -86,145 +66,96 @@ static void make_device(char *path, char *operation)
     char *conf, *pos, *end;
 
     // mmap the config file
-    if (-1 != (fd = open("/etc/mdev.conf", O_RDONLY))) {
+    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;) {
+        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++);
+          for(end = pos; end-conf<len && *end!='\n'; end++);
 
-          // Fields: regex uid:gid mode [alias] [cmd]
-          for (field = 3; field >= 0; field--) {
+          // Three fields: regex, uid:gid, mode
+          for (field = 3; field; field--) {
             // Skip whitespace
-            while (pos < end && isspace(*pos)) pos++;
-            if (pos == end || *pos == '#') break;
+            while (pos<end && isspace(*pos)) pos++;
+            if (pos==end || *pos=='#') break;
             for (end2 = pos;
-                end2 < end && !isspace(*end2) && *end2 != '#'; end2++);
+              end2<end && !isspace(*end2) && *end2!='#'; end2++);
             switch(field) {
               // Regex to match this device
               case 3:
-                {
-                  char *str = strndup(pos, end2-pos), *regex;
-                  regex_t match;
-                  regmatch_t off;
-                  int result;
-
-                  if (*str == '$') {
-                    char *p = strchr(str, '=');
-
-                    if (!p) {
-                      free(str);
-                      error_msg("bad $envvar=regex");
-                      goto end_line;
-                    } else {
-                      p++;
-                      regex = xstrdup(p);
-                      free(str);
-                    }
-                  } else {
-                    regex = xstrdup(str);
-                    free(str);
-                  }
-                  // Is this it?
-                  if (*regex == '@') {
-                    int maj, min1, min2;
-
-                    int ret = sscanf(regex, "@%u,%u-%u", &maj, &min1, &min2);
-                    free(regex);
-                    if (ret < 2 || maj < 0) {
-                      error_msg("bad @maj,min @line %d",line);
-                      goto end_line;
-                    }
-                    if (ret == 2) min2 = min1;
-                    if (!(major == maj && ( min1 <= minor || minor <= min2)))
-                      goto end_line;
-                  } else {
-                    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
+              {
+                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 = xstrndup(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 = xstrndup(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;
-                  break;
+              {
+                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;
                 }
-                // handle 4th and 5th field
-              case 0:
-                {
-                  char *str1 = NULL; 
-
-                  str2 = xstrndup(pos, end-pos);
-                  if (strchr(">=!", str2[0])) {
-                    str1 = strtok(str2, " ");
-                    sign = str1[0];
-                    alias = str1 + 1;
-                    str1 += strlen(alias) +2;
-                  } else str1 = str2;
-                  if (str1 && strchr("$@*",str1[0])) {
-                    op_pref = str1[0];
-                    cmd = str1 + 1;
-                  } else error_exit("Bad Line %d", line); 
-                  goto found_device;
+                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;
+            pos=end2;
           }
 end_line:
           // Did everything parse happily?
-          if (field && field != 3) error_exit("bad line %d", line);
+          if (field && field!=3) error_exit("Bad line %d", line);
+
           // Next line
           pos = ++end;
         }
@@ -235,46 +166,11 @@ found_device:
     }
   }
 
-  if (operation && !((op_pref == '@' && !strcmp(operation, "add")) ||
-        (op_pref == '$' && !strcmp(operation, "remove")) || (op_pref == '*')))
-    cmd = NULL;
-
-  if (alias) {
-    if (alias[strlen(alias)-1] == '/') sprintf(temp,"%s%s",alias, device_name);
-    else sprintf(temp,"%s",alias);
-  }
-  if (sign != '!' && operation && !strcmp(operation, "add")) { //not to create device otherwise
-
-    if (mknod(device_name, mode | type, makedev(major, minor)) && errno != EEXIST)
-      perror_msg("mknod /dev/%s failed", device_name);
-    if (CFG_MDEV_CONF)  { 
-      chmod(device_name, mode);
-      chown(device_name, uid, gid);
-    }
-
-    if (TT.root_maj == major && TT.root_min == minor) symlink(device_name, "root");
-
-    if (alias && (sign == '>' || sign == '=')) {
-      mkpathat(AT_FDCWD, alias, 0, 2);
-      if (rename(device_name, temp)) perror_exit("rename temp");
-      if (sign == '>') symlink(temp, device_name);
-    }
-  }
-  if (cmd) {
-    char *str = xmprintf("%s=%s", "MDEV", device_name);
-
-    putenv(str);
-    if (system(cmd) == -1) perror_msg("can't run '%s'", cmd);
-    unsetenv(str);
-    free(str);
-  }
+  sprintf(temp, "/dev/%s", device_name);
+  if (mknod(temp, mode | type, makedev(major, minor)) && errno != EEXIST)
+    perror_exit("mknod %s failed", temp);
 
-  if (operation && !strcmp(operation, "remove") && major >= -1) {
-    if (alias && sign == '>') unlink(temp);
-    unlink(device_name);
-  }
-  free(str2);
-  free(ln);
+  if (CFG_MDEV_CONF) mode=chown(temp, uid, gid);
 }
 
 static int callback(struct dirtree *node)
@@ -282,143 +178,31 @@ 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;
-  if (!dirtree_notdotdot(node)) 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;
+    int len=4;
     char *dev = dirtree_path(node, &len);
     strcpy(dev+len, "/dev");
-    if (!access(dev, R_OK)) make_device(dev, "add");
+    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|DIRTREE_SYMFOLLOW;
-}
-
-#if 0
-static int sequence_file(char *seq)
-{
-  static struct timespec tspec = { 0, 32*1000*1000 }; // time out after 2 secs
-  int time_out = 2000 / 32, fd = -1;
-  sigset_t sg;
-
-  sigemptyset(&sg);
-  sigaddset(&sg, SIGCHLD);
-  sigprocmask(SIG_BLOCK, &sg, NULL);
-
-  for (;;) {
-    ssize_t slen;
-    char buf[sizeof(int)*3 + 2];
-
-    if (fd < 0 && (fd = open("/dev/mdev.seq", O_RDWR)) < 0) break;
-    if ((slen = pread(fd, buf, sizeof(buf) - 1, 0)) < 0) {
-      close(fd);
-      fd = -1;
-      break;
-    }
-    buf[slen] = '\0';
-    if (buf[0] == '\n') {
-      xwrite(fd, seq, strlen(seq));
-      xlseek(fd, 0, SEEK_SET);
-      break;
-    }
-    if (!strcmp(seq, buf)) break;
-    if (sigtimedwait(&sg, NULL, &tspec) >= 0) continue;
-    if (!--time_out) break;
-  }
-  sigprocmask(SIG_UNBLOCK, &sg, NULL);
-  return fd;
-}
-#endif
-
-static void firmware_load(char *fware, char *sysfs_path)
-{
-  int count, fd, lfd, dfd;
-
-  xchdir("/lib/firmware");
-  fd = open(fware, O_RDONLY);
-  // check for /sys/$DEVPATH/loading ... give 30 seconds to appear
-  xchdir(sysfs_path);
-  for (count = 0; count < 30; ++count) {
-    lfd = open("loading", O_WRONLY);
-    if (lfd >= 0) goto load;
-    sleep(1);
-  }
-  goto end;
-
-load:
-  if (fd >= 0) {
-    if (writeall(lfd, "1", 1) != 1) goto end;
-    dfd = open("data", O_WRONLY);
-    if (dfd < 0) goto end;
-    xsendfile(fd, dfd);
-    close(dfd);
-  }
-  if (fd >= 0) writeall(lfd, "0", 1);
-  else writeall(lfd, "-1", 2);
-
-end:
-  xchdir("/dev");
-  close(lfd);
-  close(fd);
+  return (node->parent && node->parent->parent) ? 0 : DIRTREE_RECURSE;
 }
 
 void mdev_main(void)
 {
+  // Handle -s
 
-  char buf[PATH_MAX];
-  struct dirtree *root;
-
-  umask(0);
-  xchdir("/dev");
-  if (toys.optflags & FLAG_s) {
-    struct stat st;
-
-    xstat("/", &st);
-    TT.root_maj = major(st.st_dev);
-    TT.root_min = minor(st.st_dev);
-    putenv((char*)"ACTION=add");
-
-    root = dirtree_add_node(0, "/sys/class", 1);
-    if (root) dirtree_handle_callback(root, callback);
-
-    root = dirtree_add_node(0, "/sys/block", 1);
-    if (root) dirtree_handle_callback(root, callback);
-  } else {  // Hotplug handling
-    char *fware, *action, *devpath;
-    int logfd;
-
-    action = getenv("ACTION");
-    TT.devname = getenv("DEVNAME");
-    devpath = getenv("DEVPATH");
-
-    if (!action || !devpath) {
-      toys.exithelp++;
-      error_exit("env var action/devpath not found");
-    }
-    fware = getenv("FIRMWARE");
-
-    if ((logfd = open("/dev/mdev.log", O_WRONLY | O_APPEND)) >= 0) {
-      dup2(logfd, 2);  // 2 -> STDERR_FILENO
-      TT.verbose = 1;
-    }
-    //TODO give sequencei file support.
-
-    //    seqfd = seq_num ? sequence_file(seq_num) : -1;
-    snprintf(buf, PATH_MAX, "/sys%s/dev", devpath);
-    if (action && !strcmp("remove", action) && !fware)
-      make_device(buf, action);
-    else {
-      make_device(buf, action);
-      buf[strlen(buf) - 4] = '\0'; //remove /dev from end.
-      if (action && !strcmp("add", action) && fware)
-        firmware_load(fware, buf);
-    }
+  if (toys.optflags) {
+    dirtree_read("/sys/class", callback);
+    dirtree_read("/sys/block", callback);
   }
+
+  // hotplug support goes here
 }