parseoffset.c - sbase - suckless unix tools
 (HTM) git clone git://git.suckless.org/sbase
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       parseoffset.c (1148B)
       ---
            1 /* See LICENSE file for copyright and license details. */
            2 #include <ctype.h>
            3 #include <errno.h>
            4 #include <inttypes.h>
            5 #include <stdlib.h>
            6 #include <string.h>
            7 
            8 #include "../util.h"
            9 
           10 off_t
           11 parseoffset(const char *str)
           12 {
           13         off_t res, scale = 1;
           14         char *end;
           15 
           16         /* strictly check what strtol() usually would let pass */
           17         if (!str || !*str || isspace(*str) || *str == '+' || *str == '-') {
           18                 weprintf("parseoffset %s: invalid value\n", str);
           19                 return -1;
           20         }
           21 
           22         errno = 0;
           23         res = strtol(str, &end, 0);
           24         if (errno) {
           25                 weprintf("parseoffset %s: invalid value\n", str);
           26                 return -1;
           27         }
           28         if (res < 0) {
           29                 weprintf("parseoffset %s: negative value\n", str);
           30                 return -1;
           31         }
           32 
           33         /* suffix */
           34         if (*end) {
           35                 switch (toupper((int)*end)) {
           36                 case 'B':
           37                         scale = 512L;
           38                         break;
           39                 case 'K':
           40                         scale = 1024L;
           41                         break;
           42                 case 'M':
           43                         scale = 1024L * 1024L;
           44                         break;
           45                 case 'G':
           46                         scale = 1024L * 1024L * 1024L;
           47                         break;
           48                 default:
           49                         weprintf("parseoffset %s: invalid suffix '%s'\n", str, end);
           50                         return -1;
           51                 }
           52         }
           53 
           54         /* prevent overflow */
           55         if (res > (SSIZE_MAX / scale)) {
           56                 weprintf("parseoffset %s: out of range\n", str);
           57                 return -1;
           58         }
           59 
           60         return res * scale;
           61 }