summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2015-02-09 16:57:14 +0100
committerBeniamino Galvani <bgalvani@redhat.com>2015-06-10 18:33:05 +0200
commit832023fe1c018096f8d2adaafe51af77e2ab313f (patch)
tree5b4bc93d16b89ef9089a21e1713c585a7f7dbbbf
parentaaca52b2614551fa20cf6358fe9ce3fcca58d634 (diff)
downloadNetworkManager-832023fe1c018096f8d2adaafe51af77e2ab313f.tar.gz
core: add nm_match_spec_split() function
There are currently three device spec properties: 'main.ignore-carrier', 'main.no-auto-default' and 'keyfile.unmanaged-devices'. The first two, called g_key_file_parse_value_as_string() to split the string into individual device specs. This uses ',' as separator and supports escaping using '\\'. 'keyfile.unmanaged-devices' is split using ',' or ';' as separator without supporting escaping. Add a new function nm_match_spec_split(), to unify these two behaviors and support both formats. That is, both previous formats are mostly supported, but obviously there are some behavioral changes if the string contains one of '\\', ',', or ';'. nm_match_spec_split() is copied from glibs g_key_file_parse_value_as_string() and adjusted. (cherry picked from commit 3bcc5e4bd0bd88b15ab8f84515f0fca52db62823)
-rw-r--r--src/NetworkManagerUtils.c68
-rw-r--r--src/NetworkManagerUtils.h1
-rw-r--r--src/tests/test-general.c25
3 files changed, 85 insertions, 9 deletions
diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c
index 7ccc5cffd5..d84cd6a475 100644
--- a/src/NetworkManagerUtils.c
+++ b/src/NetworkManagerUtils.c
@@ -1027,6 +1027,74 @@ nm_match_spec_s390_subchannels (const GSList *specs, const char *subchannels)
return match;
}
+GSList *
+nm_match_spec_split (const char *value)
+{
+ char *string_value, *p, *q0, *q;
+ GSList *pieces = NULL;
+
+ if (!value || !*value)
+ return NULL;
+
+ /* Copied from glibs g_key_file_parse_value_as_string() function
+ * and adjusted. */
+
+ string_value = g_new (gchar, strlen (value) + 1);
+
+ p = (gchar *) value;
+ q0 = q = string_value;
+ while (*p) {
+ if (*p == '\\') {
+ p++;
+
+ switch (*p) {
+ case 's':
+ *q = ' ';
+ break;
+ case 'n':
+ *q = '\n';
+ break;
+ case 't':
+ *q = '\t';
+ break;
+ case 'r':
+ *q = '\r';
+ break;
+ case '\\':
+ *q = '\\';
+ break;
+ case '\0':
+ break;
+ default:
+ if (NM_IN_SET (*p, ',', ';'))
+ *q = *p;
+ else {
+ *q++ = '\\';
+ *q = *p;
+ }
+ break;
+ }
+ } else {
+ *q = *p;
+ if (NM_IN_SET (*p, ',', ';')) {
+ if (q0 < q)
+ pieces = g_slist_prepend (pieces, g_strndup (q0, q - q0));
+ q0 = q + 1;
+ }
+ }
+ if (*p == '\0')
+ break;
+ q++;
+ p++;
+ }
+
+ *q = '\0';
+ if (q0 < q)
+ pieces = g_slist_prepend (pieces, g_strndup (q0, q - q0));
+ g_free (string_value);
+ return g_slist_reverse (pieces);
+}
+
const char *
nm_utils_get_shared_wifi_permission (NMConnection *connection)
{
diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h
index c0f313c2f5..884cde9f3f 100644
--- a/src/NetworkManagerUtils.h
+++ b/src/NetworkManagerUtils.h
@@ -103,6 +103,7 @@ typedef enum {
NMMatchSpecMatchType nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr);
NMMatchSpecMatchType nm_match_spec_s390_subchannels (const GSList *specs, const char *subchannels);
NMMatchSpecMatchType nm_match_spec_interface_name (const GSList *specs, const char *interface_name);
+GSList *nm_match_spec_split (const char *value);
const char *nm_utils_get_shared_wifi_permission (NMConnection *connection);
diff --git a/src/tests/test-general.c b/src/tests/test-general.c
index b26b0e2aec..21533cc743 100644
--- a/src/tests/test-general.c
+++ b/src/tests/test-general.c
@@ -806,17 +806,13 @@ static void
test_match_spec_ifname (const char *spec_str, const char **matches, const char **neg_matches)
{
const char *m;
- char **spec_str_split;
GSList *specs, *specs_reverse = NULL;
guint i;
g_assert (spec_str);
- spec_str_split = g_strsplit_set (spec_str, ";,", -1);
- for (i = 0; spec_str_split[i]; i++) {
- if (spec_str_split[i])
- specs_reverse = g_slist_prepend (specs_reverse, spec_str_split[i]);
- }
- specs = g_slist_reverse (g_slist_copy (specs_reverse));
+
+ specs = nm_match_spec_split (spec_str);
+ specs_reverse = g_slist_reverse (g_slist_copy (specs));
for (i = 0; matches && matches[i]; i++) {
g_assert (nm_match_spec_interface_name (specs, matches[i]) == NM_MATCH_SPEC_MATCH);
@@ -836,8 +832,7 @@ test_match_spec_ifname (const char *spec_str, const char **matches, const char *
}
g_slist_free (specs_reverse);
- g_slist_free (specs);
- g_strfreev (spec_str_split);
+ g_slist_free_full (specs, g_free);
}
static void
@@ -874,6 +869,18 @@ test_nm_match_spec_interface_name (void)
test_match_spec_ifname ("interface-name:em*,except:interface-name:=em*",
S ("em", "em\\", "em\\*", "em\\1", "em\\11", "em\\2", "em1", "em11", "em2", "em3"),
S ("em*"));
+ test_match_spec_ifname ("aa,bb,cc\\,dd,e,,",
+ S ("aa", "bb", "cc,dd", "e"),
+ NULL);
+ test_match_spec_ifname ("aa;bb;cc\\;dd;e,;",
+ S ("aa", "bb", "cc;dd", "e"),
+ NULL);
+ test_match_spec_ifname ("interface-name:em\\;1,em\\,2,\\,,\\\\,,em\\\\x",
+ S ("em;1", "em,2", ",", "\\", "em\\x"),
+ NULL);
+ test_match_spec_ifname (" , interface-name:a, ,",
+ S (" ", " ", " interface-name:a"),
+ NULL);
#undef S
}