diff options
author | Thomas Haller <thaller@redhat.com> | 2015-06-16 14:06:48 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2015-07-02 15:50:04 +0200 |
commit | 7498b670a828d335e177003c9d00d68802f52561 (patch) | |
tree | a5736dbdb30440940bdc4f94fe5af79b6e790fb6 | |
parent | 11c0e107b9b903b13c741448eae68b443e98ad2e (diff) | |
download | NetworkManager-7498b670a828d335e177003c9d00d68802f52561.tar.gz |
utils: strip whitespace for device spec in nm_match_spec_split()
Via escape sequences, the user still can specify trailing and leading
white spaces: such as "\s \s" will result in 3 spaces.
-rw-r--r-- | src/NetworkManagerUtils.c | 56 | ||||
-rw-r--r-- | src/tests/test-general.c | 8 |
2 files changed, 54 insertions, 10 deletions
diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index 5a129215f7..24a6f952cb 100644 --- a/src/NetworkManagerUtils.c +++ b/src/NetworkManagerUtils.c @@ -1313,11 +1313,32 @@ nm_match_spec_s390_subchannels (const GSList *specs, const char *subchannels) return match; } +/** + * nm_match_spec_split: + * @value: the string of device specs + * + * Splits the specs from the string and returns them as individual + * entires in a #GSList. + * + * It does not validate any specs, it basically just does a special + * strsplit with ',' or ';' as separators and supporting '\\' as + * escape character. + * + * Leading and trailing spaces of each entry are removed. But the user + * can preserve them by specifying "\\s has 2 leading" or "has 2 trailing \\s". + * + * Specs can have a qualifier like "interface-name:". We still don't strip + * any whitespace after the colon, so "interface-name: X" matches an interface + * named " X". + * + * Returns: (transfer-full): the list of device specs. + */ GSList * nm_match_spec_split (const char *value) { char *string_value, *p, *q0, *q; GSList *pieces = NULL; + int trailing_ws; if (!value || !*value) return NULL; @@ -1328,7 +1349,13 @@ nm_match_spec_split (const char *value) string_value = g_new (gchar, strlen (value) + 1); p = (gchar *) value; + + /* skip over leading whitespace */ + while (g_ascii_isspace (*p)) + p++; + q0 = q = string_value; + trailing_ws = 0; while (*p) { if (*p == '\\') { p++; @@ -1360,23 +1387,34 @@ nm_match_spec_split (const char *value) } break; } + if (*p == '\0') + break; + p++; + trailing_ws = 0; } else { *q = *p; - if (NM_IN_SET (*p, ',', ';')) { - if (q0 < q) - pieces = g_slist_prepend (pieces, g_strndup (q0, q - q0)); + if (*p == '\0') + break; + if (g_ascii_isspace (*p)) { + trailing_ws++; + p++; + } else if (NM_IN_SET (*p, ',', ';')) { + if (q0 < q - trailing_ws) + pieces = g_slist_prepend (pieces, g_strndup (q0, (q - q0) - trailing_ws)); q0 = q + 1; - } + p++; + trailing_ws = 0; + while (g_ascii_isspace (*p)) + p++; + } else + p++; } - if (*p == '\0') - break; q++; - p++; } *q = '\0'; - if (q0 < q) - pieces = g_slist_prepend (pieces, g_strndup (q0, q - q0)); + if (q0 < q - trailing_ws) + pieces = g_slist_prepend (pieces, g_strndup (q0, (q - q0) - trailing_ws)); g_free (string_value); return g_slist_reverse (pieces); } diff --git a/src/tests/test-general.c b/src/tests/test-general.c index baea1d54e2..3397dd9715 100644 --- a/src/tests/test-general.c +++ b/src/tests/test-general.c @@ -680,6 +680,9 @@ test_match_spec_ifname (const char *spec_str, const char **matches, const char * g_assert (spec_str); specs = nm_match_spec_split (spec_str); + + /* also check the matches in the reverse order. They must yield the same result because + * matches are inclusive -- except "except:" which always wins. */ specs_reverse = g_slist_reverse (g_slist_copy (specs)); for (i = 0; matches && matches[i]; i++) { @@ -746,9 +749,12 @@ test_nm_match_spec_interface_name (void) 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, ,", + test_match_spec_ifname ("\\s\\s,\\sinterface-name:a,\\s,", S (" ", " ", " interface-name:a"), NULL); + test_match_spec_ifname (" aa ; bb ; cc\\;dd ;e , ; \t\\t , ", + S ("aa", "bb", "cc;dd", "e", "\t"), + NULL); #undef S } |