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