Back to home page

OSCL-LXR

 
 

    


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