1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include "alloc-util.h"
23 //#include "extract-word.h"
24 #include "parse-util.h"
25 #include "string-util.h"
28 int parse_boolean(const char *v) {
31 if (streq(v, "1") || strcaseeq(v, "yes") || strcaseeq(v, "y") || strcaseeq(v, "true") || strcaseeq(v, "t") || strcaseeq(v, "on"))
33 else if (streq(v, "0") || strcaseeq(v, "no") || strcaseeq(v, "n") || strcaseeq(v, "false") || strcaseeq(v, "f") || strcaseeq(v, "off"))
39 int parse_pid(const char *s, pid_t* ret_pid) {
47 r = safe_atolu(s, &ul);
53 if ((unsigned long) pid != ul)
63 int parse_mode(const char *s, mode_t *ret) {
70 s += strspn(s, WHITESPACE);
78 if (!x || x == s || *x)
80 if (l < 0 || l > 07777)
87 int parse_ifindex(const char *s, int *ret) {
90 r = safe_atoi(s, &ifi);
100 int parse_size(const char *t, uint64_t base, uint64_t *size) {
102 /* Soo, sometimes we want to parse IEC binary suffixes, and
103 * sometimes SI decimal suffixes. This function can parse
104 * both. Which one is the right way depends on the
105 * context. Wikipedia suggests that SI is customary for
106 * hardware metrics and network speeds, while IEC is
107 * customary for most data sizes used by software and volatile
108 * (RAM) memory. Hence be careful which one you pick!
110 * In either case we use just K, M, G as suffix, and not Ki,
111 * Mi, Gi or so (as IEC would suggest). That's because that's
112 * frickin' ugly. But this means you really need to make sure
113 * to document which base you are parsing when you use this
118 unsigned long long factor;
121 static const struct table iec[] = {
122 { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
123 { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
124 { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
125 { "G", 1024ULL*1024ULL*1024ULL },
126 { "M", 1024ULL*1024ULL },
132 static const struct table si[] = {
133 { "E", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
134 { "P", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
135 { "T", 1000ULL*1000ULL*1000ULL*1000ULL },
136 { "G", 1000ULL*1000ULL*1000ULL },
137 { "M", 1000ULL*1000ULL },
143 const struct table *table;
145 unsigned long long r = 0;
146 unsigned n_entries, start_pos = 0;
149 assert(base == 1000 || base == 1024);
154 n_entries = ELEMENTSOF(si);
157 n_entries = ELEMENTSOF(iec);
162 unsigned long long l, tmp;
167 p += strspn(p, WHITESPACE);
170 l = strtoull(p, &e, 10);
181 /* strtoull() itself would accept space/+/- */
182 if (*e >= '0' && *e <= '9') {
183 unsigned long long l2;
186 l2 = strtoull(e, &e2, 10);
190 /* Ignore failure. E.g. 10.M is valid */
197 e += strspn(e, WHITESPACE);
199 for (i = start_pos; i < n_entries; i++)
200 if (startswith(e, table[i].suffix))
206 if (l + (frac > 0) > ULLONG_MAX / table[i].factor)
209 tmp = l * table[i].factor + (unsigned long long) (frac * table[i].factor);
210 if (tmp > ULLONG_MAX - r)
214 if ((unsigned long long) (uint64_t) r != r)
217 p = e + strlen(table[i].suffix);
228 #if 0 /// UNNEEDED by elogind
229 int parse_range(const char *t, unsigned *lower, unsigned *upper) {
230 _cleanup_free_ char *word = NULL;
237 /* Extract the lower bound. */
238 r = extract_first_word(&t, &word, "-", EXTRACT_DONT_COALESCE_SEPARATORS);
244 r = safe_atou(word, &l);
248 /* Check for the upper bound and extract it if needed */
250 /* Single number with no dashes. */
253 /* Trailing dash is an error. */
256 r = safe_atou(t, &u);
266 char *format_bytes(char *buf, size_t l, uint64_t t) {
269 /* This only does IEC units so far */
271 static const struct {
275 { "E", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
276 { "P", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
277 { "T", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
278 { "G", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
279 { "M", UINT64_C(1024)*UINT64_C(1024) },
280 { "K", UINT64_C(1024) },
283 if (t == (uint64_t) -1)
286 for (i = 0; i < ELEMENTSOF(table); i++) {
288 if (t >= table[i].factor) {
290 "%" PRIu64 ".%" PRIu64 "%s",
292 ((t*UINT64_C(10)) / table[i].factor) % UINT64_C(10),
299 snprintf(buf, l, "%" PRIu64 "B", t);
308 int safe_atou(const char *s, unsigned *ret_u) {
315 /* strtoul() is happy to parse negative values, and silently
316 * converts them to unsigned values without generating an
317 * error. We want a clean error, hence let's look for the "-"
318 * prefix on our own, and generate an error. But let's do so
319 * only after strtoul() validated that the string is clean
320 * otherwise, so that we return EINVAL preferably over
323 s += strspn(s, WHITESPACE);
326 l = strtoul(s, &x, 0);
329 if (!x || x == s || *x)
333 if ((unsigned long) (unsigned) l != l)
336 *ret_u = (unsigned) l;
340 int safe_atoi(const char *s, int *ret_i) {
348 l = strtol(s, &x, 0);
351 if (!x || x == s || *x)
353 if ((long) (int) l != l)
360 int safe_atollu(const char *s, long long unsigned *ret_llu) {
362 unsigned long long l;
367 s += strspn(s, WHITESPACE);
370 l = strtoull(s, &x, 0);
373 if (!x || x == s || *x)
382 int safe_atolli(const char *s, long long int *ret_lli) {
390 l = strtoll(s, &x, 0);
393 if (!x || x == s || *x)
400 int safe_atou8(const char *s, uint8_t *ret) {
407 s += strspn(s, WHITESPACE);
410 l = strtoul(s, &x, 0);
413 if (!x || x == s || *x)
417 if ((unsigned long) (uint8_t) l != l)
424 int safe_atou16(const char *s, uint16_t *ret) {
431 s += strspn(s, WHITESPACE);
434 l = strtoul(s, &x, 0);
437 if (!x || x == s || *x)
441 if ((unsigned long) (uint16_t) l != l)
448 int safe_atoi16(const char *s, int16_t *ret) {
456 l = strtol(s, &x, 0);
459 if (!x || x == s || *x)
461 if ((long) (int16_t) l != l)
468 int safe_atod(const char *s, double *ret_d) {
476 loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0);
477 if (loc == (locale_t) 0)
481 d = strtod_l(s, &x, loc);
486 if (!x || x == s || *x) {
496 int parse_fractional_part_u(const char **p, size_t digits, unsigned *res) {
503 /* accept any number of digits, strtoull is limted to 19 */
504 for(i=0; i < digits; i++,s++) {
505 if (*s < '0' || *s > '9') {
509 /* too few digits, pad with 0 */
510 for (; i < digits; i++)
521 if (*s >= '5' && *s <= '9')
524 s += strspn(s, DIGITS);