![]() |
|
|||
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);
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.1.0 LXR engine. The LXR team |
![]() ![]() |