1*2ef9abdcSjv227347 /* 2*2ef9abdcSjv227347 * CDDL HEADER START 3*2ef9abdcSjv227347 * 4*2ef9abdcSjv227347 * The contents of this file are subject to the terms of the 5*2ef9abdcSjv227347 * Common Development and Distribution License (the "License"). 6*2ef9abdcSjv227347 * You may not use this file except in compliance with the License. 7*2ef9abdcSjv227347 * 8*2ef9abdcSjv227347 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*2ef9abdcSjv227347 * or http://www.opensolaris.org/os/licensing. 10*2ef9abdcSjv227347 * See the License for the specific language governing permissions 11*2ef9abdcSjv227347 * and limitations under the License. 12*2ef9abdcSjv227347 * 13*2ef9abdcSjv227347 * When distributing Covered Code, include this CDDL HEADER in each 14*2ef9abdcSjv227347 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*2ef9abdcSjv227347 * If applicable, add the following below this CDDL HEADER, with the 16*2ef9abdcSjv227347 * fields enclosed by brackets "[]" replaced with your own identifying 17*2ef9abdcSjv227347 * information: Portions Copyright [yyyy] [name of copyright owner] 18*2ef9abdcSjv227347 * 19*2ef9abdcSjv227347 * CDDL HEADER END 20*2ef9abdcSjv227347 */ 21*2ef9abdcSjv227347 22*2ef9abdcSjv227347 /* 23*2ef9abdcSjv227347 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24*2ef9abdcSjv227347 * Use is subject to license terms. 25*2ef9abdcSjv227347 */ 26*2ef9abdcSjv227347 27*2ef9abdcSjv227347 /* Copyright (c) 1988 AT&T */ 28*2ef9abdcSjv227347 /* All Rights Reserved */ 29*2ef9abdcSjv227347 30*2ef9abdcSjv227347 #if defined(_KERNEL) && !defined(_BOOT) 31*2ef9abdcSjv227347 #include <sys/errno.h> 32*2ef9abdcSjv227347 #else /* _KERNEL && !_BOOT */ 33*2ef9abdcSjv227347 #if !defined(_BOOT) && !defined(_KMDB) 34*2ef9abdcSjv227347 #include "lint.h" 35*2ef9abdcSjv227347 #endif /* !_BOOT && !_KMDB */ 36*2ef9abdcSjv227347 #include <errno.h> 37*2ef9abdcSjv227347 #include <ctype.h> 38*2ef9abdcSjv227347 #include <limits.h> 39*2ef9abdcSjv227347 #include <stdlib.h> 40*2ef9abdcSjv227347 #endif /* _KERNEL && !_BOOT */ 41*2ef9abdcSjv227347 #include "strtolctype.h" 42*2ef9abdcSjv227347 #include <sys/types.h> 43*2ef9abdcSjv227347 44*2ef9abdcSjv227347 #if defined(_KERNEL) && !defined(_BOOT) 45*2ef9abdcSjv227347 int 46*2ef9abdcSjv227347 ddi_strtoull(const char *str, char **nptr, int base, u_longlong_t *result) 47*2ef9abdcSjv227347 #else /* _KERNEL && !_BOOT */ 48*2ef9abdcSjv227347 u_longlong_t 49*2ef9abdcSjv227347 strtoull(const char *str, char **nptr, int base) 50*2ef9abdcSjv227347 #endif /* _KERNEL && !_BOOT */ 51*2ef9abdcSjv227347 { 52*2ef9abdcSjv227347 u_longlong_t val; 53*2ef9abdcSjv227347 int c; 54*2ef9abdcSjv227347 int xx; 55*2ef9abdcSjv227347 int neg = 0; 56*2ef9abdcSjv227347 u_longlong_t multmax; 57*2ef9abdcSjv227347 const char **ptr = (const char **)nptr; 58*2ef9abdcSjv227347 const unsigned char *ustr = (const unsigned char *)str; 59*2ef9abdcSjv227347 60*2ef9abdcSjv227347 if (ptr != (const char **)0) 61*2ef9abdcSjv227347 *ptr = (char *)ustr; /* in case no number is formed */ 62*2ef9abdcSjv227347 if (base < 0 || base > MBASE || base == 1) { 63*2ef9abdcSjv227347 /* base is invalid -- should be a fatal error */ 64*2ef9abdcSjv227347 #if defined(_KERNEL) && !defined(_BOOT) 65*2ef9abdcSjv227347 return (EINVAL); 66*2ef9abdcSjv227347 #else /* _KERNEL && !_BOOT */ 67*2ef9abdcSjv227347 errno = EINVAL; 68*2ef9abdcSjv227347 return (0); 69*2ef9abdcSjv227347 #endif /* _KERNEL && !_BOOT */ 70*2ef9abdcSjv227347 } 71*2ef9abdcSjv227347 if (!isalnum(c = *ustr)) { 72*2ef9abdcSjv227347 while (isspace(c)) 73*2ef9abdcSjv227347 c = *++ustr; 74*2ef9abdcSjv227347 switch (c) { 75*2ef9abdcSjv227347 case '-': 76*2ef9abdcSjv227347 neg++; 77*2ef9abdcSjv227347 /* FALLTHROUGH */ 78*2ef9abdcSjv227347 case '+': 79*2ef9abdcSjv227347 c = *++ustr; 80*2ef9abdcSjv227347 } 81*2ef9abdcSjv227347 } 82*2ef9abdcSjv227347 if (base == 0) 83*2ef9abdcSjv227347 if (c != '0') 84*2ef9abdcSjv227347 base = 10; 85*2ef9abdcSjv227347 else if (ustr[1] == 'x' || ustr[1] == 'X') 86*2ef9abdcSjv227347 base = 16; 87*2ef9abdcSjv227347 else 88*2ef9abdcSjv227347 base = 8; 89*2ef9abdcSjv227347 /* 90*2ef9abdcSjv227347 * for any base > 10, the digits incrementally following 91*2ef9abdcSjv227347 * 9 are assumed to be "abc...z" or "ABC...Z" 92*2ef9abdcSjv227347 */ 93*2ef9abdcSjv227347 if (!lisalnum(c) || (xx = DIGIT(c)) >= base) { 94*2ef9abdcSjv227347 /* no number formed */ 95*2ef9abdcSjv227347 #if defined(_KERNEL) && !defined(_BOOT) 96*2ef9abdcSjv227347 return (EINVAL); 97*2ef9abdcSjv227347 #else /* _KERNEL && !_BOOT */ 98*2ef9abdcSjv227347 return (0); 99*2ef9abdcSjv227347 #endif /* _KERNEL && !_BOOT */ 100*2ef9abdcSjv227347 } 101*2ef9abdcSjv227347 if (base == 16 && c == '0' && (ustr[1] == 'x' || ustr[1] == 'X') && 102*2ef9abdcSjv227347 isxdigit(ustr[2])) 103*2ef9abdcSjv227347 c = *(ustr += 2); /* skip over leading "0x" or "0X" */ 104*2ef9abdcSjv227347 105*2ef9abdcSjv227347 multmax = ULLONG_MAX / (u_longlong_t)base; 106*2ef9abdcSjv227347 val = DIGIT(c); 107*2ef9abdcSjv227347 for (c = *++ustr; lisalnum(c) && (xx = DIGIT(c)) < base; ) { 108*2ef9abdcSjv227347 if (val > multmax) 109*2ef9abdcSjv227347 goto overflow; 110*2ef9abdcSjv227347 val *= base; 111*2ef9abdcSjv227347 if (ULLONG_MAX - val < xx) 112*2ef9abdcSjv227347 goto overflow; 113*2ef9abdcSjv227347 val += xx; 114*2ef9abdcSjv227347 c = *++ustr; 115*2ef9abdcSjv227347 } 116*2ef9abdcSjv227347 if (ptr != (const char **)0) 117*2ef9abdcSjv227347 *ptr = (char *)ustr; 118*2ef9abdcSjv227347 #if defined(_KERNEL) && !defined(_BOOT) 119*2ef9abdcSjv227347 *result = neg ? -val : val; 120*2ef9abdcSjv227347 return (0); 121*2ef9abdcSjv227347 #else /* _KERNEL && !_BOOT */ 122*2ef9abdcSjv227347 return (neg ? -val : val); 123*2ef9abdcSjv227347 #endif /* _KERNEL && !_BOOT */ 124*2ef9abdcSjv227347 125*2ef9abdcSjv227347 overflow: 126*2ef9abdcSjv227347 for (c = *++ustr; lisalnum(c) && (xx = DIGIT(c)) < base; (c = *++ustr)) 127*2ef9abdcSjv227347 ; 128*2ef9abdcSjv227347 if (ptr != (const char **)0) 129*2ef9abdcSjv227347 *ptr = (char *)ustr; 130*2ef9abdcSjv227347 #if defined(_KERNEL) && !defined(_BOOT) 131*2ef9abdcSjv227347 return (ERANGE); 132*2ef9abdcSjv227347 #else /* _KERNEL && !_BOOT */ 133*2ef9abdcSjv227347 errno = ERANGE; 134*2ef9abdcSjv227347 return (ULLONG_MAX); 135*2ef9abdcSjv227347 #endif /* _KERNEL && !_BOOT */ 136*2ef9abdcSjv227347 } 137