1 /* $NetBSD: strsuftoll.c,v 1.1 2002/11/29 12:58:17 lukem Exp $ */ 2 /*- 3 * Copyright (c) 2001-2002 The NetBSD Foundation, Inc. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to The NetBSD Foundation 7 * by Luke Mewburn. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the NetBSD 20 * Foundation, Inc. and its contributors. 21 * 4. Neither the name of The NetBSD Foundation nor the names of its 22 * contributors may be used to endorse or promote products derived 23 * from this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 26 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 /*- 38 * Copyright (c) 1991, 1993, 1994 39 * The Regents of the University of California. All rights reserved. 40 * 41 * This code is derived from software contributed to Berkeley by 42 * Keith Muller of the University of California, San Diego and Lance 43 * Visser of Convex Computer Corporation. 44 * 45 * Redistribution and use in source and binary forms, with or without 46 * modification, are permitted provided that the following conditions 47 * are met: 48 * 1. Redistributions of source code must retain the above copyright 49 * notice, this list of conditions and the following disclaimer. 50 * 2. Redistributions in binary form must reproduce the above copyright 51 * notice, this list of conditions and the following disclaimer in the 52 * documentation and/or other materials provided with the distribution. 53 * 3. All advertising materials mentioning features or use of this software 54 * must display the following acknowledgement: 55 * This product includes software developed by the University of 56 * California, Berkeley and its contributors. 57 * 4. Neither the name of the University nor the names of its contributors 58 * may be used to endorse or promote products derived from this software 59 * without specific prior written permission. 60 * 61 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 62 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 63 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 64 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 65 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 66 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 67 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 68 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 69 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 70 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 71 * SUCH DAMAGE. 72 */ 73 74 #include <sys/cdefs.h> 75 76 #if defined(LIBC_SCCS) && !defined(lint) 77 __RCSID("$NetBSD: strsuftoll.c,v 1.1 2002/11/29 12:58:17 lukem Exp $"); 78 #endif /* LIBC_SCCS and not lint */ 79 80 #ifdef _LIBC 81 #include "namespace.h" 82 #endif 83 84 #if HAVE_CONFIG_H 85 #include "config.h" 86 #endif 87 88 #if !HAVE_STRSUFTOLL 89 90 #include <sys/types.h> 91 #include <sys/time.h> 92 93 #include <assert.h> 94 #include <ctype.h> 95 #include <err.h> 96 #include <errno.h> 97 #include <limits.h> 98 #include <stdio.h> 99 #include <stdlib.h> 100 #include <string.h> 101 102 #ifdef _LIBC 103 # define _STRSUFTOLL _strsuftoll 104 # define _STRSUFTOLLX _strsuftollx 105 # ifdef __weak_alias 106 __weak_alias(strsuftoll, _strsuftoll) 107 __weak_alias(strsuftollx, _strsuftollx) 108 # endif 109 #else /* !LIBC */ 110 # define _STRSUFTOLL strsuftoll 111 # define _STRSUFTOLLX strsuftollx 112 #endif /* !LIBC */ 113 114 /* 115 * Convert an expression of the following forms to a (u)int64_t. 116 * 1) A positive decimal number. 117 * 2) A positive decimal number followed by a b (mult by 512). 118 * 3) A positive decimal number followed by a k (mult by 1024). 119 * 4) A positive decimal number followed by a m (mult by 1048576). 120 * 5) A positive decimal number followed by a w (mult by sizeof int) 121 * 6) Two or more positive decimal numbers (with/without k,b or w). 122 * separated by x (also * for backwards compatibility), specifying 123 * the product of the indicated values. 124 * Returns the result upon successful conversion, or exits with an 125 * appropriate error. 126 * 127 */ 128 /* LONGLONG */ 129 long long 130 _STRSUFTOLL(const char *desc, const char *val, 131 long long min, long long max) 132 { 133 long long result; 134 char errbuf[100]; 135 136 result = strsuftollx(desc, val, min, max, errbuf, sizeof(errbuf)); 137 if (*errbuf != '\0') 138 errx(1, "%s", errbuf); 139 return (result); 140 } 141 142 /* 143 * As strsuftoll(), but returns the error message into the provided buffer 144 * rather than exiting with it. 145 */ 146 /* LONGLONG */ 147 long long 148 _STRSUFTOLLX(const char *desc, const char *val, 149 long long min, long long max, char *ebuf, size_t ebuflen) 150 { 151 long long num, t; 152 char *expr; 153 154 _DIAGASSERT(desc != NULL); 155 _DIAGASSERT(val != NULL); 156 _DIAGASSERT(ebuf != NULL); 157 158 errno = 0; 159 ebuf[0] = '\0'; 160 161 while (isspace((unsigned char)*val)) /* Skip leading space */ 162 val++; 163 164 num = strtoll(val, &expr, 0); 165 if (errno == ERANGE) 166 goto erange; /* Overflow */ 167 168 if (expr == val) /* No digits */ 169 goto badnum; 170 171 switch (*expr) { 172 case 'b': 173 t = num; 174 num *= 512; /* 1 block */ 175 if (t > num) 176 goto erange; 177 ++expr; 178 break; 179 case 'k': 180 t = num; 181 num *= 1024; /* 1 kilobyte */ 182 if (t > num) 183 goto erange; 184 ++expr; 185 break; 186 case 'm': 187 t = num; 188 num *= 1048576; /* 1 megabyte */ 189 if (t > num) 190 goto erange; 191 ++expr; 192 break; 193 case 'g': 194 t = num; 195 num *= 1073741824; /* 1 gigabyte */ 196 if (t > num) 197 goto erange; 198 ++expr; 199 break; 200 case 't': 201 t = num; 202 num *= 1099511627776LL; /* 1 terabyte */ 203 if (t > num) 204 goto erange; 205 ++expr; 206 break; 207 case 'w': 208 t = num; 209 num *= sizeof(int); /* 1 word */ 210 if (t > num) 211 goto erange; 212 ++expr; 213 break; 214 } 215 216 switch (*expr) { 217 case '\0': 218 break; 219 case '*': /* Backward compatible */ 220 case 'x': 221 t = num; 222 num *= strsuftollx(desc, expr + 1, min, max, ebuf, ebuflen); 223 if (*ebuf != '\0') 224 return (0); 225 if (t > num) { 226 erange: 227 snprintf(ebuf, ebuflen, 228 "%s: %s", desc, strerror(ERANGE)); 229 return (0); 230 } 231 break; 232 default: 233 badnum: snprintf(ebuf, ebuflen, 234 "%s `%s': illegal number", desc, val); 235 return (0); 236 } 237 if (num < min) { 238 /* LONGLONG */ 239 snprintf(ebuf, ebuflen, "%s %lld is less than %lld.", 240 desc, (long long)num, (long long)min); 241 return (0); 242 } 243 if (num > max) { 244 /* LONGLONG */ 245 snprintf(ebuf, ebuflen, 246 "%s %lld is greater than %lld.", 247 desc, (long long)num, (long long)min); 248 return (0); 249 } 250 *ebuf = '\0'; 251 return (num); 252 } 253 254 #endif /* !HAVE_STRSUFTOLL */ 255