summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2017-04-12 11:05:02 +0200
committerThomas Haller <thaller@redhat.com>2017-04-13 10:11:24 +0200
commita498a8fbb6c1835c083053d5de5730e9ce06d1b7 (patch)
treeaaaa412a5fc6bc1126c6d0a2062cac3a58ad938f
parentecec03c8b723191c7aa86946982ddd33e121e6e2 (diff)
downloadNetworkManager-th/cli-meta.tar.gz
WIP: cli: move nmc_setting_get_valid_propertiesth/cli-meta
It looks at GObject properties to determine which properties are valid. That is not correct, because certain properties are not native GObject properties: - vpn.data - bond.options - user.data Instead, that is why we have meta data.
-rw-r--r--clients/cli/connections.c33
-rw-r--r--clients/cli/settings.c31
-rw-r--r--clients/cli/settings.h1
-rw-r--r--clients/common/nm-meta-setting-access.c296
-rw-r--r--clients/common/nm-meta-setting-access.h19
-rw-r--r--clients/common/nm-meta-setting-desc.c217
-rw-r--r--clients/common/nm-meta-setting-desc.h41
-rw-r--r--clients/common/tests/test-general.c2
8 files changed, 576 insertions, 64 deletions
diff --git a/clients/cli/connections.c b/clients/cli/connections.c
index 48454099f2..d65dbcc6a9 100644
--- a/clients/cli/connections.c
+++ b/clients/cli/connections.c
@@ -3214,6 +3214,31 @@ is_setting_valid (NMConnection *connection, const NMMetaSettingValidPartItem *co
return nm_connection_get_setting_by_name (connection, setting_name);
}
+static char **
+_get_valid_properties (NMSetting *setting)
+{
+ char **valid_props = NULL;
+ GParamSpec **props, **iter;
+ guint num;
+ int i;
+
+ /* Iterate through properties */
+ i = 0;
+ props = g_object_class_list_properties (G_OBJECT_GET_CLASS (G_OBJECT (setting)), &num);
+ valid_props = g_malloc0 (sizeof (char*) * (num + 1));
+ for (iter = props; iter && *iter; iter++) {
+ const char *key_name = g_param_spec_get_name (*iter);
+
+ /* Add all properties except for "name" that is non-editable */
+ if (g_strcmp0 (key_name, "name") != 0)
+ valid_props[i++] = g_strdup (key_name);
+ }
+ valid_props[i] = NULL;
+ g_free (props);
+
+ return valid_props;
+}
+
static char *
is_property_valid (NMSetting *setting, const char *property, GError **error)
{
@@ -3221,7 +3246,7 @@ is_property_valid (NMSetting *setting, const char *property, GError **error)
const char *prop_name;
char *ret;
- valid_props = nmc_setting_get_valid_properties (setting);
+ valid_props = _get_valid_properties (setting);
prop_name = nmc_string_is_valid (property, (const char **) valid_props, error);
ret = g_strdup (prop_name);
g_strfreev (valid_props);
@@ -5052,7 +5077,7 @@ gen_property_names (const char *text, int state)
}
if (setting) {
- valid_props = nmc_setting_get_valid_properties (setting);
+ valid_props = _get_valid_properties (setting);
ret = nmc_rl_gen_func_basic (text, state, (const char **) valid_props);
}
@@ -6222,7 +6247,7 @@ print_setting_description (NMSetting *setting)
char **all_props;
int i;
- all_props = nmc_setting_get_valid_properties (setting);
+ all_props = _get_valid_properties (setting);
g_print (("<<< %s >>>\n"), nm_setting_get_name (setting));
for (i = 0; all_props && all_props[i]; i++)
print_property_description (setting, all_props[i]);
@@ -6695,7 +6720,7 @@ menu_switch_to_level1 (NmcColorOption color_option,
"nmcli %s> ", setting_name);
menu_ctx->curr_setting = setting;
g_strfreev (menu_ctx->valid_props);
- menu_ctx->valid_props = nmc_setting_get_valid_properties (menu_ctx->curr_setting);
+ menu_ctx->valid_props = _get_valid_properties (menu_ctx->curr_setting);
g_free (menu_ctx->valid_props_str);
menu_ctx->valid_props_str = g_strjoinv (", ", menu_ctx->valid_props);
}
diff --git a/clients/cli/settings.c b/clients/cli/settings.c
index 0f18ec7f67..939f82a91c 100644
--- a/clients/cli/settings.c
+++ b/clients/cli/settings.c
@@ -646,37 +646,6 @@ nmc_setting_remove_property_option (NMSetting *setting,
return TRUE;
}
-/*
- * Get valid property names for a setting.
- *
- * Returns: string array with the properties or NULL on failure.
- * The returned value should be freed with g_strfreev()
- */
-char **
-nmc_setting_get_valid_properties (NMSetting *setting)
-{
- char **valid_props = NULL;
- GParamSpec **props, **iter;
- guint num;
- int i;
-
- /* Iterate through properties */
- i = 0;
- props = g_object_class_list_properties (G_OBJECT_GET_CLASS (G_OBJECT (setting)), &num);
- valid_props = g_malloc0 (sizeof (char*) * (num + 1));
- for (iter = props; iter && *iter; iter++) {
- const char *key_name = g_param_spec_get_name (*iter);
-
- /* Add all properties except for "name" that is non-editable */
- if (g_strcmp0 (key_name, "name") != 0)
- valid_props[i++] = g_strdup (key_name);
- }
- valid_props[i] = NULL;
- g_free (props);
-
- return valid_props;
-}
-
const char *const*
nmc_setting_get_property_allowed_values (NMSetting *setting, const char *prop, char ***out_to_free)
{
diff --git a/clients/cli/settings.h b/clients/cli/settings.h
index 7dad622bf8..88b715f0a7 100644
--- a/clients/cli/settings.h
+++ b/clients/cli/settings.h
@@ -33,7 +33,6 @@ void nmc_setting_proxy_connect_handlers (NMSettingProxy *setting);
void nmc_setting_wireless_connect_handlers (NMSettingWireless *setting);
void nmc_setting_connection_connect_handlers (NMSettingConnection *setting, NMConnection *connection);
-char **nmc_setting_get_valid_properties (NMSetting *setting);
char *nmc_setting_get_property_desc (NMSetting *setting, const char *prop);
const char *const*nmc_setting_get_property_allowed_values (NMSetting *setting, const char *prop, char ***out_to_free);
char *nmc_setting_get_property (NMSetting *setting,
diff --git a/clients/common/nm-meta-setting-access.c b/clients/common/nm-meta-setting-access.c
index 7a0cefde9d..ebaf6e7ebc 100644
--- a/clients/common/nm-meta-setting-access.c
+++ b/clients/common/nm-meta-setting-access.c
@@ -21,36 +21,67 @@
#include "nm-meta-setting-access.h"
+#include <NetworkManager.h>
+
/*****************************************************************************/
const NMMetaSettingInfoEditor *
-nm_meta_setting_info_editor_find_by_name (const char *setting_name, gboolean use_alias)
+nm_meta_setting_info_editor_find_by_fuzzyname (const char *setting_name, gboolean use_alias,
+ gboolean fuzzy_match, gboolean *out_unique)
{
- const NMMetaSettingInfo *meta_setting_info;
- const NMMetaSettingInfoEditor *setting_info;
+ const NMMetaSettingInfoEditor *best_match = NULL;
+ guint found = 0;
+ gsize l;
guint i;
g_return_val_if_fail (setting_name, NULL);
- meta_setting_info = nm_meta_setting_infos_by_name (setting_name);
- setting_info = NULL;
- if (meta_setting_info) {
- nm_assert (nm_streq0 (meta_setting_info->setting_name, setting_name));
- if (meta_setting_info->meta_type < G_N_ELEMENTS (nm_meta_setting_infos_editor)) {
- setting_info = &nm_meta_setting_infos_editor[meta_setting_info->meta_type];
- nm_assert (setting_info->general == meta_setting_info);
+ if (!*setting_name)
+ goto out;
+
+ l = strlen (setting_name);
+
+ for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) {
+ const NMMetaSettingInfoEditor *si = &nm_meta_setting_infos_editor[i];
+
+ if (nm_streq (si->general->setting_name, setting_name)) {
+ NM_SET_OUT (out_unique, TRUE);
+ return si;
}
- }
- if (!setting_info && use_alias) {
- for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) {
- if (nm_streq0 (nm_meta_setting_infos_editor[i].alias, setting_name)) {
- setting_info = &nm_meta_setting_infos_editor[i];
- break;
- }
+ if ( fuzzy_match
+ && g_ascii_strncasecmp (si->general->setting_name, setting_name, l))
+ goto found_fuzzy;
+
+ if (use_alias) {
+ if (nm_streq0 (si->alias, setting_name))
+ goto found_fuzzy;
+ if ( fuzzy_match
+ && g_ascii_strncasecmp (si->alias, setting_name, l))
+ goto found_fuzzy;
}
+
+ continue;
+found_fuzzy:
+ if (!best_match)
+ best_match = si;
+ found++;
+ if (found >= 2)
+ break;
}
- return setting_info;
+out:
+ /* a non-unique match may not seem interesting at first. It is however
+ * because we need to distinguish between no setting-for-the-name
+ * (and search the property-aliases), or have-a-non-unique-match (and
+ * don't check proerty-aliases). */
+ NM_SET_OUT (out_unique, found <= 1);
+ return best_match;
+}
+
+const NMMetaSettingInfoEditor *
+nm_meta_setting_info_editor_find_by_name (const char *setting_name, gboolean use_alias)
+{
+ return nm_meta_setting_info_editor_find_by_fuzzyname (setting_name, use_alias, FALSE, NULL);
}
const NMMetaSettingInfoEditor *
@@ -93,21 +124,46 @@ nm_meta_setting_info_editor_find_by_setting (NMSetting *setting)
}
const NMMetaPropertyInfo *
-nm_meta_setting_info_editor_get_property_info (const NMMetaSettingInfoEditor *setting_info, const char *property_name)
+nm_meta_setting_info_editor_get_property_info (const NMMetaSettingInfoEditor *setting_info,
+ const char *property_name,
+ gboolean fuzzy_match)
{
+ const NMMetaPropertyInfo *best_match = NULL;
+ gsize l;
guint i;
g_return_val_if_fail (setting_info, NULL);
g_return_val_if_fail (property_name, NULL);
+ if (!property_name)
+ return NULL;
+
+ if (setting_info->get_property_info) {
+ return setting_info->get_property_info (setting_info,
+ property_name,
+ fuzzy_match);
+ }
+
+ l = strlen (property_name);
+
for (i = 0; i < setting_info->properties_num; i++) {
- nm_assert (setting_info->properties[i]->property_name);
- nm_assert (setting_info->properties[i]->setting_info == setting_info);
- if (nm_streq (setting_info->properties[i]->property_name, property_name))
- return setting_info->properties[i];
+ const NMMetaPropertyInfo *si = setting_info->properties[i];
+
+ nm_assert (si->property_name);
+ nm_assert (si->setting_info == setting_info);
+
+ if (nm_streq (si->property_name, property_name))
+ return si;
+
+ if ( fuzzy_match
+ && g_ascii_strncasecmp (si->property_name, property_name, l)) {
+ if (best_match)
+ return NULL;
+ best_match = si;
+ }
}
- return NULL;
+ return best_match;
}
const NMMetaPropertyInfo *
@@ -120,7 +176,7 @@ nm_meta_property_info_find_by_name (const char *setting_name, const char *proper
if (!setting_info)
return NULL;
- property_info = nm_meta_setting_info_editor_get_property_info (setting_info, property_name);
+ property_info = nm_meta_setting_info_editor_get_property_info (setting_info, property_name, FALSE);
if (!property_info)
return NULL;
@@ -138,7 +194,7 @@ nm_meta_property_info_find_by_setting (NMSetting *setting, const char *property_
setting_info = nm_meta_setting_info_editor_find_by_setting (setting);
if (!setting_info)
return NULL;
- property_info = nm_meta_setting_info_editor_get_property_info (setting_info, property_name);
+ property_info = nm_meta_setting_info_editor_get_property_info (setting_info, property_name, FALSE);
if (!property_info)
return NULL;
@@ -325,6 +381,73 @@ nm_meta_abstract_info_complete (const NMMetaAbstractInfo *abstract_info,
}
}
+/**
+ * nm_meta_abstract_info_get_property_names:
+ * @abstract_info: the meta data
+ * @target: (allow none): an optional target instance. The result
+ * of property names may or may not depend on the target.
+ * If present, @target must be valid for @abstract_info.
+ * @get_property_names_flags: flags argument to control the result.
+ *
+ * Returns: (transfer full): the list of valid property names for target.
+ * For most setting types, this is just the static list of GObject property
+ * names.
+ * For some types this may be a type dependent list of properties (bond.options).
+ * For other types, it may even be a list of properties that are generated based
+ * on the current @setting (user.data). */
+char **
+nm_meta_abstract_info_get_property_names (const NMMetaAbstractInfo *abstract_info,
+ gpointer target,
+ NMMetaAccessorGetPropertyNamesFlags get_property_names_flags)
+{
+ GPtrArray *result;
+
+ g_return_val_if_fail (abstract_info, NULL);
+
+ if (!abstract_info->meta_type->get_property_names)
+ return NULL;
+
+ if (!NM_FLAGS_ANY (get_property_names_flags,
+ NM_META_ACCESSOR_GET_PROPERTY_NAMES_FLAGS_WITH_THIS_LEVEL
+ | NM_META_ACCESSOR_GET_PROPERTY_NAMES_FLAGS_WITH_TOPLEVEL_LEVEL))
+ get_property_names_flags |= NM_META_ACCESSOR_GET_PROPERTY_NAMES_FLAGS_WITH_THIS_LEVEL;
+
+ result = g_ptr_array_new ();
+ abstract_info->meta_type->get_property_names (abstract_info,
+ target,
+ get_property_names_flags,
+ result);
+ if (!result->len) {
+ g_ptr_array_free (result, TRUE);
+ return NULL;
+ }
+
+ g_ptr_array_sort (result, nm_strcmp_p);
+ g_ptr_array_add (result, NULL);
+ return _nm_utils_strv_cleanup ((char **) g_ptr_array_free (result, FALSE),
+ FALSE, FALSE, TRUE);
+}
+
+gboolean
+nm_meta_abstract_info_set_property (const NMMetaAbstractInfo *abstract_info,
+ gpointer target,
+ const char *property_name,
+ const char *value,
+ GError **error)
+{
+ g_return_val_if_fail (target, FALSE);
+ g_return_val_if_fail (property_name, FALSE);
+ g_return_val_if_fail (!error || !*error, FALSE);
+ g_return_val_if_fail (abstract_info, FALSE);
+ g_return_val_if_fail (abstract_info->meta_type->set_property, FALSE);
+
+ return abstract_info->meta_type->set_property (abstract_info,
+ target,
+ property_name,
+ value,
+ error);
+}
+
/*****************************************************************************/
char *
@@ -373,6 +496,45 @@ nm_meta_abstract_infos_get_names_str (const NMMetaAbstractInfo *const*fields_arr
/*****************************************************************************/
+static void
+_parse_name (const char *name,
+ const char **out_toplevel,
+ const char **out_nested,
+ NMMetaPropertyNameModifier *out_modifier,
+ char **out_to_free)
+{
+ const char *toplevel = NULL;
+ const char *nested = NULL;
+ NMMetaPropertyNameModifier modifier = NM_META_PROPERTY_NAME_MODIFIER_NONE;
+ const char *s;
+ char *t;
+
+ if (name) {
+ if (NM_IN_SET (name[0], '+', '-')) {
+ modifier = name[0] == '+'
+ ? NM_META_PROPERTY_NAME_MODIFIER_PLUS
+ : NM_META_PROPERTY_NAME_MODIFIER_MINUS;
+ name++;
+ }
+
+ s = strchr (name, '.');
+ if (!s)
+ toplevel = name;
+ else {
+ t = g_strdup (name);
+ *out_to_free = t;
+ toplevel = t;
+ t = &t[s - name];
+ *t = '\0';
+ nested = t+1;
+ }
+ }
+
+ *out_toplevel = toplevel;
+ *out_nested = nested;
+ *out_modifier = modifier;
+}
+
typedef struct {
guint idx;
gsize self_offset_plus_1;
@@ -619,3 +781,85 @@ nm_meta_selection_create_parse_list (const NMMetaAbstractInfo *const* fields_arr
return _output_selection_pack (fields_array, array, str);
}
+
+NMMetaSelectionResultList *
+nm_meta_selection_parse_connection_property_name (NMConnection *connection,
+ const char *property_name,
+ GError **error)
+{
+ const char *const property_name_orig = property_name;
+ gs_free char *parsed_name_tmp = NULL;
+ const char *nested_name;
+ NMMetaPropertyNameModifier modifier;
+ const NMMetaSettingInfoEditor *setting_info = NULL;
+ const NMMetaPropertyInfo *property_info = NULL;
+
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+ _parse_name (property_name,
+ &property_name,
+ &nested_name,
+ &modifier,
+ &parsed_name_tmp);
+
+ if (property_name || !property_name[0])
+ goto out_invalid_toplevel_name;
+
+ {
+ gboolean unique_match;
+
+ setting_info = nm_meta_setting_info_editor_find_by_fuzzyname (property_name, TRUE, TRUE, &unique_match);
+ if (!unique_match)
+ goto out_invalid_toplevel_name;
+ }
+
+ if (setting_info) {
+ if (!nested_name) {
+ gs_strfreev char **v = NULL;
+ gs_free char *t = NULL;
+
+ v = nm_meta_abstract_info_get_property_names ((const NMMetaAbstractInfo *) setting_info,
+ nm_connection_get_setting_by_name (connection, setting_info->general->setting_name),
+ NM_META_ACCESSOR_GET_PROPERTY_NAMES_FLAGS_WITH_THIS_LEVEL);
+ g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT,
+ _("invalid property name \"%s\". Requires a property name like [%s]"),
+ property_name_orig, (t = g_strjoinv (",", v)));
+ return FALSE;
+ }
+
+ property_info = nm_meta_setting_info_editor_get_property_info (setting_info,
+ nested_name,
+ TRUE);
+ if (!property_info) {
+ gs_strfreev char **v = NULL;
+ gs_free char *t = NULL;
+
+ v = nm_meta_abstract_info_get_property_names ((const NMMetaAbstractInfo *) setting_info,
+ nm_connection_get_setting_by_name (connection, setting_info->general->setting_name),
+ NM_META_ACCESSOR_GET_PROPERTY_NAMES_FLAGS_WITH_THIS_LEVEL);
+ g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT,
+ _("invalid property name \"%s\". \"%s\" requires a property name like [%s]"),
+ property_name_orig, setting_info->general->setting_name,
+ (t = g_strjoinv (",", v)));
+ return FALSE;
+ }
+
+ } else {
+ if (nested_name)
+ goto out_invalid_toplevel_name;
+
+ /* lookup the property name by toplevel alias. */
+ }
+
+out_invalid_toplevel_name:
+ {
+ gs_free char *t = NULL;
+
+ g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT,
+ _("invalid property name \"%s\". Valid names are [%s]"),
+ property_name_orig, (t = g_strjoinv (",", nm_meta_abstract_info_get_property_names (&nm_meta_connection_info, connection, 0))));
+ }
+ return FALSE;
+}
+
+
diff --git a/clients/common/nm-meta-setting-access.h b/clients/common/nm-meta-setting-access.h
index 54fc6c84d6..ecedf499b1 100644
--- a/clients/common/nm-meta-setting-access.h
+++ b/clients/common/nm-meta-setting-access.h
@@ -29,11 +29,14 @@ NMSetting *nm_meta_setting_info_editor_new_setting (const NMMetaSettingInfoEdito
NMMetaAccessorSettingInitType init_type);
const NMMetaSettingInfoEditor *nm_meta_setting_info_editor_find_by_name (const char *setting_name, gboolean use_alias);
+const NMMetaSettingInfoEditor *nm_meta_setting_info_editor_find_by_fuzzyname (const char *setting_name, gboolean use_alias,
+ gboolean fuzzy_match, gboolean *out_unique);
const NMMetaSettingInfoEditor *nm_meta_setting_info_editor_find_by_gtype (GType gtype);
const NMMetaSettingInfoEditor *nm_meta_setting_info_editor_find_by_setting (NMSetting *setting);
const NMMetaPropertyInfo *nm_meta_setting_info_editor_get_property_info (const NMMetaSettingInfoEditor *setting_info,
- const char *property_name);
+ const char *property_name,
+ gboolean fuzzy_match);
const NMMetaPropertyInfo *nm_meta_property_info_find_by_name (const char *setting_name,
const char *property_name);
const NMMetaPropertyInfo *nm_meta_property_info_find_by_setting (NMSetting *setting,
@@ -67,6 +70,16 @@ const char *const*nm_meta_abstract_info_complete (const NMMetaAbstractInfo *abst
const char *text,
char ***out_to_free);
+char **nm_meta_abstract_info_get_property_names (const NMMetaAbstractInfo *abstract_info,
+ gpointer target,
+ NMMetaAccessorGetPropertyNamesFlags get_property_names_flags);
+
+gboolean nm_meta_abstract_info_set_property (const NMMetaAbstractInfo *abstract_info,
+ gpointer target,
+ const char *property_name,
+ const char *value,
+ GError **error);
+
/*****************************************************************************/
char *nm_meta_abstract_info_get_nested_names_str (const NMMetaAbstractInfo *abstract_info, const char *name_prefix);
@@ -98,4 +111,8 @@ NMMetaSelectionResultList *nm_meta_selection_create_parse_list (const NMMetaAbst
gboolean validate_nested,
GError **error);
+NMMetaSelectionResultList *nm_meta_selection_parse_connection_property_name (NMConnection *connection,
+ const char *property_name,
+ GError **error);
+
#endif /* _NM_META_SETTING_ACCESS_H__ */
diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c
index a55d03700b..2d3f38ef5d 100644
--- a/clients/common/nm-meta-setting-desc.c
+++ b/clients/common/nm-meta-setting-desc.c
@@ -7545,11 +7545,214 @@ _meta_type_property_info_complete_fcn (const NMMetaAbstractInfo *abstract_info,
return NULL;
}
+static void
+_meta_type_setting_info_get_property_names (const NMMetaAbstractInfo *abstract_info,
+ gpointer target,
+ NMMetaAccessorGetPropertyNamesFlags get_property_names_flags,
+ GPtrArray *result)
+{
+ const NMMetaSettingInfoEditor *setting_info = (NMMetaSettingInfoEditor *) abstract_info;
+ NMSetting *setting = NM_SETTING (target);
+ guint i, j;
+
+ nm_assert ( !setting
+ || ( NM_IS_SETTING (setting)
+ && G_TYPE_CHECK_INSTANCE_TYPE (setting, setting_info->general->get_setting_gtype ())));
+
+ if (!setting_info->properties_num)
+ return;
+
+ for (i = 0; i < setting_info->properties_num; i++) {
+ const NMMetaPropertyInfo *pi = setting_info->properties[i];
+ const NMMetaPropertyTypDataNested *nested_data;
+
+ if (NM_FLAGS_HAS (get_property_names_flags, NM_META_ACCESSOR_GET_PROPERTY_NAMES_FLAGS_WITH_THIS_LEVEL))
+ g_ptr_array_add (result, g_strdup (pi->property_name));
+
+ if ( NM_FLAGS_HAS (get_property_names_flags, NM_META_ACCESSOR_GET_PROPERTY_NAMES_FLAGS_WITH_TOPLEVEL_LEVEL)
+ && pi->property_alias)
+ g_ptr_array_add (result, g_strdup (pi->property_alias));
+
+ if ( pi->property_typ_data
+ && (nested_data = pi->property_typ_data->nested)) {
+ for (j = 0; j < nested_data->nested_len; j++) {
+ const NMMetaNestedPropertyInfo *n_pi = &nested_data->nested[j];
+
+ if (n_pi->base.property_name) {
+ /* the field-name itself is a valid property name and a top-level
+ * alias. */
+ if (NM_FLAGS_HAS (get_property_names_flags, NM_META_ACCESSOR_GET_PROPERTY_NAMES_FLAGS_WITH_TOPLEVEL_LEVEL))
+ g_ptr_array_add (result, g_strdup (n_pi->base.property_name));
+ }
+ }
+ }
+ }
+}
+
+static const NMMetaSettingValidPartItem *
+_valid_part_item_find (const NMMetaSettingValidPartItem *const*items, const NMMetaSettingInfoEditor *setting_info)
+{
+ if (items) {
+ for (; *items; items++) {
+ if ((*items)->setting_info == setting_info)
+ return *items;
+ }
+ }
+ return NULL;
+}
+
+static void
+_meta_type_connection_info_get_property_names (const NMMetaAbstractInfo *abstract_info,
+ gpointer target,
+ NMMetaAccessorGetPropertyNamesFlags get_property_names_flags,
+ GPtrArray *result)
+{
+ NMConnection *connection = NM_CONNECTION (target);
+ guint s;
+ const NMMetaSettingValidPartItem *const*setting_info_type = NULL;
+ const NMMetaSettingValidPartItem *const*setting_info_slave = NULL;
+ const NMMetaSettingInfoEditor *setting_info;
+
+ nm_assert (!connection || NM_IS_CONNECTION (connection));
+
+ if (connection) {
+ NMSettingConnection *s_con;
+
+ s_con = nm_connection_get_setting_connection (connection);
+ setting_info_type = nm_meta_setting_info_valid_parts_default;
+ if (s_con) {
+ const char *c_type = nm_setting_connection_get_connection_type (s_con);
+ const char *s_type = nm_setting_connection_get_slave_type (s_con);
+
+ if (c_type) {
+ setting_info = nm_meta_setting_info_editor_find_by_name (c_type, FALSE);
+ if (!setting_info || setting_info->valid_parts)
+ setting_info_type = setting_info->valid_parts;
+ }
+ setting_info_slave = nm_meta_setting_info_valid_parts_for_slave_type (s_type, NULL);
+ }
+ }
+
+ for (s = 0; s < _NM_META_SETTING_TYPE_NUM; s++) {
+ NMSetting *setting = NULL;
+
+ setting_info = &nm_meta_setting_infos_editor[s];
+
+ if (connection) {
+ setting = nm_connection_get_setting_by_name (connection, setting_info->general->setting_name);
+ if ( !setting
+ && !_valid_part_item_find (setting_info_type, setting_info)
+ && !_valid_part_item_find (setting_info_slave, setting_info))
+ continue;
+ }
+
+ g_ptr_array_add (result, g_strdup (setting_info->general->setting_name));
+
+ _meta_type_setting_info_get_property_names ((const NMMetaAbstractInfo *) setting_info,
+ setting,
+ NM_META_ACCESSOR_GET_PROPERTY_NAMES_FLAGS_WITH_TOPLEVEL_LEVEL,
+ result);
+ }
+}
+
+static gboolean
+_meta_type_connection_info_set_property (const NMMetaAbstractInfo *abstract_info,
+ gpointer target,
+ const char *property_name,
+ const char *value,
+ GError **error)
+{
+#if 0
+ NMConnection *connection = NM_CONNECTION (target);
+ const char *const property_name_orig = property_name;
+ gs_free char *parsed_name_tmp = NULL;
+ const char *nested_name;
+ NMMetaPropertyNameModifier modifier;
+ const NMMetaSettingInfoEditor *setting_info = NULL;
+ const NMMetaPropertyInfo *property_info = NULL;
+
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
+
+ _parse_name (property_name,
+ &property_name,
+ &nested_name,
+ &modifier,
+ &parsed_name_tmp);
+
+ if (property_name || !property_name[0])
+ goto out_invalid_toplevel_name;
+
+ {
+ gboolean unique_match;
+
+ setting_info = nm_meta_setting_info_editor_find_by_fuzzyname (property_name, TRUE, TRUE, &unique_match);
+ if (!unique_match)
+ goto out_invalid_toplevel_name;
+ }
+
+ if (setting_info) {
+ if (!nested_name) {
+ gs_strfreev char **v = NULL;
+ gs_free char *t = NULL;
+
+ v = nm_meta_abstract_info_get_property_names ((const NMMetaAbstractInfo *) setting_info,
+ nm_connection_get_setting_by_name (connection, setting_info->general->setting_name),
+ NM_META_ACCESSOR_GET_PROPERTY_NAMES_FLAGS_WITH_THIS_LEVEL);
+ g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT,
+ _("invalid property name \"%s\". Requires a property name like [%s]"),
+ property_name_orig, (t = g_strjoinv (",", v)));
+ return FALSE;
+ }
+
+ property_info = nm_meta_setting_info_editor_get_property_info (setting_info,
+ nested_name,
+ TRUE);
+ if (!property_info) {
+ gs_strfreev char **v = NULL;
+ gs_free char *t = NULL;
+
+ v = nm_meta_abstract_info_get_property_names ((const NMMetaAbstractInfo *) setting_info,
+ nm_connection_get_setting_by_name (connection, setting_info->general->setting_name),
+ NM_META_ACCESSOR_GET_PROPERTY_NAMES_FLAGS_WITH_THIS_LEVEL);
+ g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT,
+ _("invalid property name \"%s\". Requires a property name like [%s]"),
+ property_name_orig, (t = g_strjoinv (",", v)));
+ return FALSE;
+ }
+
+ } else {
+ if (nested_name)
+ goto out_invalid_toplevel_name;
+
+ /* lookup the property name by toplevel alias. */
+ }
+
+ return abstract_info->meta_type->set_property (abstract_info,
+ target,
+ property_name,
+ value,
+ error);
+
+out_invalid_toplevel_name:
+ {
+ gs_free char *t = NULL;
+
+ g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT,
+ _("invalid property name \"%s\". Valid names are [%s]"),
+ property_name_orig, (t = g_strjoinv (",", nm_meta_abstract_info_get_property_names (abstract_info, connection, 0))));
+ }
+#endif
+ return FALSE;
+}
+
+/*****************************************************************************/
+
const NMMetaType nm_meta_type_setting_info_editor = {
.type_name = "setting_info_editor",
.get_name = _meta_type_setting_info_editor_get_name,
.get_nested = _meta_type_setting_info_editor_get_nested,
.get_fcn = _meta_type_setting_info_editor_get_fcn,
+ .get_property_names = _meta_type_setting_info_get_property_names,
};
const NMMetaType nm_meta_type_property_info = {
@@ -7563,3 +7766,17 @@ const NMMetaType nm_meta_type_property_info = {
const NMMetaType nm_meta_type_nested_property_info = {
.type_name = "nested_property_info",
};
+
+static const NMMetaType meta_type_connection_info = {
+ .type_name = "connection_info",
+ .get_property_names = _meta_type_connection_info_get_property_names,
+ .set_property = _meta_type_connection_info_set_property,
+};
+
+/*****************************************************************************/
+
+const NMMetaAbstractInfo nm_meta_connection_info = {
+ .meta_type = &meta_type_connection_info,
+};
+
+/*****************************************************************************/
diff --git a/clients/common/nm-meta-setting-desc.h b/clients/common/nm-meta-setting-desc.h
index 38aa50f95f..fabd8b3efb 100644
--- a/clients/common/nm-meta-setting-desc.h
+++ b/clients/common/nm-meta-setting-desc.h
@@ -103,6 +103,12 @@ typedef enum {
} NMMetaTermFormat;
typedef enum {
+ NM_META_PROPERTY_NAME_MODIFIER_NONE,
+ NM_META_PROPERTY_NAME_MODIFIER_PLUS,
+ NM_META_PROPERTY_NAME_MODIFIER_MINUS,
+} NMMetaPropertyNameModifier;
+
+typedef enum {
NM_META_ACCESSOR_GET_TYPE_PRETTY,
NM_META_ACCESSOR_GET_TYPE_PARSABLE,
NM_META_ACCESSOR_GET_TYPE_TERMFORMAT,
@@ -151,6 +157,21 @@ typedef enum {
} NMMetaAccessorGetOutFlags;
typedef enum {
+ NM_META_ACCESSOR_GET_PROPERTY_NAMES_FLAGS_NONE = 0,
+
+ /* the name is valid on this level. For example, "stable-id" is a valid
+ * name for NMSettingConnection. Such a name has to be qualified by
+ * the parent to make "connection.stable-id". */
+ NM_META_ACCESSOR_GET_PROPERTY_NAMES_FLAGS_WITH_THIS_LEVEL = (1LL << 0),
+
+ /* the name is valid on the top level. For example, "name" is an alias
+ * for "connection.id" and is valid unqualified at the top-level.
+ * The name may still be invalid on the top level if it conflicts
+ * with other aliases or setting names. */
+ NM_META_ACCESSOR_GET_PROPERTY_NAMES_FLAGS_WITH_TOPLEVEL_LEVEL = (1LL << 1),
+} NMMetaAccessorGetPropertyNamesFlags;
+
+typedef enum {
NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_NUMERIC = (1LL << 0),
NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_NUMERIC_HEX = (1LL << 1),
NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_TEXT = (1LL << 2),
@@ -315,6 +336,11 @@ struct _NMMetaSettingInfoEditor {
void (*setting_init_fcn) (const NMMetaSettingInfoEditor *setting_info,
NMSetting *setting,
NMMetaAccessorSettingInitType init_type);
+
+ const NMMetaPropertyInfo *(*get_property_info) (const NMMetaSettingInfoEditor *setting_info,
+ const char *property_name,
+ gboolean fuzzy_match);
+
};
struct _NMMetaType {
@@ -338,6 +364,17 @@ struct _NMMetaType {
const NMMetaOperationContext *operation_context,
const char *text,
char ***out_to_free);
+ void (*get_property_names) (const NMMetaAbstractInfo *abstract_info,
+ gpointer target,
+ NMMetaAccessorGetPropertyNamesFlags get_property_names_flags,
+ GPtrArray *result);
+
+ gboolean (*set_property) (const NMMetaAbstractInfo *abstract_info,
+ gpointer target,
+ const char *property_name,
+ const char *value,
+ GError **error);
+
};
struct _NMMetaAbstractInfo {
@@ -407,4 +444,8 @@ const NMMetaPropertyTypDataNested nm_meta_property_typ_data_bond;
/*****************************************************************************/
+extern const NMMetaAbstractInfo nm_meta_connection_info;
+
+/*****************************************************************************/
+
#endif /* __NM_META_SETTING_DESC_H__ */
diff --git a/clients/common/tests/test-general.c b/clients/common/tests/test-general.c
index 591bcd98f0..bfe80297bd 100644
--- a/clients/common/tests/test-general.c
+++ b/clients/common/tests/test-general.c
@@ -133,7 +133,7 @@ test_client_meta_check (void)
for (p = 0; p < info->properties_num; p++) {
const NMMetaPropertyInfo *pi = info->properties[p];
- g_assert (nm_meta_setting_info_editor_get_property_info (info, pi->property_name) == pi);
+ g_assert (nm_meta_setting_info_editor_get_property_info (info, pi->property_name, FALSE) == pi);
g_assert (nm_meta_property_info_find_by_name (info->general->setting_name, pi->property_name) == pi);
}
}