1bf21cd93STycho Nightingale /*-
2bf21cd93STycho Nightingale * Copyright (c) 2007 Eric Anderson <anderson@FreeBSD.org>
3bf21cd93STycho Nightingale * Copyright (c) 2007 Pawel Jakub Dawidek <pjd@FreeBSD.org>
4bf21cd93STycho Nightingale * All rights reserved.
5bf21cd93STycho Nightingale *
6bf21cd93STycho Nightingale * Redistribution and use in source and binary forms, with or without
7bf21cd93STycho Nightingale * modification, are permitted provided that the following conditions
8bf21cd93STycho Nightingale * are met:
9bf21cd93STycho Nightingale * 1. Redistributions of source code must retain the above copyright
10bf21cd93STycho Nightingale * notice, this list of conditions and the following disclaimer.
11bf21cd93STycho Nightingale * 2. Redistributions in binary form must reproduce the above copyright
12bf21cd93STycho Nightingale * notice, this list of conditions and the following disclaimer in the
13bf21cd93STycho Nightingale * documentation and/or other materials provided with the distribution.
14bf21cd93STycho Nightingale *
15bf21cd93STycho Nightingale * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
16bf21cd93STycho Nightingale * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17bf21cd93STycho Nightingale * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18bf21cd93STycho Nightingale * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
19bf21cd93STycho Nightingale * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20bf21cd93STycho Nightingale * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21bf21cd93STycho Nightingale * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22bf21cd93STycho Nightingale * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23bf21cd93STycho Nightingale * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24bf21cd93STycho Nightingale * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25bf21cd93STycho Nightingale * SUCH DAMAGE.
26bf21cd93STycho Nightingale */
27bf21cd93STycho Nightingale
28bf21cd93STycho Nightingale #include <sys/cdefs.h>
29bf21cd93STycho Nightingale
30bf21cd93STycho Nightingale #include <sys/types.h>
31bf21cd93STycho Nightingale #include <ctype.h>
32bf21cd93STycho Nightingale #include <errno.h>
33bf21cd93STycho Nightingale #include <inttypes.h>
34bf21cd93STycho Nightingale #include <libutil.h>
35bf21cd93STycho Nightingale #include <stdint.h>
36bf21cd93STycho Nightingale
37bf21cd93STycho Nightingale int
expand_number(const char * buf,uint64_t * num)38bf21cd93STycho Nightingale expand_number(const char *buf, uint64_t *num)
39bf21cd93STycho Nightingale {
40bf21cd93STycho Nightingale char *endptr;
41bf21cd93STycho Nightingale uintmax_t umaxval;
42bf21cd93STycho Nightingale uint64_t number;
43bf21cd93STycho Nightingale unsigned shift;
44bf21cd93STycho Nightingale int serrno;
45bf21cd93STycho Nightingale
46bf21cd93STycho Nightingale serrno = errno;
47bf21cd93STycho Nightingale errno = 0;
48bf21cd93STycho Nightingale umaxval = strtoumax(buf, &endptr, 0);
49*b0de25cbSAndy Fiddaman #ifdef __FreeBSD__
50bf21cd93STycho Nightingale if (umaxval > UINT64_MAX)
51bf21cd93STycho Nightingale errno = ERANGE;
52*b0de25cbSAndy Fiddaman #endif
53bf21cd93STycho Nightingale if (errno != 0)
54bf21cd93STycho Nightingale return (-1);
55bf21cd93STycho Nightingale errno = serrno;
56bf21cd93STycho Nightingale number = umaxval;
57bf21cd93STycho Nightingale
58bf21cd93STycho Nightingale switch (tolower((unsigned char)*endptr)) {
59bf21cd93STycho Nightingale case 'e':
60bf21cd93STycho Nightingale shift = 60;
61bf21cd93STycho Nightingale break;
62bf21cd93STycho Nightingale case 'p':
63bf21cd93STycho Nightingale shift = 50;
64bf21cd93STycho Nightingale break;
65bf21cd93STycho Nightingale case 't':
66bf21cd93STycho Nightingale shift = 40;
67bf21cd93STycho Nightingale break;
68bf21cd93STycho Nightingale case 'g':
69bf21cd93STycho Nightingale shift = 30;
70bf21cd93STycho Nightingale break;
71bf21cd93STycho Nightingale case 'm':
72bf21cd93STycho Nightingale shift = 20;
73bf21cd93STycho Nightingale break;
74bf21cd93STycho Nightingale case 'k':
75bf21cd93STycho Nightingale shift = 10;
76bf21cd93STycho Nightingale break;
77bf21cd93STycho Nightingale case 'b':
78bf21cd93STycho Nightingale case '\0': /* No unit. */
79bf21cd93STycho Nightingale *num = number;
80bf21cd93STycho Nightingale return (0);
81bf21cd93STycho Nightingale default:
82bf21cd93STycho Nightingale /* Unrecognized unit. */
83bf21cd93STycho Nightingale errno = EINVAL;
84bf21cd93STycho Nightingale return (-1);
85bf21cd93STycho Nightingale }
86bf21cd93STycho Nightingale
87bf21cd93STycho Nightingale if ((number << shift) >> shift != number) {
88bf21cd93STycho Nightingale /* Overflow */
89bf21cd93STycho Nightingale errno = ERANGE;
90bf21cd93STycho Nightingale return (-1);
91bf21cd93STycho Nightingale }
92bf21cd93STycho Nightingale *num = number << shift;
93bf21cd93STycho Nightingale return (0);
94bf21cd93STycho Nightingale }
95