summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2015-07-01 13:59:06 +0200
committerThomas Haller <thaller@redhat.com>2015-07-03 09:24:05 +0200
commit500f590033858f565f35d553b21c822dc378efd2 (patch)
treed5650d2e0d3cf0e05fdbed1e4d9b4875c51b7d61
parente896817d809eae4e8f736c3f0bf19f163357bc62 (diff)
downloadNetworkManager-500f590033858f565f35d553b21c822dc378efd2.tar.gz
config: only handle 'option+' and 'option-' keys for known settings
It is wrong to blindly merge keys that have an 'option+' or 'option-'. Merging options is only possibly when we understand what the option means and how to merge it. No longer handle every setting but only those that are explicitly known to be string-lists (or device-specs). (cherry picked from commit a1ea678f7801188f3a1850a319dcc249a4c3bd37)
-rw-r--r--src/nm-config.c108
-rw-r--r--src/nm-config.h1
-rw-r--r--src/tests/config/conf.d/00-overrides.conf9
-rw-r--r--src/tests/config/conf.d/10-more.conf9
-rw-r--r--src/tests/config/conf.d/90-last.conf2
-rw-r--r--src/tests/config/test-config.c36
6 files changed, 134 insertions, 31 deletions
diff --git a/src/nm-config.c b/src/nm-config.c
index c5be85a85f..c318eea790 100644
--- a/src/nm-config.c
+++ b/src/nm-config.c
@@ -529,6 +529,27 @@ _sort_groups_cmp (const char **pa, const char **pb, gpointer dummy)
}
static gboolean
+_setting_is_device_spec (const char *group, const char *key)
+{
+#define _IS(group_v, key_v) (strcmp (group, (""group_v)) == 0 && strcmp (key, (""key_v)) == 0)
+ return _IS (NM_CONFIG_KEYFILE_GROUP_MAIN, "no-auto-default")
+ || _IS (NM_CONFIG_KEYFILE_GROUP_MAIN, "ignore-carrier")
+ || _IS (NM_CONFIG_KEYFILE_GROUP_MAIN, "assume-ipv6ll-only")
+ || _IS (NM_CONFIG_KEYFILE_GROUP_KEYFILE, "unmanaged-devices")
+ || (g_str_has_prefix (group, NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION) && !strcmp (key, "match-device"));
+}
+
+static gboolean
+_setting_is_string_list (const char *group, const char *key)
+{
+ return _IS (NM_CONFIG_KEYFILE_GROUP_MAIN, "plugins")
+ || _IS (NM_CONFIG_KEYFILE_GROUP_MAIN, "debug")
+ || _IS (NM_CONFIG_KEYFILE_GROUP_LOGGING, "domains")
+ || g_str_has_prefix (group, NM_CONFIG_KEYFILE_GROUPPREFIX_TEST_APPEND_STRINGLIST);
+#undef _IS
+}
+
+static gboolean
read_config (GKeyFile *keyfile, const char *path, GError **error)
{
GKeyFile *kf;
@@ -593,29 +614,72 @@ read_config (GKeyFile *keyfile, const char *path, GError **error)
if ( key_len > 1
&& (last_char == '+' || last_char == '-')) {
gs_free char *base_key = g_strndup (key, key_len - 1);
- gs_strfreev char **old_val = g_key_file_get_string_list (keyfile, group, base_key, NULL, NULL);
- gs_free char **new_val = g_key_file_get_string_list (kf, group, key, NULL, NULL);
- gs_unref_ptrarray GPtrArray *new = g_ptr_array_new_with_free_func (g_free);
- char **iter_val;
-
- for (iter_val = old_val; iter_val && *iter_val; iter_val++) {
- if ( last_char != '-'
- || _nm_utils_strv_find_first (new_val, -1, *iter_val) < 0)
- g_ptr_array_add (new, g_strdup (*iter_val));
+ gboolean is_string_list;
+
+ is_string_list = _setting_is_string_list (group, base_key);
+
+ if ( is_string_list
+ || _setting_is_device_spec (group, base_key)) {
+ gs_unref_ptrarray GPtrArray *new = g_ptr_array_new_with_free_func (g_free);
+ char **iter_val;
+ gs_strfreev char **old_val = NULL;
+ gs_free char **new_val = NULL;
+
+ if (is_string_list) {
+ old_val = g_key_file_get_string_list (keyfile, group, base_key, NULL, NULL);
+ new_val = g_key_file_get_string_list (kf, group, key, NULL, NULL);
+ } else {
+ gs_free char *old_sval = nm_config_keyfile_get_value (keyfile, group, base_key, NM_CONFIG_GET_VALUE_TYPE_SPEC);
+ gs_free char *new_sval = nm_config_keyfile_get_value (kf, group, key, NM_CONFIG_GET_VALUE_TYPE_SPEC);
+ gs_free_slist GSList *old_specs = nm_match_spec_split (old_sval);
+ gs_free_slist GSList *new_specs = nm_match_spec_split (new_sval);
+
+ /* the key is a device spec. This is a special kind of string-list, that
+ * we must split differently. */
+ old_val = _nm_utils_slist_to_strv (old_specs, FALSE);
+ new_val = _nm_utils_slist_to_strv (new_specs, FALSE);
+ }
+
+ /* merge the string lists, by omiting duplicates. */
+
+ for (iter_val = old_val; iter_val && *iter_val; iter_val++) {
+ if ( last_char != '-'
+ || _nm_utils_strv_find_first (new_val, -1, *iter_val) < 0)
+ g_ptr_array_add (new, g_strdup (*iter_val));
+ }
+ for (iter_val = new_val; iter_val && *iter_val; iter_val++) {
+ /* don't add duplicates. That means an "option=a,b"; "option+=a,c" results in "option=a,b,c" */
+ if ( last_char == '+'
+ && _nm_utils_strv_find_first (old_val, -1, *iter_val) < 0)
+ g_ptr_array_add (new, *iter_val);
+ else
+ g_free (*iter_val);
+ }
+
+ if (new->len > 0) {
+ if (is_string_list)
+ nm_config_keyfile_set_string_list (keyfile, group, base_key, (const char *const*) new->pdata, new->len);
+ else {
+ gs_free_slist GSList *specs = NULL;
+ gs_free char *specs_joined = NULL;
+
+ g_ptr_array_add (new, NULL);
+ specs = _nm_utils_strv_to_slist ((char **) new->pdata, FALSE);
+
+ specs_joined = nm_match_spec_join (specs);
+
+ g_key_file_set_value (keyfile, group, base_key, specs_joined);
+ }
+ } else {
+ if (is_string_list)
+ g_key_file_remove_key (keyfile, group, base_key, NULL);
+ else
+ g_key_file_set_value (keyfile, group, base_key, "");
+ }
+ } else {
+ /* For any other settings we don't support extending the option with +/-.
+ * Just drop the key. */
}
- for (iter_val = new_val; iter_val && *iter_val; iter_val++) {
- /* don't add duplicates. That means an "option=a,b"; "option+=a,c" results in "option=a,b,c" */
- if ( last_char == '+'
- && _nm_utils_strv_find_first (old_val, -1, *iter_val) < 0)
- g_ptr_array_add (new, *iter_val);
- else
- g_free (*iter_val);
- }
-
- if (new->len > 0)
- nm_config_keyfile_set_string_list (keyfile, group, base_key, (const char *const*) new->pdata, new->len);
- else
- g_key_file_remove_key (keyfile, group, base_key, NULL);
continue;
}
diff --git a/src/nm-config.h b/src/nm-config.h
index 20dbab388f..5b096f165d 100644
--- a/src/nm-config.h
+++ b/src/nm-config.h
@@ -49,6 +49,7 @@ G_BEGIN_DECLS
#define NM_CONFIG_KEYFILE_LIST_SEPARATOR ','
#define NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION "connection"
+#define NM_CONFIG_KEYFILE_GROUPPREFIX_TEST_APPEND_STRINGLIST ".test-append-stringlist"
#define NM_CONFIG_KEYFILE_GROUP_MAIN "main"
#define NM_CONFIG_KEYFILE_GROUP_LOGGING "logging"
diff --git a/src/tests/config/conf.d/00-overrides.conf b/src/tests/config/conf.d/00-overrides.conf
index cb0116edd8..f26ed93b9a 100644
--- a/src/tests/config/conf.d/00-overrides.conf
+++ b/src/tests/config/conf.d/00-overrides.conf
@@ -1,9 +1,16 @@
[main]
dhcp=dhcpcd
+no-auto-default=spec1,spec2
+ignore-carrier=\s space1 \s
+
[logging]
domains=PLATFORM,DNS,WIFI
+[appendable-test]
+non-appendable-key1+=i-will-be-dropped
+non-appendable-key2-=i-will-be-dropped
+
[order]
a=0
b=0
@@ -32,7 +39,7 @@ ord.key08=B-1.3.08
ord.key09=B-1.3.09
-[append]
+[.test-append-stringlist.1]
val1=a,b
val2-=VAL2
diff --git a/src/tests/config/conf.d/10-more.conf b/src/tests/config/conf.d/10-more.conf
index a1959c1948..eadb7f96f6 100644
--- a/src/tests/config/conf.d/10-more.conf
+++ b/src/tests/config/conf.d/10-more.conf
@@ -1,5 +1,12 @@
[main]
extra=hello
+
+no-auto-default-=spec1
+no-auto-default+=spec3
+
+ignore-carrier+=\sspace2\t
+
+[.test-append-stringlist.0]
new+=something
[connectivity]
@@ -29,5 +36,5 @@ ord.key09=C-2.3.09
ord.ovw01=C-0.1.ovw01
-[append]
+[.test-append-stringlist.1]
val1-=b
diff --git a/src/tests/config/conf.d/90-last.conf b/src/tests/config/conf.d/90-last.conf
index c75dcc4710..7d078788de 100644
--- a/src/tests/config/conf.d/90-last.conf
+++ b/src/tests/config/conf.d/90-last.conf
@@ -4,5 +4,5 @@ plugins+=one,two
[order]
a=90
-[append]
+[.test-append-stringlist.1]
val1+=c,a
diff --git a/src/tests/config/test-config.c b/src/tests/config/test-config.c
index 24592071ef..8b8028e63a 100644
--- a/src/tests/config/test-config.c
+++ b/src/tests/config/test-config.c
@@ -283,6 +283,7 @@ test_config_confdir (void)
NMConfig *config;
const char **plugins;
char *value;
+ GSList *specs;
config = setup_config (NULL, SRCDIR "/NetworkManager.conf", SRCDIR "/conf.d", NULL);
@@ -305,7 +306,23 @@ test_config_confdir (void)
g_assert_cmpstr (value, ==, "hello");
g_free (value);
- value = nm_config_data_get_value (nm_config_get_data_orig (config), "main", "new", NM_CONFIG_GET_VALUE_NONE);
+ value = nm_config_data_get_value (nm_config_get_data_orig (config), "main", "no-auto-default", NM_CONFIG_GET_VALUE_TYPE_SPEC);
+ specs = nm_match_spec_split (value);
+ g_free (value);
+ g_assert_cmpint (g_slist_length (specs), ==, 2);
+ g_assert_cmpstr (g_slist_nth_data (specs, 0), ==, "spec2");
+ g_assert_cmpstr (g_slist_nth_data (specs, 1), ==, "spec3");
+ g_slist_free_full (specs, g_free);
+
+ value = nm_config_data_get_value (nm_config_get_data_orig (config), "main", "ignore-carrier", NM_CONFIG_GET_VALUE_TYPE_SPEC);
+ specs = nm_match_spec_split (value);
+ g_free (value);
+ g_assert_cmpint (g_slist_length (specs), ==, 2);
+ g_assert_cmpstr (g_slist_nth_data (specs, 0), ==, " space1 ");
+ g_assert_cmpstr (g_slist_nth_data (specs, 1), ==, " space2\t");
+ g_slist_free_full (specs, g_free);
+
+ value = nm_config_data_get_value (nm_config_get_data_orig (config), NM_CONFIG_KEYFILE_GROUPPREFIX_TEST_APPEND_STRINGLIST".0", "new", NM_CONFIG_GET_VALUE_NONE);
g_assert_cmpstr (value, ==, "something"); /* not ",something" */
g_free (value);
@@ -319,6 +336,13 @@ test_config_confdir (void)
g_assert_cmpstr (value, ==, "0");
g_free (value);
+ g_assert (!nm_config_data_has_value (nm_config_get_data_orig (config), "appendable-test", "non-appendable-key1", NM_CONFIG_GET_VALUE_RAW));
+ g_assert (!nm_config_data_has_value (nm_config_get_data_orig (config), "appendable-test", "non-appendable-key1+", NM_CONFIG_GET_VALUE_RAW));
+ g_assert (!nm_config_data_has_value (nm_config_get_data_orig (config), "appendable-test", "non-appendable-key1-", NM_CONFIG_GET_VALUE_RAW));
+ g_assert (!nm_config_data_has_value (nm_config_get_data_orig (config), "appendable-test", "non-appendable-key2", NM_CONFIG_GET_VALUE_RAW));
+ g_assert (!nm_config_data_has_value (nm_config_get_data_orig (config), "appendable-test", "non-appendable-key2+", NM_CONFIG_GET_VALUE_RAW));
+ g_assert (!nm_config_data_has_value (nm_config_get_data_orig (config), "appendable-test", "non-appendable-key2-", NM_CONFIG_GET_VALUE_RAW));
+
#define ASSERT_GET_CONN_DEFAULT(xconfig, xname, xvalue) \
G_STMT_START { \
gs_free char *_value = nm_config_data_get_connection_default (nm_config_get_data_orig (xconfig), (xname), NULL); \
@@ -336,23 +360,23 @@ test_config_confdir (void)
ASSERT_GET_CONN_DEFAULT (config, "ord.key09", "C-2.1.09");
ASSERT_GET_CONN_DEFAULT (config, "ord.ovw01", "C-0.1.ovw01");
- value = nm_config_data_get_value (nm_config_get_data_orig (config), "append", "val1", NM_CONFIG_GET_VALUE_NONE);
+ value = nm_config_data_get_value (nm_config_get_data_orig (config), NM_CONFIG_KEYFILE_GROUPPREFIX_TEST_APPEND_STRINGLIST".1", "val1", NM_CONFIG_GET_VALUE_NONE);
g_assert_cmpstr (value, ==, "a,c");
g_free (value);
- value = nm_config_data_get_value (nm_config_get_data_orig (config), "append", "val2", NM_CONFIG_GET_VALUE_NONE);
+ value = nm_config_data_get_value (nm_config_get_data_orig (config), NM_CONFIG_KEYFILE_GROUPPREFIX_TEST_APPEND_STRINGLIST".1", "val2", NM_CONFIG_GET_VALUE_NONE);
g_assert_cmpstr (value, ==, "VAL2");
g_free (value);
- value = nm_config_data_get_value (nm_config_get_data_orig (config), "append", "val3", NM_CONFIG_GET_VALUE_NONE);
+ value = nm_config_data_get_value (nm_config_get_data_orig (config), NM_CONFIG_KEYFILE_GROUPPREFIX_TEST_APPEND_STRINGLIST".1", "val3", NM_CONFIG_GET_VALUE_NONE);
g_assert_cmpstr (value, ==, NULL);
g_free (value);
- value = nm_config_data_get_value (nm_config_get_data_orig (config), "append", "val4", NM_CONFIG_GET_VALUE_NONE);
+ value = nm_config_data_get_value (nm_config_get_data_orig (config), NM_CONFIG_KEYFILE_GROUPPREFIX_TEST_APPEND_STRINGLIST".1", "val4", NM_CONFIG_GET_VALUE_NONE);
g_assert_cmpstr (value, ==, "vb,vb");
g_free (value);
- value = nm_config_data_get_value (nm_config_get_data_orig (config), "append", "val5", NM_CONFIG_GET_VALUE_NONE);
+ value = nm_config_data_get_value (nm_config_get_data_orig (config), NM_CONFIG_KEYFILE_GROUPPREFIX_TEST_APPEND_STRINGLIST".1", "val5", NM_CONFIG_GET_VALUE_NONE);
g_assert_cmpstr (value, ==, "VAL5");
g_free (value);