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