parse-util.c revision 6bedfcbb2970e06a4d3280c8fb62083d252ede73
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek/***
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek This file is part of systemd.
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek Copyright 2010 Lennart Poettering
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek under the terms of the GNU Lesser General Public License as published by
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek the Free Software Foundation; either version 2.1 of the License, or
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek (at your option) any later version.
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek systemd is distributed in the hope that it will be useful, but
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek WITHOUT ANY WARRANTY; without even the implied warranty of
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek Lesser General Public License for more details.
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek You should have received a copy of the GNU Lesser General Public License
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek along with systemd; If not, see <http://www.gnu.org/licenses/>.
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek***/
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek#include "parse-util.h"
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek#include "string-util.h"
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek#include "util.h"
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmekint parse_boolean(const char *v) {
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek assert(v);
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek if (streq(v, "1") || strcaseeq(v, "yes") || strcaseeq(v, "y") || strcaseeq(v, "true") || strcaseeq(v, "t") || strcaseeq(v, "on"))
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek return 1;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek else if (streq(v, "0") || strcaseeq(v, "no") || strcaseeq(v, "n") || strcaseeq(v, "false") || strcaseeq(v, "f") || strcaseeq(v, "off"))
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek return 0;
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek return -EINVAL;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek}
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmekint parse_pid(const char *s, pid_t* ret_pid) {
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek unsigned long ul = 0;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek pid_t pid;
7449bc1f34c206e3ff8e274cd74e2db950d492a1Zbigniew Jędrzejewski-Szmek int r;
7449bc1f34c206e3ff8e274cd74e2db950d492a1Zbigniew Jędrzejewski-Szmek
7449bc1f34c206e3ff8e274cd74e2db950d492a1Zbigniew Jędrzejewski-Szmek assert(s);
7449bc1f34c206e3ff8e274cd74e2db950d492a1Zbigniew Jędrzejewski-Szmek assert(ret_pid);
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek r = safe_atolu(s, &ul);
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek if (r < 0)
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek return r;
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek pid = (pid_t) ul;
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek if ((unsigned long) pid != ul)
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek return -ERANGE;
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek if (pid <= 0)
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek return -ERANGE;
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek *ret_pid = pid;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek return 0;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek}
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmekint parse_mode(const char *s, mode_t *ret) {
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek char *x;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek long l;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek assert(s);
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek assert(ret);
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek errno = 0;
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek l = strtol(s, &x, 8);
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek if (errno != 0)
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek return -errno;
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek if (!x || x == s || *x)
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek return -EINVAL;
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek if (l < 0 || l > 07777)
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek return -ERANGE;
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek *ret = (mode_t) l;
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek return 0;
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek}
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmekint parse_size(const char *t, uint64_t base, uint64_t *size) {
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek /* Soo, sometimes we want to parse IEC binary suffixes, and
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek * sometimes SI decimal suffixes. This function can parse
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek * both. Which one is the right way depends on the
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek * context. Wikipedia suggests that SI is customary for
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek * hardware metrics and network speeds, while IEC is
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek * customary for most data sizes used by software and volatile
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek * (RAM) memory. Hence be careful which one you pick!
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek *
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek * In either case we use just K, M, G as suffix, and not Ki,
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek * Mi, Gi or so (as IEC would suggest). That's because that's
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek * frickin' ugly. But this means you really need to make sure
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek * to document which base you are parsing when you use this
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek * call. */
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek struct table {
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek const char *suffix;
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek unsigned long long factor;
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek };
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek static const struct table iec[] = {
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek { "G", 1024ULL*1024ULL*1024ULL },
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek { "M", 1024ULL*1024ULL },
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek { "K", 1024ULL },
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek { "B", 1ULL },
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek { "", 1ULL },
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek };
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek static const struct table si[] = {
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek { "E", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek { "P", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek { "T", 1000ULL*1000ULL*1000ULL*1000ULL },
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek { "G", 1000ULL*1000ULL*1000ULL },
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek { "M", 1000ULL*1000ULL },
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek { "K", 1000ULL },
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek { "B", 1ULL },
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek { "", 1ULL },
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek };
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek const struct table *table;
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek const char *p;
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek unsigned long long r = 0;
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek unsigned n_entries, start_pos = 0;
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek assert(t);
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek assert(base == 1000 || base == 1024);
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek assert(size);
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek if (base == 1000) {
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek table = si;
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek n_entries = ELEMENTSOF(si);
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek } else {
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek table = iec;
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek n_entries = ELEMENTSOF(iec);
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek }
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek p = t;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek do {
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek unsigned long long l, tmp;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek double frac = 0;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek char *e;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek unsigned i;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek p += strspn(p, WHITESPACE);
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek if (*p == '-')
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek return -ERANGE;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek errno = 0;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek l = strtoull(p, &e, 10);
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek if (errno > 0)
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek return -errno;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek if (e == p)
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek return -EINVAL;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek if (*e == '.') {
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek e++;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek /* strtoull() itself would accept space/+/- */
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek if (*e >= '0' && *e <= '9') {
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek unsigned long long l2;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek char *e2;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek l2 = strtoull(e, &e2, 10);
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek if (errno > 0)
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek return -errno;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek /* Ignore failure. E.g. 10.M is valid */
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek frac = l2;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek for (; e < e2; e++)
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek frac /= 10;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek }
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek }
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek e += strspn(e, WHITESPACE);
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek for (i = start_pos; i < n_entries; i++)
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek if (startswith(e, table[i].suffix))
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek break;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek if (i >= n_entries)
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek return -EINVAL;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek if (l + (frac > 0) > ULLONG_MAX / table[i].factor)
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek return -ERANGE;
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek tmp = l * table[i].factor + (unsigned long long) (frac * table[i].factor);
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek if (tmp > ULLONG_MAX - r)
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek return -ERANGE;
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek r += tmp;
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek if ((unsigned long long) (uint64_t) r != r)
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek return -ERANGE;
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek p = e + strlen(table[i].suffix);
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek start_pos = i + 1;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek } while (*p);
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek *size = r;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek return 0;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek}
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmekchar *format_bytes(char *buf, size_t l, uint64_t t) {
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek unsigned i;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek /* This only does IEC units so far */
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek static const struct {
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek const char *suffix;
7449bc1f34c206e3ff8e274cd74e2db950d492a1Zbigniew Jędrzejewski-Szmek uint64_t factor;
7449bc1f34c206e3ff8e274cd74e2db950d492a1Zbigniew Jędrzejewski-Szmek } table[] = {
7449bc1f34c206e3ff8e274cd74e2db950d492a1Zbigniew Jędrzejewski-Szmek { "E", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
7449bc1f34c206e3ff8e274cd74e2db950d492a1Zbigniew Jędrzejewski-Szmek { "P", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
7449bc1f34c206e3ff8e274cd74e2db950d492a1Zbigniew Jędrzejewski-Szmek { "T", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
7449bc1f34c206e3ff8e274cd74e2db950d492a1Zbigniew Jędrzejewski-Szmek { "G", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
7449bc1f34c206e3ff8e274cd74e2db950d492a1Zbigniew Jędrzejewski-Szmek { "M", UINT64_C(1024)*UINT64_C(1024) },
7449bc1f34c206e3ff8e274cd74e2db950d492a1Zbigniew Jędrzejewski-Szmek { "K", UINT64_C(1024) },
7449bc1f34c206e3ff8e274cd74e2db950d492a1Zbigniew Jędrzejewski-Szmek };
7449bc1f34c206e3ff8e274cd74e2db950d492a1Zbigniew Jędrzejewski-Szmek
7449bc1f34c206e3ff8e274cd74e2db950d492a1Zbigniew Jędrzejewski-Szmek if (t == (uint64_t) -1)
7449bc1f34c206e3ff8e274cd74e2db950d492a1Zbigniew Jędrzejewski-Szmek return NULL;
7449bc1f34c206e3ff8e274cd74e2db950d492a1Zbigniew Jędrzejewski-Szmek
7449bc1f34c206e3ff8e274cd74e2db950d492a1Zbigniew Jędrzejewski-Szmek for (i = 0; i < ELEMENTSOF(table); i++) {
7449bc1f34c206e3ff8e274cd74e2db950d492a1Zbigniew Jędrzejewski-Szmek
7449bc1f34c206e3ff8e274cd74e2db950d492a1Zbigniew Jędrzejewski-Szmek if (t >= table[i].factor) {
7449bc1f34c206e3ff8e274cd74e2db950d492a1Zbigniew Jędrzejewski-Szmek snprintf(buf, l,
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek "%" PRIu64 ".%" PRIu64 "%s",
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek t / table[i].factor,
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek ((t*UINT64_C(10)) / table[i].factor) % UINT64_C(10),
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek table[i].suffix);
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek goto finish;
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek }
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek }
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek snprintf(buf, l, "%" PRIu64 "B", t);
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmekfinish:
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek buf[l-1] = 0;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek return buf;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek}
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmekint safe_atou(const char *s, unsigned *ret_u) {
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek char *x = NULL;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek unsigned long l;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek assert(s);
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek assert(ret_u);
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek errno = 0;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek l = strtoul(s, &x, 0);
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek if (!x || x == s || *x || errno)
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek return errno > 0 ? -errno : -EINVAL;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek if ((unsigned long) (unsigned) l != l)
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek return -ERANGE;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek *ret_u = (unsigned) l;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek return 0;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek}
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmekint safe_atoi(const char *s, int *ret_i) {
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek char *x = NULL;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek long l;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek assert(s);
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek assert(ret_i);
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek errno = 0;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek l = strtol(s, &x, 0);
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek if (!x || x == s || *x || errno)
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek return errno > 0 ? -errno : -EINVAL;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek if ((long) (int) l != l)
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek return -ERANGE;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek *ret_i = (int) l;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek return 0;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek}
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmekint safe_atollu(const char *s, long long unsigned *ret_llu) {
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek char *x = NULL;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek unsigned long long l;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek assert(s);
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek assert(ret_llu);
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek errno = 0;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek l = strtoull(s, &x, 0);
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek if (!x || x == s || *x || errno)
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek return errno ? -errno : -EINVAL;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek *ret_llu = l;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek return 0;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek}
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmekint safe_atolli(const char *s, long long int *ret_lli) {
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek char *x = NULL;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek long long l;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek assert(s);
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek assert(ret_lli);
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek errno = 0;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek l = strtoll(s, &x, 0);
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek if (!x || x == s || *x || errno)
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek return errno ? -errno : -EINVAL;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek *ret_lli = l;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek return 0;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek}
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmekint safe_atou8(const char *s, uint8_t *ret) {
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek char *x = NULL;
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek unsigned long l;
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek assert(s);
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek assert(ret);
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek errno = 0;
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek l = strtoul(s, &x, 0);
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek if (!x || x == s || *x || errno)
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek return errno > 0 ? -errno : -EINVAL;
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek if ((unsigned long) (uint8_t) l != l)
eacbb4d33e2bb5c54311544851140efe3dd0f774Zbigniew Jędrzejewski-Szmek return -ERANGE;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek *ret = (uint8_t) l;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek return 0;
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek}
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmekint safe_atou16(const char *s, uint16_t *ret) {
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek char *x = NULL;
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek unsigned long l;
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek assert(s);
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek assert(ret);
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek errno = 0;
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek l = strtoul(s, &x, 0);
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek if (!x || x == s || *x || errno)
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek return errno > 0 ? -errno : -EINVAL;
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek if ((unsigned long) (uint16_t) l != l)
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek return -ERANGE;
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek *ret = (uint16_t) l;
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek return 0;
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek}
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmekint safe_atoi16(const char *s, int16_t *ret) {
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek char *x = NULL;
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek long l;
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek assert(s);
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek assert(ret);
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek errno = 0;
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek l = strtol(s, &x, 0);
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek if (!x || x == s || *x || errno)
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek return errno > 0 ? -errno : -EINVAL;
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek if ((long) (int16_t) l != l)
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek return -ERANGE;
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek *ret = (int16_t) l;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek return 0;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek}
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmekint safe_atod(const char *s, double *ret_d) {
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek char *x = NULL;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek double d = 0;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek locale_t loc;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek assert(s);
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek assert(ret_d);
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0);
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek if (loc == (locale_t) 0)
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek return -errno;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek errno = 0;
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek d = strtod_l(s, &x, loc);
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek if (!x || x == s || *x || errno) {
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek freelocale(loc);
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek return errno ? -errno : -EINVAL;
a3152e7655231b94fa7b9582906fb86ab00b9c99Zbigniew Jędrzejewski-Szmek }
722b6795655149a68277b3cffeba711e1d440e5aZbigniew Jędrzejewski-Szmek
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek freelocale(loc);
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek *ret_d = (double) d;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek return 0;
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek}
3d090cc6f34e5970765dd1e7ee5e648a056d180dZbigniew Jędrzejewski-Szmek