1 /* $NetBSD: strsuftoll.c,v 1.2 2003/02/08 07:27:51 itohy 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.2 2003/02/08 07:27:51 itohy 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 # ifdef __weak_alias 104 __weak_alias(strsuftoll, _strsuftoll) 105 __weak_alias(strsuftollx, _strsuftollx) 106 # endif 107 #endif /* LIBC */ 108 109 /* 110 * Convert an expression of the following forms to a (u)int64_t. 111 * 1) A positive decimal number. 112 * 2) A positive decimal number followed by a b (mult by 512). 113 * 3) A positive decimal number followed by a k (mult by 1024). 114 * 4) A positive decimal number followed by a m (mult by 1048576). 115 * 5) A positive decimal number followed by a w (mult by sizeof int) 116 * 6) Two or more positive decimal numbers (with/without k,b or w). 117 * separated by x (also * for backwards compatibility), specifying 118 * the product of the indicated values. 119 * Returns the result upon successful conversion, or exits with an 120 * appropriate error. 121 * 122 */ 123 /* LONGLONG */ 124 long long 125 strsuftoll(const char *desc, const char *val, 126 long long min, long long max) 127 { 128 long long result; 129 char errbuf[100]; 130 131 result = strsuftollx(desc, val, min, max, errbuf, sizeof(errbuf)); 132 if (*errbuf != '\0') 133 errx(1, "%s", errbuf); 134 return (result); 135 } 136 137 /* 138 * As strsuftoll(), but returns the error message into the provided buffer 139 * rather than exiting with it. 140 */ 141 /* LONGLONG */ 142 long long 143 strsuftollx(const char *desc, const char *val, 144 long long min, long long max, char *ebuf, size_t ebuflen) 145 { 146 long long num, t; 147 char *expr; 148 149 _DIAGASSERT(desc != NULL); 150 _DIAGASSERT(val != NULL); 151 _DIAGASSERT(ebuf != NULL); 152 153 errno = 0; 154 ebuf[0] = '\0'; 155 156 while (isspace((unsigned char)*val)) /* Skip leading space */ 157 val++; 158 159 num = strtoll(val, &expr, 0); 160 if (errno == ERANGE) 161 goto erange; /* Overflow */ 162 163 if (expr == val) /* No digits */ 164 goto badnum; 165 166 switch (*expr) { 167 case 'b': 168 t = num; 169 num *= 512; /* 1 block */ 170 if (t > num) 171 goto erange; 172 ++expr; 173 break; 174 case 'k': 175 t = num; 176 num *= 1024; /* 1 kilobyte */ 177 if (t > num) 178 goto erange; 179 ++expr; 180 break; 181 case 'm': 182 t = num; 183 num *= 1048576; /* 1 megabyte */ 184 if (t > num) 185 goto erange; 186 ++expr; 187 break; 188 case 'g': 189 t = num; 190 num *= 1073741824; /* 1 gigabyte */ 191 if (t > num) 192 goto erange; 193 ++expr; 194 break; 195 case 't': 196 t = num; 197 num *= 1099511627776LL; /* 1 terabyte */ 198 if (t > num) 199 goto erange; 200 ++expr; 201 break; 202 case 'w': 203 t = num; 204 num *= sizeof(int); /* 1 word */ 205 if (t > num) 206 goto erange; 207 ++expr; 208 break; 209 } 210 211 switch (*expr) { 212 case '\0': 213 break; 214 case '*': /* Backward compatible */ 215 case 'x': 216 t = num; 217 num *= strsuftollx(desc, expr + 1, min, max, ebuf, ebuflen); 218 if (*ebuf != '\0') 219 return (0); 220 if (t > num) { 221 erange: 222 snprintf(ebuf, ebuflen, 223 "%s: %s", desc, strerror(ERANGE)); 224 return (0); 225 } 226 break; 227 default: 228 badnum: snprintf(ebuf, ebuflen, 229 "%s `%s': illegal number", desc, val); 230 return (0); 231 } 232 if (num < min) { 233 /* LONGLONG */ 234 snprintf(ebuf, ebuflen, "%s %lld is less than %lld.", 235 desc, (long long)num, (long long)min); 236 return (0); 237 } 238 if (num > max) { 239 /* LONGLONG */ 240 snprintf(ebuf, ebuflen, 241 "%s %lld is greater than %lld.", 242 desc, (long long)num, (long long)min); 243 return (0); 244 } 245 *ebuf = '\0'; 246 return (num); 247 } 248 249 #endif /* !HAVE_STRSUFTOLL */ 250