parse-util.c revision b3267152783d5784c45010615045d4e8ee459da2
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/***
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering This file is part of systemd.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Copyright 2010 Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is free software; you can redistribute it and/or modify it
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering under the terms of the GNU Lesser General Public License as published by
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (at your option) any later version.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is distributed in the hope that it will be useful, but
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Lesser General Public License for more details.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering You should have received a copy of the GNU Lesser General Public License
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering***/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <errno.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <inttypes.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <locale.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <stdio.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <stdlib.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <string.h>
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering#include <xlocale.h>
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "alloc-util.h"
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#include "extract-word.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "macro.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "parse-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "string-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenint parse_boolean(const char *v) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(v);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (streq(v, "1") || strcaseeq(v, "yes") || strcaseeq(v, "y") || strcaseeq(v, "true") || strcaseeq(v, "t") || strcaseeq(v, "on"))
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return 1;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else if (streq(v, "0") || strcaseeq(v, "no") || strcaseeq(v, "n") || strcaseeq(v, "false") || strcaseeq(v, "f") || strcaseeq(v, "off"))
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering return 0;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EINVAL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint parse_pid(const char *s, pid_t* ret_pid) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering unsigned long ul = 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering pid_t pid;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering assert(s);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(ret_pid);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = safe_atolu(s, &ul);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering pid = (pid_t) ul;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if ((unsigned long) pid != ul)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -ERANGE;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (pid <= 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return -ERANGE;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen *ret_pid = pid;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint parse_mode(const char *s, mode_t *ret) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char *x;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen long l;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(s);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(ret);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen s += strspn(s, WHITESPACE);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (s[0] == '-')
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return -ERANGE;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen errno = 0;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen l = strtol(s, &x, 8);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (errno > 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!x || x == s || *x)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EINVAL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (l < 0 || l > 07777)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -ERANGE;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen *ret = (mode_t) l;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint parse_ifindex(const char *s, int *ret) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int ifi, r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = safe_atoi(s, &ifi);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (r < 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return r;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (ifi <= 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return -EINVAL;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen *ret = ifi;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint parse_size(const char *t, uint64_t base, uint64_t *size) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen /* Soo, sometimes we want to parse IEC binary suffixes, and
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen * sometimes SI decimal suffixes. This function can parse
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen * both. Which one is the right way depends on the
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering * context. Wikipedia suggests that SI is customary for
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * hardware metrics and network speeds, while IEC is
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * customary for most data sizes used by software and volatile
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen * (RAM) memory. Hence be careful which one you pick!
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen *
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen * In either case we use just K, M, G as suffix, and not Ki,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering * Mi, Gi or so (as IEC would suggest). That's because that's
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering * frickin' ugly. But this means you really need to make sure
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering * to document which base you are parsing when you use this
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering * call. */
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering struct table {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering const char *suffix;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering unsigned long long factor;
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering };
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering static const struct table iec[] = {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering { "G", 1024ULL*1024ULL*1024ULL },
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering { "M", 1024ULL*1024ULL },
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering { "K", 1024ULL },
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering { "B", 1ULL },
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering { "", 1ULL },
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering };
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering static const struct table si[] = {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen { "E", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering { "P", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering { "T", 1000ULL*1000ULL*1000ULL*1000ULL },
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen { "G", 1000ULL*1000ULL*1000ULL },
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering { "M", 1000ULL*1000ULL },
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering { "K", 1000ULL },
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering { "B", 1ULL },
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering { "", 1ULL },
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen };
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen const struct table *table;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering const char *p;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering unsigned long long r = 0;
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering unsigned n_entries, start_pos = 0;
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering assert(t);
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering assert(base == 1000 || base == 1024);
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering assert(size);
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (base == 1000) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering table = si;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering n_entries = ELEMENTSOF(si);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering } else {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering table = iec;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering n_entries = ELEMENTSOF(iec);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering }
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering p = t;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering do {
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering unsigned long long l, tmp;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering double frac = 0;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering char *e;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering unsigned i;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers p += strspn(p, WHITESPACE);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers errno = 0;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers l = strtoull(p, &e, 10);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (errno > 0)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (e == p)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EINVAL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (*p == '-')
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -ERANGE;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (*e == '.') {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering e++;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* strtoull() itself would accept space/+/- */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (*e >= '0' && *e <= '9') {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering unsigned long long l2;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char *e2;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering l2 = strtoull(e, &e2, 10);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (errno > 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Ignore failure. E.g. 10.M is valid */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering frac = l2;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (; e < e2; e++)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering frac /= 10;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering e += strspn(e, WHITESPACE);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (i = start_pos; i < n_entries; i++)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (startswith(e, table[i].suffix))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering break;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (i >= n_entries)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EINVAL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (l + (frac > 0) > ULLONG_MAX / table[i].factor)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -ERANGE;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering tmp = l * table[i].factor + (unsigned long long) (frac * table[i].factor);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (tmp > ULLONG_MAX - r)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -ERANGE;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r += tmp;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if ((unsigned long long) (uint64_t) r != r)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -ERANGE;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering p = e + strlen(table[i].suffix);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering start_pos = i + 1;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering } while (*p);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering *size = r;
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sieversint parse_range(const char *t, unsigned *lower, unsigned *upper) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers _cleanup_free_ char *word = NULL;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers unsigned l, u;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers int r;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers assert(lower);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers assert(upper);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers /* Extract the lower bound. */
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers r = extract_first_word(&t, &word, "-", EXTRACT_DONT_COALESCE_SEPARATORS);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (r < 0)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return r;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (r == 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return -EINVAL;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = safe_atou(word, &l);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers /* Check for the upper bound and extract it if needed */
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (!t)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers /* Single number with no dashes. */
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers u = l;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen else if (!*t)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers /* Trailing dash is an error. */
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return -EINVAL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = safe_atou(t, &u);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers *lower = l;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering *upper = u;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return 0;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers}
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sieverschar *format_bytes(char *buf, size_t l, uint64_t t) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers unsigned i;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers /* This only does IEC units so far */
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering static const struct {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers const char *suffix;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers uint64_t factor;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering } table[] = {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers { "E", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers { "P", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering { "T", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers { "G", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen { "M", UINT64_C(1024)*UINT64_C(1024) },
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers { "K", UINT64_C(1024) },
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen };
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (t == (uint64_t) -1)
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering return NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (i = 0; i < ELEMENTSOF(table); i++) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (t >= table[i].factor) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen snprintf(buf, l,
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers "%" PRIu64 ".%" PRIu64 "%s",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering t / table[i].factor,
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers ((t*UINT64_C(10)) / table[i].factor) % UINT64_C(10),
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering table[i].suffix);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto finish;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering snprintf(buf, l, "%" PRIu64 "B", t);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sieversfinish:
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen buf[l-1] = 0;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return buf;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers}
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sieversint safe_atou(const char *s, unsigned *ret_u) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers char *x = NULL;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers unsigned long l;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(s);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(ret_u);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* strtoul() is happy to parse negative values, and silently
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen * converts them to unsigned values without generating an
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen * error. We want a clean error, hence let's look for the "-"
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen * prefix on our own, and generate an error. But let's do so
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen * only after strtoul() validated that the string is clean
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen * otherwise, so that we return EINVAL preferably over
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen * ERANGE. */
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen s += strspn(s, WHITESPACE);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen errno = 0;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen l = strtoul(s, &x, 0);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (errno > 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return -errno;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (!x || x == s || *x)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return -EINVAL;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (s[0] == '-')
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return -ERANGE;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if ((unsigned long) (unsigned) l != l)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -ERANGE;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers *ret_u = (unsigned) l;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return 0;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers}
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint safe_atoi(const char *s, int *ret_i) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char *x = NULL;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers long l;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(s);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(ret_i);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering errno = 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering l = strtol(s, &x, 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (errno > 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!x || x == s || *x)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EINVAL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if ((long) (int) l != l)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -ERANGE;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering *ret_i = (int) l;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return 0;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenint safe_atollu(const char *s, long long unsigned *ret_llu) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen char *x = NULL;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen unsigned long long l;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(s);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(ret_llu);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen s += strspn(s, WHITESPACE);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen errno = 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering l = strtoull(s, &x, 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (errno > 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!x || x == s || *x)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EINVAL;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (*s == '-')
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return -ERANGE;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering *ret_llu = l;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint safe_atolli(const char *s, long long int *ret_lli) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char *x = NULL;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen long long l;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(s);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(ret_lli);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen errno = 0;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen l = strtoll(s, &x, 0);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (errno > 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return -errno;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (!x || x == s || *x)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return -EINVAL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen *ret_lli = l;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint safe_atou8(const char *s, uint8_t *ret) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char *x = NULL;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering unsigned long l;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(s);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(ret);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering s += strspn(s, WHITESPACE);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering errno = 0;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering l = strtoul(s, &x, 0);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (errno > 0)
f69157a66ffe413b4cf8bd79057487fc8921e78bThomas Hindoe Paaboel Andersen return -errno;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (!x || x == s || *x)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return -EINVAL;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (s[0] == '-')
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return -ERANGE;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if ((unsigned long) (uint8_t) l != l)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return -ERANGE;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering *ret = (uint8_t) l;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return 0;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering}
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringint safe_atou16(const char *s, uint16_t *ret) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering char *x = NULL;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering unsigned long l;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(s);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(ret);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering s += strspn(s, WHITESPACE);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering errno = 0;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering l = strtoul(s, &x, 0);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (errno > 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return -errno;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (!x || x == s || *x)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return -EINVAL;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (s[0] == '-')
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return -ERANGE;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if ((unsigned long) (uint16_t) l != l)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return -ERANGE;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering *ret = (uint16_t) l;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return 0;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering}
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringint safe_atoi16(const char *s, int16_t *ret) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering char *x = NULL;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering long l;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(s);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(ret);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering errno = 0;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering l = strtol(s, &x, 0);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (errno > 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return -errno;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (!x || x == s || *x)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return -EINVAL;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if ((long) (int16_t) l != l)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return -ERANGE;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering *ret = (int16_t) l;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return 0;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering}
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringint safe_atod(const char *s, double *ret_d) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering char *x = NULL;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering double d = 0;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering locale_t loc;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(s);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(ret_d);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (loc == (locale_t) 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return -errno;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering errno = 0;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering d = strtod_l(s, &x, loc);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (errno > 0) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering freelocale(loc);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return -errno;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (!x || x == s || *x) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering freelocale(loc);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return -EINVAL;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering freelocale(loc);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering *ret_d = (double) d;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return 0;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering}
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringint parse_fractional_part_u(const char **p, size_t digits, unsigned *res) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering size_t i;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering unsigned val = 0;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering const char *s;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering s = *p;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering /* accept any number of digits, strtoull is limted to 19 */
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering for(i=0; i < digits; i++,s++) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (*s < '0' || *s > '9') {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (i == 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return -EINVAL;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering /* too few digits, pad with 0 */
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering for (; i < digits; i++)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering val *= 10;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering break;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering val *= 10;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering val += *s - '0';
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering /* maybe round up */
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (*s >= '5' && *s <= '9')
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering val++;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering s += strspn(s, DIGITS);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering *p = s;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering *res = val;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return 0;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering}
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering