40b0b3f8fb2d8 (Thomas Gleixner 2019-06-03 07:44:46 +0200 1) // SPDX-License-Identifier: GPL-2.0-only
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 3) * lib/parser.c - simple parser for mount, etc. options.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 4) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 5)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 6) #include <linux/ctype.h>
8bc3bcc93a2b4 (Paul Gortmaker 2011-11-16 21:29:17 -0500 7) #include <linux/types.h>
8bc3bcc93a2b4 (Paul Gortmaker 2011-11-16 21:29:17 -0500 8) #include <linux/export.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 9) #include <linux/parser.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 10) #include <linux/slab.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 11) #include <linux/string.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 12)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 13) /**
b9bffa10b267b (BingJing Chang 2021-01-29 13:00:37 +0800 14) * match_one - Determines if a string matches a simple pattern
25985edcedea6 (Lucas De Marchi 2011-03-30 22:57:33 -0300 15) * @s: the string to examine for presence of the pattern
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 16) * @p: the string containing the pattern
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 17) * @args: array of %MAX_OPT_ARGS &substring_t elements. Used to return match
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 18) * locations.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 19) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 20) * Description: Determines if the pattern @p is present in string @s. Can only
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 21) * match extremely simple token=arg style patterns. If the pattern is found,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 22) * the location(s) of the arguments will be returned in the @args array.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 23) */
ef4533f8af7a8 (David Howells 2007-05-03 03:10:39 -0700 24) static int match_one(char *s, const char *p, substring_t args[])
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 25) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 26) char *meta;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 27) int argc = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 28)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 29) if (!p)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 30) return 1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 31)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 32) while(1) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 33) int len = -1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 34) meta = strchr(p, '%');
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 35) if (!meta)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 36) return strcmp(p, s) == 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 37)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 38) if (strncmp(p, s, meta-p))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 39) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 40)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 41) s += meta - p;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 42) p = meta + 1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 43)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 44) if (isdigit(*p))
ef4533f8af7a8 (David Howells 2007-05-03 03:10:39 -0700 45) len = simple_strtoul(p, (char **) &p, 10);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 46) else if (*p == '%') {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 47) if (*s++ != '%')
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 48) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 49) p++;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 50) continue;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 51) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 52)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 53) if (argc >= MAX_OPT_ARGS)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 54) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 55)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 56) args[argc].from = s;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 57) switch (*p++) {
b5f54b07c06f6 (André Goddard Rosa 2009-12-14 18:01:08 -0800 58) case 's': {
b5f54b07c06f6 (André Goddard Rosa 2009-12-14 18:01:08 -0800 59) size_t str_len = strlen(s);
b5f54b07c06f6 (André Goddard Rosa 2009-12-14 18:01:08 -0800 60)
b5f54b07c06f6 (André Goddard Rosa 2009-12-14 18:01:08 -0800 61) if (str_len == 0)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 62) return 0;
b5f54b07c06f6 (André Goddard Rosa 2009-12-14 18:01:08 -0800 63) if (len == -1 || len > str_len)
b5f54b07c06f6 (André Goddard Rosa 2009-12-14 18:01:08 -0800 64) len = str_len;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 65) args[argc].to = s + len;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 66) break;
b5f54b07c06f6 (André Goddard Rosa 2009-12-14 18:01:08 -0800 67) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 68) case 'd':
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 69) simple_strtol(s, &args[argc].to, 0);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 70) goto num;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 71) case 'u':
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 72) simple_strtoul(s, &args[argc].to, 0);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 73) goto num;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 74) case 'o':
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 75) simple_strtoul(s, &args[argc].to, 8);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 76) goto num;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 77) case 'x':
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 78) simple_strtoul(s, &args[argc].to, 16);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 79) num:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 80) if (args[argc].to == args[argc].from)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 81) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 82) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 83) default:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 84) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 85) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 86) s = args[argc].to;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 87) argc++;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 88) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 89) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 90)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 91) /**
b9bffa10b267b (BingJing Chang 2021-01-29 13:00:37 +0800 92) * match_token - Find a token (and optional args) in a string
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 93) * @s: the string to examine for token/argument pairs
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 94) * @table: match_table_t describing the set of allowed option tokens and the
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 95) * arguments that may be associated with them. Must be terminated with a
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 96) * &struct match_token whose pattern is set to the NULL pointer.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 97) * @args: array of %MAX_OPT_ARGS &substring_t elements. Used to return match
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 98) * locations.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 99) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 100) * Description: Detects which if any of a set of token strings has been passed
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 101) * to it. Tokens can include up to %MAX_OPT_ARGS instances of basic c-style
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 102) * format identifiers which will be taken into account when matching the
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 103) * tokens, and whose locations will be returned in the @args array.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 104) */
a447c0932445f (Steven Whitehouse 2008-10-13 10:46:57 +0100 105) int match_token(char *s, const match_table_t table, substring_t args[])
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 106) {
ef4533f8af7a8 (David Howells 2007-05-03 03:10:39 -0700 107) const struct match_token *p;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 108)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 109) for (p = table; !match_one(s, p->pattern, args) ; p++)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 110) ;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 111)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 112) return p->token;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 113) }
a3d2cca43cd31 (Andrew Morton 2014-01-23 15:54:13 -0800 114) EXPORT_SYMBOL(match_token);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 115)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 116) /**
b9bffa10b267b (BingJing Chang 2021-01-29 13:00:37 +0800 117) * match_number - scan a number in the given base from a substring_t
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 118) * @s: substring to be scanned
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 119) * @result: resulting integer on success
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 120) * @base: base to use when converting string
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 121) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 122) * Description: Given a &substring_t and a base, attempts to parse the substring
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 123) * as a number in that base.
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 124) *
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 125) * Return: On success, sets @result to the integer represented by the
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 126) * string and returns 0. Returns -ENOMEM, -EINVAL, or -ERANGE on failure.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 127) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 128) static int match_number(substring_t *s, int *result, int base)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 129) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 130) char *endp;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 131) char *buf;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 132) int ret;
77dd3b0bd17a0 (Alex Elder 2012-10-04 17:13:16 -0700 133) long val;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 134)
36c8d1e7a27f9 (Eric Biggers 2018-10-30 15:05:30 -0700 135) buf = match_strdup(s);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 136) if (!buf)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 137) return -ENOMEM;
77dd3b0bd17a0 (Alex Elder 2012-10-04 17:13:16 -0700 138)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 139) ret = 0;
77dd3b0bd17a0 (Alex Elder 2012-10-04 17:13:16 -0700 140) val = simple_strtol(buf, &endp, base);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 141) if (endp == buf)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 142) ret = -EINVAL;
77dd3b0bd17a0 (Alex Elder 2012-10-04 17:13:16 -0700 143) else if (val < (long)INT_MIN || val > (long)INT_MAX)
77dd3b0bd17a0 (Alex Elder 2012-10-04 17:13:16 -0700 144) ret = -ERANGE;
77dd3b0bd17a0 (Alex Elder 2012-10-04 17:13:16 -0700 145) else
77dd3b0bd17a0 (Alex Elder 2012-10-04 17:13:16 -0700 146) *result = (int) val;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 147) kfree(buf);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 148) return ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 149) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 150)
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 151) /**
b9bffa10b267b (BingJing Chang 2021-01-29 13:00:37 +0800 152) * match_u64int - scan a number in the given base from a substring_t
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 153) * @s: substring to be scanned
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 154) * @result: resulting u64 on success
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 155) * @base: base to use when converting string
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 156) *
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 157) * Description: Given a &substring_t and a base, attempts to parse the substring
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 158) * as a number in that base.
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 159) *
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 160) * Return: On success, sets @result to the integer represented by the
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 161) * string and returns 0. Returns -ENOMEM, -EINVAL, or -ERANGE on failure.
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 162) */
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 163) static int match_u64int(substring_t *s, u64 *result, int base)
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 164) {
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 165) char *buf;
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 166) int ret;
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 167) u64 val;
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 168)
4ed97b3c6d088 (Eric Biggers 2018-10-30 15:05:26 -0700 169) buf = match_strdup(s);
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 170) if (!buf)
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 171) return -ENOMEM;
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 172)
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 173) ret = kstrtoull(buf, base, &val);
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 174) if (!ret)
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 175) *result = val;
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 176) kfree(buf);
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 177) return ret;
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 178) }
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 179)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 180) /**
b9bffa10b267b (BingJing Chang 2021-01-29 13:00:37 +0800 181) * match_int - scan a decimal representation of an integer from a substring_t
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 182) * @s: substring_t to be scanned
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 183) * @result: resulting integer on success
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 184) *
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 185) * Description: Attempts to parse the &substring_t @s as a decimal integer.
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 186) *
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 187) * Return: On success, sets @result to the integer represented by the string
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 188) * and returns 0. Returns -ENOMEM, -EINVAL, or -ERANGE on failure.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 189) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 190) int match_int(substring_t *s, int *result)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 191) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 192) return match_number(s, result, 0);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 193) }
a3d2cca43cd31 (Andrew Morton 2014-01-23 15:54:13 -0800 194) EXPORT_SYMBOL(match_int);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 195)
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 196) /**
01531ac354051 (BingJing Chang 2021-01-29 12:52:42 +0800 197) * match_uint - scan a decimal representation of an integer from a substring_t
01531ac354051 (BingJing Chang 2021-01-29 12:52:42 +0800 198) * @s: substring_t to be scanned
01531ac354051 (BingJing Chang 2021-01-29 12:52:42 +0800 199) * @result: resulting integer on success
01531ac354051 (BingJing Chang 2021-01-29 12:52:42 +0800 200) *
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 201) * Description: Attempts to parse the &substring_t @s as a decimal integer.
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 202) *
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 203) * Return: On success, sets @result to the integer represented by the string
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 204) * and returns 0. Returns -ENOMEM, -EINVAL, or -ERANGE on failure.
01531ac354051 (BingJing Chang 2021-01-29 12:52:42 +0800 205) */
01531ac354051 (BingJing Chang 2021-01-29 12:52:42 +0800 206) int match_uint(substring_t *s, unsigned int *result)
01531ac354051 (BingJing Chang 2021-01-29 12:52:42 +0800 207) {
01531ac354051 (BingJing Chang 2021-01-29 12:52:42 +0800 208) int err = -ENOMEM;
01531ac354051 (BingJing Chang 2021-01-29 12:52:42 +0800 209) char *buf = match_strdup(s);
01531ac354051 (BingJing Chang 2021-01-29 12:52:42 +0800 210)
01531ac354051 (BingJing Chang 2021-01-29 12:52:42 +0800 211) if (buf) {
01531ac354051 (BingJing Chang 2021-01-29 12:52:42 +0800 212) err = kstrtouint(buf, 10, result);
01531ac354051 (BingJing Chang 2021-01-29 12:52:42 +0800 213) kfree(buf);
01531ac354051 (BingJing Chang 2021-01-29 12:52:42 +0800 214) }
01531ac354051 (BingJing Chang 2021-01-29 12:52:42 +0800 215) return err;
01531ac354051 (BingJing Chang 2021-01-29 12:52:42 +0800 216) }
01531ac354051 (BingJing Chang 2021-01-29 12:52:42 +0800 217) EXPORT_SYMBOL(match_uint);
01531ac354051 (BingJing Chang 2021-01-29 12:52:42 +0800 218)
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 219) /**
b9bffa10b267b (BingJing Chang 2021-01-29 13:00:37 +0800 220) * match_u64 - scan a decimal representation of a u64 from
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 221) * a substring_t
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 222) * @s: substring_t to be scanned
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 223) * @result: resulting unsigned long long on success
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 224) *
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 225) * Description: Attempts to parse the &substring_t @s as a long decimal
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 226) * integer.
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 227) *
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 228) * Return: On success, sets @result to the integer represented by the string
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 229) * and returns 0. Returns -ENOMEM, -EINVAL, or -ERANGE on failure.
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 230) */
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 231) int match_u64(substring_t *s, u64 *result)
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 232) {
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 233) return match_u64int(s, result, 0);
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 234) }
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 235) EXPORT_SYMBOL(match_u64);
a317178e36b52 (James Smart 2016-10-21 23:51:54 +0300 236)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 237) /**
b9bffa10b267b (BingJing Chang 2021-01-29 13:00:37 +0800 238) * match_octal - scan an octal representation of an integer from a substring_t
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 239) * @s: substring_t to be scanned
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 240) * @result: resulting integer on success
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 241) *
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 242) * Description: Attempts to parse the &substring_t @s as an octal integer.
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 243) *
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 244) * Return: On success, sets @result to the integer represented by the string
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 245) * and returns 0. Returns -ENOMEM, -EINVAL, or -ERANGE on failure.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 246) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 247) int match_octal(substring_t *s, int *result)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 248) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 249) return match_number(s, result, 8);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 250) }
a3d2cca43cd31 (Andrew Morton 2014-01-23 15:54:13 -0800 251) EXPORT_SYMBOL(match_octal);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 252)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 253) /**
b9bffa10b267b (BingJing Chang 2021-01-29 13:00:37 +0800 254) * match_hex - scan a hex representation of an integer from a substring_t
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 255) * @s: substring_t to be scanned
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 256) * @result: resulting integer on success
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 257) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 258) * Description: Attempts to parse the &substring_t @s as a hexadecimal integer.
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 259) *
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 260) * Return: On success, sets @result to the integer represented by the string
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 261) * and returns 0. Returns -ENOMEM, -EINVAL, or -ERANGE on failure.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 262) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 263) int match_hex(substring_t *s, int *result)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 264) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 265) return match_number(s, result, 16);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 266) }
a3d2cca43cd31 (Andrew Morton 2014-01-23 15:54:13 -0800 267) EXPORT_SYMBOL(match_hex);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 268)
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 269) /**
b9bffa10b267b (BingJing Chang 2021-01-29 13:00:37 +0800 270) * match_wildcard - parse if a string matches given wildcard pattern
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 271) * @pattern: wildcard pattern
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 272) * @str: the string to be parsed
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 273) *
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 274) * Description: Parse the string @str to check if matches wildcard
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 275) * pattern @pattern. The pattern may contain two types of wildcards:
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 276) * '*' - matches zero or more characters
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 277) * '?' - matches one character
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 278) *
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 279) * Return: If the @str matches the @pattern, return true, else return false.
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 280) */
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 281) bool match_wildcard(const char *pattern, const char *str)
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 282) {
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 283) const char *s = str;
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 284) const char *p = pattern;
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 285) bool star = false;
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 286)
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 287) while (*s) {
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 288) switch (*p) {
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 289) case '?':
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 290) s++;
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 291) p++;
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 292) break;
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 293) case '*':
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 294) star = true;
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 295) str = s;
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 296) if (!*++p)
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 297) return true;
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 298) pattern = p;
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 299) break;
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 300) default:
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 301) if (*s == *p) {
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 302) s++;
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 303) p++;
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 304) } else {
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 305) if (!star)
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 306) return false;
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 307) str++;
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 308) s = str;
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 309) p = pattern;
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 310) }
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 311) break;
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 312) }
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 313) }
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 314)
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 315) if (*p == '*')
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 316) ++p;
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 317) return !*p;
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 318) }
a3d2cca43cd31 (Andrew Morton 2014-01-23 15:54:13 -0800 319) EXPORT_SYMBOL(match_wildcard);
aace05097a0fd (Changbin Du 2014-01-23 15:54:12 -0800 320)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 321) /**
b9bffa10b267b (BingJing Chang 2021-01-29 13:00:37 +0800 322) * match_strlcpy - Copy the characters from a substring_t to a sized buffer
b32a09db4fb9a (Markus Armbruster 2008-02-26 09:57:11 -0600 323) * @dest: where to copy to
b32a09db4fb9a (Markus Armbruster 2008-02-26 09:57:11 -0600 324) * @src: &substring_t to copy
b32a09db4fb9a (Markus Armbruster 2008-02-26 09:57:11 -0600 325) * @size: size of destination buffer
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 326) *
b32a09db4fb9a (Markus Armbruster 2008-02-26 09:57:11 -0600 327) * Description: Copy the characters in &substring_t @src to the
b32a09db4fb9a (Markus Armbruster 2008-02-26 09:57:11 -0600 328) * c-style string @dest. Copy no more than @size - 1 characters, plus
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 329) * the terminating NUL.
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 330) *
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 331) * Return: length of @src.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 332) */
b32a09db4fb9a (Markus Armbruster 2008-02-26 09:57:11 -0600 333) size_t match_strlcpy(char *dest, const substring_t *src, size_t size)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 334) {
b32a09db4fb9a (Markus Armbruster 2008-02-26 09:57:11 -0600 335) size_t ret = src->to - src->from;
b32a09db4fb9a (Markus Armbruster 2008-02-26 09:57:11 -0600 336)
b32a09db4fb9a (Markus Armbruster 2008-02-26 09:57:11 -0600 337) if (size) {
b32a09db4fb9a (Markus Armbruster 2008-02-26 09:57:11 -0600 338) size_t len = ret >= size ? size - 1 : ret;
b32a09db4fb9a (Markus Armbruster 2008-02-26 09:57:11 -0600 339) memcpy(dest, src->from, len);
b32a09db4fb9a (Markus Armbruster 2008-02-26 09:57:11 -0600 340) dest[len] = '\0';
b32a09db4fb9a (Markus Armbruster 2008-02-26 09:57:11 -0600 341) }
b32a09db4fb9a (Markus Armbruster 2008-02-26 09:57:11 -0600 342) return ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 343) }
a3d2cca43cd31 (Andrew Morton 2014-01-23 15:54:13 -0800 344) EXPORT_SYMBOL(match_strlcpy);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 345)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 346) /**
b9bffa10b267b (BingJing Chang 2021-01-29 13:00:37 +0800 347) * match_strdup - allocate a new string with the contents of a substring_t
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 348) * @s: &substring_t to copy
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 349) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 350) * Description: Allocates and returns a string filled with the contents of
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 351) * the &substring_t @s. The caller is responsible for freeing the returned
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 352) * string with kfree().
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 353) *
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 354) * Return: the address of the newly allocated NUL-terminated string or
edd9334c8dfed (Randy Dunlap 2021-05-06 18:03:49 -0700 355) * %NULL on error.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 356) */
ef4533f8af7a8 (David Howells 2007-05-03 03:10:39 -0700 357) char *match_strdup(const substring_t *s)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 358) {
30f7bc99a2a97 (Eric Biggers 2018-10-30 15:05:22 -0700 359) return kmemdup_nul(s->from, s->to - s->from, GFP_KERNEL);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 360) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 361) EXPORT_SYMBOL(match_strdup);