parse-util.c revision b3267152783d5784c45010615045d4e8ee459da2
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering This file is part of systemd.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Copyright 2010 Lennart 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 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 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/>.
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenint parse_boolean(const char *v) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (streq(v, "1") || strcaseeq(v, "yes") || strcaseeq(v, "y") || strcaseeq(v, "true") || strcaseeq(v, "t") || strcaseeq(v, "on"))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else if (streq(v, "0") || strcaseeq(v, "no") || strcaseeq(v, "n") || strcaseeq(v, "false") || strcaseeq(v, "f") || strcaseeq(v, "off"))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint parse_pid(const char *s, pid_t* ret_pid) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering unsigned long ul = 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint parse_mode(const char *s, mode_t *ret) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (s[0] == '-')
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!x || x == s || *x)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (l < 0 || l > 07777)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint parse_ifindex(const char *s, int *ret) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint parse_size(const char *t, uint64_t base, uint64_t *size) {
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 * 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 unsigned long long factor;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen { "E", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering { "P", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering { "T", 1000ULL*1000ULL*1000ULL*1000ULL },
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering const char *p;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering unsigned long long r = 0;
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering unsigned long long l, tmp;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (*p == '-')
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (*e == '.') {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* strtoull() itself would accept space/+/- */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering unsigned long long l2;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Ignore failure. E.g. 10.M is valid */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (; e < e2; e++)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (l + (frac > 0) > ULLONG_MAX / table[i].factor)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering tmp = l * table[i].factor + (unsigned long long) (frac * table[i].factor);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if ((unsigned long long) (uint64_t) r != r)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sieversint parse_range(const char *t, unsigned *lower, unsigned *upper) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers unsigned l, u;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers /* Extract the lower bound. */
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers r = extract_first_word(&t, &word, "-", EXTRACT_DONT_COALESCE_SEPARATORS);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers /* Check for the upper bound and extract it if needed */
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers /* Single number with no dashes. */
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen else if (!*t)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers /* Trailing dash is an error. */
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sieverschar *format_bytes(char *buf, size_t l, uint64_t t) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers /* This only does IEC units so far */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering static const struct {
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) },
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (i = 0; i < ELEMENTSOF(table); i++) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers ((t*UINT64_C(10)) / table[i].factor) % UINT64_C(10),
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers unsigned long l;
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 l = strtoul(s, &x, 0);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (!x || x == s || *x)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (s[0] == '-')
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if ((unsigned long) (unsigned) l != l)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers *ret_u = (unsigned) l;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint safe_atoi(const char *s, int *ret_i) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering l = strtol(s, &x, 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!x || x == s || *x)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if ((long) (int) l != l)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenint safe_atollu(const char *s, long long unsigned *ret_llu) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen unsigned long long l;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!x || x == s || *x)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (*s == '-')
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint safe_atolli(const char *s, long long int *ret_lli) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen l = strtoll(s, &x, 0);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (!x || x == s || *x)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint safe_atou8(const char *s, uint8_t *ret) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering unsigned long l;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (!x || x == s || *x)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (s[0] == '-')
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if ((unsigned long) (uint8_t) l != l)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringint safe_atou16(const char *s, uint16_t *ret) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering unsigned long l;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (!x || x == s || *x)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (s[0] == '-')
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if ((unsigned long) (uint16_t) l != l)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringint safe_atoi16(const char *s, int16_t *ret) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering l = strtol(s, &x, 0);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (!x || x == s || *x)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if ((long) (int16_t) l != l)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringint safe_atod(const char *s, double *ret_d) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (!x || x == s || *x) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering *ret_d = (double) d;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringint parse_fractional_part_u(const char **p, size_t digits, unsigned *res) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering const char *s;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering /* accept any number of digits, strtoull is limted to 19 */
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering for(i=0; i < digits; i++,s++) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering /* too few digits, pad with 0 */
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering for (; i < digits; i++)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering /* maybe round up */