/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ /* NetworkManager -- Network link manager * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA. * * (C) Copyright 2016 Red Hat, Inc. */ #include "nm-default.h" #include "nm-shared-utils.h" #include /*****************************************************************************/ /* _nm_utils_ascii_str_to_int64: * * A wrapper for g_ascii_strtoll, that checks whether the whole string * can be successfully converted to a number and is within a given * range. On any error, @fallback will be returned and %errno will be set * to a non-zero value. On success, %errno will be set to zero, check %errno * for errors. Any trailing or leading (ascii) white space is ignored and the * functions is locale independent. * * The function is guaranteed to return a value between @min and @max * (inclusive) or @fallback. Also, the parsing is rather strict, it does * not allow for any unrecognized characters, except leading and trailing * white space. **/ gint64 _nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 max, gint64 fallback) { gint64 v; size_t len; char buf[64], *s, *str_free = NULL; if (str) { while (g_ascii_isspace (str[0])) str++; } if (!str || !str[0]) { errno = EINVAL; return fallback; } len = strlen (str); if (g_ascii_isspace (str[--len])) { /* backward search the first non-ws character. * We already know that str[0] is non-ws. */ while (g_ascii_isspace (str[--len])) ; /* str[len] is now the last non-ws character... */ len++; if (len >= sizeof (buf)) s = str_free = g_malloc (len + 1); else s = buf; memcpy (s, str, len); s[len] = 0; nm_assert (len > 0 && len < strlen (str) && len == strlen (s)); nm_assert (!g_ascii_isspace (str[len-1]) && g_ascii_isspace (str[len])); nm_assert (strncmp (str, s, len) == 0); str = s; } errno = 0; v = g_ascii_strtoll (str, &s, base); if (errno != 0) v = fallback; else if (s[0] != 0) { errno = EINVAL; v = fallback; } else if (v > max || v < min) { errno = ERANGE; v = fallback; } if (G_UNLIKELY (str_free)) g_free (str_free); return v; } /*****************************************************************************/