From 5221f633a04ed0edf7edc10c07d0e5934abc038c Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 1 Oct 2003 10:58:08 -0700 Subject: [PATCH] table-driven filesystems option parsing From: "Randy.Dunlap" , Will Dyson , me Add generic filesystem options parser (infrastructure) and use it to parse mount options in several filesystems (adfs, affs, autofs, autofs4, ext2, ext3, fat, hfs, hpfs, isofs, jfs, procfs, udf, and ufs). It saves between 128 and 512 bytes per filesystem. --- lib/parser.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 lib/parser.c (limited to 'lib/parser.c') diff --git a/lib/parser.c b/lib/parser.c new file mode 100644 index 000000000000..858061397fe2 --- /dev/null +++ b/lib/parser.c @@ -0,0 +1,138 @@ +/* + * lib/parser.c - simple parser for mount, etc. options. + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ + +#include +#include +#include +#include +#include + +static int match_one(char *s, char *p, substring_t args[]) +{ + char *meta; + int argc = 0; + + if (!p) + return 1; + + while(1) { + int len = -1; + meta = strchr(p, '%'); + if (!meta) + return strcmp(p, s) == 0; + + if (strncmp(p, s, meta-p)) + return 0; + + s += meta - p; + p = meta + 1; + + if (isdigit(*p)) + len = simple_strtoul(p, &p, 10); + else if (*p == '%') { + if (*s++ != '%') + return 0; + continue; + } + + if (argc >= MAX_OPT_ARGS) + return 0; + + args[argc].from = s; + switch (*p++) { + case 's': + if (len == -1 || len > strlen(s)) + len = strlen(s); + args[argc].to = s + len; + break; + case 'd': + simple_strtol(s, &args[argc].to, 0); + goto num; + case 'u': + simple_strtoul(s, &args[argc].to, 0); + goto num; + case 'o': + simple_strtoul(s, &args[argc].to, 8); + goto num; + case 'x': + simple_strtoul(s, &args[argc].to, 16); + num: + if (args[argc].to == args[argc].from) + return 0; + break; + default: + return 0; + } + s = args[argc].to; + argc++; + } +} + +int match_token(char *s, match_table_t table, substring_t args[]) +{ + struct match_token *p; + + for (p = table; !match_one(s, p->pattern, args) ; p++) + ; + + return p->token; +} + +static int match_number(substring_t *s, int *result, int base) +{ + char *endp; + char *buf; + int ret; + + buf = kmalloc(s->to - s->from + 1, GFP_KERNEL); + if (!buf) + return -ENOMEM; + memcpy(buf, s->from, s->to - s->from); + buf[s->to - s->from] = '\0'; + *result = simple_strtol(buf, &endp, base); + ret = 0; + if (endp == buf) + ret = -EINVAL; + kfree(buf); + return ret; +} + +int match_int(substring_t *s, int *result) +{ + return match_number(s, result, 0); +} + +int match_octal(substring_t *s, int *result) +{ + return match_number(s, result, 8); +} + +int match_hex(substring_t *s, int *result) +{ + return match_number(s, result, 16); +} + +void match_strcpy(char *to, substring_t *s) +{ + memcpy(to, s->from, s->to - s->from); + to[s->to - s->from] = '\0'; +} + +char *match_strdup(substring_t *s) +{ + char *p = kmalloc(s->to - s->from + 1, GFP_KERNEL); + if (p) + match_strcpy(p, s); + return p; +} + +EXPORT_SYMBOL(match_token); +EXPORT_SYMBOL(match_int); +EXPORT_SYMBOL(match_octal); +EXPORT_SYMBOL(match_hex); +EXPORT_SYMBOL(match_strcpy); +EXPORT_SYMBOL(match_strdup); -- cgit v1.2.3