1155408Srwatson/* $NetBSD: strsuftoll.c,v 1.6 2004/03/05 05:58:29 lukem Exp $ */ 2155408Srwatson/*- 3188315Srwatson * Copyright (c) 2001-2002,2004 The NetBSD Foundation, Inc. 4155408Srwatson * All rights reserved. 5155408Srwatson * 6155408Srwatson * This code is derived from software contributed to The NetBSD Foundation 7155408Srwatson * by Luke Mewburn. 8155408Srwatson * 9155408Srwatson * Redistribution and use in source and binary forms, with or without 10155408Srwatson * modification, are permitted provided that the following conditions 11155408Srwatson * are met: 12155408Srwatson * 1. Redistributions of source code must retain the above copyright 13155408Srwatson * notice, this list of conditions and the following disclaimer. 14155408Srwatson * 2. Redistributions in binary form must reproduce the above copyright 15155408Srwatson * notice, this list of conditions and the following disclaimer in the 16155408Srwatson * documentation and/or other materials provided with the distribution. 17155408Srwatson * 18155408Srwatson * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19155408Srwatson * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20155408Srwatson * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21155408Srwatson * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22155408Srwatson * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23155408Srwatson * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24155408Srwatson * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25155408Srwatson * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26155408Srwatson * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27155408Srwatson * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28155408Srwatson * POSSIBILITY OF SUCH DAMAGE. 29155408Srwatson */ 30178186Srwatson/*- 31178186Srwatson * Copyright (c) 1991, 1993, 1994 32178186Srwatson * The Regents of the University of California. All rights reserved. 33155408Srwatson * 34155408Srwatson * This code is derived from software contributed to Berkeley by 35155408Srwatson * Keith Muller of the University of California, San Diego and Lance 36155408Srwatson * Visser of Convex Computer Corporation. 37155408Srwatson * 38155408Srwatson * Redistribution and use in source and binary forms, with or without 39155408Srwatson * modification, are permitted provided that the following conditions 40155408Srwatson * are met: 41155408Srwatson * 1. Redistributions of source code must retain the above copyright 42155408Srwatson * notice, this list of conditions and the following disclaimer. 43155408Srwatson * 2. Redistributions in binary form must reproduce the above copyright 44155408Srwatson * notice, this list of conditions and the following disclaimer in the 45184488Srwatson * documentation and/or other materials provided with the distribution. 46155408Srwatson * 3. Neither the name of the University nor the names of its contributors 47155408Srwatson * may be used to endorse or promote products derived from this software 48155408Srwatson * without specific prior written permission. 49155408Srwatson * 50184508Srwatson * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 51155408Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 52155408Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 53155408Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 54155408Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 55156880Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 56155408Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 57155408Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 58155408Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 59155408Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 60184545Srwatson * SUCH DAMAGE. 61184545Srwatson */ 62184545Srwatson 63184545Srwatson#include <sys/cdefs.h> 64155408Srwatson__FBSDID("$FreeBSD$"); 65155408Srwatson 66155408Srwatson#include <sys/types.h> 67155408Srwatson#include <sys/time.h> 68155408Srwatson 69155408Srwatson#include <assert.h> 70155408Srwatson#include <ctype.h> 71155408Srwatson#include <err.h> 72174894Swkoszek#include <errno.h> 73159269Srwatson#include <limits.h> 74155408Srwatson#include <stdio.h> 75155408Srwatson#include <stdlib.h> 76155408Srwatson#include <string.h> 77155408Srwatson 78156883Srwatson#ifdef _LIBC 79188315Srwatson# ifdef __weak_alias 80155408Srwatson__weak_alias(strsuftoll, _strsuftoll) 81155408Srwatson__weak_alias(strsuftollx, _strsuftollx) 82155408Srwatson# endif 83155408Srwatson#endif /* LIBC */ 84155408Srwatson 85155408Srwatson/* 86155408Srwatson * Convert an expression of the following forms to a (u)int64_t. 87155408Srwatson * 1) A positive decimal number. 88155408Srwatson * 2) A positive decimal number followed by a b (mult by 512). 89155408Srwatson * 3) A positive decimal number followed by a k (mult by 1024). 90155408Srwatson * 4) A positive decimal number followed by a m (mult by 1048576). 91155408Srwatson * 5) A positive decimal number followed by a g (mult by 1073741824). 92159269Srwatson * 6) A positive decimal number followed by a t (mult by 1099511627776). 93159269Srwatson * 7) A positive decimal number followed by a w (mult by sizeof int) 94159269Srwatson * 8) Two or more positive decimal numbers (with/without k,b or w). 95159269Srwatson * separated by x (also * for backwards compatibility), specifying 96159269Srwatson * the product of the indicated values. 97159269Srwatson * Returns the result upon successful conversion, or exits with an 98159269Srwatson * appropriate error. 99159269Srwatson * 100159269Srwatson */ 101159269Srwatson 102159269Srwatson/* 103159269Srwatson * As strsuftoll(), but returns the error message into the provided buffer 104159269Srwatson * rather than exiting with it. 105159269Srwatson */ 106159269Srwatson/* LONGLONG */ 107159269Srwatsonlong long 108159269Srwatsonstrsuftollx(const char *desc, const char *val, 109155408Srwatson long long min, long long max, char *ebuf, size_t ebuflen) 110155408Srwatson{ 111155408Srwatson long long num, t; 112155408Srwatson char *expr; 113155408Srwatson 114155408Srwatson errno = 0; 115155408Srwatson ebuf[0] = '\0'; 116155408Srwatson 117155408Srwatson while (isspace((unsigned char)*val)) /* Skip leading space */ 118155408Srwatson val++; 119155408Srwatson 120155408Srwatson num = strtoll(val, &expr, 10); 121184488Srwatson if (errno == ERANGE) 122184488Srwatson goto erange; /* Overflow */ 123184488Srwatson 124184508Srwatson if (expr == val) /* No digits */ 125184488Srwatson goto badnum; 126184488Srwatson 127184508Srwatson switch (*expr) { 128184508Srwatson case 'b': 129184508Srwatson t = num; 130184508Srwatson num *= 512; /* 1 block */ 131184508Srwatson if (t > num) 132184508Srwatson goto erange; 133184508Srwatson ++expr; 134184508Srwatson break; 135184488Srwatson case 'k': 136184488Srwatson t = num; 137184488Srwatson num *= 1024; /* 1 kilobyte */ 138184488Srwatson if (t > num) 139184488Srwatson goto erange; 140184536Srwatson ++expr; 141184536Srwatson break; 142184536Srwatson case 'm': 143184536Srwatson t = num; 144184536Srwatson num *= 1048576; /* 1 megabyte */ 145184536Srwatson if (t > num) 146184536Srwatson goto erange; 147155408Srwatson ++expr; 148155408Srwatson break; 149184536Srwatson case 'g': 150184536Srwatson t = num; 151155408Srwatson num *= 1073741824; /* 1 gigabyte */ 152184540Srwatson if (t > num) 153184540Srwatson goto erange; 154184540Srwatson ++expr; 155155408Srwatson break; 156155408Srwatson case 't': 157155408Srwatson t = num; 158155408Srwatson num *= 1099511627776LL; /* 1 terabyte */ 159159269Srwatson if (t > num) 160159269Srwatson goto erange; 161159269Srwatson ++expr; 162159269Srwatson break; 163159269Srwatson case 'w': 164159269Srwatson t = num; 165159269Srwatson num *= sizeof(int); /* 1 word */ 166159269Srwatson if (t > num) 167159269Srwatson goto erange; 168159269Srwatson ++expr; 169159269Srwatson break; 170184508Srwatson } 171184508Srwatson 172186662Srwatson switch (*expr) { 173186662Srwatson case '\0': 174159269Srwatson break; 175155408Srwatson case '*': /* Backward compatible */ 176155408Srwatson case 'x': 177159269Srwatson t = num; 178159269Srwatson num *= strsuftollx(desc, expr + 1, min, max, ebuf, ebuflen); 179159269Srwatson if (*ebuf != '\0') 180155408Srwatson return (0); 181155408Srwatson if (t > num) { 182155408Srwatson erange: 183184508Srwatson snprintf(ebuf, ebuflen, 184184508Srwatson "%s: %s", desc, strerror(ERANGE)); 185184508Srwatson return (0); 186184508Srwatson } 187184508Srwatson break; 188184508Srwatson default: 189184508Srwatson badnum: snprintf(ebuf, ebuflen, 190184488Srwatson "%s `%s': illegal number", desc, val); 191184508Srwatson return (0); 192184508Srwatson } 193184508Srwatson if (num < min) { 194184508Srwatson /* LONGLONG */ 195184508Srwatson snprintf(ebuf, ebuflen, "%s %lld is less than %lld.", 196184508Srwatson desc, (long long)num, (long long)min); 197155408Srwatson return (0); 198184488Srwatson } 199184488Srwatson if (num > max) { 200184488Srwatson /* LONGLONG */ 201184488Srwatson snprintf(ebuf, ebuflen, 202155408Srwatson "%s %lld is greater than %lld.", 203155408Srwatson desc, (long long)num, (long long)max); 204184488Srwatson return (0); 205155408Srwatson } 206184488Srwatson *ebuf = '\0'; 207184488Srwatson return (num); 208184488Srwatson} 209184488Srwatson 210184488Srwatson/* LONGLONG */ 211184488Srwatsonlong long 212184488Srwatsonstrsuftoll(const char *desc, const char *val, 213184488Srwatson long long min, long long max) 214155408Srwatson{ 215155408Srwatson long long result; 216155408Srwatson char errbuf[100]; 217155408Srwatson 218155408Srwatson result = strsuftollx(desc, val, min, max, errbuf, sizeof(errbuf)); 219155408Srwatson if (*errbuf != '\0') 220155408Srwatson errx(1, "%s", errbuf); 221155408Srwatson return (result); 222155408Srwatson} 223155408Srwatson