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
kstrtos64(const char * cp,unsigned int base,int64_t * res)183 kstrtos64(const char *cp, unsigned int base, int64_t *res)
184 {
185 char *end;
186
187 *res = strtoq(cp, &end, base);
188
189 /* skip newline character, if any */
190 if (*end == '\n')
191 end++;
192 if (*cp == 0 || *end != 0)
193 return (-EINVAL);
194 return (0);
195 }
196
197 static inline int
kstrtoll(const char * cp,unsigned int base,long long * res)198 kstrtoll(const char *cp, unsigned int base, long long *res)
199 {
200 return (kstrtos64(cp, base, (int64_t *)res));
201 }
202
203 static inline int
kstrtou64(const char * cp,unsigned int base,u64 * res)204 kstrtou64(const char *cp, unsigned int base, u64 *res)
205 {
206 char *end;
207
208 *res = strtouq(cp, &end, base);
209
210 /* skip newline character, if any */
211 if (*end == '\n')
212 end++;
213 if (*cp == 0 || *end != 0)
214 return (-EINVAL);
215 return (0);
216 }
217
218 static inline int
kstrtoull(const char * cp,unsigned int base,unsigned long long * res)219 kstrtoull(const char *cp, unsigned int base, unsigned long long *res)
220 {
221 return (kstrtou64(cp, base, (uint64_t *)res));
222 }
223
224 static inline int
kstrtobool(const char * s,bool * res)225 kstrtobool(const char *s, bool *res)
226 {
227 int len;
228
229 if (s == NULL || (len = strlen(s)) == 0 || res == NULL)
230 return (-EINVAL);
231
232 /* skip newline character, if any */
233 if (s[len - 1] == '\n')
234 len--;
235
236 if (len == 1 && strchr("yY1", s[0]) != NULL)
237 *res = true;
238 else if (len == 1 && strchr("nN0", s[0]) != NULL)
239 *res = false;
240 else if (strncasecmp("on", s, len) == 0)
241 *res = true;
242 else if (strncasecmp("off", s, len) == 0)
243 *res = false;
244 else
245 return (-EINVAL);
246
247 return (0);
248 }
249
250 static inline int
kstrtobool_from_user(const char __user * s,size_t count,bool * res)251 kstrtobool_from_user(const char __user *s, size_t count, bool *res)
252 {
253 char buf[8] = {};
254
255 if (count > (sizeof(buf) - 1))
256 count = (sizeof(buf) - 1);
257
258 if (copy_from_user(buf, s, count))
259 return (-EFAULT);
260
261 return (kstrtobool(buf, res));
262 }
263
264 static inline int
kstrtoint_from_user(const char __user * s,size_t count,unsigned int base,int * p)265 kstrtoint_from_user(const char __user *s, size_t count, unsigned int base,
266 int *p)
267 {
268 char buf[36] = {};
269
270 if (count > (sizeof(buf) - 1))
271 count = (sizeof(buf) - 1);
272
273 if (copy_from_user(buf, s, count))
274 return (-EFAULT);
275
276 return (kstrtoint(buf, base, p));
277 }
278
279 static inline int
kstrtouint_from_user(const char __user * s,size_t count,unsigned int base,unsigned int * p)280 kstrtouint_from_user(const char __user *s, size_t count, unsigned int base,
281 unsigned int *p)
282 {
283 char buf[36] = {};
284
285 if (count > (sizeof(buf) - 1))
286 count = (sizeof(buf) - 1);
287
288 if (copy_from_user(buf, s, count))
289 return (-EFAULT);
290
291 return (kstrtouint(buf, base, p));
292 }
293
294 static inline int
kstrtou32_from_user(const char __user * s,size_t count,unsigned int base,unsigned int * p)295 kstrtou32_from_user(const char __user *s, size_t count, unsigned int base,
296 unsigned int *p)
297 {
298
299 return (kstrtouint_from_user(s, count, base, p));
300 }
301
302 static inline int
kstrtou8_from_user(const char __user * s,size_t count,unsigned int base,uint8_t * p)303 kstrtou8_from_user(const char __user *s, size_t count, unsigned int base,
304 uint8_t *p)
305 {
306 char buf[8] = {};
307
308 if (count > (sizeof(buf) - 1))
309 count = (sizeof(buf) - 1);
310
311 if (copy_from_user(buf, s, count))
312 return (-EFAULT);
313
314 return (kstrtou8(buf, base, p));
315 }
316
317 #endif /* _LINUXKPI_LINUX_KSTRTOX_H_ */
318