diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2013-02-26 00:40:46 +0100 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2013-02-26 00:40:46 +0100 |
| commit | 40b97fb31ec7c24db706b47182f400f2a13dbbfc (patch) | |
| tree | c963df67c75ca61f86bbdc3f3f000ce0b1991731 /util-linux | |
| parent | 1961aea305e258ba7ab3910d084451220f55ed44 (diff) | |
| download | busybox-w32-40b97fb31ec7c24db706b47182f400f2a13dbbfc.tar.gz busybox-w32-40b97fb31ec7c24db706b47182f400f2a13dbbfc.tar.bz2 busybox-w32-40b97fb31ec7c24db706b47182f400f2a13dbbfc.zip | |
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>
Diffstat (limited to 'util-linux')
| -rw-r--r-- | util-linux/mdev.c | 77 |
1 files changed, 71 insertions, 6 deletions
diff --git a/util-linux/mdev.c b/util-linux/mdev.c index c592ef687..775e5c241 100644 --- a/util-linux/mdev.c +++ b/util-linux/mdev.c | |||
| @@ -80,7 +80,7 @@ | |||
| 80 | //usage: IF_FEATURE_MDEV_CONF( | 80 | //usage: IF_FEATURE_MDEV_CONF( |
| 81 | //usage: "\n" | 81 | //usage: "\n" |
| 82 | //usage: "It uses /etc/mdev.conf with lines\n" | 82 | //usage: "It uses /etc/mdev.conf with lines\n" |
| 83 | //usage: " [-]DEVNAME UID:GID PERM" | 83 | //usage: " [-][ENV=regex;]...DEVNAME UID:GID PERM" |
| 84 | //usage: IF_FEATURE_MDEV_RENAME(" [>|=PATH]|[!]") | 84 | //usage: IF_FEATURE_MDEV_RENAME(" [>|=PATH]|[!]") |
| 85 | //usage: IF_FEATURE_MDEV_EXEC(" [@|$|*PROG]") | 85 | //usage: IF_FEATURE_MDEV_EXEC(" [@|$|*PROG]") |
| 86 | //usage: "\n" | 86 | //usage: "\n" |
| @@ -233,6 +233,12 @@ | |||
| 233 | static const char keywords[] ALIGN1 = "add\0remove\0change\0"; | 233 | static const char keywords[] ALIGN1 = "add\0remove\0change\0"; |
| 234 | enum { OP_add, OP_remove }; | 234 | enum { OP_add, OP_remove }; |
| 235 | 235 | ||
| 236 | struct envmatch { | ||
| 237 | struct envmatch *next; | ||
| 238 | char *envname; | ||
| 239 | regex_t match; | ||
| 240 | }; | ||
| 241 | |||
| 236 | struct rule { | 242 | struct rule { |
| 237 | bool keep_matching; | 243 | bool keep_matching; |
| 238 | bool regex_compiled; | 244 | bool regex_compiled; |
| @@ -243,6 +249,7 @@ struct rule { | |||
| 243 | char *ren_mov; | 249 | char *ren_mov; |
| 244 | IF_FEATURE_MDEV_EXEC(char *r_cmd;) | 250 | IF_FEATURE_MDEV_EXEC(char *r_cmd;) |
| 245 | regex_t match; | 251 | regex_t match; |
| 252 | struct envmatch *envmatch; | ||
| 246 | }; | 253 | }; |
| 247 | 254 | ||
| 248 | struct globals { | 255 | struct globals { |
| @@ -288,14 +295,48 @@ static void make_default_cur_rule(void) | |||
| 288 | 295 | ||
| 289 | static void clean_up_cur_rule(void) | 296 | static void clean_up_cur_rule(void) |
| 290 | { | 297 | { |
| 298 | struct envmatch *e; | ||
| 299 | |||
| 291 | free(G.cur_rule.envvar); | 300 | free(G.cur_rule.envvar); |
| 301 | free(G.cur_rule.ren_mov); | ||
| 292 | if (G.cur_rule.regex_compiled) | 302 | if (G.cur_rule.regex_compiled) |
| 293 | regfree(&G.cur_rule.match); | 303 | regfree(&G.cur_rule.match); |
| 294 | free(G.cur_rule.ren_mov); | ||
| 295 | IF_FEATURE_MDEV_EXEC(free(G.cur_rule.r_cmd);) | 304 | IF_FEATURE_MDEV_EXEC(free(G.cur_rule.r_cmd);) |
| 305 | e = G.cur_rule.envmatch; | ||
| 306 | while (e) { | ||
| 307 | free(e->envname); | ||
| 308 | regfree(&e->match); | ||
| 309 | e = e->next; | ||
| 310 | } | ||
| 296 | make_default_cur_rule(); | 311 | make_default_cur_rule(); |
| 297 | } | 312 | } |
| 298 | 313 | ||
| 314 | static char *parse_envmatch_pfx(char *val) | ||
| 315 | { | ||
| 316 | struct envmatch **nextp = &G.cur_rule.envmatch; | ||
| 317 | |||
| 318 | for (;;) { | ||
| 319 | struct envmatch *e; | ||
| 320 | char *semicolon; | ||
| 321 | char *eq = strchr(val, '='); | ||
| 322 | if (!eq /* || eq == val? */) | ||
| 323 | return val; | ||
| 324 | if (endofname(val) != eq) | ||
| 325 | return val; | ||
| 326 | semicolon = strchr(eq, ';'); | ||
| 327 | if (!semicolon) | ||
| 328 | return val; | ||
| 329 | /* ENVVAR=regex;... */ | ||
| 330 | *nextp = e = xzalloc(sizeof(*e)); | ||
| 331 | nextp = &e->next; | ||
| 332 | e->envname = xstrndup(val, eq - val); | ||
| 333 | *semicolon = '\0'; | ||
| 334 | xregcomp(&e->match, eq + 1, REG_EXTENDED); | ||
| 335 | *semicolon = ';'; | ||
| 336 | val = semicolon + 1; | ||
| 337 | } | ||
| 338 | } | ||
| 339 | |||
| 299 | static void parse_next_rule(void) | 340 | static void parse_next_rule(void) |
| 300 | { | 341 | { |
| 301 | /* Note: on entry, G.cur_rule is set to default */ | 342 | /* Note: on entry, G.cur_rule is set to default */ |
| @@ -314,6 +355,7 @@ static void parse_next_rule(void) | |||
| 314 | val = tokens[0]; | 355 | val = tokens[0]; |
| 315 | G.cur_rule.keep_matching = ('-' == val[0]); | 356 | G.cur_rule.keep_matching = ('-' == val[0]); |
| 316 | val += G.cur_rule.keep_matching; /* swallow leading dash */ | 357 | val += G.cur_rule.keep_matching; /* swallow leading dash */ |
| 358 | val = parse_envmatch_pfx(val); | ||
| 317 | if (val[0] == '@') { | 359 | if (val[0] == '@') { |
| 318 | /* @major,minor[-minor2] */ | 360 | /* @major,minor[-minor2] */ |
| 319 | /* (useful when name is ambiguous: | 361 | /* (useful when name is ambiguous: |
| @@ -328,8 +370,10 @@ static void parse_next_rule(void) | |||
| 328 | if (sc == 2) | 370 | if (sc == 2) |
| 329 | G.cur_rule.min1 = G.cur_rule.min0; | 371 | G.cur_rule.min1 = G.cur_rule.min0; |
| 330 | } else { | 372 | } else { |
| 373 | char *eq = strchr(val, '='); | ||
| 331 | if (val[0] == '$') { | 374 | if (val[0] == '$') { |
| 332 | char *eq = strchr(++val, '='); | 375 | /* $ENVVAR=regex ... */ |
| 376 | val++; | ||
| 333 | if (!eq) { | 377 | if (!eq) { |
| 334 | bb_error_msg("bad $envvar=regex on line %d", G.parser->lineno); | 378 | bb_error_msg("bad $envvar=regex on line %d", G.parser->lineno); |
| 335 | goto next_rule; | 379 | goto next_rule; |
| @@ -423,6 +467,21 @@ static const struct rule *next_rule(void) | |||
| 423 | return rule; | 467 | return rule; |
| 424 | } | 468 | } |
| 425 | 469 | ||
| 470 | static int env_matches(struct envmatch *e) | ||
| 471 | { | ||
| 472 | while (e) { | ||
| 473 | int r; | ||
| 474 | char *val = getenv(e->envname); | ||
| 475 | if (!val) | ||
| 476 | return 0; | ||
| 477 | r = regexec(&e->match, val, /*size*/ 0, /*range[]*/ NULL, /*eflags*/ 0); | ||
| 478 | if (r != 0) /* no match */ | ||
| 479 | return 0; | ||
| 480 | e = e->next; | ||
| 481 | } | ||
| 482 | return 1; | ||
| 483 | } | ||
| 484 | |||
| 426 | #else | 485 | #else |
| 427 | 486 | ||
| 428 | # define next_rule() (&G.cur_rule) | 487 | # define next_rule() (&G.cur_rule) |
| @@ -537,6 +596,8 @@ static void make_device(char *device_name, char *path, int operation) | |||
| 537 | rule = next_rule(); | 596 | rule = next_rule(); |
| 538 | 597 | ||
| 539 | #if ENABLE_FEATURE_MDEV_CONF | 598 | #if ENABLE_FEATURE_MDEV_CONF |
| 599 | if (!env_matches(rule->envmatch)) | ||
| 600 | continue; | ||
| 540 | if (rule->maj >= 0) { /* @maj,min rule */ | 601 | if (rule->maj >= 0) { /* @maj,min rule */ |
| 541 | if (major != rule->maj) | 602 | if (major != rule->maj) |
| 542 | continue; | 603 | continue; |
| @@ -749,8 +810,10 @@ static int FAST_FUNC dirAction(const char *fileName UNUSED_PARAM, | |||
| 749 | if (1 == depth) { | 810 | if (1 == depth) { |
| 750 | free(G.subsystem); | 811 | free(G.subsystem); |
| 751 | G.subsystem = strrchr(fileName, '/'); | 812 | G.subsystem = strrchr(fileName, '/'); |
| 752 | if (G.subsystem) | 813 | if (G.subsystem) { |
| 753 | G.subsystem = xstrdup(G.subsystem + 1); | 814 | G.subsystem = xstrdup(G.subsystem + 1); |
| 815 | xsetenv("SUBSYSTEM", G.subsystem); | ||
| 816 | } | ||
| 754 | } | 817 | } |
| 755 | 818 | ||
| 756 | return (depth >= MAX_SYSFS_DEPTH ? SKIP : TRUE); | 819 | return (depth >= MAX_SYSFS_DEPTH ? SKIP : TRUE); |
| @@ -843,8 +906,8 @@ int mdev_main(int argc UNUSED_PARAM, char **argv) | |||
| 843 | xchdir("/dev"); | 906 | xchdir("/dev"); |
| 844 | 907 | ||
| 845 | if (argv[1] && strcmp(argv[1], "-s") == 0) { | 908 | if (argv[1] && strcmp(argv[1], "-s") == 0) { |
| 846 | /* Scan: | 909 | /* |
| 847 | * mdev -s | 910 | * Scan: mdev -s |
| 848 | */ | 911 | */ |
| 849 | struct stat st; | 912 | struct stat st; |
| 850 | 913 | ||
| @@ -856,6 +919,8 @@ int mdev_main(int argc UNUSED_PARAM, char **argv) | |||
| 856 | G.root_major = major(st.st_dev); | 919 | G.root_major = major(st.st_dev); |
| 857 | G.root_minor = minor(st.st_dev); | 920 | G.root_minor = minor(st.st_dev); |
| 858 | 921 | ||
| 922 | putenv((char*)"ACTION=add"); | ||
| 923 | |||
| 859 | /* ACTION_FOLLOWLINKS is needed since in newer kernels | 924 | /* ACTION_FOLLOWLINKS is needed since in newer kernels |
| 860 | * /sys/block/loop* (for example) are symlinks to dirs, | 925 | * /sys/block/loop* (for example) are symlinks to dirs, |
| 861 | * not real directories. | 926 | * not real directories. |
