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
78 *res = strtoul(cp, &end, base);
79
80 /* skip newline character, if any */
81 if (*end == '\n')
82 end++;
83 if (*cp == 0 || *end != 0)
84 return (-EINVAL);
85 return (0);
86 }
87
88 static inline int
kstrtol(const char * cp,unsigned int base,long * res)89 kstrtol(const char *cp, unsigned int base, long *res)
90 {
91 char *end;
92
93 *res = strtol(cp, &end, base);
94
95 /* skip newline character, if any */
96 if (*end == '\n')
97 end++;
98 if (*cp == 0 || *end != 0)
99 return (-EINVAL);
100 return (0);
101 }
102
103 static inline int
kstrtoint(const char * cp,unsigned int base,int * res)104 kstrtoint(const char *cp, unsigned int base, int *res)
105 {
106 char *end;
107 long temp;
108
109 *res = temp = strtol(cp, &end, base);
110
111 /* skip newline character, if any */
112 if (*end == '\n')
113 end++;
114 if (*cp == 0 || *end != 0)
115 return (-EINVAL);
116 if (temp != (int)temp)
117 return (-ERANGE);
118 return (0);
119 }
120
121 static inline int
kstrtouint(const char * cp,unsigned int base,unsigned int * res)122 kstrtouint(const char *cp, unsigned int base, unsigned int *res)
123 {
124 char *end;
125 unsigned long temp;
126
127 *res = temp = strtoul(cp, &end, base);
128
129 /* skip newline character, if any */
130 if (*end == '\n')
131 end++;
132 if (*cp == 0 || *end != 0)
133 return (-EINVAL);
134 if (temp != (unsigned int)temp)
135 return (-ERANGE);
136 return (0);
137 }
138
139 static inline int
kstrtou8(const char * cp,unsigned int base,uint8_t * res)140 kstrtou8(const char *cp, unsigned int base, uint8_t *res)
141 {
142 char *end;
143 unsigned long temp;
144
145 *res = temp = strtoul(cp, &end, base);
146
147 /* skip newline character, if any */
148 if (*end == '\n')
149 end++;
150 if (*cp == 0 || *end != 0)
151 return (-EINVAL);
152 if (temp != (uint8_t)temp)
153 return (-ERANGE);
154 return (0);
155 }
156
157 static inline int
kstrtou16(const char * cp,unsigned int base,uint16_t * res)158 kstrtou16(const char *cp, unsigned int base, uint16_t *res)
159 {
160 char *end;
161 unsigned long temp;
162
163 *res = temp = strtoul(cp, &end, base);
164
165 /* skip newline character, if any */
166 if (*end == '\n')
167 end++;
168 if (*cp == 0 || *end != 0)
169 return (-EINVAL);
170 if (temp != (uint16_t)temp)
171 return (-ERANGE);
172 return (0);
173 }
174
175 static inline int
kstrtou32(const char * cp,unsigned int base,uint32_t * res)176 kstrtou32(const char *cp, unsigned int base, uint32_t *res)
177 {
178
179 return (kstrtouint(cp, base, res));
180 }
181
182 static inline int
kstrtos32(const char * cp,unsigned int base,int32_t * res)183 kstrtos32(const char *cp, unsigned int base, int32_t *res)
184 {
185
186 return (kstrtoint(cp, base, res));
187 }
188
189 static inline int
kstrtos64(const char * cp,unsigned int base,int64_t * res)190 kstrtos64(const char *cp, unsigned int base, int64_t *res)
191 {
192 char *end;
193
194 *res = strtoq(cp, &end, base);
195
196 /* skip newline character, if any */
197 if (*end == '\n')
198 end++;
199 if (*cp == 0 || *end != 0)
200 return (-EINVAL);
201 return (0);
202 }
203
204 static inline int
kstrtoll(const char * cp,unsigned int base,long long * res)205 kstrtoll(const char *cp, unsigned int base, long long *res)
206 {
207 return (kstrtos64(cp, base, (int64_t *)res));
208 }
209
210 static inline int
kstrtou64(const char * cp,unsigned int base,u64 * res)211 kstrtou64(const char *cp, unsigned int base, u64 *res)
212 {
213 char *end;
214
215 *res = strtouq(cp, &end, base);
216
217 /* skip newline character, if any */
218 if (*end == '\n')
219 end++;
220 if (*cp == 0 || *end != 0)
221 return (-EINVAL);
222 return (0);
223 }
224
225 static inline int
kstrtoull(const char * cp,unsigned int base,unsigned long long * res)226 kstrtoull(const char *cp, unsigned int base, unsigned long long *res)
227 {
228 return (kstrtou64(cp, base, (uint64_t *)res));
229 }
230
231 static inline int
kstrtobool(const char * s,bool * res)232 kstrtobool(const char *s, bool *res)
233 {
234 int len;
235
236 if (s == NULL || (len = strlen(s)) == 0 || res == NULL)
237 return (-EINVAL);
238
239 /* skip newline character, if any */
240 if (s[len - 1] == '\n')
241 len--;
242
243 if (len == 1 && strchr("yY1", s[0]) != NULL)
244 *res = true;
245 else if (len == 1 && strchr("nN0", s[0]) != NULL)
246 *res = false;
247 else if (strncasecmp("on", s, len) == 0)
248 *res = true;
249 else if (strncasecmp("off", s, len) == 0)
250 *res = false;
251 else
252 return (-EINVAL);
253
254 return (0);
255 }
256
257 static inline int
kstrtobool_from_user(const char __user * s,size_t count,bool * res)258 kstrtobool_from_user(const char __user *s, size_t count, bool *res)
259 {
260 char buf[8] = {};
261
262 if (count > (sizeof(buf) - 1))
263 count = (sizeof(buf) - 1);
264
265 if (copy_from_user(buf, s, count))
266 return (-EFAULT);
267
268 return (kstrtobool(buf, res));
269 }
270
271 static inline int
kstrtoint_from_user(const char __user * s,size_t count,unsigned int base,int * p)272 kstrtoint_from_user(const char __user *s, size_t count, unsigned int base,
273 int *p)
274 {
275 char buf[36] = {};
276
277 if (count > (sizeof(buf) - 1))
278 count = (sizeof(buf) - 1);
279
280 if (copy_from_user(buf, s, count))
281 return (-EFAULT);
282
283 return (kstrtoint(buf, base, p));
284 }
285
286 static inline int
kstrtouint_from_user(const char __user * s,size_t count,unsigned int base,unsigned int * p)287 kstrtouint_from_user(const char __user *s, size_t count, unsigned int base,
288 unsigned int *p)
289 {
290 char buf[36] = {};
291
292 if (count > (sizeof(buf) - 1))
293 count = (sizeof(buf) - 1);
294
295 if (copy_from_user(buf, s, count))
296 return (-EFAULT);
297
298 return (kstrtouint(buf, base, p));
299 }
300
301 static inline int
kstrtou32_from_user(const char __user * s,size_t count,unsigned int base,unsigned int * p)302 kstrtou32_from_user(const char __user *s, size_t count, unsigned int base,
303 unsigned int *p)
304 {
305
306 return (kstrtouint_from_user(s, count, base, p));
307 }
308
309 static inline int
kstrtou8_from_user(const char __user * s,size_t count,unsigned int base,uint8_t * p)310 kstrtou8_from_user(const char __user *s, size_t count, unsigned int base,
311 uint8_t *p)
312 {
313 char buf[8] = {};
314
315 if (count > (sizeof(buf) - 1))
316 count = (sizeof(buf) - 1);
317
318 if (copy_from_user(buf, s, count))
319 return (-EFAULT);
320
321 return (kstrtou8(buf, base, p));
322 }
323
324 #endif /* _LINUXKPI_LINUX_KSTRTOX_H_ */
325