mdev: add environment variable match
function old new delta make_device 1998 2189 +191 clean_up_cur_rule 61 96 +35 dirAction 75 87 +12 mdev_main 838 849 +11 packed_usage 29272 29273 +1 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 5/0 up/down: 250/0) Total: 250 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
1961aea305
commit
40b97fb31e
@ -51,9 +51,9 @@ device nodes if your system needs something more than the default root/root
|
||||
660 permissions.
|
||||
|
||||
The file has the format:
|
||||
[-]<device regex> <uid>:<gid> <permissions>
|
||||
[-][envmatch]<device regex> <uid>:<gid> <permissions>
|
||||
or
|
||||
@<maj[,min1[-min2]]> <uid>:<gid> <permissions>
|
||||
[envmatch]@<maj[,min1[-min2]]> <uid>:<gid> <permissions>
|
||||
or
|
||||
$envvar=<regex> <uid>:<gid> <permissions>
|
||||
|
||||
|
@ -80,7 +80,7 @@
|
||||
//usage: IF_FEATURE_MDEV_CONF(
|
||||
//usage: "\n"
|
||||
//usage: "It uses /etc/mdev.conf with lines\n"
|
||||
//usage: " [-]DEVNAME UID:GID PERM"
|
||||
//usage: " [-][ENV=regex;]...DEVNAME UID:GID PERM"
|
||||
//usage: IF_FEATURE_MDEV_RENAME(" [>|=PATH]|[!]")
|
||||
//usage: IF_FEATURE_MDEV_EXEC(" [@|$|*PROG]")
|
||||
//usage: "\n"
|
||||
@ -233,6 +233,12 @@
|
||||
static const char keywords[] ALIGN1 = "add\0remove\0change\0";
|
||||
enum { OP_add, OP_remove };
|
||||
|
||||
struct envmatch {
|
||||
struct envmatch *next;
|
||||
char *envname;
|
||||
regex_t match;
|
||||
};
|
||||
|
||||
struct rule {
|
||||
bool keep_matching;
|
||||
bool regex_compiled;
|
||||
@ -243,6 +249,7 @@ struct rule {
|
||||
char *ren_mov;
|
||||
IF_FEATURE_MDEV_EXEC(char *r_cmd;)
|
||||
regex_t match;
|
||||
struct envmatch *envmatch;
|
||||
};
|
||||
|
||||
struct globals {
|
||||
@ -288,14 +295,48 @@ static void make_default_cur_rule(void)
|
||||
|
||||
static void clean_up_cur_rule(void)
|
||||
{
|
||||
struct envmatch *e;
|
||||
|
||||
free(G.cur_rule.envvar);
|
||||
free(G.cur_rule.ren_mov);
|
||||
if (G.cur_rule.regex_compiled)
|
||||
regfree(&G.cur_rule.match);
|
||||
free(G.cur_rule.ren_mov);
|
||||
IF_FEATURE_MDEV_EXEC(free(G.cur_rule.r_cmd);)
|
||||
e = G.cur_rule.envmatch;
|
||||
while (e) {
|
||||
free(e->envname);
|
||||
regfree(&e->match);
|
||||
e = e->next;
|
||||
}
|
||||
make_default_cur_rule();
|
||||
}
|
||||
|
||||
static char *parse_envmatch_pfx(char *val)
|
||||
{
|
||||
struct envmatch **nextp = &G.cur_rule.envmatch;
|
||||
|
||||
for (;;) {
|
||||
struct envmatch *e;
|
||||
char *semicolon;
|
||||
char *eq = strchr(val, '=');
|
||||
if (!eq /* || eq == val? */)
|
||||
return val;
|
||||
if (endofname(val) != eq)
|
||||
return val;
|
||||
semicolon = strchr(eq, ';');
|
||||
if (!semicolon)
|
||||
return val;
|
||||
/* ENVVAR=regex;... */
|
||||
*nextp = e = xzalloc(sizeof(*e));
|
||||
nextp = &e->next;
|
||||
e->envname = xstrndup(val, eq - val);
|
||||
*semicolon = '\0';
|
||||
xregcomp(&e->match, eq + 1, REG_EXTENDED);
|
||||
*semicolon = ';';
|
||||
val = semicolon + 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void parse_next_rule(void)
|
||||
{
|
||||
/* Note: on entry, G.cur_rule is set to default */
|
||||
@ -314,6 +355,7 @@ static void parse_next_rule(void)
|
||||
val = tokens[0];
|
||||
G.cur_rule.keep_matching = ('-' == val[0]);
|
||||
val += G.cur_rule.keep_matching; /* swallow leading dash */
|
||||
val = parse_envmatch_pfx(val);
|
||||
if (val[0] == '@') {
|
||||
/* @major,minor[-minor2] */
|
||||
/* (useful when name is ambiguous:
|
||||
@ -328,8 +370,10 @@ static void parse_next_rule(void)
|
||||
if (sc == 2)
|
||||
G.cur_rule.min1 = G.cur_rule.min0;
|
||||
} else {
|
||||
char *eq = strchr(val, '=');
|
||||
if (val[0] == '$') {
|
||||
char *eq = strchr(++val, '=');
|
||||
/* $ENVVAR=regex ... */
|
||||
val++;
|
||||
if (!eq) {
|
||||
bb_error_msg("bad $envvar=regex on line %d", G.parser->lineno);
|
||||
goto next_rule;
|
||||
@ -423,6 +467,21 @@ static const struct rule *next_rule(void)
|
||||
return rule;
|
||||
}
|
||||
|
||||
static int env_matches(struct envmatch *e)
|
||||
{
|
||||
while (e) {
|
||||
int r;
|
||||
char *val = getenv(e->envname);
|
||||
if (!val)
|
||||
return 0;
|
||||
r = regexec(&e->match, val, /*size*/ 0, /*range[]*/ NULL, /*eflags*/ 0);
|
||||
if (r != 0) /* no match */
|
||||
return 0;
|
||||
e = e->next;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
# define next_rule() (&G.cur_rule)
|
||||
@ -537,6 +596,8 @@ static void make_device(char *device_name, char *path, int operation)
|
||||
rule = next_rule();
|
||||
|
||||
#if ENABLE_FEATURE_MDEV_CONF
|
||||
if (!env_matches(rule->envmatch))
|
||||
continue;
|
||||
if (rule->maj >= 0) { /* @maj,min rule */
|
||||
if (major != rule->maj)
|
||||
continue;
|
||||
@ -749,8 +810,10 @@ static int FAST_FUNC dirAction(const char *fileName UNUSED_PARAM,
|
||||
if (1 == depth) {
|
||||
free(G.subsystem);
|
||||
G.subsystem = strrchr(fileName, '/');
|
||||
if (G.subsystem)
|
||||
if (G.subsystem) {
|
||||
G.subsystem = xstrdup(G.subsystem + 1);
|
||||
xsetenv("SUBSYSTEM", G.subsystem);
|
||||
}
|
||||
}
|
||||
|
||||
return (depth >= MAX_SYSFS_DEPTH ? SKIP : TRUE);
|
||||
@ -843,8 +906,8 @@ int mdev_main(int argc UNUSED_PARAM, char **argv)
|
||||
xchdir("/dev");
|
||||
|
||||
if (argv[1] && strcmp(argv[1], "-s") == 0) {
|
||||
/* Scan:
|
||||
* mdev -s
|
||||
/*
|
||||
* Scan: mdev -s
|
||||
*/
|
||||
struct stat st;
|
||||
|
||||
@ -856,6 +919,8 @@ int mdev_main(int argc UNUSED_PARAM, char **argv)
|
||||
G.root_major = major(st.st_dev);
|
||||
G.root_minor = minor(st.st_dev);
|
||||
|
||||
putenv((char*)"ACTION=add");
|
||||
|
||||
/* ACTION_FOLLOWLINKS is needed since in newer kernels
|
||||
* /sys/block/loop* (for example) are symlinks to dirs,
|
||||
* not real directories.
|
||||
|
Loading…
Reference in New Issue
Block a user