xref: /openbmc/linux/lib/kstrtox.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
233ee3b2eSAlexey Dobriyan /*
333ee3b2eSAlexey Dobriyan  * Convert integer string representation to an integer.
433ee3b2eSAlexey Dobriyan  * If an integer doesn't fit into specified type, -E is returned.
533ee3b2eSAlexey Dobriyan  *
633ee3b2eSAlexey Dobriyan  * Integer starts with optional sign.
733ee3b2eSAlexey Dobriyan  * kstrtou*() functions do not accept sign "-".
833ee3b2eSAlexey Dobriyan  *
933ee3b2eSAlexey Dobriyan  * Radix 0 means autodetection: leading "0x" implies radix 16,
1033ee3b2eSAlexey Dobriyan  * leading "0" implies radix 8, otherwise radix is 10.
1133ee3b2eSAlexey Dobriyan  * Autodetection hints work after optional sign, but not before.
1233ee3b2eSAlexey Dobriyan  *
1333ee3b2eSAlexey Dobriyan  * If -E is returned, result is not touched.
1433ee3b2eSAlexey Dobriyan  */
1533ee3b2eSAlexey Dobriyan #include <linux/ctype.h>
1633ee3b2eSAlexey Dobriyan #include <linux/errno.h>
178bc3bcc9SPaul Gortmaker #include <linux/export.h>
184c527293SAndy Shevchenko #include <linux/kstrtox.h>
194c527293SAndy Shevchenko #include <linux/math64.h>
2033ee3b2eSAlexey Dobriyan #include <linux/types.h>
217c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
224c527293SAndy Shevchenko 
231dff46d6SAlexey Dobriyan #include "kstrtox.h"
2433ee3b2eSAlexey Dobriyan 
2570ac6992SAlexey Dobriyan noinline
_parse_integer_fixup_radix(const char * s,unsigned int * base)261dff46d6SAlexey Dobriyan const char *_parse_integer_fixup_radix(const char *s, unsigned int *base)
2733ee3b2eSAlexey Dobriyan {
281dff46d6SAlexey Dobriyan 	if (*base == 0) {
2933ee3b2eSAlexey Dobriyan 		if (s[0] == '0') {
3033ee3b2eSAlexey Dobriyan 			if (_tolower(s[1]) == 'x' && isxdigit(s[2]))
311dff46d6SAlexey Dobriyan 				*base = 16;
3233ee3b2eSAlexey Dobriyan 			else
331dff46d6SAlexey Dobriyan 				*base = 8;
3433ee3b2eSAlexey Dobriyan 		} else
351dff46d6SAlexey Dobriyan 			*base = 10;
3633ee3b2eSAlexey Dobriyan 	}
371dff46d6SAlexey Dobriyan 	if (*base == 16 && s[0] == '0' && _tolower(s[1]) == 'x')
3833ee3b2eSAlexey Dobriyan 		s += 2;
391dff46d6SAlexey Dobriyan 	return s;
401dff46d6SAlexey Dobriyan }
4133ee3b2eSAlexey Dobriyan 
421dff46d6SAlexey Dobriyan /*
431dff46d6SAlexey Dobriyan  * Convert non-negative integer string representation in explicitly given radix
44900fdc45SRichard Fitzgerald  * to an integer. A maximum of max_chars characters will be converted.
45900fdc45SRichard Fitzgerald  *
461dff46d6SAlexey Dobriyan  * Return number of characters consumed maybe or-ed with overflow bit.
471dff46d6SAlexey Dobriyan  * If overflow occurs, result integer (incorrect) is still returned.
481dff46d6SAlexey Dobriyan  *
491dff46d6SAlexey Dobriyan  * Don't you dare use this function.
501dff46d6SAlexey Dobriyan  */
5170ac6992SAlexey Dobriyan noinline
_parse_integer_limit(const char * s,unsigned int base,unsigned long long * p,size_t max_chars)52900fdc45SRichard Fitzgerald unsigned int _parse_integer_limit(const char *s, unsigned int base, unsigned long long *p,
53900fdc45SRichard Fitzgerald 				  size_t max_chars)
541dff46d6SAlexey Dobriyan {
55690d137fSDavid Howells 	unsigned long long res;
561dff46d6SAlexey Dobriyan 	unsigned int rv;
571dff46d6SAlexey Dobriyan 
58690d137fSDavid Howells 	res = 0;
591dff46d6SAlexey Dobriyan 	rv = 0;
60900fdc45SRichard Fitzgerald 	while (max_chars--) {
61be5f3c77SAlexey Dobriyan 		unsigned int c = *s;
62*3d0b7139SAndy Shevchenko 		unsigned int lc = _tolower(c);
6333ee3b2eSAlexey Dobriyan 		unsigned int val;
6433ee3b2eSAlexey Dobriyan 
65be5f3c77SAlexey Dobriyan 		if ('0' <= c && c <= '9')
66be5f3c77SAlexey Dobriyan 			val = c - '0';
67be5f3c77SAlexey Dobriyan 		else if ('a' <= lc && lc <= 'f')
68be5f3c77SAlexey Dobriyan 			val = lc - 'a' + 10;
6933ee3b2eSAlexey Dobriyan 		else
701dff46d6SAlexey Dobriyan 			break;
7133ee3b2eSAlexey Dobriyan 
7233ee3b2eSAlexey Dobriyan 		if (val >= base)
731dff46d6SAlexey Dobriyan 			break;
74690d137fSDavid Howells 		/*
75690d137fSDavid Howells 		 * Check for overflow only if we are within range of
76690d137fSDavid Howells 		 * it in the max base we support (16)
77690d137fSDavid Howells 		 */
78690d137fSDavid Howells 		if (unlikely(res & (~0ull << 60))) {
79690d137fSDavid Howells 			if (res > div_u64(ULLONG_MAX - val, base))
808cfd56d4SAlexey Dobriyan 				rv |= KSTRTOX_OVERFLOW;
81690d137fSDavid Howells 		}
82690d137fSDavid Howells 		res = res * base + val;
831dff46d6SAlexey Dobriyan 		rv++;
8433ee3b2eSAlexey Dobriyan 		s++;
8533ee3b2eSAlexey Dobriyan 	}
86690d137fSDavid Howells 	*p = res;
871dff46d6SAlexey Dobriyan 	return rv;
881dff46d6SAlexey Dobriyan }
891dff46d6SAlexey Dobriyan 
9070ac6992SAlexey Dobriyan noinline
_parse_integer(const char * s,unsigned int base,unsigned long long * p)91900fdc45SRichard Fitzgerald unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *p)
92900fdc45SRichard Fitzgerald {
93900fdc45SRichard Fitzgerald 	return _parse_integer_limit(s, base, p, INT_MAX);
94900fdc45SRichard Fitzgerald }
95900fdc45SRichard Fitzgerald 
_kstrtoull(const char * s,unsigned int base,unsigned long long * res)961dff46d6SAlexey Dobriyan static int _kstrtoull(const char *s, unsigned int base, unsigned long long *res)
971dff46d6SAlexey Dobriyan {
981dff46d6SAlexey Dobriyan 	unsigned long long _res;
991dff46d6SAlexey Dobriyan 	unsigned int rv;
1001dff46d6SAlexey Dobriyan 
1011dff46d6SAlexey Dobriyan 	s = _parse_integer_fixup_radix(s, &base);
1021dff46d6SAlexey Dobriyan 	rv = _parse_integer(s, base, &_res);
1031dff46d6SAlexey Dobriyan 	if (rv & KSTRTOX_OVERFLOW)
1041dff46d6SAlexey Dobriyan 		return -ERANGE;
1051dff46d6SAlexey Dobriyan 	if (rv == 0)
10633ee3b2eSAlexey Dobriyan 		return -EINVAL;
1071dff46d6SAlexey Dobriyan 	s += rv;
1081dff46d6SAlexey Dobriyan 	if (*s == '\n')
1091dff46d6SAlexey Dobriyan 		s++;
1101dff46d6SAlexey Dobriyan 	if (*s)
1111dff46d6SAlexey Dobriyan 		return -EINVAL;
1121dff46d6SAlexey Dobriyan 	*res = _res;
11333ee3b2eSAlexey Dobriyan 	return 0;
11433ee3b2eSAlexey Dobriyan }
11533ee3b2eSAlexey Dobriyan 
1164c925d60SEldad Zack /**
1174c925d60SEldad Zack  * kstrtoull - convert a string to an unsigned long long
1184c925d60SEldad Zack  * @s: The start of the string. The string must be null-terminated, and may also
1194c925d60SEldad Zack  *  include a single newline before its terminating null. The first character
1204c925d60SEldad Zack  *  may also be a plus sign, but not a minus sign.
1214c925d60SEldad Zack  * @base: The number base to use. The maximum supported base is 16. If base is
1224c925d60SEldad Zack  *  given as 0, then the base of the string is automatically detected with the
1234c925d60SEldad Zack  *  conventional semantics - If it begins with 0x the number will be parsed as a
1244c925d60SEldad Zack  *  hexadecimal (case insensitive), if it otherwise begins with 0, it will be
1254c925d60SEldad Zack  *  parsed as an octal number. Otherwise it will be parsed as a decimal.
1264c925d60SEldad Zack  * @res: Where to write the result of the conversion on success.
1274c925d60SEldad Zack  *
1284c925d60SEldad Zack  * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
129ef0f2685SKars Mulder  * Preferred over simple_strtoull(). Return code must be checked.
1304c925d60SEldad Zack  */
13170ac6992SAlexey Dobriyan noinline
kstrtoull(const char * s,unsigned int base,unsigned long long * res)13233ee3b2eSAlexey Dobriyan int kstrtoull(const char *s, unsigned int base, unsigned long long *res)
13333ee3b2eSAlexey Dobriyan {
13433ee3b2eSAlexey Dobriyan 	if (s[0] == '+')
13533ee3b2eSAlexey Dobriyan 		s++;
13633ee3b2eSAlexey Dobriyan 	return _kstrtoull(s, base, res);
13733ee3b2eSAlexey Dobriyan }
13833ee3b2eSAlexey Dobriyan EXPORT_SYMBOL(kstrtoull);
13933ee3b2eSAlexey Dobriyan 
1404c925d60SEldad Zack /**
1414c925d60SEldad Zack  * kstrtoll - convert a string to a long long
1424c925d60SEldad Zack  * @s: The start of the string. The string must be null-terminated, and may also
1434c925d60SEldad Zack  *  include a single newline before its terminating null. The first character
1444c925d60SEldad Zack  *  may also be a plus sign or a minus sign.
1454c925d60SEldad Zack  * @base: The number base to use. The maximum supported base is 16. If base is
1464c925d60SEldad Zack  *  given as 0, then the base of the string is automatically detected with the
1474c925d60SEldad Zack  *  conventional semantics - If it begins with 0x the number will be parsed as a
1484c925d60SEldad Zack  *  hexadecimal (case insensitive), if it otherwise begins with 0, it will be
1494c925d60SEldad Zack  *  parsed as an octal number. Otherwise it will be parsed as a decimal.
1504c925d60SEldad Zack  * @res: Where to write the result of the conversion on success.
1514c925d60SEldad Zack  *
1524c925d60SEldad Zack  * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
153ef0f2685SKars Mulder  * Preferred over simple_strtoll(). Return code must be checked.
1544c925d60SEldad Zack  */
15570ac6992SAlexey Dobriyan noinline
kstrtoll(const char * s,unsigned int base,long long * res)15633ee3b2eSAlexey Dobriyan int kstrtoll(const char *s, unsigned int base, long long *res)
15733ee3b2eSAlexey Dobriyan {
15833ee3b2eSAlexey Dobriyan 	unsigned long long tmp;
15933ee3b2eSAlexey Dobriyan 	int rv;
16033ee3b2eSAlexey Dobriyan 
16133ee3b2eSAlexey Dobriyan 	if (s[0] == '-') {
16233ee3b2eSAlexey Dobriyan 		rv = _kstrtoull(s + 1, base, &tmp);
16333ee3b2eSAlexey Dobriyan 		if (rv < 0)
16433ee3b2eSAlexey Dobriyan 			return rv;
1652d2e4715SAlexey Dobriyan 		if ((long long)-tmp > 0)
16633ee3b2eSAlexey Dobriyan 			return -ERANGE;
16733ee3b2eSAlexey Dobriyan 		*res = -tmp;
16833ee3b2eSAlexey Dobriyan 	} else {
16933ee3b2eSAlexey Dobriyan 		rv = kstrtoull(s, base, &tmp);
17033ee3b2eSAlexey Dobriyan 		if (rv < 0)
17133ee3b2eSAlexey Dobriyan 			return rv;
17233ee3b2eSAlexey Dobriyan 		if ((long long)tmp < 0)
17333ee3b2eSAlexey Dobriyan 			return -ERANGE;
17433ee3b2eSAlexey Dobriyan 		*res = tmp;
17533ee3b2eSAlexey Dobriyan 	}
17633ee3b2eSAlexey Dobriyan 	return 0;
17733ee3b2eSAlexey Dobriyan }
17833ee3b2eSAlexey Dobriyan EXPORT_SYMBOL(kstrtoll);
17933ee3b2eSAlexey Dobriyan 
18033ee3b2eSAlexey Dobriyan /* Internal, do not use. */
_kstrtoul(const char * s,unsigned int base,unsigned long * res)18133ee3b2eSAlexey Dobriyan int _kstrtoul(const char *s, unsigned int base, unsigned long *res)
18233ee3b2eSAlexey Dobriyan {
18333ee3b2eSAlexey Dobriyan 	unsigned long long tmp;
18433ee3b2eSAlexey Dobriyan 	int rv;
18533ee3b2eSAlexey Dobriyan 
18633ee3b2eSAlexey Dobriyan 	rv = kstrtoull(s, base, &tmp);
18733ee3b2eSAlexey Dobriyan 	if (rv < 0)
18833ee3b2eSAlexey Dobriyan 		return rv;
189048e513dSAlexey Dobriyan 	if (tmp != (unsigned long)tmp)
19033ee3b2eSAlexey Dobriyan 		return -ERANGE;
19133ee3b2eSAlexey Dobriyan 	*res = tmp;
19233ee3b2eSAlexey Dobriyan 	return 0;
19333ee3b2eSAlexey Dobriyan }
19433ee3b2eSAlexey Dobriyan EXPORT_SYMBOL(_kstrtoul);
19533ee3b2eSAlexey Dobriyan 
19633ee3b2eSAlexey Dobriyan /* Internal, do not use. */
_kstrtol(const char * s,unsigned int base,long * res)19733ee3b2eSAlexey Dobriyan int _kstrtol(const char *s, unsigned int base, long *res)
19833ee3b2eSAlexey Dobriyan {
19933ee3b2eSAlexey Dobriyan 	long long tmp;
20033ee3b2eSAlexey Dobriyan 	int rv;
20133ee3b2eSAlexey Dobriyan 
20233ee3b2eSAlexey Dobriyan 	rv = kstrtoll(s, base, &tmp);
20333ee3b2eSAlexey Dobriyan 	if (rv < 0)
20433ee3b2eSAlexey Dobriyan 		return rv;
205048e513dSAlexey Dobriyan 	if (tmp != (long)tmp)
20633ee3b2eSAlexey Dobriyan 		return -ERANGE;
20733ee3b2eSAlexey Dobriyan 	*res = tmp;
20833ee3b2eSAlexey Dobriyan 	return 0;
20933ee3b2eSAlexey Dobriyan }
21033ee3b2eSAlexey Dobriyan EXPORT_SYMBOL(_kstrtol);
21133ee3b2eSAlexey Dobriyan 
2124c925d60SEldad Zack /**
2134c925d60SEldad Zack  * kstrtouint - convert a string to an unsigned int
2144c925d60SEldad Zack  * @s: The start of the string. The string must be null-terminated, and may also
2154c925d60SEldad Zack  *  include a single newline before its terminating null. The first character
2164c925d60SEldad Zack  *  may also be a plus sign, but not a minus sign.
2174c925d60SEldad Zack  * @base: The number base to use. The maximum supported base is 16. If base is
2184c925d60SEldad Zack  *  given as 0, then the base of the string is automatically detected with the
2194c925d60SEldad Zack  *  conventional semantics - If it begins with 0x the number will be parsed as a
2204c925d60SEldad Zack  *  hexadecimal (case insensitive), if it otherwise begins with 0, it will be
2214c925d60SEldad Zack  *  parsed as an octal number. Otherwise it will be parsed as a decimal.
2224c925d60SEldad Zack  * @res: Where to write the result of the conversion on success.
2234c925d60SEldad Zack  *
2244c925d60SEldad Zack  * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
225ef0f2685SKars Mulder  * Preferred over simple_strtoul(). Return code must be checked.
2264c925d60SEldad Zack  */
22770ac6992SAlexey Dobriyan noinline
kstrtouint(const char * s,unsigned int base,unsigned int * res)22833ee3b2eSAlexey Dobriyan int kstrtouint(const char *s, unsigned int base, unsigned int *res)
22933ee3b2eSAlexey Dobriyan {
23033ee3b2eSAlexey Dobriyan 	unsigned long long tmp;
23133ee3b2eSAlexey Dobriyan 	int rv;
23233ee3b2eSAlexey Dobriyan 
23333ee3b2eSAlexey Dobriyan 	rv = kstrtoull(s, base, &tmp);
23433ee3b2eSAlexey Dobriyan 	if (rv < 0)
23533ee3b2eSAlexey Dobriyan 		return rv;
236048e513dSAlexey Dobriyan 	if (tmp != (unsigned int)tmp)
23733ee3b2eSAlexey Dobriyan 		return -ERANGE;
23833ee3b2eSAlexey Dobriyan 	*res = tmp;
23933ee3b2eSAlexey Dobriyan 	return 0;
24033ee3b2eSAlexey Dobriyan }
24133ee3b2eSAlexey Dobriyan EXPORT_SYMBOL(kstrtouint);
24233ee3b2eSAlexey Dobriyan 
2434c925d60SEldad Zack /**
2444c925d60SEldad Zack  * kstrtoint - convert a string to an int
2454c925d60SEldad Zack  * @s: The start of the string. The string must be null-terminated, and may also
2464c925d60SEldad Zack  *  include a single newline before its terminating null. The first character
2474c925d60SEldad Zack  *  may also be a plus sign or a minus sign.
2484c925d60SEldad Zack  * @base: The number base to use. The maximum supported base is 16. If base is
2494c925d60SEldad Zack  *  given as 0, then the base of the string is automatically detected with the
2504c925d60SEldad Zack  *  conventional semantics - If it begins with 0x the number will be parsed as a
2514c925d60SEldad Zack  *  hexadecimal (case insensitive), if it otherwise begins with 0, it will be
2524c925d60SEldad Zack  *  parsed as an octal number. Otherwise it will be parsed as a decimal.
2534c925d60SEldad Zack  * @res: Where to write the result of the conversion on success.
2544c925d60SEldad Zack  *
2554c925d60SEldad Zack  * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
256ef0f2685SKars Mulder  * Preferred over simple_strtol(). Return code must be checked.
2574c925d60SEldad Zack  */
25870ac6992SAlexey Dobriyan noinline
kstrtoint(const char * s,unsigned int base,int * res)25933ee3b2eSAlexey Dobriyan int kstrtoint(const char *s, unsigned int base, int *res)
26033ee3b2eSAlexey Dobriyan {
26133ee3b2eSAlexey Dobriyan 	long long tmp;
26233ee3b2eSAlexey Dobriyan 	int rv;
26333ee3b2eSAlexey Dobriyan 
26433ee3b2eSAlexey Dobriyan 	rv = kstrtoll(s, base, &tmp);
26533ee3b2eSAlexey Dobriyan 	if (rv < 0)
26633ee3b2eSAlexey Dobriyan 		return rv;
267048e513dSAlexey Dobriyan 	if (tmp != (int)tmp)
26833ee3b2eSAlexey Dobriyan 		return -ERANGE;
26933ee3b2eSAlexey Dobriyan 	*res = tmp;
27033ee3b2eSAlexey Dobriyan 	return 0;
27133ee3b2eSAlexey Dobriyan }
27233ee3b2eSAlexey Dobriyan EXPORT_SYMBOL(kstrtoint);
27333ee3b2eSAlexey Dobriyan 
27470ac6992SAlexey Dobriyan noinline
kstrtou16(const char * s,unsigned int base,u16 * res)27533ee3b2eSAlexey Dobriyan int kstrtou16(const char *s, unsigned int base, u16 *res)
27633ee3b2eSAlexey Dobriyan {
27733ee3b2eSAlexey Dobriyan 	unsigned long long tmp;
27833ee3b2eSAlexey Dobriyan 	int rv;
27933ee3b2eSAlexey Dobriyan 
28033ee3b2eSAlexey Dobriyan 	rv = kstrtoull(s, base, &tmp);
28133ee3b2eSAlexey Dobriyan 	if (rv < 0)
28233ee3b2eSAlexey Dobriyan 		return rv;
283048e513dSAlexey Dobriyan 	if (tmp != (u16)tmp)
28433ee3b2eSAlexey Dobriyan 		return -ERANGE;
28533ee3b2eSAlexey Dobriyan 	*res = tmp;
28633ee3b2eSAlexey Dobriyan 	return 0;
28733ee3b2eSAlexey Dobriyan }
28833ee3b2eSAlexey Dobriyan EXPORT_SYMBOL(kstrtou16);
28933ee3b2eSAlexey Dobriyan 
29070ac6992SAlexey Dobriyan noinline
kstrtos16(const char * s,unsigned int base,s16 * res)29133ee3b2eSAlexey Dobriyan int kstrtos16(const char *s, unsigned int base, s16 *res)
29233ee3b2eSAlexey Dobriyan {
29333ee3b2eSAlexey Dobriyan 	long long tmp;
29433ee3b2eSAlexey Dobriyan 	int rv;
29533ee3b2eSAlexey Dobriyan 
29633ee3b2eSAlexey Dobriyan 	rv = kstrtoll(s, base, &tmp);
29733ee3b2eSAlexey Dobriyan 	if (rv < 0)
29833ee3b2eSAlexey Dobriyan 		return rv;
299048e513dSAlexey Dobriyan 	if (tmp != (s16)tmp)
30033ee3b2eSAlexey Dobriyan 		return -ERANGE;
30133ee3b2eSAlexey Dobriyan 	*res = tmp;
30233ee3b2eSAlexey Dobriyan 	return 0;
30333ee3b2eSAlexey Dobriyan }
30433ee3b2eSAlexey Dobriyan EXPORT_SYMBOL(kstrtos16);
30533ee3b2eSAlexey Dobriyan 
30670ac6992SAlexey Dobriyan noinline
kstrtou8(const char * s,unsigned int base,u8 * res)30733ee3b2eSAlexey Dobriyan int kstrtou8(const char *s, unsigned int base, u8 *res)
30833ee3b2eSAlexey Dobriyan {
30933ee3b2eSAlexey Dobriyan 	unsigned long long tmp;
31033ee3b2eSAlexey Dobriyan 	int rv;
31133ee3b2eSAlexey Dobriyan 
31233ee3b2eSAlexey Dobriyan 	rv = kstrtoull(s, base, &tmp);
31333ee3b2eSAlexey Dobriyan 	if (rv < 0)
31433ee3b2eSAlexey Dobriyan 		return rv;
315048e513dSAlexey Dobriyan 	if (tmp != (u8)tmp)
31633ee3b2eSAlexey Dobriyan 		return -ERANGE;
31733ee3b2eSAlexey Dobriyan 	*res = tmp;
31833ee3b2eSAlexey Dobriyan 	return 0;
31933ee3b2eSAlexey Dobriyan }
32033ee3b2eSAlexey Dobriyan EXPORT_SYMBOL(kstrtou8);
32133ee3b2eSAlexey Dobriyan 
32270ac6992SAlexey Dobriyan noinline
kstrtos8(const char * s,unsigned int base,s8 * res)32333ee3b2eSAlexey Dobriyan int kstrtos8(const char *s, unsigned int base, s8 *res)
32433ee3b2eSAlexey Dobriyan {
32533ee3b2eSAlexey Dobriyan 	long long tmp;
32633ee3b2eSAlexey Dobriyan 	int rv;
32733ee3b2eSAlexey Dobriyan 
32833ee3b2eSAlexey Dobriyan 	rv = kstrtoll(s, base, &tmp);
32933ee3b2eSAlexey Dobriyan 	if (rv < 0)
33033ee3b2eSAlexey Dobriyan 		return rv;
331048e513dSAlexey Dobriyan 	if (tmp != (s8)tmp)
33233ee3b2eSAlexey Dobriyan 		return -ERANGE;
33333ee3b2eSAlexey Dobriyan 	*res = tmp;
33433ee3b2eSAlexey Dobriyan 	return 0;
33533ee3b2eSAlexey Dobriyan }
33633ee3b2eSAlexey Dobriyan EXPORT_SYMBOL(kstrtos8);
337c196e32aSAlexey Dobriyan 
338ef951599SKees Cook /**
339ef951599SKees Cook  * kstrtobool - convert common user inputs into boolean values
340ef951599SKees Cook  * @s: input string
341ef951599SKees Cook  * @res: result
342ef951599SKees Cook  *
3430d6ea3acSJagdish Gediya  * This routine returns 0 iff the first character is one of 'YyTt1NnFf0', or
344a81a5a17SKees Cook  * [oO][NnFf] for "on" and "off". Otherwise it will return -EINVAL.  Value
345a81a5a17SKees Cook  * pointed to by res is updated upon finding a match.
346ef951599SKees Cook  */
34770ac6992SAlexey Dobriyan noinline
kstrtobool(const char * s,bool * res)348ef951599SKees Cook int kstrtobool(const char *s, bool *res)
349ef951599SKees Cook {
350ef951599SKees Cook 	if (!s)
351ef951599SKees Cook 		return -EINVAL;
352ef951599SKees Cook 
353ef951599SKees Cook 	switch (s[0]) {
354ef951599SKees Cook 	case 'y':
355ef951599SKees Cook 	case 'Y':
3560d6ea3acSJagdish Gediya 	case 't':
3570d6ea3acSJagdish Gediya 	case 'T':
358ef951599SKees Cook 	case '1':
359ef951599SKees Cook 		*res = true;
360ef951599SKees Cook 		return 0;
361ef951599SKees Cook 	case 'n':
362ef951599SKees Cook 	case 'N':
3630d6ea3acSJagdish Gediya 	case 'f':
3640d6ea3acSJagdish Gediya 	case 'F':
365ef951599SKees Cook 	case '0':
366ef951599SKees Cook 		*res = false;
367ef951599SKees Cook 		return 0;
368a81a5a17SKees Cook 	case 'o':
369a81a5a17SKees Cook 	case 'O':
370a81a5a17SKees Cook 		switch (s[1]) {
371a81a5a17SKees Cook 		case 'n':
372a81a5a17SKees Cook 		case 'N':
373a81a5a17SKees Cook 			*res = true;
374a81a5a17SKees Cook 			return 0;
375a81a5a17SKees Cook 		case 'f':
376a81a5a17SKees Cook 		case 'F':
377a81a5a17SKees Cook 			*res = false;
378a81a5a17SKees Cook 			return 0;
379a81a5a17SKees Cook 		default:
380a81a5a17SKees Cook 			break;
381a81a5a17SKees Cook 		}
38236f9ff9eSGustavo A. R. Silva 		break;
383ef951599SKees Cook 	default:
384ef951599SKees Cook 		break;
385ef951599SKees Cook 	}
386ef951599SKees Cook 
387ef951599SKees Cook 	return -EINVAL;
388ef951599SKees Cook }
389ef951599SKees Cook EXPORT_SYMBOL(kstrtobool);
390ef951599SKees Cook 
391ef951599SKees Cook /*
392ef951599SKees Cook  * Since "base" would be a nonsense argument, this open-codes the
393ef951599SKees Cook  * _from_user helper instead of using the helper macro below.
394ef951599SKees Cook  */
kstrtobool_from_user(const char __user * s,size_t count,bool * res)395ef951599SKees Cook int kstrtobool_from_user(const char __user *s, size_t count, bool *res)
396ef951599SKees Cook {
397ef951599SKees Cook 	/* Longest string needed to differentiate, newline, terminator */
398ef951599SKees Cook 	char buf[4];
399ef951599SKees Cook 
400ef951599SKees Cook 	count = min(count, sizeof(buf) - 1);
401ef951599SKees Cook 	if (copy_from_user(buf, s, count))
402ef951599SKees Cook 		return -EFAULT;
403ef951599SKees Cook 	buf[count] = '\0';
404ef951599SKees Cook 	return kstrtobool(buf, res);
405ef951599SKees Cook }
406ef951599SKees Cook EXPORT_SYMBOL(kstrtobool_from_user);
407ef951599SKees Cook 
408c196e32aSAlexey Dobriyan #define kstrto_from_user(f, g, type)					\
409c196e32aSAlexey Dobriyan int f(const char __user *s, size_t count, unsigned int base, type *res)	\
410c196e32aSAlexey Dobriyan {									\
411c196e32aSAlexey Dobriyan 	/* sign, base 2 representation, newline, terminator */		\
412c196e32aSAlexey Dobriyan 	char buf[1 + sizeof(type) * 8 + 1 + 1];				\
413c196e32aSAlexey Dobriyan 									\
414c196e32aSAlexey Dobriyan 	count = min(count, sizeof(buf) - 1);				\
415c196e32aSAlexey Dobriyan 	if (copy_from_user(buf, s, count))				\
416c196e32aSAlexey Dobriyan 		return -EFAULT;						\
417c196e32aSAlexey Dobriyan 	buf[count] = '\0';						\
418c196e32aSAlexey Dobriyan 	return g(buf, base, res);					\
419c196e32aSAlexey Dobriyan }									\
420c196e32aSAlexey Dobriyan EXPORT_SYMBOL(f)
421c196e32aSAlexey Dobriyan 
422c196e32aSAlexey Dobriyan kstrto_from_user(kstrtoull_from_user,	kstrtoull,	unsigned long long);
423c196e32aSAlexey Dobriyan kstrto_from_user(kstrtoll_from_user,	kstrtoll,	long long);
424c196e32aSAlexey Dobriyan kstrto_from_user(kstrtoul_from_user,	kstrtoul,	unsigned long);
425c196e32aSAlexey Dobriyan kstrto_from_user(kstrtol_from_user,	kstrtol,	long);
426c196e32aSAlexey Dobriyan kstrto_from_user(kstrtouint_from_user,	kstrtouint,	unsigned int);
427c196e32aSAlexey Dobriyan kstrto_from_user(kstrtoint_from_user,	kstrtoint,	int);
428c196e32aSAlexey Dobriyan kstrto_from_user(kstrtou16_from_user,	kstrtou16,	u16);
429c196e32aSAlexey Dobriyan kstrto_from_user(kstrtos16_from_user,	kstrtos16,	s16);
430c196e32aSAlexey Dobriyan kstrto_from_user(kstrtou8_from_user,	kstrtou8,	u8);
431c196e32aSAlexey Dobriyan kstrto_from_user(kstrtos8_from_user,	kstrtos8,	s8);
432