xref: /freebsd/sys/compat/linuxkpi/common/include/linux/kstrtox.h (revision cd245b79418638e0fa8dc4027275ef5da9039993)
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 
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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