1 /* Copyright 2018 Alain Knaff.
2 * This file is part of mtools.
3 *
4 * Mtools is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * Mtools is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with Mtools. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18 #include "sysincludes.h"
19 #include "mtools.h"
20
strtol_with_range(const char * nptr,char ** endptr,int base,long min,long max)21 static long strtol_with_range(const char *nptr, char **endptr, int base,
22 long min, long max) {
23 long l = strtol(nptr, endptr, base);
24 if(l > max) {
25 errno = ERANGE;
26 return max;
27 }
28 if(l < min) {
29 errno = ERANGE;
30 return min;
31 }
32 return l;
33 }
34
strtoul_with_range(const char * nptr,char ** endptr,int base,unsigned long max)35 static unsigned long strtoul_with_range(const char *nptr, char **endptr,
36 int base, unsigned long max) {
37 unsigned long l = strtoul(nptr, endptr, base);
38 if(l > max) {
39 errno = ERANGE;
40 return max;
41 }
42 return l;
43 }
44
45 #ifndef HAVE_STRTOUI
strtoui(const char * nptr,char ** endptr,int base)46 unsigned int strtoui(const char *nptr, char **endptr, int base) {
47 return (unsigned int) strtoul_with_range(nptr, endptr, base, UINT_MAX);
48 }
49 #endif
50
atoui(const char * str)51 unsigned int atoui(const char *str) {
52 return strtoui(str, 0, 0);
53 }
54
55 #ifndef HAVE_STRTOI
strtoi(const char * nptr,char ** endptr,int base)56 int strtoi(const char *nptr, char **endptr, int base) {
57 return (int) strtol_with_range(nptr, endptr, base, INT_MIN, INT_MAX);
58 }
59 #endif
60
atoul(const char * str)61 unsigned long atoul(const char *str) {
62 return strtoul(str, 0, 0);
63 }
64
strtou8(const char * nptr,char ** endptr,int base)65 uint8_t strtou8(const char *nptr, char **endptr, int base) {
66 return (uint8_t) strtoul_with_range(nptr, endptr, base, UINT8_MAX);
67 }
68
atou8(const char * str)69 uint8_t atou8(const char *str) {
70 return strtou8(str, 0, 0);
71 }
72
strtou16(const char * nptr,char ** endptr,int base)73 uint16_t strtou16(const char *nptr, char **endptr, int base) {
74 return (uint16_t) strtoul_with_range(nptr, endptr, base, UINT16_MAX);
75 }
76
atou16(const char * str)77 uint16_t atou16(const char *str) {
78 return strtou16(str, 0, 0);
79 }
80
strtou32(const char * nptr,char ** endptr,int base)81 uint32_t strtou32(const char *nptr, char **endptr, int base) {
82 return (uint32_t) strtoul_with_range(nptr, endptr, base, UINT32_MAX);
83 }
84
atou32(const char * str)85 uint32_t atou32(const char *str) {
86 return strtou32(str, 0, 0);
87 }
88
checkOverflow(uint32_t tot_sectors,int bits)89 static void checkOverflow(uint32_t tot_sectors, int bits) {
90 if(tot_sectors > UINT32_MAX >> bits) {
91 fprintf(stderr, "Too many sectors\n");
92 exit(1);
93 }
94 }
95
parseSize(char * sizeStr)96 uint32_t parseSize(char *sizeStr) {
97 char *eptr;
98 uint32_t tot_sectors = strtou32(sizeStr, &eptr, 10);
99 if(eptr == sizeStr) {
100 fprintf(stderr, "Bad size %s\n", sizeStr);
101 exit(1);
102 }
103 switch(toupper(*eptr)) {
104 case 'T':
105 checkOverflow(tot_sectors, 10);
106 tot_sectors *= 1024;
107 /* FALL THROUGH */
108 case 'G':
109 checkOverflow(tot_sectors, 10);
110 tot_sectors *= 1024;
111 /* FALL THROUGH */
112 case 'M':
113 checkOverflow(tot_sectors, 10);
114 tot_sectors *= 1024;
115 /* FALL THROUGH */
116 case 'K':
117 checkOverflow(tot_sectors, 1);
118 tot_sectors *= 2;
119 eptr++;
120 break;
121 case '\0':
122 /* By default, assume sectors */
123 break;
124 }
125 if(*eptr) {
126 fprintf(stderr, "Bad suffix %s\n", eptr);
127 exit(1);
128 }
129 return tot_sectors;
130 }
131