2011-03-23 02:34:40 +03:00
/*
* Convert integer string representation to an integer .
* If an integer doesn ' t fit into specified type , - E is returned .
*
* Integer starts with optional sign .
* kstrtou * ( ) functions do not accept sign " - " .
*
* Radix 0 means autodetection : leading " 0x " implies radix 16 ,
* leading " 0 " implies radix 8 , otherwise radix is 10.
* Autodetection hints work after optional sign , but not before .
*
* If - E is returned , result is not touched .
*/
# include <linux/ctype.h>
# include <linux/errno.h>
# include <linux/kernel.h>
# include <linux/math64.h>
2011-11-17 06:29:17 +04:00
# include <linux/export.h>
2011-03-23 02:34:40 +03:00
# include <linux/types.h>
2011-05-25 04:13:31 +04:00
# include <asm/uaccess.h>
2011-11-01 04:12:28 +04:00
# include "kstrtox.h"
2011-03-23 02:34:40 +03:00
2011-11-01 04:12:28 +04:00
const char * _parse_integer_fixup_radix ( const char * s , unsigned int * base )
2011-03-23 02:34:40 +03:00
{
2011-11-01 04:12:28 +04:00
if ( * base = = 0 ) {
2011-03-23 02:34:40 +03:00
if ( s [ 0 ] = = ' 0 ' ) {
if ( _tolower ( s [ 1 ] ) = = ' x ' & & isxdigit ( s [ 2 ] ) )
2011-11-01 04:12:28 +04:00
* base = 16 ;
2011-03-23 02:34:40 +03:00
else
2011-11-01 04:12:28 +04:00
* base = 8 ;
2011-03-23 02:34:40 +03:00
} else
2011-11-01 04:12:28 +04:00
* base = 10 ;
2011-03-23 02:34:40 +03:00
}
2011-11-01 04:12:28 +04:00
if ( * base = = 16 & & s [ 0 ] = = ' 0 ' & & _tolower ( s [ 1 ] ) = = ' x ' )
2011-03-23 02:34:40 +03:00
s + = 2 ;
2011-11-01 04:12:28 +04:00
return s ;
}
/*
* Convert non - negative integer string representation in explicitly given radix
* to an integer .
* Return number of characters consumed maybe or - ed with overflow bit .
* If overflow occurs , result integer ( incorrect ) is still returned .
*
* Don ' t you dare use this function .
*/
2012-02-09 19:48:20 +04:00
unsigned int _parse_integer ( const char * s , unsigned int base , unsigned long long * p )
2011-11-01 04:12:28 +04:00
{
2012-02-09 19:48:20 +04:00
unsigned long long res ;
2011-11-01 04:12:28 +04:00
unsigned int rv ;
int overflow ;
2011-03-23 02:34:40 +03:00
2012-02-09 19:48:20 +04:00
res = 0 ;
2011-11-01 04:12:28 +04:00
rv = 0 ;
overflow = 0 ;
2011-03-23 02:34:40 +03:00
while ( * s ) {
unsigned int val ;
if ( ' 0 ' < = * s & & * s < = ' 9 ' )
val = * s - ' 0 ' ;
else if ( ' a ' < = _tolower ( * s ) & & _tolower ( * s ) < = ' f ' )
val = _tolower ( * s ) - ' a ' + 10 ;
2011-04-15 02:22:02 +04:00
else
2011-11-01 04:12:28 +04:00
break ;
2011-03-23 02:34:40 +03:00
if ( val > = base )
2011-11-01 04:12:28 +04:00
break ;
2012-02-09 19:48:20 +04:00
/*
* Check for overflow only if we are within range of
* it in the max base we support ( 16 )
*/
if ( unlikely ( res & ( ~ 0ull < < 60 ) ) ) {
if ( res > div_u64 ( ULLONG_MAX - val , base ) )
overflow = 1 ;
}
res = res * base + val ;
2011-11-01 04:12:28 +04:00
rv + + ;
2011-03-23 02:34:40 +03:00
s + + ;
}
2012-02-09 19:48:20 +04:00
* p = res ;
2011-11-01 04:12:28 +04:00
if ( overflow )
rv | = KSTRTOX_OVERFLOW ;
return rv ;
}
static int _kstrtoull ( const char * s , unsigned int base , unsigned long long * res )
{
unsigned long long _res ;
unsigned int rv ;
s = _parse_integer_fixup_radix ( s , & base ) ;
rv = _parse_integer ( s , base , & _res ) ;
if ( rv & KSTRTOX_OVERFLOW )
return - ERANGE ;
if ( rv = = 0 )
return - EINVAL ;
s + = rv ;
if ( * s = = ' \n ' )
s + + ;
if ( * s )
2011-03-23 02:34:40 +03:00
return - EINVAL ;
2011-11-01 04:12:28 +04:00
* res = _res ;
2011-03-23 02:34:40 +03:00
return 0 ;
}
2012-12-18 04:03:04 +04:00
/**
* 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 0 x 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 .
*/
2011-03-23 02:34:40 +03:00
int kstrtoull ( const char * s , unsigned int base , unsigned long long * res )
{
if ( s [ 0 ] = = ' + ' )
s + + ;
return _kstrtoull ( s , base , res ) ;
}
EXPORT_SYMBOL ( kstrtoull ) ;
2012-12-18 04:03:04 +04:00
/**
* 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 0 x 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 .
*/
2011-03-23 02:34:40 +03:00
int kstrtoll ( const char * s , unsigned int base , long long * res )
{
unsigned long long tmp ;
int rv ;
if ( s [ 0 ] = = ' - ' ) {
rv = _kstrtoull ( s + 1 , base , & tmp ) ;
if ( rv < 0 )
return rv ;
2015-09-10 01:36:17 +03:00
if ( ( long long ) - tmp > 0 )
2011-03-23 02:34:40 +03:00
return - ERANGE ;
* res = - tmp ;
} else {
rv = kstrtoull ( s , base , & tmp ) ;
if ( rv < 0 )
return rv ;
if ( ( long long ) tmp < 0 )
return - ERANGE ;
* res = tmp ;
}
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 ) ;
2012-12-18 04:03:04 +04:00
/**
* 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 0 x 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 .
*/
2011-03-23 02:34:40 +03:00
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 ) ;
2012-12-18 04:03:04 +04:00
/**
* 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 0 x 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 .
*/
2011-03-23 02:34:40 +03:00
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 ) ;
2011-05-25 04:13:31 +04:00
# define kstrto_from_user(f, g, type) \
int f ( const char __user * s , size_t count , unsigned int base , type * res ) \
{ \
/* sign, base 2 representation, newline, terminator */ \
char buf [ 1 + sizeof ( type ) * 8 + 1 + 1 ] ; \
\
count = min ( count , sizeof ( buf ) - 1 ) ; \
if ( copy_from_user ( buf , s , count ) ) \
return - EFAULT ; \
buf [ count ] = ' \0 ' ; \
return g ( buf , base , res ) ; \
} \
EXPORT_SYMBOL ( f )
kstrto_from_user ( kstrtoull_from_user , kstrtoull , unsigned long long ) ;
kstrto_from_user ( kstrtoll_from_user , kstrtoll , long long ) ;
kstrto_from_user ( kstrtoul_from_user , kstrtoul , unsigned long ) ;
kstrto_from_user ( kstrtol_from_user , kstrtol , long ) ;
kstrto_from_user ( kstrtouint_from_user , kstrtouint , unsigned int ) ;
kstrto_from_user ( kstrtoint_from_user , kstrtoint , int ) ;
kstrto_from_user ( kstrtou16_from_user , kstrtou16 , u16 ) ;
kstrto_from_user ( kstrtos16_from_user , kstrtos16 , s16 ) ;
kstrto_from_user ( kstrtou8_from_user , kstrtou8 , u8 ) ;
kstrto_from_user ( kstrtos8_from_user , kstrtos8 , s8 ) ;