1 /*-
2 * Copyright (c) 2010 Isilon Systems, Inc.
3 * Copyright (c) 2010 iX Systems, Inc.
4 * Copyright (c) 2010 Panasas, Inc.
5 * Copyright (c) 2017-2018 Mellanox Technologies, Ltd.
6 * All rights reserved.
7 * Copyright (c) 2018 Johannes Lundberg <johalun0@gmail.com>
8 * Copyright (c) 2020-2022 The FreeBSD Foundation
9 * Copyright (c) 2021 Vladimir Kondratyev <wulf@FreeBSD.org>
10 * Copyright (c) 2023 Serenity Cyber Security, LLC
11 *
12 * Portions of this software were developed by Bjoern A. Zeeb and
13 * Emmanuel Vadot under sponsorship from the FreeBSD Foundation.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 * notice unmodified, this list of conditions, and the following
20 * disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 */
36
37 #ifndef _LINUXKPI_LINUX_KSTRTOX_H_
38 #define _LINUXKPI_LINUX_KSTRTOX_H_
39
40 #include <sys/types.h>
41 #include <sys/errno.h>
42 #include <sys/libkern.h>
43
44 #include <linux/compiler.h>
45 #include <linux/types.h>
46
47 #include <asm/uaccess.h>
48
49 static inline unsigned long long
simple_strtoull(const char * cp,char ** endp,unsigned int base)50 simple_strtoull(const char *cp, char **endp, unsigned int base)
51 {
52 return (strtouq(cp, endp, base));
53 }
54
55 static inline long long
simple_strtoll(const char * cp,char ** endp,unsigned int base)56 simple_strtoll(const char *cp, char **endp, unsigned int base)
57 {
58 return (strtoq(cp, endp, base));
59 }
60
61 static inline unsigned long
simple_strtoul(const char * cp,char ** endp,unsigned int base)62 simple_strtoul(const char *cp, char **endp, unsigned int base)
63 {
64 return (strtoul(cp, endp, base));
65 }
66
67 static inline long
simple_strtol(const char * cp,char ** endp,unsigned int base)68 simple_strtol(const char *cp, char **endp, unsigned int base)
69 {
70 return (strtol(cp, endp, base));
71 }
72
73 static inline int
kstrtoul(const char * cp,unsigned int base,unsigned long * res)74 kstrtoul(const char *cp, unsigned int base, unsigned long *res)
75 {
76 char *end;
77 unsigned long temp;
78
79 temp = strtoul(cp, &end, base);
80
81 /* skip newline character, if any */
82 if (*end == '\n')
83 end++;
84 if (*cp == 0 || *end != 0)
85 return (-EINVAL);
86
87 *res = temp;
88 return (0);
89 }
90
91 static inline int
kstrtol(const char * cp,unsigned int base,long * res)92 kstrtol(const char *cp, unsigned int base, long *res)
93 {
94 char *end;
95 long temp;
96
97 temp = strtol(cp, &end, base);
98
99 /* skip newline character, if any */
100 if (*end == '\n')
101 end++;
102 if (*cp == 0 || *end != 0)
103 return (-EINVAL);
104
105 *res = temp;
106 return (0);
107 }
108
109 static inline int
kstrtoint(const char * cp,unsigned int base,int * res)110 kstrtoint(const char *cp, unsigned int base, int *res)
111 {
112 char *end;
113 long temp;
114
115 temp = strtol(cp, &end, base);
116
117 /* skip newline character, if any */
118 if (*end == '\n')
119 end++;
120 if (*cp == 0 || *end != 0)
121 return (-EINVAL);
122 if (temp != (int)temp)
123 return (-ERANGE);
124
125 *res = (int)temp;
126 return (0);
127 }
128
129 static inline int
kstrtouint(const char * cp,unsigned int base,unsigned int * res)130 kstrtouint(const char *cp, unsigned int base, unsigned int *res)
131 {
132 char *end;
133 unsigned long temp;
134
135 temp = strtoul(cp, &end, base);
136
137 /* skip newline character, if any */
138 if (*end == '\n')
139 end++;
140 if (*cp == 0 || *end != 0)
141 return (-EINVAL);
142 if (temp != (unsigned int)temp)
143 return (-ERANGE);
144
145 *res = (unsigned int)temp;
146 return (0);
147 }
148
149 static inline int
kstrtou8(const char * cp,unsigned int base,uint8_t * res)150 kstrtou8(const char *cp, unsigned int base, uint8_t *res)
151 {
152 char *end;
153 unsigned long temp;
154
155 temp = strtoul(cp, &end, base);
156
157 /* skip newline character, if any */
158 if (*end == '\n')
159 end++;
160 if (*cp == 0 || *end != 0)
161 return (-EINVAL);
162 if (temp != (uint8_t)temp)
163 return (-ERANGE);
164
165 *res = (uint8_t)temp;
166 return (0);
167 }
168
169 static inline int
kstrtou16(const char * cp,unsigned int base,uint16_t * res)170 kstrtou16(const char *cp, unsigned int base, uint16_t *res)
171 {
172 char *end;
173 unsigned long temp;
174
175 temp = strtoul(cp, &end, base);
176
177 /* skip newline character, if any */
178 if (*end == '\n')
179 end++;
180 if (*cp == 0 || *end != 0)
181 return (-EINVAL);
182 if (temp != (uint16_t)temp)
183 return (-ERANGE);
184
185 *res = (uint16_t)temp;
186 return (0);
187 }
188
189 static inline int
kstrtou32(const char * cp,unsigned int base,uint32_t * res)190 kstrtou32(const char *cp, unsigned int base, uint32_t *res)
191 {
192 return (kstrtouint(cp, base, res));
193 }
194
195 static inline int
kstrtos32(const char * cp,unsigned int base,int32_t * res)196 kstrtos32(const char *cp, unsigned int base, int32_t *res)
197 {
198 return (kstrtoint(cp, base, res));
199 }
200
201 static inline int
kstrtos64(const char * cp,unsigned int base,int64_t * res)202 kstrtos64(const char *cp, unsigned int base, int64_t *res)
203 {
204 char *end;
205 quad_t temp;
206
207 temp = strtoq(cp, &end, base);
208
209 /* skip newline character, if any */
210 if (*end == '\n')
211 end++;
212 if (*cp == 0 || *end != 0)
213 return (-EINVAL);
214
215 *res = (int64_t)temp;
216 return (0);
217 }
218
219 static inline int
kstrtoll(const char * cp,unsigned int base,long long * res)220 kstrtoll(const char *cp, unsigned int base, long long *res)
221 {
222 return (kstrtos64(cp, base, (int64_t *)res));
223 }
224
225 static inline int
kstrtou64(const char * cp,unsigned int base,uint64_t * res)226 kstrtou64(const char *cp, unsigned int base, uint64_t *res)
227 {
228 char *end;
229 u_quad_t temp;
230
231 temp = strtouq(cp, &end, base);
232
233 /* skip newline character, if any */
234 if (*end == '\n')
235 end++;
236 if (*cp == 0 || *end != 0)
237 return (-EINVAL);
238
239 *res = (uint64_t)temp;
240 return (0);
241 }
242
243 static inline int
kstrtoull(const char * cp,unsigned int base,unsigned long long * res)244 kstrtoull(const char *cp, unsigned int base, unsigned long long *res)
245 {
246 return (kstrtou64(cp, base, (uint64_t *)res));
247 }
248
249 static inline int
kstrtobool(const char * s,bool * res)250 kstrtobool(const char *s, bool *res)
251 {
252 if (s == NULL || *s == '\0')
253 return (-EINVAL);
254
255 if (strchr("eEtTyY1", s[0]) != NULL)
256 *res = true;
257 else if (strchr("dDfFnN0", s[0]) != NULL)
258 *res = false;
259 else if (strncasecmp("on", s, 2) == 0)
260 *res = true;
261 else if (strncasecmp("of", s, 2) == 0)
262 *res = false;
263 else
264 return (-EINVAL);
265
266 return (0);
267 }
268
269 static inline int
kstrtobool_from_user(const char __user * s,size_t count,bool * res)270 kstrtobool_from_user(const char __user *s, size_t count, bool *res)
271 {
272 char buf[8] = {};
273
274 if (count > (sizeof(buf) - 1))
275 count = (sizeof(buf) - 1);
276
277 if (copy_from_user(buf, s, count))
278 return (-EFAULT);
279
280 return (kstrtobool(buf, res));
281 }
282
283 static inline int
kstrtoint_from_user(const char __user * s,size_t count,unsigned int base,int * p)284 kstrtoint_from_user(const char __user *s, size_t count, unsigned int base,
285 int *p)
286 {
287 char buf[36] = {};
288
289 if (count > (sizeof(buf) - 1))
290 count = (sizeof(buf) - 1);
291
292 if (copy_from_user(buf, s, count))
293 return (-EFAULT);
294
295 return (kstrtoint(buf, base, p));
296 }
297
298 static inline int
kstrtouint_from_user(const char __user * s,size_t count,unsigned int base,unsigned int * p)299 kstrtouint_from_user(const char __user *s, size_t count, unsigned int base,
300 unsigned int *p)
301 {
302 char buf[36] = {};
303
304 if (count > (sizeof(buf) - 1))
305 count = (sizeof(buf) - 1);
306
307 if (copy_from_user(buf, s, count))
308 return (-EFAULT);
309
310 return (kstrtouint(buf, base, p));
311 }
312
313 static inline int
kstrtou32_from_user(const char __user * s,size_t count,unsigned int base,unsigned int * p)314 kstrtou32_from_user(const char __user *s, size_t count, unsigned int base,
315 unsigned int *p)
316 {
317 return (kstrtouint_from_user(s, count, base, p));
318 }
319
320 static inline int
kstrtou8_from_user(const char __user * s,size_t count,unsigned int base,uint8_t * p)321 kstrtou8_from_user(const char __user *s, size_t count, unsigned int base,
322 uint8_t *p)
323 {
324 char buf[8] = {};
325
326 if (count > (sizeof(buf) - 1))
327 count = (sizeof(buf) - 1);
328
329 if (copy_from_user(buf, s, count))
330 return (-EFAULT);
331
332 return (kstrtou8(buf, base, p));
333 }
334
335 #endif /* _LINUXKPI_LINUX_KSTRTOX_H_ */
336