From 18fac0407ed4acbaddeb00ca41df8624fc9b33b1 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 19 Mar 2019 20:39:10 +0100 Subject: [PATCH] cli: merge set_fcn() and remove_fcn() set_fcn() and remove_fcn() are strongly related. They should accept arguments in the same format, hence the parsing of the arguments should be done at one place. In fact, previously the parsing was separate, leading to ugly inconsistencies: $ nmcli connection modify "$PROFILE" +vpn.data x=y $ nmcli connection modify "$PROFILE" -vpn.data x=y Error: failed to remove a value from vpn.data: invalid option 'x=y'. or $ nmcli connection modify "$PROFILE" +ipv4.addresses 192.168.1.5/24,192.168.2.5/24 $ nmcli connection modify "$PROFILE" -ipv4.addresses 192.168.1.5/24,192.168.2.5/24 Error: failed to remove a value from ipv4.addresses: invalid prefix '24,192.168.2.5/24'; <1-32> allowed. Let set_fcn() handle set-default, set-all, add, and subtract. --- clients/cli/settings.c | 15 +- clients/common/nm-meta-setting-desc.c | 432 +++++++++++++------------- clients/common/nm-meta-setting-desc.h | 15 +- 3 files changed, 218 insertions(+), 244 deletions(-) diff --git a/clients/cli/settings.c b/clients/cli/settings.c index 8a1279bcb3..7697bfba83 100644 --- a/clients/cli/settings.c +++ b/clients/cli/settings.c @@ -530,16 +530,11 @@ nmc_setting_set_property (NMClient *client, if (!property_info->property_type->set_fcn) goto out_fail_read_only; - if (modifier == '-') { - if ( value - && property_info->property_type->remove_fcn) { - return property_info->property_type->remove_fcn (property_info, - nmc_meta_environment, - nmc_meta_environment_arg, - setting, - value, - error); - } + if ( modifier == '-' + && !property_info->property_type->set_supports_remove) { + /* The property is a plain property. It does not support '-'. + * + * Maybe we should fail, but just return silently. */ return TRUE; } diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c index 72da617cda..7ce8f39c78 100644 --- a/clients/common/nm-meta-setting-desc.c +++ b/clients/common/nm-meta-setting-desc.c @@ -641,23 +641,45 @@ _env_warn_fcn (const NMMetaEnvironment *environment, const NMMetaSettingInfoEditor *setting_info, NMSetting *setting, NMMetaAccessorSettingInitType init_type static gboolean -_SET_FCN_DO_RESET_DEFAULT (char modifier, const char *value) +_SET_FCN_DO_RESET_DEFAULT (const NMMetaPropertyInfo *property_info, char modifier, const char *value) { + nm_assert (property_info); + nm_assert (!property_info->property_type->set_supports_remove); nm_assert (NM_IN_SET (modifier, '\0', '+')); nm_assert (value || modifier == '\0'); return value == NULL; } +static gboolean +_SET_FCN_DO_RESET_DEFAULT_WITH_SUPPORTS_REMOVE (const NMMetaPropertyInfo *property_info, char modifier, const char *value) +{ + nm_assert (property_info); + nm_assert (property_info->property_type->set_supports_remove); + nm_assert (NM_IN_SET (modifier, '\0', '+', '-')); + nm_assert (value || modifier == '\0'); + + return value == NULL; +} + static gboolean _SET_FCN_DO_SET_ALL (char modifier, const char *value) { - nm_assert (NM_IN_SET (modifier, '\0', '+')); + nm_assert (NM_IN_SET (modifier, '\0', '+', '-')); nm_assert (value); return modifier == '\0'; } +static gboolean +_SET_FCN_DO_REMOVE (char modifier, const char *value) +{ + nm_assert (NM_IN_SET (modifier, '\0', '+', '-')); + nm_assert (value); + + return modifier == '-'; +} + #define RETURN_UNSUPPORTED_GET_TYPE() \ G_STMT_START { \ if (!NM_IN_SET (get_type, \ @@ -1046,7 +1068,7 @@ _set_fcn_gobject_string (ARGS_SET_FCN) { gs_free char *to_free = NULL; - if (_SET_FCN_DO_RESET_DEFAULT (modifier, value)) + if (_SET_FCN_DO_RESET_DEFAULT (property_info, modifier, value)) return _gobject_property_reset_default (setting, property_info->property_name); if (property_info->property_typ_data) { @@ -1071,7 +1093,7 @@ _set_fcn_gobject_bool (ARGS_SET_FCN) { gboolean val_bool; - if (_SET_FCN_DO_RESET_DEFAULT (modifier, value)) + if (_SET_FCN_DO_RESET_DEFAULT (property_info, modifier, value)) return _gobject_property_reset_default (setting, property_info->property_name); if (!nmc_string_to_bool (value, &val_bool, error)) @@ -1095,7 +1117,7 @@ _set_fcn_gobject_int (ARGS_SET_FCN) guint base = 10; const NMMetaUtilsIntValueInfo *value_infos; - if (_SET_FCN_DO_RESET_DEFAULT (modifier, value)) + if (_SET_FCN_DO_RESET_DEFAULT (property_info, modifier, value)) return _gobject_property_reset_default (setting, property_info->property_name); pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (setting)), property_info->property_name); @@ -1234,7 +1256,7 @@ _set_fcn_gobject_mtu (ARGS_SET_FCN) const GParamSpec *pspec; gint64 v; - if (_SET_FCN_DO_RESET_DEFAULT (modifier, value)) + if (_SET_FCN_DO_RESET_DEFAULT (property_info, modifier, value)) return _gobject_property_reset_default (setting, property_info->property_name); if (nm_streq (value, "auto")) @@ -1275,7 +1297,7 @@ _set_fcn_gobject_mac (ARGS_SET_FCN) NMMetaPropertyTypeMacMode mode; gboolean valid; - if (_SET_FCN_DO_RESET_DEFAULT (modifier, value)) + if (_SET_FCN_DO_RESET_DEFAULT (property_info, modifier, value)) return _gobject_property_reset_default (setting, property_info->property_name); if (property_info->property_typ_data) @@ -1313,7 +1335,7 @@ _set_fcn_gobject_enum (ARGS_SET_FCN) gboolean is_flags; int v; - if (_SET_FCN_DO_RESET_DEFAULT (modifier, value)) + if (_SET_FCN_DO_RESET_DEFAULT (property_info, modifier, value)) return _gobject_property_reset_default (setting, property_info->property_name); if (property_info->property_typ_data) { @@ -1682,9 +1704,34 @@ _set_fcn_multilist (ARGS_SET_FCN) gs_free const char **strv = NULL; gsize i, nstrv; - if (_SET_FCN_DO_RESET_DEFAULT (modifier, value)) + if (_SET_FCN_DO_RESET_DEFAULT_WITH_SUPPORTS_REMOVE (property_info, modifier, value)) return _gobject_property_reset_default (setting, property_info->property_name); + if (_SET_FCN_DO_REMOVE (modifier, value)) { + gint64 idx; + + /* FIXME: support a list of numbers. */ + idx = _nm_utils_ascii_str_to_int64 (value, 10, 0, G_MAXINT64, -1); + if (idx != -1) { + guint num; + + if (property_info->property_typ_data->subtype.multilist.get_num_fcn_u32) + num = property_info->property_typ_data->subtype.multilist.get_num_fcn_u32 (setting); + else + num = property_info->property_typ_data->subtype.multilist.get_num_fcn_u (setting); + + if (idx < (gint64) num) { + if (property_info->property_typ_data->subtype.multilist.remove_by_idx_fcn_u32) + property_info->property_typ_data->subtype.multilist.remove_by_idx_fcn_u32 (setting, idx); + else if (property_info->property_typ_data->subtype.multilist.remove_by_idx_fcn_s) + property_info->property_typ_data->subtype.multilist.remove_by_idx_fcn_s (setting, idx); + else + property_info->property_typ_data->subtype.multilist.remove_by_idx_fcn_u (setting, idx); + } + return TRUE; + } + } + if (property_info->property_typ_data->subtype.multilist.with_escaped_spaces) strv = nm_utils_strsplit_set (value, " \t", TRUE); else @@ -1704,7 +1751,12 @@ _set_fcn_multilist (ARGS_SET_FCN) else g_strchomp ((char *) item); - item = _multilist_do_validate (property_info, TRUE, setting, item, error); + /* FIXME: don't validate differently for remove/add. */ + item = _multilist_do_validate (property_info, + !_SET_FCN_DO_REMOVE (modifier, value), + setting, + item, + error); if (!item) return FALSE; @@ -1716,47 +1768,16 @@ _set_fcn_multilist (ARGS_SET_FCN) _gobject_property_reset_default (setting, property_info->property_name); for (i = 0; i < nstrv; i++) { - if (property_info->property_typ_data->subtype.multilist.add2_fcn) - property_info->property_typ_data->subtype.multilist.add2_fcn (setting, strv[i]); - else - property_info->property_typ_data->subtype.multilist.add_fcn (setting, strv[i]); - } - return TRUE; -} - -static gboolean -_remove_fcn_multilist (ARGS_REMOVE_FCN) -{ - gs_free char *value_to_free = NULL; - gint64 idx; - - idx = _nm_utils_ascii_str_to_int64 (value, 10, 0, G_MAXINT64, -1); - if (idx != -1) { - guint num; - - if (property_info->property_typ_data->subtype.multilist.get_num_fcn_u32) - num = property_info->property_typ_data->subtype.multilist.get_num_fcn_u32 (setting); - else - num = property_info->property_typ_data->subtype.multilist.get_num_fcn_u (setting); - - if (idx < (gint64) num) { - if (property_info->property_typ_data->subtype.multilist.remove_by_idx_fcn_u32) - property_info->property_typ_data->subtype.multilist.remove_by_idx_fcn_u32 (setting, idx); - else if (property_info->property_typ_data->subtype.multilist.remove_by_idx_fcn_s) - property_info->property_typ_data->subtype.multilist.remove_by_idx_fcn_s (setting, idx); + if (_SET_FCN_DO_REMOVE (modifier, value)) { + property_info->property_typ_data->subtype.multilist.remove_by_value_fcn (setting, + strv[i]); + } else { + if (property_info->property_typ_data->subtype.multilist.add2_fcn) + property_info->property_typ_data->subtype.multilist.add2_fcn (setting, strv[i]); else - property_info->property_typ_data->subtype.multilist.remove_by_idx_fcn_u (setting, idx); + property_info->property_typ_data->subtype.multilist.add_fcn (setting, strv[i]); } - return TRUE; } - - value = nm_strstrip_avoid_copy (value, &value_to_free); - - value = _multilist_do_validate (property_info, FALSE, setting, value, error); - if (!value) - return FALSE; - - property_info->property_typ_data->subtype.multilist.remove_by_value_fcn (setting, value); return TRUE; } @@ -1769,7 +1790,7 @@ _set_fcn_optionlist (ARGS_SET_FCN) nm_assert (!error || !*error); - if (_SET_FCN_DO_RESET_DEFAULT (modifier, value)) + if (_SET_FCN_DO_RESET_DEFAULT_WITH_SUPPORTS_REMOVE (property_info, modifier, value)) return _gobject_property_reset_default (setting, property_info->property_name); nstrv = 0; @@ -1779,28 +1800,18 @@ _set_fcn_optionlist (ARGS_SET_FCN) for (i = 0; strv[i]; i++) { const char *opt_name; const char *opt_value; - char *left; - char *right; - left = (char *) nm_str_skip_leading_spaces (strv[i]); + opt_name = nm_str_skip_leading_spaces (strv[i]); /* FIXME: support backslash escaping for the option list. */ - right = strchr (left, '='); - - if ( !right - || left == right) { - nm_utils_error_set (error, NM_UTILS_ERROR_INVALID_ARGUMENT, - _("'%s' is not valid; use