From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751722AbbEBBKp (ORCPT ); Fri, 1 May 2015 21:10:45 -0400 Received: from mail-wg0-f52.google.com ([74.125.82.52]:34662 "EHLO mail-wg0-f52.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750870AbbEBBKn (ORCPT ); Fri, 1 May 2015 21:10:43 -0400 Date: Sat, 2 May 2015 04:10:39 +0300 From: Alexey Dobriyan To: akpm@linux-foundation.org Cc: linux-kernel@vger.kernel.org Subject: [PATCH CORRECT 03/10] parse_integer: convert sscanf() Message-ID: <20150502011039.GA21806@p183.telecom.by> References: <20150502004714.GA21655@p183.telecom.by> <20150502005008.GC21655@p183.telecom.by> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20150502005008.GC21655@p183.telecom.by> User-Agent: Mutt/1.5.23 (2014-03-12) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Rewrite kstrto*() functions through parse_integer(). _kstrtoul() and _kstrtol() are removed because parse_integer() can dispatch based on BITS_PER_LONG saving function call. Also move function definitions and comment one instance. Remove redundant boilerplate comments from elsewhere. High bit base hack suggested by Andrew M. Signed-off-by: Alexey Dobriyan --- I copied patch twice, lol. include/linux/kernel.h | 124 ----------------------- include/linux/parse-integer.h | 109 ++++++++++++++++++++ lib/kstrtox.c | 222 ------------------------------------------ lib/parse-integer.c | 38 ++++++- 4 files changed, 143 insertions(+), 350 deletions(-) --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -264,130 +264,6 @@ void do_exit(long error_code) void complete_and_exit(struct completion *, long) __noreturn; -/* Internal, do not use. */ -int __must_check _kstrtoul(const char *s, unsigned int base, unsigned long *res); -int __must_check _kstrtol(const char *s, unsigned int base, long *res); - -int __must_check kstrtoull(const char *s, unsigned int base, unsigned long long *res); -int __must_check kstrtoll(const char *s, unsigned int base, long long *res); - -/** - * kstrtoul - convert a string to an unsigned long - * @s: The start of the string. The string must be null-terminated, and may also - * include a single newline before its terminating null. The first character - * may also be a plus sign, but not a minus sign. - * @base: The number base to use. The maximum supported base is 16. If base is - * given as 0, then the base of the string is automatically detected with the - * conventional semantics - If it begins with 0x the number will be parsed as a - * hexadecimal (case insensitive), if it otherwise begins with 0, it will be - * parsed as an octal number. Otherwise it will be parsed as a decimal. - * @res: Where to write the result of the conversion on success. - * - * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error. - * Used as a replacement for the obsolete simple_strtoull. Return code must - * be checked. -*/ -static inline int __must_check kstrtoul(const char *s, unsigned int base, unsigned long *res) -{ - /* - * We want to shortcut function call, but - * __builtin_types_compatible_p(unsigned long, unsigned long long) = 0. - */ - if (sizeof(unsigned long) == sizeof(unsigned long long) && - __alignof__(unsigned long) == __alignof__(unsigned long long)) - return kstrtoull(s, base, (unsigned long long *)res); - else - return _kstrtoul(s, base, res); -} - -/** - * kstrtol - convert a string to a long - * @s: The start of the string. The string must be null-terminated, and may also - * include a single newline before its terminating null. The first character - * may also be a plus sign or a minus sign. - * @base: The number base to use. The maximum supported base is 16. If base is - * given as 0, then the base of the string is automatically detected with the - * conventional semantics - If it begins with 0x the number will be parsed as a - * hexadecimal (case insensitive), if it otherwise begins with 0, it will be - * parsed as an octal number. Otherwise it will be parsed as a decimal. - * @res: Where to write the result of the conversion on success. - * - * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error. - * Used as a replacement for the obsolete simple_strtoull. Return code must - * be checked. - */ -static inline int __must_check kstrtol(const char *s, unsigned int base, long *res) -{ - /* - * We want to shortcut function call, but - * __builtin_types_compatible_p(long, long long) = 0. - */ - if (sizeof(long) == sizeof(long long) && - __alignof__(long) == __alignof__(long long)) - return kstrtoll(s, base, (long long *)res); - else - return _kstrtol(s, base, res); -} - -int __must_check kstrtouint(const char *s, unsigned int base, unsigned int *res); -int __must_check kstrtoint(const char *s, unsigned int base, int *res); - -static inline int __must_check kstrtou64(const char *s, unsigned int base, u64 *res) -{ - return kstrtoull(s, base, res); -} - -static inline int __must_check kstrtos64(const char *s, unsigned int base, s64 *res) -{ - return kstrtoll(s, base, res); -} - -static inline int __must_check kstrtou32(const char *s, unsigned int base, u32 *res) -{ - return kstrtouint(s, base, res); -} - -static inline int __must_check kstrtos32(const char *s, unsigned int base, s32 *res) -{ - return kstrtoint(s, base, res); -} - -int __must_check kstrtou16(const char *s, unsigned int base, u16 *res); -int __must_check kstrtos16(const char *s, unsigned int base, s16 *res); -int __must_check kstrtou8(const char *s, unsigned int base, u8 *res); -int __must_check kstrtos8(const char *s, unsigned int base, s8 *res); - -int __must_check kstrtoull_from_user(const char __user *s, size_t count, unsigned int base, unsigned long long *res); -int __must_check kstrtoll_from_user(const char __user *s, size_t count, unsigned int base, long long *res); -int __must_check kstrtoul_from_user(const char __user *s, size_t count, unsigned int base, unsigned long *res); -int __must_check kstrtol_from_user(const char __user *s, size_t count, unsigned int base, long *res); -int __must_check kstrtouint_from_user(const char __user *s, size_t count, unsigned int base, unsigned int *res); -int __must_check kstrtoint_from_user(const char __user *s, size_t count, unsigned int base, int *res); -int __must_check kstrtou16_from_user(const char __user *s, size_t count, unsigned int base, u16 *res); -int __must_check kstrtos16_from_user(const char __user *s, size_t count, unsigned int base, s16 *res); -int __must_check kstrtou8_from_user(const char __user *s, size_t count, unsigned int base, u8 *res); -int __must_check kstrtos8_from_user(const char __user *s, size_t count, unsigned int base, s8 *res); - -static inline int __must_check kstrtou64_from_user(const char __user *s, size_t count, unsigned int base, u64 *res) -{ - return kstrtoull_from_user(s, count, base, res); -} - -static inline int __must_check kstrtos64_from_user(const char __user *s, size_t count, unsigned int base, s64 *res) -{ - return kstrtoll_from_user(s, count, base, res); -} - -static inline int __must_check kstrtou32_from_user(const char __user *s, size_t count, unsigned int base, u32 *res) -{ - return kstrtouint_from_user(s, count, base, res); -} - -static inline int __must_check kstrtos32_from_user(const char __user *s, size_t count, unsigned int base, s32 *res) -{ - return kstrtoint_from_user(s, count, base, res); -} - /* * Obsolete, do not use. * Use parse_integer(), kstrto*(), kstrto*_from_user(), sscanf(). --- a/include/linux/parse-integer.h +++ b/include/linux/parse-integer.h @@ -76,4 +76,113 @@ int _parse_integer_ll(const char *s, unsigned int base, long long *val); int _parse_integer_ull(const char *s, unsigned int base, unsigned long long *val); void _parse_integer_link_time_error(void); const char *_parse_integer_fixup_radix(const char *s, unsigned int *base); +#define PARSE_INTEGER_NEWLINE 0x80000000u + +/* + * Convert integer string representation terminated by \n\0 or \0 to an integer. + * + * Return 0 on success or -E. + * + * See parse_integer(). + */ +static inline int __must_check kstrtoull(const char *s, unsigned int base, unsigned long long *res) +{ + return parse_integer(s, base | PARSE_INTEGER_NEWLINE, res); +} + +static inline int __must_check kstrtoll(const char *s, unsigned int base, long long *res) +{ + return parse_integer(s, base | PARSE_INTEGER_NEWLINE, res); +} + +static inline int __must_check kstrtoul(const char *s, unsigned int base, unsigned long *res) +{ + return parse_integer(s, base | PARSE_INTEGER_NEWLINE, res); +} + +static inline int __must_check kstrtol(const char *s, unsigned int base, long *res) +{ + return parse_integer(s, base | PARSE_INTEGER_NEWLINE, res); +} + +static inline int __must_check kstrtouint(const char *s, unsigned int base, unsigned int *res) +{ + return parse_integer(s, base | PARSE_INTEGER_NEWLINE, res); +} + +static inline int __must_check kstrtoint(const char *s, unsigned int base, int *res) +{ + return parse_integer(s, base | PARSE_INTEGER_NEWLINE, res); +} + +static inline int __must_check kstrtou64(const char *s, unsigned int base, u64 *res) +{ + return kstrtoull(s, base, res); +} + +static inline int __must_check kstrtos64(const char *s, unsigned int base, s64 *res) +{ + return kstrtoll(s, base, res); +} + +static inline int __must_check kstrtou32(const char *s, unsigned int base, u32 *res) +{ + return kstrtouint(s, base, res); +} + +static inline int __must_check kstrtos32(const char *s, unsigned int base, s32 *res) +{ + return kstrtoint(s, base, res); +} + +static inline int __must_check kstrtou16(const char *s, unsigned int base, u16 *res) +{ + return parse_integer(s, base | PARSE_INTEGER_NEWLINE, res); +} + +static inline int __must_check kstrtos16(const char *s, unsigned int base, s16 *res) +{ + return parse_integer(s, base | PARSE_INTEGER_NEWLINE, res); +} + +static inline int __must_check kstrtou8(const char *s, unsigned int base, u8 *res) +{ + return parse_integer(s, base | PARSE_INTEGER_NEWLINE, res); +} + +static inline int __must_check kstrtos8(const char *s, unsigned int base, s8 *res) +{ + return parse_integer(s, base | PARSE_INTEGER_NEWLINE, res); +} + +int __must_check kstrtoull_from_user(const char __user *s, size_t count, unsigned int base, unsigned long long *res); +int __must_check kstrtoll_from_user(const char __user *s, size_t count, unsigned int base, long long *res); +int __must_check kstrtoul_from_user(const char __user *s, size_t count, unsigned int base, unsigned long *res); +int __must_check kstrtol_from_user(const char __user *s, size_t count, unsigned int base, long *res); +int __must_check kstrtouint_from_user(const char __user *s, size_t count, unsigned int base, unsigned int *res); +int __must_check kstrtoint_from_user(const char __user *s, size_t count, unsigned int base, int *res); +int __must_check kstrtou16_from_user(const char __user *s, size_t count, unsigned int base, u16 *res); +int __must_check kstrtos16_from_user(const char __user *s, size_t count, unsigned int base, s16 *res); +int __must_check kstrtou8_from_user(const char __user *s, size_t count, unsigned int base, u8 *res); +int __must_check kstrtos8_from_user(const char __user *s, size_t count, unsigned int base, s8 *res); + +static inline int __must_check kstrtou64_from_user(const char __user *s, size_t count, unsigned int base, u64 *res) +{ + return kstrtoull_from_user(s, count, base, res); +} + +static inline int __must_check kstrtos64_from_user(const char __user *s, size_t count, unsigned int base, s64 *res) +{ + return kstrtoll_from_user(s, count, base, res); +} + +static inline int __must_check kstrtou32_from_user(const char __user *s, size_t count, unsigned int base, u32 *res) +{ + return kstrtouint_from_user(s, count, base, res); +} + +static inline int __must_check kstrtos32_from_user(const char __user *s, size_t count, unsigned int base, s32 *res) +{ + return kstrtoint_from_user(s, count, base, res); +} #endif --- a/lib/kstrtox.c +++ b/lib/kstrtox.c @@ -67,228 +67,6 @@ unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long return rv; } -/** - * kstrtoull - convert a string to an unsigned long long - * @s: The start of the string. The string must be null-terminated, and may also - * include a single newline before its terminating null. The first character - * may also be a plus sign, but not a minus sign. - * @base: The number base to use. The maximum supported base is 16. If base is - * given as 0, then the base of the string is automatically detected with the - * conventional semantics - If it begins with 0x the number will be parsed as a - * hexadecimal (case insensitive), if it otherwise begins with 0, it will be - * parsed as an octal number. Otherwise it will be parsed as a decimal. - * @res: Where to write the result of the conversion on success. - * - * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error. - * Used as a replacement for the obsolete simple_strtoull. Return code must - * be checked. - */ -int kstrtoull(const char *s, unsigned int base, unsigned long long *res) -{ - unsigned long long _res; - int rv; - - rv = parse_integer(s, base, &_res); - if (rv < 0) - return rv; - s += rv; - if (*s == '\n') - s++; - if (*s) - return -EINVAL; - *res = _res; - return 0; -} -EXPORT_SYMBOL(kstrtoull); - -/** - * kstrtoll - convert a string to a long long - * @s: The start of the string. The string must be null-terminated, and may also - * include a single newline before its terminating null. The first character - * may also be a plus sign or a minus sign. - * @base: The number base to use. The maximum supported base is 16. If base is - * given as 0, then the base of the string is automatically detected with the - * conventional semantics - If it begins with 0x the number will be parsed as a - * hexadecimal (case insensitive), if it otherwise begins with 0, it will be - * parsed as an octal number. Otherwise it will be parsed as a decimal. - * @res: Where to write the result of the conversion on success. - * - * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error. - * Used as a replacement for the obsolete simple_strtoull. Return code must - * be checked. - */ -int kstrtoll(const char *s, unsigned int base, long long *res) -{ - long long _res; - int rv; - - rv = parse_integer(s, base, &_res); - if (rv < 0) - return rv; - s += rv; - if (*s == '\n') - s++; - if (*s) - return -EINVAL; - *res = _res; - return 0; -} -EXPORT_SYMBOL(kstrtoll); - -/* Internal, do not use. */ -int _kstrtoul(const char *s, unsigned int base, unsigned long *res) -{ - unsigned long long tmp; - int rv; - - rv = kstrtoull(s, base, &tmp); - if (rv < 0) - return rv; - if (tmp != (unsigned long long)(unsigned long)tmp) - return -ERANGE; - *res = tmp; - return 0; -} -EXPORT_SYMBOL(_kstrtoul); - -/* Internal, do not use. */ -int _kstrtol(const char *s, unsigned int base, long *res) -{ - long long tmp; - int rv; - - rv = kstrtoll(s, base, &tmp); - if (rv < 0) - return rv; - if (tmp != (long long)(long)tmp) - return -ERANGE; - *res = tmp; - return 0; -} -EXPORT_SYMBOL(_kstrtol); - -/** - * kstrtouint - convert a string to an unsigned int - * @s: The start of the string. The string must be null-terminated, and may also - * include a single newline before its terminating null. The first character - * may also be a plus sign, but not a minus sign. - * @base: The number base to use. The maximum supported base is 16. If base is - * given as 0, then the base of the string is automatically detected with the - * conventional semantics - If it begins with 0x the number will be parsed as a - * hexadecimal (case insensitive), if it otherwise begins with 0, it will be - * parsed as an octal number. Otherwise it will be parsed as a decimal. - * @res: Where to write the result of the conversion on success. - * - * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error. - * Used as a replacement for the obsolete simple_strtoull. Return code must - * be checked. - */ -int kstrtouint(const char *s, unsigned int base, unsigned int *res) -{ - unsigned long long tmp; - int rv; - - rv = kstrtoull(s, base, &tmp); - if (rv < 0) - return rv; - if (tmp != (unsigned long long)(unsigned int)tmp) - return -ERANGE; - *res = tmp; - return 0; -} -EXPORT_SYMBOL(kstrtouint); - -/** - * kstrtoint - convert a string to an int - * @s: The start of the string. The string must be null-terminated, and may also - * include a single newline before its terminating null. The first character - * may also be a plus sign or a minus sign. - * @base: The number base to use. The maximum supported base is 16. If base is - * given as 0, then the base of the string is automatically detected with the - * conventional semantics - If it begins with 0x the number will be parsed as a - * hexadecimal (case insensitive), if it otherwise begins with 0, it will be - * parsed as an octal number. Otherwise it will be parsed as a decimal. - * @res: Where to write the result of the conversion on success. - * - * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error. - * Used as a replacement for the obsolete simple_strtoull. Return code must - * be checked. - */ -int kstrtoint(const char *s, unsigned int base, int *res) -{ - long long tmp; - int rv; - - rv = kstrtoll(s, base, &tmp); - if (rv < 0) - return rv; - if (tmp != (long long)(int)tmp) - return -ERANGE; - *res = tmp; - return 0; -} -EXPORT_SYMBOL(kstrtoint); - -int kstrtou16(const char *s, unsigned int base, u16 *res) -{ - unsigned long long tmp; - int rv; - - rv = kstrtoull(s, base, &tmp); - if (rv < 0) - return rv; - if (tmp != (unsigned long long)(u16)tmp) - return -ERANGE; - *res = tmp; - return 0; -} -EXPORT_SYMBOL(kstrtou16); - -int kstrtos16(const char *s, unsigned int base, s16 *res) -{ - long long tmp; - int rv; - - rv = kstrtoll(s, base, &tmp); - if (rv < 0) - return rv; - if (tmp != (long long)(s16)tmp) - return -ERANGE; - *res = tmp; - return 0; -} -EXPORT_SYMBOL(kstrtos16); - -int kstrtou8(const char *s, unsigned int base, u8 *res) -{ - unsigned long long tmp; - int rv; - - rv = kstrtoull(s, base, &tmp); - if (rv < 0) - return rv; - if (tmp != (unsigned long long)(u8)tmp) - return -ERANGE; - *res = tmp; - return 0; -} -EXPORT_SYMBOL(kstrtou8); - -int kstrtos8(const char *s, unsigned int base, s8 *res) -{ - long long tmp; - int rv; - - rv = kstrtoll(s, base, &tmp); - if (rv < 0) - return rv; - if (tmp != (long long)(s8)tmp) - return -ERANGE; - *res = tmp; - return 0; -} -EXPORT_SYMBOL(kstrtos8); - #define kstrto_from_user(f, g, type) \ int f(const char __user *s, size_t count, unsigned int base, type *res) \ { \ --- a/lib/parse-integer.c +++ b/lib/parse-integer.c @@ -31,7 +31,7 @@ const char *_parse_integer_fixup_radix(const char *s, unsigned int *base) return s; } -static int __parse_integer(const char *s, unsigned int base, unsigned long long *val) +static int ___parse_integer(const char *s, unsigned int base, unsigned long long *val) { const char *s0 = s, *sd; unsigned long long acc; @@ -63,6 +63,27 @@ static int __parse_integer(const char *s, unsigned int base, unsigned long long return s - s0; } +static int __parse_integer(const char *s, unsigned int base, unsigned long long *val) +{ + if (base & PARSE_INTEGER_NEWLINE) { + unsigned long long _val; + int rv; + + /* Accept "integer\0" or "integer\n\0" */ + rv = ___parse_integer(s, base & ~PARSE_INTEGER_NEWLINE, &_val); + if (rv < 0) + return rv; + s += rv; + if (*s == '\n') + s++; + if (*s) + return -EINVAL; + *val = _val; + return 0; + } else + return ___parse_integer(s, base, val); +} + int _parse_integer_ull(const char *s, unsigned int base, unsigned long long *val) { int rv; @@ -73,7 +94,10 @@ int _parse_integer_ull(const char *s, unsigned int base, unsigned long long *val rv = __parse_integer(s + 1, base, val); if (rv < 0) return rv; - return rv + 1; + if (base & PARSE_INTEGER_NEWLINE) + return 0; + else + return rv + 1; } else return __parse_integer(s, base, val); } @@ -91,7 +115,10 @@ int _parse_integer_ll(const char *s, unsigned int base, long long *val) if ((long long)-tmp >= 0) return -ERANGE; *val = -tmp; - return rv + 1; + if (base & PARSE_INTEGER_NEWLINE) + return 0; + else + return rv + 1; } else if (*s == '+') { rv = __parse_integer(s + 1, base, &tmp); if (rv < 0) @@ -99,7 +126,10 @@ int _parse_integer_ll(const char *s, unsigned int base, long long *val) if ((long long)tmp < 0) return -ERANGE; *val = tmp; - return rv + 1; + if (base & PARSE_INTEGER_NEWLINE) + return 0; + else + return rv + 1; } else { rv = __parse_integer(s, base, &tmp); if (rv < 0)