From 47b1dc382843937fcd54aeade418ecdf44238cab Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Mon, 4 Dec 2017 11:40:32 +0100 Subject: [PATCH] libnm-core/utils: add some special properties for the attributes "no_value" indicates that the the attribute is a single word, not a key=value pair. If the type is BOOLEAN then the attribute is considered true, if it's a STRING then the key is used instead of a value. "consumes_rest" indicates that the particular key takes the unparseable tail of the string for a value. This allows parsing tc-style strings. Consider this filter: ,------ regular key/value pair ,-----'----. root handle 1234: matchall action simple foo bar baz | | `-----------.-----------' | | `- "", STRING, consumes_rest | `------------------- "kind", STRING, no_value `-------------------------------------- "root', BOOLEAN, no_value --- libnm-core/nm-setting-ip-config.c | 4 +-- libnm-core/nm-utils-private.h | 4 ++- libnm-core/nm-utils.c | 49 ++++++++++++++++++++----------- 3 files changed, 37 insertions(+), 20 deletions(-) diff --git a/libnm-core/nm-setting-ip-config.c b/libnm-core/nm-setting-ip-config.c index 37079edb07..212ca7b511 100644 --- a/libnm-core/nm-setting-ip-config.c +++ b/libnm-core/nm-setting-ip-config.c @@ -16,7 +16,7 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA. * - * Copyright 2007 - 2014 Red Hat, Inc. + * Copyright 2007 - 2017 Red Hat, Inc. * Copyright 2007 - 2008 Novell, Inc. */ @@ -1238,7 +1238,7 @@ nm_ip_route_set_attribute (NMIPRoute *route, const char *name, GVariant *value) } #define ATTR_SPEC_PTR(name, type, v4, v6, str_type) \ - &(NMVariantAttributeSpec) { name, type, v4, v6, str_type } + &(NMVariantAttributeSpec) { name, type, v4, v6, FALSE, FALSE, str_type } static const NMVariantAttributeSpec * const ip_route_attribute_spec[] = { ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_TABLE, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ), diff --git a/libnm-core/nm-utils-private.h b/libnm-core/nm-utils-private.h index b7fde275ed..c76b320088 100644 --- a/libnm-core/nm-utils-private.h +++ b/libnm-core/nm-utils-private.h @@ -15,7 +15,7 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA. * - * Copyright 2005 - 2014 Red Hat, Inc. + * Copyright 2005 - 2017 Red Hat, Inc. */ #ifndef __NM_UTILS_PRIVATE_H__ @@ -33,6 +33,8 @@ struct _NMVariantAttributeSpec { const GVariantType *type; bool v4:1; bool v6:1; + bool no_value:1; + bool consumes_rest:1; char str_type; }; diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c index 44d360b398..665f399428 100644 --- a/libnm-core/nm-utils.c +++ b/libnm-core/nm-utils.c @@ -5438,22 +5438,16 @@ nm_utils_parse_variant_attributes (const char *string, break; } - if (*sep != key_value_separator) { - g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED, - _("missing key-value separator '%c'"), key_value_separator); - return NULL; - } - - /* The attribute and key/value separators are the same. Look for the next one. */ - if (ptr == sep) - goto next; - name = attribute_unescape (start, sep); - value = attribute_unescape (sep + 1, ptr); for (s = spec; *s; s++) { + if (g_hash_table_contains (ht, (*s)->name)) + continue; if (nm_streq (name, (*s)->name)) break; + if ( (*s)->no_value + && g_variant_type_equal ((*s)->type, G_VARIANT_TYPE_STRING)) + break; } if (!*s) { @@ -5466,12 +5460,33 @@ nm_utils_parse_variant_attributes (const char *string, } } + if ((*s)->no_value) { + if ((*s)->consumes_rest) { + value = g_strdup (start); + ptr = strchr (start, '\0'); + } else { + value = g_steal_pointer (&name); + } + } else { + if (*sep != key_value_separator) { + g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED, + _("missing key-value separator '%c' after '%s'"), key_value_separator, name); + return NULL; + } + + /* The attribute and key/value separators are the same. Look for the next one. */ + if (ptr == sep) + goto next; + + value = attribute_unescape (sep + 1, ptr); + } + if (g_variant_type_equal ((*s)->type, G_VARIANT_TYPE_UINT32)) { gint64 num = _nm_utils_ascii_str_to_int64 (value, 10, 0, G_MAXUINT32, -1); if (num == -1) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED, - _("invalid uint32 value '%s' for attribute '%s'"), value, name); + _("invalid uint32 value '%s' for attribute '%s'"), value, (*s)->name); return NULL; } variant = g_variant_new_uint32 (num); @@ -5480,17 +5495,17 @@ nm_utils_parse_variant_attributes (const char *string, if (num == -1) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED, - _("invalid uint8 value '%s' for attribute '%s'"), value, name); + _("invalid uint8 value '%s' for attribute '%s'"), value, (*s)->name); return NULL; } variant = g_variant_new_byte ((guchar) num); } else if (g_variant_type_equal ((*s)->type, G_VARIANT_TYPE_BOOLEAN)) { int b; - b = _nm_utils_ascii_str_to_bool (value, -1); + b = (*s)->no_value ? TRUE :_nm_utils_ascii_str_to_bool (value, -1); if (b == -1) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED, - _("invalid boolean value '%s' for attribute '%s'"), value, name); + _("invalid boolean value '%s' for attribute '%s'"), value, (*s)->name); return NULL; } variant = g_variant_new_boolean (b); @@ -5498,12 +5513,12 @@ nm_utils_parse_variant_attributes (const char *string, variant = g_variant_new_take_string (g_steal_pointer (&value)); } else { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED, - _("unsupported attribute '%s' of type '%s'"), name, + _("unsupported attribute '%s' of type '%s'"), (*s)->name, (char *) (*s)->type); return NULL; } - g_hash_table_insert (ht, g_steal_pointer (&name), variant); + g_hash_table_insert (ht, g_strdup ((*s)->name), variant); start = NULL; } next: