16bea8766SBrooks Davis /* $NetBSD: strsuftoll.c,v 1.6 2004/03/05 05:58:29 lukem Exp $ */ 26bea8766SBrooks Davis /*- 3*5e53a4f9SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-NetBSD 4*5e53a4f9SPedro F. Giffuni * 56bea8766SBrooks Davis * Copyright (c) 2001-2002,2004 The NetBSD Foundation, Inc. 66bea8766SBrooks Davis * All rights reserved. 76bea8766SBrooks Davis * 86bea8766SBrooks Davis * This code is derived from software contributed to The NetBSD Foundation 96bea8766SBrooks Davis * by Luke Mewburn. 106bea8766SBrooks Davis * 116bea8766SBrooks Davis * Redistribution and use in source and binary forms, with or without 126bea8766SBrooks Davis * modification, are permitted provided that the following conditions 136bea8766SBrooks Davis * are met: 146bea8766SBrooks Davis * 1. Redistributions of source code must retain the above copyright 156bea8766SBrooks Davis * notice, this list of conditions and the following disclaimer. 166bea8766SBrooks Davis * 2. Redistributions in binary form must reproduce the above copyright 176bea8766SBrooks Davis * notice, this list of conditions and the following disclaimer in the 186bea8766SBrooks Davis * documentation and/or other materials provided with the distribution. 196bea8766SBrooks Davis * 206bea8766SBrooks Davis * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 216bea8766SBrooks Davis * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 226bea8766SBrooks Davis * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 236bea8766SBrooks Davis * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 246bea8766SBrooks Davis * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 256bea8766SBrooks Davis * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 266bea8766SBrooks Davis * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 276bea8766SBrooks Davis * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 286bea8766SBrooks Davis * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 296bea8766SBrooks Davis * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 306bea8766SBrooks Davis * POSSIBILITY OF SUCH DAMAGE. 316bea8766SBrooks Davis */ 326bea8766SBrooks Davis /*- 336bea8766SBrooks Davis * Copyright (c) 1991, 1993, 1994 346bea8766SBrooks Davis * The Regents of the University of California. All rights reserved. 356bea8766SBrooks Davis * 366bea8766SBrooks Davis * This code is derived from software contributed to Berkeley by 376bea8766SBrooks Davis * Keith Muller of the University of California, San Diego and Lance 386bea8766SBrooks Davis * Visser of Convex Computer Corporation. 396bea8766SBrooks Davis * 406bea8766SBrooks Davis * Redistribution and use in source and binary forms, with or without 416bea8766SBrooks Davis * modification, are permitted provided that the following conditions 426bea8766SBrooks Davis * are met: 436bea8766SBrooks Davis * 1. Redistributions of source code must retain the above copyright 446bea8766SBrooks Davis * notice, this list of conditions and the following disclaimer. 456bea8766SBrooks Davis * 2. Redistributions in binary form must reproduce the above copyright 466bea8766SBrooks Davis * notice, this list of conditions and the following disclaimer in the 476bea8766SBrooks Davis * documentation and/or other materials provided with the distribution. 486bea8766SBrooks Davis * 3. Neither the name of the University nor the names of its contributors 496bea8766SBrooks Davis * may be used to endorse or promote products derived from this software 506bea8766SBrooks Davis * without specific prior written permission. 516bea8766SBrooks Davis * 526bea8766SBrooks Davis * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 536bea8766SBrooks Davis * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 546bea8766SBrooks Davis * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 556bea8766SBrooks Davis * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 566bea8766SBrooks Davis * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 576bea8766SBrooks Davis * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 586bea8766SBrooks Davis * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 596bea8766SBrooks Davis * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 606bea8766SBrooks Davis * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 616bea8766SBrooks Davis * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 626bea8766SBrooks Davis * SUCH DAMAGE. 636bea8766SBrooks Davis */ 646bea8766SBrooks Davis 656bea8766SBrooks Davis #include <sys/cdefs.h> 666bea8766SBrooks Davis __FBSDID("$FreeBSD$"); 676bea8766SBrooks Davis 686bea8766SBrooks Davis #include <sys/types.h> 696bea8766SBrooks Davis #include <sys/time.h> 706bea8766SBrooks Davis 716bea8766SBrooks Davis #include <assert.h> 726bea8766SBrooks Davis #include <ctype.h> 736bea8766SBrooks Davis #include <err.h> 746bea8766SBrooks Davis #include <errno.h> 756bea8766SBrooks Davis #include <limits.h> 766bea8766SBrooks Davis #include <stdio.h> 776bea8766SBrooks Davis #include <stdlib.h> 786bea8766SBrooks Davis #include <string.h> 796bea8766SBrooks Davis 806bea8766SBrooks Davis #ifdef _LIBC 816bea8766SBrooks Davis # ifdef __weak_alias 826bea8766SBrooks Davis __weak_alias(strsuftoll, _strsuftoll) 836bea8766SBrooks Davis __weak_alias(strsuftollx, _strsuftollx) 846bea8766SBrooks Davis # endif 856bea8766SBrooks Davis #endif /* LIBC */ 866bea8766SBrooks Davis 876bea8766SBrooks Davis /* 886bea8766SBrooks Davis * Convert an expression of the following forms to a (u)int64_t. 896bea8766SBrooks Davis * 1) A positive decimal number. 906bea8766SBrooks Davis * 2) A positive decimal number followed by a b (mult by 512). 916bea8766SBrooks Davis * 3) A positive decimal number followed by a k (mult by 1024). 926bea8766SBrooks Davis * 4) A positive decimal number followed by a m (mult by 1048576). 936bea8766SBrooks Davis * 5) A positive decimal number followed by a g (mult by 1073741824). 946bea8766SBrooks Davis * 6) A positive decimal number followed by a t (mult by 1099511627776). 956bea8766SBrooks Davis * 7) A positive decimal number followed by a w (mult by sizeof int) 966bea8766SBrooks Davis * 8) Two or more positive decimal numbers (with/without k,b or w). 976bea8766SBrooks Davis * separated by x (also * for backwards compatibility), specifying 986bea8766SBrooks Davis * the product of the indicated values. 996bea8766SBrooks Davis * Returns the result upon successful conversion, or exits with an 1006bea8766SBrooks Davis * appropriate error. 1016bea8766SBrooks Davis * 1026bea8766SBrooks Davis */ 1036bea8766SBrooks Davis 1046bea8766SBrooks Davis /* 1056bea8766SBrooks Davis * As strsuftoll(), but returns the error message into the provided buffer 1066bea8766SBrooks Davis * rather than exiting with it. 1076bea8766SBrooks Davis */ 1086bea8766SBrooks Davis /* LONGLONG */ 1096bea8766SBrooks Davis long long 1106bea8766SBrooks Davis strsuftollx(const char *desc, const char *val, 1116bea8766SBrooks Davis long long min, long long max, char *ebuf, size_t ebuflen) 1126bea8766SBrooks Davis { 1136bea8766SBrooks Davis long long num, t; 1146bea8766SBrooks Davis char *expr; 1156bea8766SBrooks Davis 1166bea8766SBrooks Davis errno = 0; 1176bea8766SBrooks Davis ebuf[0] = '\0'; 1186bea8766SBrooks Davis 1196bea8766SBrooks Davis while (isspace((unsigned char)*val)) /* Skip leading space */ 1206bea8766SBrooks Davis val++; 1216bea8766SBrooks Davis 1226bea8766SBrooks Davis num = strtoll(val, &expr, 10); 1236bea8766SBrooks Davis if (errno == ERANGE) 1246bea8766SBrooks Davis goto erange; /* Overflow */ 1256bea8766SBrooks Davis 1266bea8766SBrooks Davis if (expr == val) /* No digits */ 1276bea8766SBrooks Davis goto badnum; 1286bea8766SBrooks Davis 1296bea8766SBrooks Davis switch (*expr) { 1306bea8766SBrooks Davis case 'b': 1316bea8766SBrooks Davis t = num; 1326bea8766SBrooks Davis num *= 512; /* 1 block */ 1336bea8766SBrooks Davis if (t > num) 1346bea8766SBrooks Davis goto erange; 1356bea8766SBrooks Davis ++expr; 1366bea8766SBrooks Davis break; 1376bea8766SBrooks Davis case 'k': 1386bea8766SBrooks Davis t = num; 1396bea8766SBrooks Davis num *= 1024; /* 1 kilobyte */ 1406bea8766SBrooks Davis if (t > num) 1416bea8766SBrooks Davis goto erange; 1426bea8766SBrooks Davis ++expr; 1436bea8766SBrooks Davis break; 1446bea8766SBrooks Davis case 'm': 1456bea8766SBrooks Davis t = num; 1466bea8766SBrooks Davis num *= 1048576; /* 1 megabyte */ 1476bea8766SBrooks Davis if (t > num) 1486bea8766SBrooks Davis goto erange; 1496bea8766SBrooks Davis ++expr; 1506bea8766SBrooks Davis break; 1516bea8766SBrooks Davis case 'g': 1526bea8766SBrooks Davis t = num; 1536bea8766SBrooks Davis num *= 1073741824; /* 1 gigabyte */ 1546bea8766SBrooks Davis if (t > num) 1556bea8766SBrooks Davis goto erange; 1566bea8766SBrooks Davis ++expr; 1576bea8766SBrooks Davis break; 1586bea8766SBrooks Davis case 't': 1596bea8766SBrooks Davis t = num; 1606bea8766SBrooks Davis num *= 1099511627776LL; /* 1 terabyte */ 1616bea8766SBrooks Davis if (t > num) 1626bea8766SBrooks Davis goto erange; 1636bea8766SBrooks Davis ++expr; 1646bea8766SBrooks Davis break; 1656bea8766SBrooks Davis case 'w': 1666bea8766SBrooks Davis t = num; 1676bea8766SBrooks Davis num *= sizeof(int); /* 1 word */ 1686bea8766SBrooks Davis if (t > num) 1696bea8766SBrooks Davis goto erange; 1706bea8766SBrooks Davis ++expr; 1716bea8766SBrooks Davis break; 1726bea8766SBrooks Davis } 1736bea8766SBrooks Davis 1746bea8766SBrooks Davis switch (*expr) { 1756bea8766SBrooks Davis case '\0': 1766bea8766SBrooks Davis break; 1776bea8766SBrooks Davis case '*': /* Backward compatible */ 1786bea8766SBrooks Davis case 'x': 1796bea8766SBrooks Davis t = num; 1806bea8766SBrooks Davis num *= strsuftollx(desc, expr + 1, min, max, ebuf, ebuflen); 1816bea8766SBrooks Davis if (*ebuf != '\0') 1826bea8766SBrooks Davis return (0); 1836bea8766SBrooks Davis if (t > num) { 1846bea8766SBrooks Davis erange: 1856bea8766SBrooks Davis snprintf(ebuf, ebuflen, 1866bea8766SBrooks Davis "%s: %s", desc, strerror(ERANGE)); 1876bea8766SBrooks Davis return (0); 1886bea8766SBrooks Davis } 1896bea8766SBrooks Davis break; 1906bea8766SBrooks Davis default: 1916bea8766SBrooks Davis badnum: snprintf(ebuf, ebuflen, 1926bea8766SBrooks Davis "%s `%s': illegal number", desc, val); 1936bea8766SBrooks Davis return (0); 1946bea8766SBrooks Davis } 1956bea8766SBrooks Davis if (num < min) { 1966bea8766SBrooks Davis /* LONGLONG */ 1976bea8766SBrooks Davis snprintf(ebuf, ebuflen, "%s %lld is less than %lld.", 1986bea8766SBrooks Davis desc, (long long)num, (long long)min); 1996bea8766SBrooks Davis return (0); 2006bea8766SBrooks Davis } 2016bea8766SBrooks Davis if (num > max) { 2026bea8766SBrooks Davis /* LONGLONG */ 2036bea8766SBrooks Davis snprintf(ebuf, ebuflen, 2046bea8766SBrooks Davis "%s %lld is greater than %lld.", 2056bea8766SBrooks Davis desc, (long long)num, (long long)max); 2066bea8766SBrooks Davis return (0); 2076bea8766SBrooks Davis } 2086bea8766SBrooks Davis *ebuf = '\0'; 2096bea8766SBrooks Davis return (num); 2106bea8766SBrooks Davis } 2116bea8766SBrooks Davis 2126bea8766SBrooks Davis /* LONGLONG */ 2136bea8766SBrooks Davis long long 2146bea8766SBrooks Davis strsuftoll(const char *desc, const char *val, 2156bea8766SBrooks Davis long long min, long long max) 2166bea8766SBrooks Davis { 2176bea8766SBrooks Davis long long result; 2186bea8766SBrooks Davis char errbuf[100]; 2196bea8766SBrooks Davis 2206bea8766SBrooks Davis result = strsuftollx(desc, val, min, max, errbuf, sizeof(errbuf)); 2216bea8766SBrooks Davis if (*errbuf != '\0') 2226bea8766SBrooks Davis errx(1, "%s", errbuf); 2236bea8766SBrooks Davis return (result); 2246bea8766SBrooks Davis } 225