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