From d15eb7dd6e319638a14e7136dadd4ac00ea9c706 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 11 May 2021 13:34:31 +0200 Subject: [PATCH 1/2] libnmc-base: optionally accept "ignore" in nmc_string_to_ternary() for NMTernary value --- src/libnmc-base/nm-client-utils.c | 16 +++++++++++++--- src/libnmc-base/nm-client-utils.h | 17 ++++++++++++++++- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/libnmc-base/nm-client-utils.c b/src/libnmc-base/nm-client-utils.c index 4737adb921..49234d9752 100644 --- a/src/libnmc-base/nm-client-utils.c +++ b/src/libnmc-base/nm-client-utils.c @@ -130,7 +130,10 @@ nmc_string_to_bool(const char *str, gboolean *val_bool, GError **error) } gboolean -nmc_string_to_ternary(const char *str, NMTernary *val, GError **error) +nmc_string_to_ternary_full(const char * str, + NMCStringToTernaryFlags flags, + NMTernary * val, + GError ** error) { gs_free char *str_to_free = NULL; int i; @@ -156,9 +159,16 @@ nmc_string_to_ternary(const char *str, NMTernary *val, GError **error) *val = NM_TERNARY_TRUE; else if (nmc_string_is_valid(str, NM_MAKE_STRV("false", "no", "off"), NULL)) *val = NM_TERNARY_FALSE; - else if (nmc_string_is_valid(str, NM_MAKE_STRV("unknown", "default"), NULL)) + else if (nmc_string_is_valid( + str, + NM_MAKE_STRV("unknown", + "default", + NM_FLAGS_HAS(flags, NMC_STRING_TO_TERNARY_FLAGS_IGNORE_FOR_DEFAULT) + ? "ignore" + : NULL), + NULL)) *val = NM_TERNARY_DEFAULT; - else if ((i = _nm_utils_ascii_str_to_int64(str, 0, -1, 1, -2)) >= -1) + else if ((i = _nm_utils_ascii_str_to_int64(str, 0, -1, 1, -2)) != -2) *val = (NMTernary) i; else { nm_utils_error_set(error, diff --git a/src/libnmc-base/nm-client-utils.h b/src/libnmc-base/nm-client-utils.h index 0fcc06582d..1fc18acaf6 100644 --- a/src/libnmc-base/nm-client-utils.h +++ b/src/libnmc-base/nm-client-utils.h @@ -23,7 +23,22 @@ gboolean nmc_string_to_uint(const char * str, unsigned long int max, unsigned long int *value); gboolean nmc_string_to_bool(const char *str, gboolean *val_bool, GError **error); -gboolean nmc_string_to_ternary(const char *str, NMTernary *val, GError **error); + +typedef enum { + NMC_STRING_TO_TERNARY_FLAGS_NONE = 0, + NMC_STRING_TO_TERNARY_FLAGS_IGNORE_FOR_DEFAULT = (1LL << 0), +} NMCStringToTernaryFlags; + +gboolean nmc_string_to_ternary_full(const char * str, + NMCStringToTernaryFlags flags, + NMTernary * val, + GError ** error); + +static inline gboolean +nmc_string_to_ternary(const char *str, NMTernary *val, GError **error) +{ + return nmc_string_to_ternary_full(str, NMC_STRING_TO_TERNARY_FLAGS_NONE, val, error); +} gboolean matches(const char *cmd, const char *pattern); From e5b46aa38ab1002ae73a9ae42412b9e2340a3b87 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 11 May 2021 13:27:55 +0200 Subject: [PATCH 2/2] cli: use nmc_string_to_ternary() to parse ternary in _set_fcn_ethtool() nmc_string_to_ternary() is much more flexible, in that it case insensitive and accepts any unambiguous abbreviation. Also, nmc_string_to_ternary() accepts "unknown" as alias for "default". Also, nmc_string_to_ternary() accepts numeric values -1, 0, 1. By using nmc_string_to_ternary(), we treat ethtool boolean options like other ternary properties and accept the same keywords. --- src/libnmc-setting/nm-meta-setting-desc.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/libnmc-setting/nm-meta-setting-desc.c b/src/libnmc-setting/nm-meta-setting-desc.c index 1a3484fcf5..9a0a4b64aa 100644 --- a/src/libnmc-setting/nm-meta-setting-desc.c +++ b/src/libnmc-setting/nm-meta-setting-desc.c @@ -4284,10 +4284,9 @@ static gconstpointer _get_fcn_ethtool(ARGS_GET_FCN) static gboolean _set_fcn_ethtool(ARGS_SET_FCN) { - NMEthtoolID ethtool_id = property_info->property_typ_data->subtype.ethtool.ethtool_id; - gs_free char *value_to_free = NULL; - gint64 i64; - gboolean b; + NMEthtoolID ethtool_id = property_info->property_typ_data->subtype.ethtool.ethtool_id; + gint64 i64; + NMTernary t; if (_SET_FCN_DO_RESET_DEFAULT(property_info, modifier, value)) goto do_unset; @@ -4311,14 +4310,10 @@ static gboolean _set_fcn_ethtool(ARGS_SET_FCN) nm_assert(nm_ethtool_id_is_feature(ethtool_id) || nm_ethtool_id_is_pause(ethtool_id)); - value = nm_strstrip_avoid_copy_a(300, value, &value_to_free); - if (NM_IN_STRSET(value, "1", "yes", "true", "on")) - b = TRUE; - else if (NM_IN_STRSET(value, "0", "no", "false", "off")) - b = FALSE; - else if (NM_IN_STRSET(value, "", "ignore", "default")) - goto do_unset; - else { + if (!nmc_string_to_ternary_full(value, + NMC_STRING_TO_TERNARY_FLAGS_IGNORE_FOR_DEFAULT, + &t, + error)) { g_set_error(error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT, @@ -4326,8 +4321,10 @@ static gboolean _set_fcn_ethtool(ARGS_SET_FCN) value); return FALSE; } + if (t == NM_TERNARY_DEFAULT) + goto do_unset; - nm_setting_option_set_boolean(setting, nm_ethtool_data[ethtool_id]->optname, b); + nm_setting_option_set_boolean(setting, nm_ethtool_data[ethtool_id]->optname, !!t); return TRUE; do_unset: