xref: /freebsd/sys/compat/linuxkpi/common/include/linux/kstrtox.h (revision a97f3a9ec96a2de542326a158d1ab8e65ad4fe5f)
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  *
11  * Portions of this software were developed by Bjoern A. Zeeb and
12  * Emmanuel Vadot under sponsorship from the FreeBSD Foundation.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  * 1. Redistributions of source code must retain the above copyright
18  *    notice unmodified, this list of conditions, and the following
19  *    disclaimer.
20  * 2. Redistributions in binary form must reproduce the above copyright
21  *    notice, this list of conditions and the following disclaimer in the
22  *    documentation and/or other materials provided with the distribution.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 #ifndef	_LINUXKPI_LINUX_KSTRTOX_H_
37 #define	_LINUXKPI_LINUX_KSTRTOX_H_
38 
39 #include <sys/types.h>
40 #include <sys/errno.h>
41 #include <sys/libkern.h>
42 
43 #include <linux/compiler.h>
44 #include <linux/types.h>
45 
46 #include <asm/uaccess.h>
47 
48 static inline unsigned long long
49 simple_strtoull(const char *cp, char **endp, unsigned int base)
50 {
51 	return (strtouq(cp, endp, base));
52 }
53 
54 static inline long long
55 simple_strtoll(const char *cp, char **endp, unsigned int base)
56 {
57 	return (strtoq(cp, endp, base));
58 }
59 
60 static inline unsigned long
61 simple_strtoul(const char *cp, char **endp, unsigned int base)
62 {
63 	return (strtoul(cp, endp, base));
64 }
65 
66 static inline long
67 simple_strtol(const char *cp, char **endp, unsigned int base)
68 {
69 	return (strtol(cp, endp, base));
70 }
71 
72 static inline int
73 kstrtoul(const char *cp, unsigned int base, unsigned long *res)
74 {
75 	char *end;
76 
77 	*res = strtoul(cp, &end, base);
78 
79 	/* skip newline character, if any */
80 	if (*end == '\n')
81 		end++;
82 	if (*cp == 0 || *end != 0)
83 		return (-EINVAL);
84 	return (0);
85 }
86 
87 static inline int
88 kstrtol(const char *cp, unsigned int base, long *res)
89 {
90 	char *end;
91 
92 	*res = strtol(cp, &end, base);
93 
94 	/* skip newline character, if any */
95 	if (*end == '\n')
96 		end++;
97 	if (*cp == 0 || *end != 0)
98 		return (-EINVAL);
99 	return (0);
100 }
101 
102 static inline int
103 kstrtoint(const char *cp, unsigned int base, int *res)
104 {
105 	char *end;
106 	long temp;
107 
108 	*res = temp = strtol(cp, &end, base);
109 
110 	/* skip newline character, if any */
111 	if (*end == '\n')
112 		end++;
113 	if (*cp == 0 || *end != 0)
114 		return (-EINVAL);
115 	if (temp != (int)temp)
116 		return (-ERANGE);
117 	return (0);
118 }
119 
120 static inline int
121 kstrtouint(const char *cp, unsigned int base, unsigned int *res)
122 {
123 	char *end;
124 	unsigned long temp;
125 
126 	*res = temp = strtoul(cp, &end, base);
127 
128 	/* skip newline character, if any */
129 	if (*end == '\n')
130 		end++;
131 	if (*cp == 0 || *end != 0)
132 		return (-EINVAL);
133 	if (temp != (unsigned int)temp)
134 		return (-ERANGE);
135 	return (0);
136 }
137 
138 static inline int
139 kstrtou8(const char *cp, unsigned int base, u8 *res)
140 {
141 	char *end;
142 	unsigned long temp;
143 
144 	*res = temp = strtoul(cp, &end, base);
145 
146 	/* skip newline character, if any */
147 	if (*end == '\n')
148 		end++;
149 	if (*cp == 0 || *end != 0)
150 		return (-EINVAL);
151 	if (temp != (u8)temp)
152 		return (-ERANGE);
153 	return (0);
154 }
155 
156 static inline int
157 kstrtou16(const char *cp, unsigned int base, u16 *res)
158 {
159 	char *end;
160 	unsigned long temp;
161 
162 	*res = temp = strtoul(cp, &end, base);
163 
164 	/* skip newline character, if any */
165 	if (*end == '\n')
166 		end++;
167 	if (*cp == 0 || *end != 0)
168 		return (-EINVAL);
169 	if (temp != (u16)temp)
170 		return (-ERANGE);
171 	return (0);
172 }
173 
174 static inline int
175 kstrtou32(const char *cp, unsigned int base, u32 *res)
176 {
177 
178 	return (kstrtouint(cp, base, res));
179 }
180 
181 static inline int
182 kstrtos64(const char *cp, unsigned int base, s64 *res)
183 {
184 	char *end;
185 
186 	*res = strtoq(cp, &end, base);
187 
188 	/* skip newline character, if any */
189 	if (*end == '\n')
190 		end++;
191 	if (*cp == 0 || *end != 0)
192 		return (-EINVAL);
193 	return (0);
194 }
195 
196 static inline int
197 kstrtou64(const char *cp, unsigned int base, u64 *res)
198 {
199 	char *end;
200 
201 	*res = strtouq(cp, &end, base);
202 
203 	/* skip newline character, if any */
204 	if (*end == '\n')
205 		end++;
206 	if (*cp == 0 || *end != 0)
207 		return (-EINVAL);
208 	return (0);
209 }
210 
211 static inline int
212 kstrtoull(const char *cp, unsigned int base, unsigned long long *res)
213 {
214 	return (kstrtou64(cp, base, (u64 *)res));
215 }
216 
217 static inline int
218 kstrtobool(const char *s, bool *res)
219 {
220 	int len;
221 
222 	if (s == NULL || (len = strlen(s)) == 0 || res == NULL)
223 		return (-EINVAL);
224 
225 	/* skip newline character, if any */
226 	if (s[len - 1] == '\n')
227 		len--;
228 
229 	if (len == 1 && strchr("yY1", s[0]) != NULL)
230 		*res = true;
231 	else if (len == 1 && strchr("nN0", s[0]) != NULL)
232 		*res = false;
233 	else if (strncasecmp("on", s, len) == 0)
234 		*res = true;
235 	else if (strncasecmp("off", s, len) == 0)
236 		*res = false;
237 	else
238 		return (-EINVAL);
239 
240 	return (0);
241 }
242 
243 static inline int
244 kstrtobool_from_user(const char __user *s, size_t count, bool *res)
245 {
246 	char buf[8] = {};
247 
248 	if (count > (sizeof(buf) - 1))
249 		count = (sizeof(buf) - 1);
250 
251 	if (copy_from_user(buf, s, count))
252 		return (-EFAULT);
253 
254 	return (kstrtobool(buf, res));
255 }
256 
257 static inline int
258 kstrtoint_from_user(const char __user *s, size_t count, unsigned int base,
259     int *p)
260 {
261 	char buf[36] = {};
262 
263 	if (count > (sizeof(buf) - 1))
264 		count = (sizeof(buf) - 1);
265 
266 	if (copy_from_user(buf, s, count))
267 		return (-EFAULT);
268 
269 	return (kstrtoint(buf, base, p));
270 }
271 
272 static inline int
273 kstrtouint_from_user(const char __user *s, size_t count, unsigned int base,
274     unsigned int *p)
275 {
276 	char buf[36] = {};
277 
278 	if (count > (sizeof(buf) - 1))
279 		count = (sizeof(buf) - 1);
280 
281 	if (copy_from_user(buf, s, count))
282 		return (-EFAULT);
283 
284 	return (kstrtouint(buf, base, p));
285 }
286 
287 static inline int
288 kstrtou32_from_user(const char __user *s, size_t count, unsigned int base,
289     unsigned int *p)
290 {
291 
292 	return (kstrtouint_from_user(s, count, base, p));
293 }
294 
295 static inline int
296 kstrtou8_from_user(const char __user *s, size_t count, unsigned int base,
297     u8 *p)
298 {
299 	char buf[8] = {};
300 
301 	if (count > (sizeof(buf) - 1))
302 		count = (sizeof(buf) - 1);
303 
304 	if (copy_from_user(buf, s, count))
305 		return (-EFAULT);
306 
307 	return (kstrtou8(buf, base, p));
308 }
309 
310 #endif	/* _LINUXKPI_LINUX_KSTRTOX_H_ */
311