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 kstrtos64(const char *cp, unsigned int base, int64_t *res) 184 { 185 char *end; 186 187 *res = strtoq(cp, &end, base); 188 189 /* skip newline character, if any */ 190 if (*end == '\n') 191 end++; 192 if (*cp == 0 || *end != 0) 193 return (-EINVAL); 194 return (0); 195 } 196 197 static inline int 198 kstrtoll(const char *cp, unsigned int base, long long *res) 199 { 200 return (kstrtos64(cp, base, (int64_t *)res)); 201 } 202 203 static inline int 204 kstrtou64(const char *cp, unsigned int base, u64 *res) 205 { 206 char *end; 207 208 *res = strtouq(cp, &end, base); 209 210 /* skip newline character, if any */ 211 if (*end == '\n') 212 end++; 213 if (*cp == 0 || *end != 0) 214 return (-EINVAL); 215 return (0); 216 } 217 218 static inline int 219 kstrtoull(const char *cp, unsigned int base, unsigned long long *res) 220 { 221 return (kstrtou64(cp, base, (uint64_t *)res)); 222 } 223 224 static inline int 225 kstrtobool(const char *s, bool *res) 226 { 227 int len; 228 229 if (s == NULL || (len = strlen(s)) == 0 || res == NULL) 230 return (-EINVAL); 231 232 /* skip newline character, if any */ 233 if (s[len - 1] == '\n') 234 len--; 235 236 if (len == 1 && strchr("yY1", s[0]) != NULL) 237 *res = true; 238 else if (len == 1 && strchr("nN0", s[0]) != NULL) 239 *res = false; 240 else if (strncasecmp("on", s, len) == 0) 241 *res = true; 242 else if (strncasecmp("off", s, len) == 0) 243 *res = false; 244 else 245 return (-EINVAL); 246 247 return (0); 248 } 249 250 static inline int 251 kstrtobool_from_user(const char __user *s, size_t count, bool *res) 252 { 253 char buf[8] = {}; 254 255 if (count > (sizeof(buf) - 1)) 256 count = (sizeof(buf) - 1); 257 258 if (copy_from_user(buf, s, count)) 259 return (-EFAULT); 260 261 return (kstrtobool(buf, res)); 262 } 263 264 static inline int 265 kstrtoint_from_user(const char __user *s, size_t count, unsigned int base, 266 int *p) 267 { 268 char buf[36] = {}; 269 270 if (count > (sizeof(buf) - 1)) 271 count = (sizeof(buf) - 1); 272 273 if (copy_from_user(buf, s, count)) 274 return (-EFAULT); 275 276 return (kstrtoint(buf, base, p)); 277 } 278 279 static inline int 280 kstrtouint_from_user(const char __user *s, size_t count, unsigned int base, 281 unsigned int *p) 282 { 283 char buf[36] = {}; 284 285 if (count > (sizeof(buf) - 1)) 286 count = (sizeof(buf) - 1); 287 288 if (copy_from_user(buf, s, count)) 289 return (-EFAULT); 290 291 return (kstrtouint(buf, base, p)); 292 } 293 294 static inline int 295 kstrtou32_from_user(const char __user *s, size_t count, unsigned int base, 296 unsigned int *p) 297 { 298 299 return (kstrtouint_from_user(s, count, base, p)); 300 } 301 302 static inline int 303 kstrtou8_from_user(const char __user *s, size_t count, unsigned int base, 304 uint8_t *p) 305 { 306 char buf[8] = {}; 307 308 if (count > (sizeof(buf) - 1)) 309 count = (sizeof(buf) - 1); 310 311 if (copy_from_user(buf, s, count)) 312 return (-EFAULT); 313 314 return (kstrtou8(buf, base, p)); 315 } 316 317 #endif /* _LINUXKPI_LINUX_KSTRTOX_H_ */ 318