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