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