Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
lib
kstrtox.c
Go to the documentation of this file.
1
/*
2
* Convert integer string representation to an integer.
3
* If an integer doesn't fit into specified type, -E is returned.
4
*
5
* Integer starts with optional sign.
6
* kstrtou*() functions do not accept sign "-".
7
*
8
* Radix 0 means autodetection: leading "0x" implies radix 16,
9
* leading "0" implies radix 8, otherwise radix is 10.
10
* Autodetection hints work after optional sign, but not before.
11
*
12
* If -E is returned, result is not touched.
13
*/
14
#include <linux/ctype.h>
15
#include <linux/errno.h>
16
#include <linux/kernel.h>
17
#include <
linux/math64.h
>
18
#include <linux/export.h>
19
#include <linux/types.h>
20
#include <asm/uaccess.h>
21
#include "
kstrtox.h
"
22
23
const
char
*
_parse_integer_fixup_radix
(
const
char
*
s
,
unsigned
int
*base)
24
{
25
if
(*base == 0) {
26
if
(s[0] ==
'0'
) {
27
if
(_tolower(s[1]) ==
'x'
&&
isxdigit
(s[2]))
28
*base = 16;
29
else
30
*base = 8;
31
}
else
32
*base = 10;
33
}
34
if
(*base == 16 && s[0] ==
'0'
&& _tolower(s[1]) ==
'x'
)
35
s += 2;
36
return
s
;
37
}
38
39
/*
40
* Convert non-negative integer string representation in explicitly given radix
41
* to an integer.
42
* Return number of characters consumed maybe or-ed with overflow bit.
43
* If overflow occurs, result integer (incorrect) is still returned.
44
*
45
* Don't you dare use this function.
46
*/
47
unsigned
int
_parse_integer
(
const
char
*
s
,
unsigned
int
base,
unsigned
long
long
*
p
)
48
{
49
unsigned
long
long
res
;
50
unsigned
int
rv;
51
int
overflow
;
52
53
res = 0;
54
rv = 0;
55
overflow = 0;
56
while
(*s) {
57
unsigned
int
val
;
58
59
if
(
'0'
<= *s && *s <=
'9'
)
60
val = *s -
'0'
;
61
else
if
(
'a'
<= _tolower(*s) && _tolower(*s) <=
'f'
)
62
val = _tolower(*s) -
'a'
+ 10;
63
else
64
break
;
65
66
if
(val >= base)
67
break
;
68
/*
69
* Check for overflow only if we are within range of
70
* it in the max base we support (16)
71
*/
72
if
(
unlikely
(res & (~0ull << 60))) {
73
if
(res > div_u64(
ULLONG_MAX
- val, base))
74
overflow = 1;
75
}
76
res = res * base +
val
;
77
rv++;
78
s++;
79
}
80
*p =
res
;
81
if
(overflow)
82
rv |=
KSTRTOX_OVERFLOW
;
83
return
rv;
84
}
85
86
static
int
_kstrtoull(
const
char
*
s
,
unsigned
int
base,
unsigned
long
long
*
res
)
87
{
88
unsigned
long
long
_res;
89
unsigned
int
rv;
90
91
s =
_parse_integer_fixup_radix
(s, &base);
92
rv =
_parse_integer
(s, base, &_res);
93
if
(rv &
KSTRTOX_OVERFLOW
)
94
return
-
ERANGE
;
95
rv &= ~KSTRTOX_OVERFLOW;
96
if
(rv == 0)
97
return
-
EINVAL
;
98
s += rv;
99
if
(*s ==
'\n'
)
100
s++;
101
if
(*s)
102
return
-
EINVAL
;
103
*res = _res;
104
return
0;
105
}
106
107
int
kstrtoull
(
const
char
*s,
unsigned
int
base,
unsigned
long
long
*res)
108
{
109
if
(s[0] ==
'+'
)
110
s++;
111
return
_kstrtoull(s, base, res);
112
}
113
EXPORT_SYMBOL
(
kstrtoull
);
114
115
int
kstrtoll
(
const
char
*s,
unsigned
int
base,
long
long
*res)
116
{
117
unsigned
long
long
tmp
;
118
int
rv;
119
120
if
(s[0] ==
'-'
) {
121
rv = _kstrtoull(s + 1, base, &tmp);
122
if
(rv < 0)
123
return
rv;
124
if
((
long
long
)(-tmp) >= 0)
125
return
-
ERANGE
;
126
*res = -
tmp
;
127
}
else
{
128
rv =
kstrtoull
(s, base, &tmp);
129
if
(rv < 0)
130
return
rv;
131
if
((
long
long
)tmp < 0)
132
return
-
ERANGE
;
133
*res =
tmp
;
134
}
135
return
0;
136
}
137
EXPORT_SYMBOL
(
kstrtoll
);
138
139
/* Internal, do not use. */
140
int
_kstrtoul
(
const
char
*s,
unsigned
int
base,
unsigned
long
*res)
141
{
142
unsigned
long
long
tmp
;
143
int
rv;
144
145
rv =
kstrtoull
(s, base, &tmp);
146
if
(rv < 0)
147
return
rv;
148
if
(tmp != (
unsigned
long
long
)(
unsigned
long
)tmp)
149
return
-
ERANGE
;
150
*res =
tmp
;
151
return
0;
152
}
153
EXPORT_SYMBOL
(
_kstrtoul
);
154
155
/* Internal, do not use. */
156
int
_kstrtol
(
const
char
*s,
unsigned
int
base,
long
*res)
157
{
158
long
long
tmp
;
159
int
rv;
160
161
rv =
kstrtoll
(s, base, &tmp);
162
if
(rv < 0)
163
return
rv;
164
if
(tmp != (
long
long
)(
long
)tmp)
165
return
-
ERANGE
;
166
*res =
tmp
;
167
return
0;
168
}
169
EXPORT_SYMBOL
(
_kstrtol
);
170
171
int
kstrtouint
(
const
char
*s,
unsigned
int
base,
unsigned
int
*res)
172
{
173
unsigned
long
long
tmp
;
174
int
rv;
175
176
rv =
kstrtoull
(s, base, &tmp);
177
if
(rv < 0)
178
return
rv;
179
if
(tmp != (
unsigned
long
long
)(
unsigned
int
)tmp)
180
return
-
ERANGE
;
181
*res =
tmp
;
182
return
0;
183
}
184
EXPORT_SYMBOL
(
kstrtouint
);
185
186
int
kstrtoint
(
const
char
*s,
unsigned
int
base,
int
*res)
187
{
188
long
long
tmp
;
189
int
rv;
190
191
rv =
kstrtoll
(s, base, &tmp);
192
if
(rv < 0)
193
return
rv;
194
if
(tmp != (
long
long
)(
int
)tmp)
195
return
-
ERANGE
;
196
*res =
tmp
;
197
return
0;
198
}
199
EXPORT_SYMBOL
(
kstrtoint
);
200
201
int
kstrtou16
(
const
char
*s,
unsigned
int
base,
u16
*res)
202
{
203
unsigned
long
long
tmp
;
204
int
rv;
205
206
rv =
kstrtoull
(s, base, &tmp);
207
if
(rv < 0)
208
return
rv;
209
if
(tmp != (
unsigned
long
long
)(
u16
)tmp)
210
return
-
ERANGE
;
211
*res =
tmp
;
212
return
0;
213
}
214
EXPORT_SYMBOL
(
kstrtou16
);
215
216
int
kstrtos16
(
const
char
*s,
unsigned
int
base,
s16
*res)
217
{
218
long
long
tmp
;
219
int
rv;
220
221
rv =
kstrtoll
(s, base, &tmp);
222
if
(rv < 0)
223
return
rv;
224
if
(tmp != (
long
long
)(
s16
)tmp)
225
return
-
ERANGE
;
226
*res =
tmp
;
227
return
0;
228
}
229
EXPORT_SYMBOL
(
kstrtos16
);
230
231
int
kstrtou8
(
const
char
*s,
unsigned
int
base,
u8
*res)
232
{
233
unsigned
long
long
tmp
;
234
int
rv;
235
236
rv =
kstrtoull
(s, base, &tmp);
237
if
(rv < 0)
238
return
rv;
239
if
(tmp != (
unsigned
long
long
)(
u8
)tmp)
240
return
-
ERANGE
;
241
*res =
tmp
;
242
return
0;
243
}
244
EXPORT_SYMBOL
(
kstrtou8
);
245
246
int
kstrtos8
(
const
char
*s,
unsigned
int
base,
s8
*res)
247
{
248
long
long
tmp
;
249
int
rv;
250
251
rv =
kstrtoll
(s, base, &tmp);
252
if
(rv < 0)
253
return
rv;
254
if
(tmp != (
long
long
)(
s8
)tmp)
255
return
-
ERANGE
;
256
*res =
tmp
;
257
return
0;
258
}
259
EXPORT_SYMBOL
(
kstrtos8
);
260
261
#define kstrto_from_user(f, g, type) \
262
int f(const char __user *s, size_t count, unsigned int base, type *res) \
263
{ \
264
/* sign, base 2 representation, newline, terminator */
\
265
char buf[1 + sizeof(type) * 8 + 1 + 1]; \
266
\
267
count = min(count, sizeof(buf) - 1); \
268
if (copy_from_user(buf, s, count)) \
269
return -EFAULT; \
270
buf[count] = '\0'; \
271
return g(buf, base, res); \
272
} \
273
EXPORT_SYMBOL(f)
274
275
kstrto_from_user
(
kstrtoull_from_user
,
kstrtoull
,
unsigned
long
long
);
276
kstrto_from_user
(
kstrtoll_from_user
,
kstrtoll
,
long
long
);
277
kstrto_from_user
(
kstrtoul_from_user
, kstrtoul,
unsigned
long
);
278
kstrto_from_user
(
kstrtol_from_user
, kstrtol,
long
);
279
kstrto_from_user
(
kstrtouint_from_user
,
kstrtouint
,
unsigned
int
);
280
kstrto_from_user
(
kstrtoint_from_user
,
kstrtoint
,
int
);
281
kstrto_from_user
(
kstrtou16_from_user
,
kstrtou16
,
u16
);
282
kstrto_from_user
(
kstrtos16_from_user
,
kstrtos16
,
s16
);
283
kstrto_from_user
(
kstrtou8_from_user
,
kstrtou8
,
u8
);
284
kstrto_from_user
(
kstrtos8_from_user
,
kstrtos8
,
s8
);
Generated on Thu Jan 10 2013 14:55:41 for Linux Kernel by
1.8.2