xref: /freebsd/sys/compat/linuxkpi/common/include/linux/kstrtox.h (revision d448578b445da95806ef9af996a0db9754daadeb)
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
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
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
62 simple_strtoul(const char *cp, char **endp, unsigned int base)
63 {
64 	return (strtoul(cp, endp, base));
65 }
66 
67 static inline long
68 simple_strtol(const char *cp, char **endp, unsigned int base)
69 {
70 	return (strtol(cp, endp, base));
71 }
72 
73 static inline int
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
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
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
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
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
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
190 kstrtou32(const char *cp, unsigned int base, uint32_t *res)
191 {
192 	return (kstrtouint(cp, base, res));
193 }
194 
195 static inline int
196 kstrtos32(const char *cp, unsigned int base, int32_t *res)
197 {
198 	return (kstrtoint(cp, base, res));
199 }
200 
201 static inline int
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
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
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
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
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
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
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
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
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
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