Back to home page

LXR

 
 

    


0001 /*
0002  * lib/parser.c - simple parser for mount, etc. options.
0003  *
0004  * This source code is licensed under the GNU General Public License,
0005  * Version 2.  See the file COPYING for more details.
0006  */
0007 
0008 #include <linux/ctype.h>
0009 #include <linux/types.h>
0010 #include <linux/export.h>
0011 #include <linux/parser.h>
0012 #include <linux/slab.h>
0013 #include <linux/string.h>
0014 
0015 /**
0016  * match_one: - Determines if a string matches a simple pattern
0017  * @s: the string to examine for presence of the pattern
0018  * @p: the string containing the pattern
0019  * @args: array of %MAX_OPT_ARGS &substring_t elements. Used to return match
0020  * locations.
0021  *
0022  * Description: Determines if the pattern @p is present in string @s. Can only
0023  * match extremely simple token=arg style patterns. If the pattern is found,
0024  * the location(s) of the arguments will be returned in the @args array.
0025  */
0026 static int match_one(char *s, const char *p, substring_t args[])
0027 {
0028     char *meta;
0029     int argc = 0;
0030 
0031     if (!p)
0032         return 1;
0033 
0034     while(1) {
0035         int len = -1;
0036         meta = strchr(p, '%');
0037         if (!meta)
0038             return strcmp(p, s) == 0;
0039 
0040         if (strncmp(p, s, meta-p))
0041             return 0;
0042 
0043         s += meta - p;
0044         p = meta + 1;
0045 
0046         if (isdigit(*p))
0047             len = simple_strtoul(p, (char **) &p, 10);
0048         else if (*p == '%') {
0049             if (*s++ != '%')
0050                 return 0;
0051             p++;
0052             continue;
0053         }
0054 
0055         if (argc >= MAX_OPT_ARGS)
0056             return 0;
0057 
0058         args[argc].from = s;
0059         switch (*p++) {
0060         case 's': {
0061             size_t str_len = strlen(s);
0062 
0063             if (str_len == 0)
0064                 return 0;
0065             if (len == -1 || len > str_len)
0066                 len = str_len;
0067             args[argc].to = s + len;
0068             break;
0069         }
0070         case 'd':
0071             simple_strtol(s, &args[argc].to, 0);
0072             goto num;
0073         case 'u':
0074             simple_strtoul(s, &args[argc].to, 0);
0075             goto num;
0076         case 'o':
0077             simple_strtoul(s, &args[argc].to, 8);
0078             goto num;
0079         case 'x':
0080             simple_strtoul(s, &args[argc].to, 16);
0081         num:
0082             if (args[argc].to == args[argc].from)
0083                 return 0;
0084             break;
0085         default:
0086             return 0;
0087         }
0088         s = args[argc].to;
0089         argc++;
0090     }
0091 }
0092 
0093 /**
0094  * match_token: - Find a token (and optional args) in a string
0095  * @s: the string to examine for token/argument pairs
0096  * @table: match_table_t describing the set of allowed option tokens and the
0097  * arguments that may be associated with them. Must be terminated with a
0098  * &struct match_token whose pattern is set to the NULL pointer.
0099  * @args: array of %MAX_OPT_ARGS &substring_t elements. Used to return match
0100  * locations.
0101  *
0102  * Description: Detects which if any of a set of token strings has been passed
0103  * to it. Tokens can include up to MAX_OPT_ARGS instances of basic c-style
0104  * format identifiers which will be taken into account when matching the
0105  * tokens, and whose locations will be returned in the @args array.
0106  */
0107 int match_token(char *s, const match_table_t table, substring_t args[])
0108 {
0109     const struct match_token *p;
0110 
0111     for (p = table; !match_one(s, p->pattern, args) ; p++)
0112         ;
0113 
0114     return p->token;
0115 }
0116 EXPORT_SYMBOL(match_token);
0117 
0118 /**
0119  * match_number: scan a number in the given base from a substring_t
0120  * @s: substring to be scanned
0121  * @result: resulting integer on success
0122  * @base: base to use when converting string
0123  *
0124  * Description: Given a &substring_t and a base, attempts to parse the substring
0125  * as a number in that base. On success, sets @result to the integer represented
0126  * by the string and returns 0. Returns -ENOMEM, -EINVAL, or -ERANGE on failure.
0127  */
0128 static int match_number(substring_t *s, int *result, int base)
0129 {
0130     char *endp;
0131     char *buf;
0132     int ret;
0133     long val;
0134     size_t len = s->to - s->from;
0135 
0136     buf = kmalloc(len + 1, GFP_KERNEL);
0137     if (!buf)
0138         return -ENOMEM;
0139     memcpy(buf, s->from, len);
0140     buf[len] = '\0';
0141 
0142     ret = 0;
0143     val = simple_strtol(buf, &endp, base);
0144     if (endp == buf)
0145         ret = -EINVAL;
0146     else if (val < (long)INT_MIN || val > (long)INT_MAX)
0147         ret = -ERANGE;
0148     else
0149         *result = (int) val;
0150     kfree(buf);
0151     return ret;
0152 }
0153 
0154 /**
0155  * match_u64int: scan a number in the given base from a substring_t
0156  * @s: substring to be scanned
0157  * @result: resulting u64 on success
0158  * @base: base to use when converting string
0159  *
0160  * Description: Given a &substring_t and a base, attempts to parse the substring
0161  * as a number in that base. On success, sets @result to the integer represented
0162  * by the string and returns 0. Returns -ENOMEM, -EINVAL, or -ERANGE on failure.
0163  */
0164 static int match_u64int(substring_t *s, u64 *result, int base)
0165 {
0166     char *buf;
0167     int ret;
0168     u64 val;
0169     size_t len = s->to - s->from;
0170 
0171     buf = kmalloc(len + 1, GFP_KERNEL);
0172     if (!buf)
0173         return -ENOMEM;
0174     memcpy(buf, s->from, len);
0175     buf[len] = '\0';
0176 
0177     ret = kstrtoull(buf, base, &val);
0178     if (!ret)
0179         *result = val;
0180     kfree(buf);
0181     return ret;
0182 }
0183 
0184 /**
0185  * match_int: - scan a decimal representation of an integer from a substring_t
0186  * @s: substring_t to be scanned
0187  * @result: resulting integer on success
0188  *
0189  * Description: Attempts to parse the &substring_t @s as a decimal integer. On
0190  * success, sets @result to the integer represented by the string and returns 0.
0191  * Returns -ENOMEM, -EINVAL, or -ERANGE on failure.
0192  */
0193 int match_int(substring_t *s, int *result)
0194 {
0195     return match_number(s, result, 0);
0196 }
0197 EXPORT_SYMBOL(match_int);
0198 
0199 /**
0200  * match_u64: - scan a decimal representation of a u64 from
0201  *                  a substring_t
0202  * @s: substring_t to be scanned
0203  * @result: resulting unsigned long long on success
0204  *
0205  * Description: Attempts to parse the &substring_t @s as a long decimal
0206  * integer. On success, sets @result to the integer represented by the
0207  * string and returns 0.
0208  * Returns -ENOMEM, -EINVAL, or -ERANGE on failure.
0209  */
0210 int match_u64(substring_t *s, u64 *result)
0211 {
0212     return match_u64int(s, result, 0);
0213 }
0214 EXPORT_SYMBOL(match_u64);
0215 
0216 /**
0217  * match_octal: - scan an octal representation of an integer from a substring_t
0218  * @s: substring_t to be scanned
0219  * @result: resulting integer on success
0220  *
0221  * Description: Attempts to parse the &substring_t @s as an octal integer. On
0222  * success, sets @result to the integer represented by the string and returns
0223  * 0. Returns -ENOMEM, -EINVAL, or -ERANGE on failure.
0224  */
0225 int match_octal(substring_t *s, int *result)
0226 {
0227     return match_number(s, result, 8);
0228 }
0229 EXPORT_SYMBOL(match_octal);
0230 
0231 /**
0232  * match_hex: - scan a hex representation of an integer from a substring_t
0233  * @s: substring_t to be scanned
0234  * @result: resulting integer on success
0235  *
0236  * Description: Attempts to parse the &substring_t @s as a hexadecimal integer.
0237  * On success, sets @result to the integer represented by the string and
0238  * returns 0. Returns -ENOMEM, -EINVAL, or -ERANGE on failure.
0239  */
0240 int match_hex(substring_t *s, int *result)
0241 {
0242     return match_number(s, result, 16);
0243 }
0244 EXPORT_SYMBOL(match_hex);
0245 
0246 /**
0247  * match_wildcard: - parse if a string matches given wildcard pattern
0248  * @pattern: wildcard pattern
0249  * @str: the string to be parsed
0250  *
0251  * Description: Parse the string @str to check if matches wildcard
0252  * pattern @pattern. The pattern may contain two type wildcardes:
0253  *   '*' - matches zero or more characters
0254  *   '?' - matches one character
0255  * If it's matched, return true, else return false.
0256  */
0257 bool match_wildcard(const char *pattern, const char *str)
0258 {
0259     const char *s = str;
0260     const char *p = pattern;
0261     bool star = false;
0262 
0263     while (*s) {
0264         switch (*p) {
0265         case '?':
0266             s++;
0267             p++;
0268             break;
0269         case '*':
0270             star = true;
0271             str = s;
0272             if (!*++p)
0273                 return true;
0274             pattern = p;
0275             break;
0276         default:
0277             if (*s == *p) {
0278                 s++;
0279                 p++;
0280             } else {
0281                 if (!star)
0282                     return false;
0283                 str++;
0284                 s = str;
0285                 p = pattern;
0286             }
0287             break;
0288         }
0289     }
0290 
0291     if (*p == '*')
0292         ++p;
0293     return !*p;
0294 }
0295 EXPORT_SYMBOL(match_wildcard);
0296 
0297 /**
0298  * match_strlcpy: - Copy the characters from a substring_t to a sized buffer
0299  * @dest: where to copy to
0300  * @src: &substring_t to copy
0301  * @size: size of destination buffer
0302  *
0303  * Description: Copy the characters in &substring_t @src to the
0304  * c-style string @dest.  Copy no more than @size - 1 characters, plus
0305  * the terminating NUL.  Return length of @src.
0306  */
0307 size_t match_strlcpy(char *dest, const substring_t *src, size_t size)
0308 {
0309     size_t ret = src->to - src->from;
0310 
0311     if (size) {
0312         size_t len = ret >= size ? size - 1 : ret;
0313         memcpy(dest, src->from, len);
0314         dest[len] = '\0';
0315     }
0316     return ret;
0317 }
0318 EXPORT_SYMBOL(match_strlcpy);
0319 
0320 /**
0321  * match_strdup: - allocate a new string with the contents of a substring_t
0322  * @s: &substring_t to copy
0323  *
0324  * Description: Allocates and returns a string filled with the contents of
0325  * the &substring_t @s. The caller is responsible for freeing the returned
0326  * string with kfree().
0327  */
0328 char *match_strdup(const substring_t *s)
0329 {
0330     size_t sz = s->to - s->from + 1;
0331     char *p = kmalloc(sz, GFP_KERNEL);
0332     if (p)
0333         match_strlcpy(p, s, sz);
0334     return p;
0335 }
0336 EXPORT_SYMBOL(match_strdup);