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