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
10off_t
11parseoffset(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}