1244557Sbrooks/* $NetBSD: strsuftoll.c,v 1.6 2004/03/05 05:58:29 lukem Exp $ */ 2244557Sbrooks/*- 3244557Sbrooks * Copyright (c) 2001-2002,2004 The NetBSD Foundation, Inc. 4244557Sbrooks * All rights reserved. 5244557Sbrooks * 6244557Sbrooks * This code is derived from software contributed to The NetBSD Foundation 7244557Sbrooks * by Luke Mewburn. 8244557Sbrooks * 9244557Sbrooks * Redistribution and use in source and binary forms, with or without 10244557Sbrooks * modification, are permitted provided that the following conditions 11244557Sbrooks * are met: 12244557Sbrooks * 1. Redistributions of source code must retain the above copyright 13244557Sbrooks * notice, this list of conditions and the following disclaimer. 14244557Sbrooks * 2. Redistributions in binary form must reproduce the above copyright 15244557Sbrooks * notice, this list of conditions and the following disclaimer in the 16244557Sbrooks * documentation and/or other materials provided with the distribution. 17244557Sbrooks * 18244557Sbrooks * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19244557Sbrooks * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20244557Sbrooks * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21244557Sbrooks * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22244557Sbrooks * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23244557Sbrooks * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24244557Sbrooks * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25244557Sbrooks * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26244557Sbrooks * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27244557Sbrooks * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28244557Sbrooks * POSSIBILITY OF SUCH DAMAGE. 29244557Sbrooks */ 30244557Sbrooks/*- 31244557Sbrooks * Copyright (c) 1991, 1993, 1994 32244557Sbrooks * The Regents of the University of California. All rights reserved. 33244557Sbrooks * 34244557Sbrooks * This code is derived from software contributed to Berkeley by 35244557Sbrooks * Keith Muller of the University of California, San Diego and Lance 36244557Sbrooks * Visser of Convex Computer Corporation. 37244557Sbrooks * 38244557Sbrooks * Redistribution and use in source and binary forms, with or without 39244557Sbrooks * modification, are permitted provided that the following conditions 40244557Sbrooks * are met: 41244557Sbrooks * 1. Redistributions of source code must retain the above copyright 42244557Sbrooks * notice, this list of conditions and the following disclaimer. 43244557Sbrooks * 2. Redistributions in binary form must reproduce the above copyright 44244557Sbrooks * notice, this list of conditions and the following disclaimer in the 45244557Sbrooks * documentation and/or other materials provided with the distribution. 46244557Sbrooks * 3. Neither the name of the University nor the names of its contributors 47244557Sbrooks * may be used to endorse or promote products derived from this software 48244557Sbrooks * without specific prior written permission. 49244557Sbrooks * 50244557Sbrooks * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 51244557Sbrooks * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 52244557Sbrooks * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 53244557Sbrooks * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 54244557Sbrooks * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 55244557Sbrooks * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 56244557Sbrooks * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 57244557Sbrooks * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 58244557Sbrooks * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 59244557Sbrooks * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 60244557Sbrooks * SUCH DAMAGE. 61244557Sbrooks */ 62244557Sbrooks 63244557Sbrooks#include <sys/cdefs.h> 64244557Sbrooks__FBSDID("$FreeBSD: releng/10.2/lib/libnetbsd/strsuftoll.c 244557 2012-12-21 20:37:38Z brooks $"); 65244557Sbrooks 66244557Sbrooks#include <sys/types.h> 67244557Sbrooks#include <sys/time.h> 68244557Sbrooks 69244557Sbrooks#include <assert.h> 70244557Sbrooks#include <ctype.h> 71244557Sbrooks#include <err.h> 72244557Sbrooks#include <errno.h> 73244557Sbrooks#include <limits.h> 74244557Sbrooks#include <stdio.h> 75244557Sbrooks#include <stdlib.h> 76244557Sbrooks#include <string.h> 77244557Sbrooks 78244557Sbrooks#ifdef _LIBC 79244557Sbrooks# ifdef __weak_alias 80244557Sbrooks__weak_alias(strsuftoll, _strsuftoll) 81244557Sbrooks__weak_alias(strsuftollx, _strsuftollx) 82244557Sbrooks# endif 83244557Sbrooks#endif /* LIBC */ 84244557Sbrooks 85244557Sbrooks/* 86244557Sbrooks * Convert an expression of the following forms to a (u)int64_t. 87244557Sbrooks * 1) A positive decimal number. 88244557Sbrooks * 2) A positive decimal number followed by a b (mult by 512). 89244557Sbrooks * 3) A positive decimal number followed by a k (mult by 1024). 90244557Sbrooks * 4) A positive decimal number followed by a m (mult by 1048576). 91244557Sbrooks * 5) A positive decimal number followed by a g (mult by 1073741824). 92244557Sbrooks * 6) A positive decimal number followed by a t (mult by 1099511627776). 93244557Sbrooks * 7) A positive decimal number followed by a w (mult by sizeof int) 94244557Sbrooks * 8) Two or more positive decimal numbers (with/without k,b or w). 95244557Sbrooks * separated by x (also * for backwards compatibility), specifying 96244557Sbrooks * the product of the indicated values. 97244557Sbrooks * Returns the result upon successful conversion, or exits with an 98244557Sbrooks * appropriate error. 99244557Sbrooks * 100244557Sbrooks */ 101244557Sbrooks 102244557Sbrooks/* 103244557Sbrooks * As strsuftoll(), but returns the error message into the provided buffer 104244557Sbrooks * rather than exiting with it. 105244557Sbrooks */ 106244557Sbrooks/* LONGLONG */ 107244557Sbrookslong long 108244557Sbrooksstrsuftollx(const char *desc, const char *val, 109244557Sbrooks long long min, long long max, char *ebuf, size_t ebuflen) 110244557Sbrooks{ 111244557Sbrooks long long num, t; 112244557Sbrooks char *expr; 113244557Sbrooks 114244557Sbrooks errno = 0; 115244557Sbrooks ebuf[0] = '\0'; 116244557Sbrooks 117244557Sbrooks while (isspace((unsigned char)*val)) /* Skip leading space */ 118244557Sbrooks val++; 119244557Sbrooks 120244557Sbrooks num = strtoll(val, &expr, 10); 121244557Sbrooks if (errno == ERANGE) 122244557Sbrooks goto erange; /* Overflow */ 123244557Sbrooks 124244557Sbrooks if (expr == val) /* No digits */ 125244557Sbrooks goto badnum; 126244557Sbrooks 127244557Sbrooks switch (*expr) { 128244557Sbrooks case 'b': 129244557Sbrooks t = num; 130244557Sbrooks num *= 512; /* 1 block */ 131244557Sbrooks if (t > num) 132244557Sbrooks goto erange; 133244557Sbrooks ++expr; 134244557Sbrooks break; 135244557Sbrooks case 'k': 136244557Sbrooks t = num; 137244557Sbrooks num *= 1024; /* 1 kilobyte */ 138244557Sbrooks if (t > num) 139244557Sbrooks goto erange; 140244557Sbrooks ++expr; 141244557Sbrooks break; 142244557Sbrooks case 'm': 143244557Sbrooks t = num; 144244557Sbrooks num *= 1048576; /* 1 megabyte */ 145244557Sbrooks if (t > num) 146244557Sbrooks goto erange; 147244557Sbrooks ++expr; 148244557Sbrooks break; 149244557Sbrooks case 'g': 150244557Sbrooks t = num; 151244557Sbrooks num *= 1073741824; /* 1 gigabyte */ 152244557Sbrooks if (t > num) 153244557Sbrooks goto erange; 154244557Sbrooks ++expr; 155244557Sbrooks break; 156244557Sbrooks case 't': 157244557Sbrooks t = num; 158244557Sbrooks num *= 1099511627776LL; /* 1 terabyte */ 159244557Sbrooks if (t > num) 160244557Sbrooks goto erange; 161244557Sbrooks ++expr; 162244557Sbrooks break; 163244557Sbrooks case 'w': 164244557Sbrooks t = num; 165244557Sbrooks num *= sizeof(int); /* 1 word */ 166244557Sbrooks if (t > num) 167244557Sbrooks goto erange; 168244557Sbrooks ++expr; 169244557Sbrooks break; 170244557Sbrooks } 171244557Sbrooks 172244557Sbrooks switch (*expr) { 173244557Sbrooks case '\0': 174244557Sbrooks break; 175244557Sbrooks case '*': /* Backward compatible */ 176244557Sbrooks case 'x': 177244557Sbrooks t = num; 178244557Sbrooks num *= strsuftollx(desc, expr + 1, min, max, ebuf, ebuflen); 179244557Sbrooks if (*ebuf != '\0') 180244557Sbrooks return (0); 181244557Sbrooks if (t > num) { 182244557Sbrooks erange: 183244557Sbrooks snprintf(ebuf, ebuflen, 184244557Sbrooks "%s: %s", desc, strerror(ERANGE)); 185244557Sbrooks return (0); 186244557Sbrooks } 187244557Sbrooks break; 188244557Sbrooks default: 189244557Sbrooks badnum: snprintf(ebuf, ebuflen, 190244557Sbrooks "%s `%s': illegal number", desc, val); 191244557Sbrooks return (0); 192244557Sbrooks } 193244557Sbrooks if (num < min) { 194244557Sbrooks /* LONGLONG */ 195244557Sbrooks snprintf(ebuf, ebuflen, "%s %lld is less than %lld.", 196244557Sbrooks desc, (long long)num, (long long)min); 197244557Sbrooks return (0); 198244557Sbrooks } 199244557Sbrooks if (num > max) { 200244557Sbrooks /* LONGLONG */ 201244557Sbrooks snprintf(ebuf, ebuflen, 202244557Sbrooks "%s %lld is greater than %lld.", 203244557Sbrooks desc, (long long)num, (long long)max); 204244557Sbrooks return (0); 205244557Sbrooks } 206244557Sbrooks *ebuf = '\0'; 207244557Sbrooks return (num); 208244557Sbrooks} 209244557Sbrooks 210244557Sbrooks/* LONGLONG */ 211244557Sbrookslong long 212244557Sbrooksstrsuftoll(const char *desc, const char *val, 213244557Sbrooks long long min, long long max) 214244557Sbrooks{ 215244557Sbrooks long long result; 216244557Sbrooks char errbuf[100]; 217244557Sbrooks 218244557Sbrooks result = strsuftollx(desc, val, min, max, errbuf, sizeof(errbuf)); 219244557Sbrooks if (*errbuf != '\0') 220244557Sbrooks errx(1, "%s", errbuf); 221244557Sbrooks return (result); 222244557Sbrooks} 223