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.
This commit is contained in:
@@ -1313,11 +1313,32 @@ nm_match_spec_s390_subchannels (const GSList *specs, const char *subchannels)
|
|||||||
return match;
|
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 *
|
GSList *
|
||||||
nm_match_spec_split (const char *value)
|
nm_match_spec_split (const char *value)
|
||||||
{
|
{
|
||||||
char *string_value, *p, *q0, *q;
|
char *string_value, *p, *q0, *q;
|
||||||
GSList *pieces = NULL;
|
GSList *pieces = NULL;
|
||||||
|
int trailing_ws;
|
||||||
|
|
||||||
if (!value || !*value)
|
if (!value || !*value)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1328,7 +1349,13 @@ nm_match_spec_split (const char *value)
|
|||||||
string_value = g_new (gchar, strlen (value) + 1);
|
string_value = g_new (gchar, strlen (value) + 1);
|
||||||
|
|
||||||
p = (gchar *) value;
|
p = (gchar *) value;
|
||||||
|
|
||||||
|
/* skip over leading whitespace */
|
||||||
|
while (g_ascii_isspace (*p))
|
||||||
|
p++;
|
||||||
|
|
||||||
q0 = q = string_value;
|
q0 = q = string_value;
|
||||||
|
trailing_ws = 0;
|
||||||
while (*p) {
|
while (*p) {
|
||||||
if (*p == '\\') {
|
if (*p == '\\') {
|
||||||
p++;
|
p++;
|
||||||
@@ -1360,23 +1387,34 @@ nm_match_spec_split (const char *value)
|
|||||||
}
|
}
|
||||||
break;
|
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')
|
if (*p == '\0')
|
||||||
break;
|
break;
|
||||||
q++;
|
|
||||||
p++;
|
p++;
|
||||||
|
trailing_ws = 0;
|
||||||
|
} else {
|
||||||
|
*q = *p;
|
||||||
|
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++;
|
||||||
|
}
|
||||||
|
q++;
|
||||||
}
|
}
|
||||||
|
|
||||||
*q = '\0';
|
*q = '\0';
|
||||||
if (q0 < q)
|
if (q0 < q - trailing_ws)
|
||||||
pieces = g_slist_prepend (pieces, g_strndup (q0, q - q0));
|
pieces = g_slist_prepend (pieces, g_strndup (q0, (q - q0) - trailing_ws));
|
||||||
g_free (string_value);
|
g_free (string_value);
|
||||||
return g_slist_reverse (pieces);
|
return g_slist_reverse (pieces);
|
||||||
}
|
}
|
||||||
|
@@ -680,6 +680,9 @@ test_match_spec_ifname (const char *spec_str, const char **matches, const char *
|
|||||||
g_assert (spec_str);
|
g_assert (spec_str);
|
||||||
|
|
||||||
specs = nm_match_spec_split (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));
|
specs_reverse = g_slist_reverse (g_slist_copy (specs));
|
||||||
|
|
||||||
for (i = 0; matches && matches[i]; i++) {
|
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",
|
test_match_spec_ifname ("interface-name:em\\;1,em\\,2,\\,,\\\\,,em\\\\x",
|
||||||
S ("em;1", "em,2", ",", "\\", "em\\x"),
|
S ("em;1", "em,2", ",", "\\", "em\\x"),
|
||||||
NULL);
|
NULL);
|
||||||
test_match_spec_ifname (" , interface-name:a, ,",
|
test_match_spec_ifname ("\\s\\s,\\sinterface-name:a,\\s,",
|
||||||
S (" ", " ", " interface-name:a"),
|
S (" ", " ", " interface-name:a"),
|
||||||
NULL);
|
NULL);
|
||||||
|
test_match_spec_ifname (" aa ; bb ; cc\\;dd ;e , ; \t\\t , ",
|
||||||
|
S ("aa", "bb", "cc;dd", "e", "\t"),
|
||||||
|
NULL);
|
||||||
#undef S
|
#undef S
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user