- 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(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=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 = 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))
- 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;
- pass = getpwnam(strndupa(pos,s-pos));
- if (!pass)
- goto end_line;
- 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)
- goto end_line;
- gid = grp->gr_gid;
- }
- break;
- }
- /* mode */
- case 1:
- {
- mode = strtoul(pos,&pos,8);
- if (pos != end2)
- goto end_line;
- else
- goto found_device;
- }
- }
- pos = end2;
- }
-end_line:
- /* Did everything parse happily? */
- if (field && field!=3)
- bb_error_msg_and_die("Bad line %d",line);
+ val = tokens[0];
+ keep_matching = ('-' == val[0]);
+ val += keep_matching; /* swallow leading dash */
+
+ /* Fields: regex uid:gid mode [alias] [cmd] */
+
+ /* 1st field: @<numeric maj,min>... */
+ if (val[0] == '@') {
+ /* @major,minor[-last] */
+ /* (useful when name is ambiguous:
+ * "/sys/class/usb/lp0" and
+ * "/sys/class/printer/lp0") */
+ int cmaj, cmin0, cmin1, sc;
+ if (major < 0)
+ continue; /* no dev, no match */
+ sc = sscanf(val, "@%u,%u-%u", &cmaj, &cmin0, &cmin1);
+ if (sc < 1 || major != cmaj
+ || (sc == 2 && minor != cmin0)
+ || (sc == 3 && (minor < cmin0 || minor > cmin1))
+ ) {
+ continue; /* this line doesn't match */
+ }
+ } else { /* ... or regex to match device name */
+ regex_t match;
+ int result;
+ const char *dev_name_or_subsystem = device_name;
+ if ('/' == val[0] && subsystem) {
+ dev_name_or_subsystem = subsystem;
+ val++;
+ }