mdev: add support for - "dont stop here" char
authorDenis Vlasenko <vda.linux@googlemail.com>
Mon, 13 Apr 2009 23:18:52 +0000 (23:18 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Mon, 13 Apr 2009 23:18:52 +0000 (23:18 -0000)
function                                             old     new   delta
make_device                                         1340    1362     +22
packed_usage                                       26291   26299      +8
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 30/0)               Total: 30 bytes

include/usage.h
util-linux/mdev.c

index 7111e90bc1501646cfdd49c9169f3e2cba28f900..d3bf7849e0f95099a03f576dab68e82a73234218 100644 (file)
        " echo /bin/mdev >/proc/sys/kernel/hotplug\n" \
        USE_FEATURE_MDEV_CONF( \
        "It uses /etc/mdev.conf with lines\n" \
-       "DEVNAME UID:GID PERM" \
+       "[-]DEVNAME UID:GID PERM" \
                        USE_FEATURE_MDEV_RENAME(" [>|=PATH]") \
                        USE_FEATURE_MDEV_EXEC(" [@|$|*COMMAND]") \
        ) \
index 3b0ef351e4a7911d5081d7eae07a76140b31ab78..b1f3d051c7b4927ad8f24e91638891694fca674d 100644 (file)
@@ -57,21 +57,12 @@ static char *build_alias(char *alias, const char *device_name)
 /* NB: "mdev -s" may call us many times, do not leak memory/fds! */
 static void make_device(char *path, int delete)
 {
-       const char *device_name;
-       int major, minor, type, len;
-       int mode = 0660;
 #if ENABLE_FEATURE_MDEV_CONF
-       struct bb_uidgid_t ugid = { 0, 0 };
        parser_t *parser;
-       char *tokens[5];
-# if ENABLE_FEATURE_MDEV_EXEC
-       char *command = NULL;
-# endif
-# if ENABLE_FEATURE_MDEV_RENAME
-       char *alias = NULL;
-       char aliaslink = aliaslink; /* for compiler */
-# endif
 #endif
+       const char *device_name;
+       int major, minor, type, len;
+       int mode;
        char *dev_maj_min = path + strlen(path);
 
        /* Force the configuration file settings exactly. */
@@ -111,14 +102,37 @@ static void make_device(char *path, int delete)
        parser = config_open2("/etc/mdev.conf", fopen_for_read);
 
        /* If we have config file, look up user settings */
-       while (config_read(parser, tokens, 4, 3, "# \t", PARSE_NORMAL)) {
+       while (1) {
                regmatch_t off[1 + 9*ENABLE_FEATURE_MDEV_RENAME_REGEXP];
-               char *val = tokens[0];
+               int keep_matching;
+               char *val;
+               struct bb_uidgid_t ugid;
+               char *tokens[4];
+# if ENABLE_FEATURE_MDEV_EXEC
+               char *command = NULL;
+# endif
+# if ENABLE_FEATURE_MDEV_RENAME
+               char *alias = NULL;
+               char aliaslink = aliaslink; /* for compiler */
+# endif
+               /* Defaults in case we won't match any line */
+               ugid.uid = ugid.gid = 0;
+               keep_matching = 0;
+               mode = 0660;
+
+               if (!config_read(parser, tokens, 4, 3, "# \t", PARSE_NORMAL)) {
+                       /* End of file, create dev node with default params */
+                       goto line_matches;
+               }
+
+               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 (tokens[0][0] == '@') {
+               if (val[0] == '@') {
                        /* @major,minor[-last] */
                        /* (useful when name is ambiguous:
                         * "/sys/class/usb/lp0" and
@@ -126,12 +140,12 @@ static void make_device(char *path, int delete)
                        int cmaj, cmin0, cmin1, sc;
                        if (major < 0)
                                continue; /* no dev, no match */
-                       sc = sscanf(tokens[0], "@%u,%u-%u", &cmaj, &cmin0, &cmin1);
+                       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; /* no match */
+                               continue; /* this line doesn't match */
                        }
                } else { /* ... or regex to match device name */
                        regex_t match;
@@ -160,12 +174,12 @@ static void make_device(char *path, int delete)
                        if (result || off[0].rm_so
                         || ((int)off[0].rm_eo != (int)strlen(dev_name_or_subsystem))
                        ) {
-                               continue;
+                               continue; /* this line doesn't match */
                        }
                }
 
-               /* This line matches: stop parsing the file
-                * after parsing the rest of fields */
+               /* This line matches: stop parsing the file after parsing
+                * the rest of fields unless keep_matching == 1 */
 
                /* 2nd field: uid:gid - device ownership */
                parse_chown_usergroup_or_die(&ugid, tokens[1]);
@@ -174,24 +188,25 @@ static void make_device(char *path, int delete)
                mode = strtoul(tokens[2], NULL, 8);
 
                val = tokens[3];
-               /* 4th field (opt): >alias */
+               /* 4th field (opt): >|=alias */
 # if ENABLE_FEATURE_MDEV_RENAME
                if (!val)
-                       break;
-               aliaslink = *val;
+                       goto line_matches;
+               aliaslink = val[0];
                if (aliaslink == '>' || aliaslink == '=') {
-                       char *s, *st;
+                       char *a, *s, *st;
 #  if ENABLE_FEATURE_MDEV_RENAME_REGEXP
                        char *p;
                        unsigned i, n;
 #  endif
-                       char *a = val;
+                       a = val;
                        s = strchrnul(val, ' ');
                        st = strchrnul(val, '\t');
                        if (st < s)
                                s = st;
                        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;
@@ -223,12 +238,12 @@ static void make_device(char *path, int delete)
 # endif /* ENABLE_FEATURE_MDEV_RENAME */
 
 # if ENABLE_FEATURE_MDEV_EXEC
-               /* The rest (opt): command to run */
+               /* The rest (opt): @|$|*command */
                if (!val)
-                       break;
+                       goto line_matches;
                {
                        const char *s = "@$*";
-                       const char *s2 = strchr(s, *val);
+                       const char *s2 = strchr(s, val[0]);
 
                        if (!s2)
                                bb_error_msg_and_die("bad line %u", parser->lineno);
@@ -244,71 +259,71 @@ static void make_device(char *path, int delete)
                        }
                }
 # endif
-               /* end of field parsing */
-               break; /* we found matching line, stop */
-       } /* end of "while line is read from /etc/mdev.conf" */
-
-       config_close(parser);
+               /* End of field parsing */
+ line_matches:
 #endif /* ENABLE_FEATURE_MDEV_CONF */
 
-       if (!delete && major >= 0) {
-
-               if (ENABLE_FEATURE_MDEV_RENAME)
-                       unlink(device_name);
-
-               if (mknod(device_name, mode | type, makedev(major, minor)) && errno != EEXIST)
-                       bb_perror_msg_and_die("mknod %s", device_name);
-
-               if (major == root_major && minor == root_minor)
-                       symlink(device_name, "root");
+               /* "Execute" the line we found */
 
+               if (!delete && major >= 0) {
+                       if (ENABLE_FEATURE_MDEV_RENAME)
+                               unlink(device_name);
+                       if (mknod(device_name, mode | type, makedev(major, minor)) && errno != EEXIST)
+                               bb_perror_msg_and_die("mknod %s", device_name);
+                       if (major == root_major && minor == root_minor)
+                               symlink(device_name, "root");
 #if ENABLE_FEATURE_MDEV_CONF
-               chown(device_name, ugid.uid, ugid.gid);
-
+                       chown(device_name, ugid.uid, ugid.gid);
 # if ENABLE_FEATURE_MDEV_RENAME
-               if (alias) {
-                       alias = build_alias(alias, device_name);
-
-                       /* move the device, and optionally
-                        * make a symlink to moved device node */
-                       if (rename(device_name, alias) == 0 && aliaslink == '>')
-                               symlink(alias, device_name);
-
-                       free(alias);
-               }
+                       if (alias) {
+                               alias = build_alias(alias, device_name);
+                               /* move the device, and optionally
+                                * make a symlink to moved device node */
+                               if (rename(device_name, alias) == 0 && aliaslink == '>')
+                                       symlink(alias, device_name);
+                               free(alias);
+                       }
 # endif
 #endif
-       }
-
+               }
 #if ENABLE_FEATURE_MDEV_EXEC
-       if (command) {
-               /* setenv will leak memory, use putenv/unsetenv/free */
-               char *s = xasprintf("%s=%s", "MDEV", device_name);
-               char *s1 = xasprintf("%s=%s", "SUBSYSTEM", subsystem);
-               putenv(s);
-               putenv(s1);
-               if (system(command) == -1)
-                       bb_perror_msg_and_die("can't run '%s'", command);
-               unsetenv("SUBSYSTEM");
-               free(s1);
-               unsetenv("MDEV");
-               free(s);
-               free(command);
-       }
+               if (command) {
+                       /* setenv will leak memory, use putenv/unsetenv/free */
+                       char *s = xasprintf("%s=%s", "MDEV", device_name);
+                       char *s1 = xasprintf("%s=%s", "SUBSYSTEM", subsystem);
+                       putenv(s);
+                       putenv(s1);
+                       if (system(command) == -1)
+                               bb_perror_msg_and_die("can't run '%s'", command);
+                       unsetenv("SUBSYSTEM");
+                       free(s1);
+                       unsetenv("MDEV");
+                       free(s);
+                       free(command);
+               }
 #endif
-
-       if (delete) {
-               unlink(device_name);
-               /* At creation time, device might have been moved
-                * and a symlink might have been created. Undo that. */
+               if (delete) {
+                       unlink(device_name);
+                       /* At creation time, device might have been moved
+                        * and a symlink might have been created. Undo that. */
 #if ENABLE_FEATURE_MDEV_RENAME
-               if (alias) {
-                       alias = build_alias(alias, device_name);
-                       unlink(alias);
-                       free(alias);
-               }
+                       if (alias) {
+                               alias = build_alias(alias, device_name);
+                               unlink(alias);
+                               free(alias);
+                       }
 #endif
-       }
+               }
+
+#if ENABLE_FEATURE_MDEV_CONF
+               /* We found matching line.
+                * Stop unless it was prefixed with '-' */
+               if (!keep_matching)
+                       break;
+       } /* end of "while line is read from /etc/mdev.conf" */
+
+       config_close(parser);
+#endif /* ENABLE_FEATURE_MDEV_CONF */
 }
 
 /* File callback for /sys/ traversal */