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