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