1 /** $MirOS: src/usr.sbin/makefs/nbsrc/lib/libc/stdlib/strsuftoll.c,v 1.10 2010/03/06 23:24:17 tg Exp $ */
2 /* $NetBSD: strsuftoll.c,v 1.8 2008/04/28 20:23:00 martin Exp $ */
3 /*-
4 * Copyright (c) 2009
5 * Thorsten Glaser <tg@mirbsd.org>
6 * Copyright (c) 2001-2002,2004 The NetBSD Foundation, Inc.
7 * All rights reserved.
8 *
9 * This code is derived from software contributed to The NetBSD Foundation
10 * by Luke Mewburn.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33 /*-
34 * Copyright (c) 1991, 1993, 1994
35 * The Regents of the University of California. All rights reserved.
36 *
37 * This code is derived from software contributed to Berkeley by
38 * Keith Muller of the University of California, San Diego and Lance
39 * Visser of Convex Computer Corporation.
40 *
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
43 * are met:
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 * 3. Neither the name of the University nor the names of its contributors
50 * may be used to endorse or promote products derived from this software
51 * without specific prior written permission.
52 *
53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63 * SUCH DAMAGE.
64 */
65
66 #if HAVE_NBTOOL_CONFIG_H
67 #include "nbtool_config.h"
68 #endif
69
70 #if defined(__MirBSD__) || defined(DEBIAN)
71 #include "mbsdtree.h"
72 #endif
73
74 #include <sys/cdefs.h>
75
76 #if defined(LIBC_SCCS) && !defined(lint)
77 __RCSID("$NetBSD: strsuftoll.c,v 1.8 2008/04/28 20:23:00 martin Exp $");
78 __IDSTRING(mbsdid, "$MirOS: src/usr.sbin/makefs/nbsrc/lib/libc/stdlib/strsuftoll.c,v 1.10 2010/03/06 23:24:17 tg Exp $");
79 #endif /* LIBC_SCCS and not lint */
80
81 #ifdef _LIBC
82 #include "namespace.h"
83 #endif
84
85 #if !HAVE_STRSUFTOLL
86
87 #include <sys/types.h>
88 #include <sys/time.h>
89
90 #include <assert.h>
91 #include <ctype.h>
92 #include <err.h>
93 #include <errno.h>
94 #include <limits.h>
95 #include <stdio.h>
96 #include <stdlib.h>
97 #include <string.h>
98
99 #ifdef _LIBC
100 # ifdef __weak_alias
__weak_alias(strsuftoll,_strsuftoll)101 __weak_alias(strsuftoll, _strsuftoll)
102 __weak_alias(strsuftollx, _strsuftollx)
103 # endif
104 #endif /* LIBC */
105
106 /*
107 * Convert an expression of the following forms to a (u)int64_t.
108 * 1) A positive decimal number.
109 * 2) A positive decimal number followed by a b (mult by 512).
110 * 3) A positive decimal number followed by a k (mult by 1024).
111 * 4) A positive decimal number followed by a m (mult by 1048576).
112 * 5) A positive decimal number followed by a g (mult by 1073741824).
113 * 6) A positive decimal number followed by a t (mult by 1099511627776).
114 * 7) A positive decimal number followed by a w (mult by sizeof int)
115 * 8) Two or more positive decimal numbers (with/without k,b or w).
116 * separated by x (also * for backwards compatibility), specifying
117 * the product of the indicated values.
118 * Returns the result upon successful conversion, or exits with an
119 * appropriate error.
120 *
121 */
122 /* LONGLONG */
123 long long
124 strsuftoll(const char *desc, const char *val,
125 long long min, long long max)
126 {
127 long long result;
128 char errbuf[100];
129
130 result = strsuftollx(desc, val, min, max, errbuf, sizeof(errbuf));
131 if (*errbuf != '\0')
132 errx(1, "%s", errbuf);
133 return (result);
134 }
135
136 /*
137 * As strsuftoll(), but returns the error message into the provided buffer
138 * rather than exiting with it.
139 */
140 /* LONGLONG */
141 long long
strsuftollx(const char * desc,const char * val,long long min,long long max,char * ebuf,size_t ebuflen)142 strsuftollx(const char *desc, const char *val,
143 long long min, long long max, char *ebuf, size_t ebuflen)
144 {
145 long long num, t;
146 char *expr;
147
148 _DIAGASSERT(desc != NULL);
149 _DIAGASSERT(val != NULL);
150 _DIAGASSERT(ebuf != NULL);
151
152 errno = 0;
153 ebuf[0] = '\0';
154
155 while (isspace((unsigned char)*val)) /* Skip leading space */
156 val++;
157
158 if (*val == '0')
159 num = strtoll(val, &expr, 0);
160 else
161 num = strtoll(val, &expr, 10);
162 if (errno == ERANGE)
163 goto erange; /* Overflow */
164
165 if (expr == val) /* No digits */
166 goto badnum;
167
168 switch (*expr) {
169 case 'b':
170 t = num;
171 num *= 512; /* 1 block */
172 if (t > num)
173 goto erange;
174 ++expr;
175 break;
176 case 'k':
177 t = num;
178 num *= 1024; /* 1 kibibyte */
179 if (t > num)
180 goto erange;
181 ++expr;
182 break;
183 case 'm':
184 t = num;
185 num *= 1048576; /* 1 mebibyte */
186 if (t > num)
187 goto erange;
188 ++expr;
189 break;
190 case 'g':
191 t = num;
192 num *= 1073741824; /* 1 gibibyte */
193 if (t > num)
194 goto erange;
195 ++expr;
196 break;
197 case 't':
198 t = num;
199 num *= 1099511627776LL; /* 1 tebibyte */
200 if (t > num)
201 goto erange;
202 ++expr;
203 break;
204 case 'w':
205 t = num;
206 num *= sizeof(int); /* 1 word */
207 if (t > num)
208 goto erange;
209 ++expr;
210 break;
211 }
212
213 switch (*expr) {
214 case '\0':
215 break;
216 case '*': /* Backward compatible */
217 case 'x':
218 t = num;
219 num *= strsuftollx(desc, expr + 1, min, max, ebuf, ebuflen);
220 if (*ebuf != '\0')
221 return (0);
222 if (t > num) {
223 erange:
224 snprintf(ebuf, ebuflen,
225 "%s: %s", desc, strerror(ERANGE));
226 return (0);
227 }
228 break;
229 default:
230 badnum: snprintf(ebuf, ebuflen,
231 "%s `%s': illegal number", desc, val);
232 return (0);
233 }
234 if (num < min) {
235 /* LONGLONG */
236 snprintf(ebuf, ebuflen, "%s %lld is less than %lld.",
237 desc, (long long)num, (long long)min);
238 return (0);
239 }
240 if (num > max) {
241 /* LONGLONG */
242 snprintf(ebuf, ebuflen,
243 "%s %lld is greater than %lld.",
244 desc, (long long)num, (long long)max);
245 return (0);
246 }
247 *ebuf = '\0';
248 return (num);
249 }
250
251 #endif /* !HAVE_STRSUFTOLL */
252