diff --git a/.gitignore b/.gitignore index 40dfe59f5c..36666d0607 100644 --- a/.gitignore +++ b/.gitignore @@ -180,6 +180,7 @@ valgrind-*.log /libnm-glib/tests/test-remote-settings-client /src/tests/test-dcb /src/tests/test-dhcp-options +/src/tests/test-general /src/tests/test-ip4-config /src/tests/test-ip6-config /src/tests/test-policy-hosts diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index ffd706c27a..c5824d73c6 100644 --- a/src/NetworkManagerUtils.c +++ b/src/NetworkManagerUtils.c @@ -695,3 +695,63 @@ nm_utils_match_connection (GSList *connections, return best_match; } +/* 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. 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 + * (included) 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; + char *end; + char *str_free = NULL; + + if (str) { + while (str[0] && g_ascii_isspace (str[0])) + str++; + } + if (!str || !str[0]) { + errno = EINVAL; + return fallback; + } + + if (g_ascii_isspace (str[strlen (str) - 1])) { + str_free = g_strdup (str); + g_strstrip (str_free); + str = str_free; + } + + errno = 0; + v = g_ascii_strtoll (str, &end, base); + + if (errno != 0) { + g_free (str_free); + return fallback; + } + + if (end[0] != 0) { + g_free (str_free); + errno = EINVAL; + return fallback; + } + + g_free (str_free); + if (v > max || v < min) { + errno = ERANGE; + return fallback; + } + + return v; +} + + + diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h index 06058a5612..7e62b71aed 100644 --- a/src/NetworkManagerUtils.h +++ b/src/NetworkManagerUtils.h @@ -94,4 +94,6 @@ NMConnection *nm_utils_match_connection (GSList *connections, NMUtilsMatchFilterFunc match_filter_func, gpointer match_filter_data); +gint64 nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 max, gint64 fallback); + #endif /* NETWORK_MANAGER_UTILS_H */ diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am index eaa9d516fc..eef2650bd5 100644 --- a/src/tests/Makefile.am +++ b/src/tests/Makefile.am @@ -12,6 +12,7 @@ AM_CPPFLAGS = \ noinst_PROGRAMS = \ test-dhcp-options \ + test-general \ test-policy-hosts \ test-wifi-ap-utils \ test-ip4-config \ @@ -80,6 +81,14 @@ test_resolvconf_capture_SOURCES = \ test_resolvconf_capture_LDADD = \ $(top_builddir)/src/libNetworkManager.la +####### general test ####### + +test_general_SOURCES = \ + test-general.c + +test_general_LDADD = \ + $(top_builddir)/src/libNetworkManager.la + ####### secret agent interface test ####### EXTRA_DIST = test-secret-agent.py @@ -94,4 +103,5 @@ check-local: test-dhcp-options test-policy-hosts test-wifi-ap-utils test-ip4-con $(abs_builddir)/test-ip6-config $(abs_builddir)/test-dcb $(abs_builddir)/test-resolvconf-capture + $(abs_builddir)/test-general diff --git a/src/tests/test-general.c b/src/tests/test-general.c new file mode 100644 index 0000000000..649653c75e --- /dev/null +++ b/src/tests/test-general.c @@ -0,0 +1,76 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2014 Red Hat, Inc. + * + */ + +#include +#include +#include + +#include "NetworkManagerUtils.h" + + +static void +test_nm_utils_ascii_str_to_int64_do (const char *str, guint base, gint64 min, + gint64 max, gint64 fallback, int exp_errno, + gint64 exp_val) +{ + gint64 v; + + errno = 0; + v = nm_utils_ascii_str_to_int64 (str, base, min, max, fallback); + g_assert_cmpint (errno, ==, exp_errno); + g_assert_cmpint (v, ==, exp_val); +} + +static void +test_nm_utils_ascii_str_to_int64 (void) +{ + test_nm_utils_ascii_str_to_int64_do ("4711", 10, 0, 10000, -1, 0, 4711); + test_nm_utils_ascii_str_to_int64_do ("", 10, 0, 10000, -1, EINVAL, -1); + test_nm_utils_ascii_str_to_int64_do (NULL, 10, 0, 10000, -1, EINVAL, -1); + test_nm_utils_ascii_str_to_int64_do (" 1x ", 10, 0, 10000, -1, EINVAL, -1); + test_nm_utils_ascii_str_to_int64_do (" 10000 ", 10, 0, 10000, -1, 0, 10000); + test_nm_utils_ascii_str_to_int64_do (" 10001 ", 10, 0, 10000, -1, ERANGE, -1); + test_nm_utils_ascii_str_to_int64_do (" 0xFF ", 16, 0, 10000, -1, 0, 255); + test_nm_utils_ascii_str_to_int64_do (" FF ", 16, 0, 10000, -1, 0, 255); + test_nm_utils_ascii_str_to_int64_do (" FF ", 10, 0, 10000, -2, EINVAL, -2); + test_nm_utils_ascii_str_to_int64_do (" 9223372036854775807 ", 10, 0, G_MAXINT64, -2, 0, G_MAXINT64); + test_nm_utils_ascii_str_to_int64_do (" 0x7FFFFFFFFFFFFFFF ", 16, 0, G_MAXINT64, -2, 0, G_MAXINT64); + test_nm_utils_ascii_str_to_int64_do (" 7FFFFFFFFFFFFFFF ", 16, 0, G_MAXINT64, -2, 0, G_MAXINT64); + test_nm_utils_ascii_str_to_int64_do (" 9223372036854775808 ", 10, 0, G_MAXINT64, -2, ERANGE, -2); + test_nm_utils_ascii_str_to_int64_do (" -9223372036854775808 ", 10, G_MININT64, 0, -2, 0, G_MININT64); + test_nm_utils_ascii_str_to_int64_do (" -9223372036854775808 ", 10, G_MININT64+1, 0, -2, ERANGE, -2); + test_nm_utils_ascii_str_to_int64_do (" -9223372036854775809 ", 10, G_MININT64, 0, -2, ERANGE, -2); + test_nm_utils_ascii_str_to_int64_do ("\r\n\t10000\t\n\t\n", 10, 0, 10000, -1, 0, 10000); +} + +/*******************************************/ + +int +main (int argc, char **argv) +{ + g_test_init (&argc, &argv, NULL); + + g_type_init (); + + g_test_add_func ("/general/nm_utils_ascii_str_to_int64", test_nm_utils_ascii_str_to_int64); + + return g_test_run (); +} +