1/* $NetBSD: strsuftoll.c,v 1.5 2004/01/17 23:02:51 dbj Exp $ */ 2/*- 3 * Copyright (c) 2001-2002,2004 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. Neither the name of the University nor the names of its contributors 54 * may be used to endorse or promote products derived from this software 55 * without specific prior written permission. 56 * 57 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 58 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 59 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 60 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 61 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 62 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 63 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 64 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 65 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 66 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 67 * SUCH DAMAGE. 68 */ 69 70#if HAVE_NBTOOL_CONFIG_H 71#include "nbtool_config.h" 72#endif 73 74#include <sys/cdefs.h> 75 76#if defined(LIBC_SCCS) && !defined(lint) 77__RCSID("$NetBSD: strsuftoll.c,v 1.5 2004/01/17 23:02:51 dbj Exp $"); 78#endif /* LIBC_SCCS and not lint */ 79 80#ifdef _LIBC 81#include "namespace.h" 82#endif 83 84#if !HAVE_STRSUFTOLL 85 86#include <sys/types.h> 87#include <sys/time.h> 88 89#include <assert.h> 90#include <ctype.h> 91#include <err.h> 92#include <errno.h> 93#include <limits.h> 94#include <stdio.h> 95#include <stdlib.h> 96#include <string.h> 97 98#ifdef _LIBC 99# ifdef __weak_alias 100__weak_alias(strsuftoll, _strsuftoll) 101__weak_alias(strsuftollx, _strsuftollx) 102# endif 103#endif /* LIBC */ 104 105/* 106 * Convert an expression of the following forms to a (u)int64_t. 107 * 1) A positive decimal number. 108 * 2) A positive decimal number followed by a b (mult by 512). 109 * 3) A positive decimal number followed by a k (mult by 1024). 110 * 4) A positive decimal number followed by a m (mult by 1048576). 111 * 5) A positive decimal number followed by a g (mult by 1073741824). 112 * 6) A positive decimal number followed by a t (mult by 1099511627776). 113 * 7) A positive decimal number followed by a w (mult by sizeof int) 114 * 8) Two or more positive decimal numbers (with/without k,b or w). 115 * separated by x (also * for backwards compatibility), specifying 116 * the product of the indicated values. 117 * Returns the result upon successful conversion, or exits with an 118 * appropriate error. 119 * 120 */ 121/* LONGLONG */ 122long long 123strsuftoll(const char *desc, const char *val, 124 long long min, long long max) 125{ 126 long long result; 127 char errbuf[100]; 128 129 result = strsuftollx(desc, val, min, max, errbuf, sizeof(errbuf)); 130 if (*errbuf != '\0') 131 errx(1, "%s", errbuf); 132 return (result); 133} 134 135/* 136 * As strsuftoll(), but returns the error message into the provided buffer 137 * rather than exiting with it. 138 */ 139/* LONGLONG */ 140long long 141strsuftollx(const char *desc, const char *val, 142 long long min, long long max, char *ebuf, size_t ebuflen) 143{ 144 long long num, t; 145 char *expr; 146 147 _DIAGASSERT(desc != NULL); 148 _DIAGASSERT(val != NULL); 149 _DIAGASSERT(ebuf != NULL); 150 151 errno = 0; 152 ebuf[0] = '\0'; 153 154 while (isspace((unsigned char)*val)) /* Skip leading space */ 155 val++; 156 157 num = strtoll(val, &expr, 10); 158 if (errno == ERANGE) 159 goto erange; /* Overflow */ 160 161 if (expr == val) /* No digits */ 162 goto badnum; 163 164 switch (*expr) { 165 case 'b': 166 t = num; 167 num *= 512; /* 1 block */ 168 if (t > num) 169 goto erange; 170 ++expr; 171 break; 172 case 'k': 173 t = num; 174 num *= 1024; /* 1 kilobyte */ 175 if (t > num) 176 goto erange; 177 ++expr; 178 break; 179 case 'm': 180 t = num; 181 num *= 1048576; /* 1 megabyte */ 182 if (t > num) 183 goto erange; 184 ++expr; 185 break; 186 case 'g': 187 t = num; 188 num *= 1073741824; /* 1 gigabyte */ 189 if (t > num) 190 goto erange; 191 ++expr; 192 break; 193 case 't': 194 t = num; 195 num *= 1099511627776LL; /* 1 terabyte */ 196 if (t > num) 197 goto erange; 198 ++expr; 199 break; 200 case 'w': 201 t = num; 202 num *= sizeof(int); /* 1 word */ 203 if (t > num) 204 goto erange; 205 ++expr; 206 break; 207 } 208 209 switch (*expr) { 210 case '\0': 211 break; 212 case '*': /* Backward compatible */ 213 case 'x': 214 t = num; 215 num *= strsuftollx(desc, expr + 1, min, max, ebuf, ebuflen); 216 if (*ebuf != '\0') 217 return (0); 218 if (t > num) { 219 erange: 220 snprintf(ebuf, ebuflen, 221 "%s: %s", desc, strerror(ERANGE)); 222 return (0); 223 } 224 break; 225 default: 226 badnum: snprintf(ebuf, ebuflen, 227 "%s `%s': illegal number", desc, val); 228 return (0); 229 } 230 if (num < min) { 231 /* LONGLONG */ 232 snprintf(ebuf, ebuflen, "%s %lld is less than %lld.", 233 desc, (long long)num, (long long)min); 234 return (0); 235 } 236 if (num > max) { 237 /* LONGLONG */ 238 snprintf(ebuf, ebuflen, 239 "%s %lld is greater than %lld.", 240 desc, (long long)num, (long long)max); 241 return (0); 242 } 243 *ebuf = '\0'; 244 return (num); 245} 246 247#endif /* !HAVE_STRSUFTOLL */ 248