- device_name = strrchr(path, '/') + 1;
- type = path[5]=='c' ? S_IFCHR : S_IFBLK;
- if (sscanf(temp, "%d:%d", &major, &minor) != 2) return;
-
- /* If we have a config file, look up permissions for this device */
-
- if (ENABLE_FEATURE_MDEV_CONF) {
- char *conf, *pos, *end;
-
- /* mmap the config file */
- if (-1 != (fd=open("/etc/mdev.conf",O_RDONLY))) {
- len = lseek(fd, 0, SEEK_END);
- 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=0; field < (3 + ENABLE_FEATURE_MDEV_EXEC);
- field++)
- {
- /* Skip whitespace */
- while (pos<end && isspace(*pos)) pos++;
- if (pos==end || *pos=='#') break;
- for (end2=pos;
- end2<end && !isspace(*end2) && *end2!='#'; end2++)
- ;
-
- if (!field) {
- /* Regex to match this device */
-
- char *regex = strndupa(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);
-
- /* If not this device, skip rest of line */
- if (result || off.rm_so
- || off.rm_eo != strlen(device_name))
- break;
-
- } else if (field == 1) {
- /* uid:gid */
-
- char *s, *s2;
-
- /* Find : */
- for(s=pos; s<end2 && *s!=':'; s++)
- ;
- if (s == end2) break;
-
- /* Parse UID */
- uid = strtoul(pos,&s2,10);
- if (s != s2) {
- struct passwd *pass;
- pass = getpwnam(strndupa(pos, s-pos));
- if (!pass) break;
- uid = pass->pw_uid;
- }
- s++;
- /* parse GID */
- gid = strtoul(s, &s2, 10);
- if (end2 != s2) {
- struct group *grp;
- grp = getgrnam(strndupa(s, end2-s));
- if (!grp) break;
- gid = grp->gr_gid;
- }
- } else if (field == 2) {
- /* mode */
-
- mode = strtoul(pos, &pos, 8);
- if (pos != end2) break;
- } else if (ENABLE_FEATURE_MDEV_EXEC && field == 3) {
- // Command to run
- char *s = "@$*", *s2;
- if (!(s2 = strchr(s, *pos++))) {
- // Force error
- field = 1;
- break;
- }
- if ((s2-s+1) & (1<<delete))
- command = bb_xstrndup(pos, end-pos);
- }
-
- pos = end2;
+ /* This line matches: stop parsing the file
+ * after parsing the rest of fields */
+
+ /* 2nd field: uid:gid - device ownership */
+ parse_chown_usergroup_or_die(&ugid, tokens[1]);
+
+ /* 3rd field: mode - device permissions */
+ mode = strtoul(tokens[2], NULL, 8);
+
+ val = tokens[3];
+ /* 4th field (opt): >alias */
+#if ENABLE_FEATURE_MDEV_RENAME
+ if (!val)
+ break;
+ aliaslink = *val;
+ if (aliaslink == '>' || aliaslink == '=') {
+ char *s;
+#if ENABLE_FEATURE_MDEV_RENAME_REGEXP
+ char *p;
+ unsigned i, n;
+#endif
+ char *a = val;
+ s = strchrnul(val, ' ');
+ val = (s[0] && s[1]) ? s+1 : NULL;
+ s[0] = '\0';
+#if ENABLE_FEATURE_MDEV_RENAME_REGEXP
+ /* substitute %1..9 with off[1..9], if any */
+ n = 0;
+ s = a;
+ while (*s)
+ if (*s++ == '%')
+ n++;
+
+ p = alias = xzalloc(strlen(a) + n * strlen(device_name));
+ s = a + 1;
+ while (*s) {
+ *p = *s;
+ if ('%' == *s) {
+ i = (s[1] - '0');
+ if (i <= 9 && off[i].rm_so >= 0) {
+ n = off[i].rm_eo - off[i].rm_so;
+ strncpy(p, device_name + off[i].rm_so, n);
+ p += n - 1;
+ s++;