libnm/keyfile: properly read user data from keyfile

Hack keyfile reader support for NMSettingUser.
Writer support already works.

(cherry picked from commit 22fd7d2e39)
This commit is contained in:
Thomas Haller 2017-05-04 14:50:07 +02:00
parent c429951c46
commit a9ee1dcd5c
2 changed files with 113 additions and 16 deletions

View file

@ -35,6 +35,8 @@
#include "nm-core-internal.h"
#include "nm-keyfile-utils.h"
#include "nm-setting-user.h"
typedef struct {
NMConnection *connection;
GKeyFile *keyfile;
@ -716,33 +718,56 @@ read_hash_of_string (GKeyFile *file, NMSetting *setting, const char *key)
{
gs_strfreev char **keys = NULL;
const char *const*iter;
char *value;
const char *setting_name = nm_setting_get_name (setting);
gboolean is_vpn;
keys = nm_keyfile_plugin_kf_get_keys (file, setting_name, NULL, NULL);
if (!keys || !*keys)
return;
for (iter = (const char *const*) keys; *iter; iter++) {
gs_free char *to_free = NULL;
const char *name;
if ( (is_vpn = NM_IS_SETTING_VPN (setting))
|| NM_IS_SETTING_BOND (setting)) {
for (iter = (const char *const*) keys; *iter; iter++) {
gs_free char *to_free = NULL;
gs_free char *value = NULL;
const char *name;
value = nm_keyfile_plugin_kf_get_string (file, setting_name, *iter, NULL);
if (!value)
continue;
value = nm_keyfile_plugin_kf_get_string (file, setting_name, *iter, NULL);
if (!value)
continue;
name = nm_keyfile_key_decode (*iter, &to_free);
name = nm_keyfile_key_decode (*iter, &to_free);
if (NM_IS_SETTING_VPN (setting)) {
/* Add any item that's not a class property to the data hash */
if (!g_object_class_find_property (G_OBJECT_GET_CLASS (setting), name))
nm_setting_vpn_add_data_item (NM_SETTING_VPN (setting), name, value);
if (is_vpn) {
/* Add any item that's not a class property to the data hash */
if (!g_object_class_find_property (G_OBJECT_GET_CLASS (setting), name))
nm_setting_vpn_add_data_item (NM_SETTING_VPN (setting), name, value);
} else {
if (strcmp (name, "interface-name"))
nm_setting_bond_add_option (NM_SETTING_BOND (setting), name, value);
}
}
if (NM_IS_SETTING_BOND (setting)) {
if (strcmp (name, "interface-name"))
nm_setting_bond_add_option (NM_SETTING_BOND (setting), name, value);
return;
}
if (NM_IS_SETTING_USER (setting)) {
gs_unref_hashtable GHashTable *data = NULL;
data = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
for (iter = (const char *const*) keys; *iter; iter++) {
gs_free char *to_free = NULL;
char *value = NULL;
const char *name;
value = nm_keyfile_plugin_kf_get_string (file, setting_name, *iter, NULL);
if (!value)
continue;
name = nm_keyfile_key_decode (*iter, &to_free);
g_hash_table_insert (data,
g_steal_pointer (&to_free) ?: g_strdup (name),
value);
}
g_free (value);
g_object_set (setting, NM_SETTING_USER_DATA, data, NULL);
}
}
@ -1460,6 +1485,9 @@ read_one_setting_value (NMSetting *setting,
if (NM_IS_SETTING_VPN (setting))
check_for_key = FALSE;
if (NM_IS_SETTING_USER (setting))
check_for_key = FALSE;
/* Bonding 'options' don't have the exact key name. The options are right under [bond] group. */
if (NM_IS_SETTING_BOND (setting))
check_for_key = FALSE;

View file

@ -28,6 +28,7 @@
#include "nm-setting-wired.h"
#include "nm-setting-8021x.h"
#include "nm-setting-team.h"
#include "nm-setting-user.h"
#include "nm-setting-proxy.h"
#include "nm-utils/nm-test-utils.h"
@ -646,6 +647,73 @@ test_team_conf_read_invalid (void)
/*****************************************************************************/
static void
test_user_1 (void)
{
gs_unref_keyfile GKeyFile *keyfile = NULL;
gs_unref_object NMConnection *con = NULL;
NMSettingUser *s_user;
con = nmtst_create_connection_from_keyfile (
"[connection]\n"
"id=t\n"
"type=ethernet\n"
"\n"
"[user]\n"
"my-value.x=value1\n"
"",
"/test_user_1/invalid", NULL);
g_assert (con);
s_user = NM_SETTING_USER (nm_connection_get_setting (con, NM_TYPE_SETTING_USER));
g_assert (s_user);
g_assert_cmpstr (nm_setting_user_get_data (s_user, "my-value.x"), ==, "value1");
CLEAR (&con, &keyfile);
con = nmtst_create_minimal_connection ("user-2", "8b85fb8d-3070-48ba-93d9-53eee231d9a2", NM_SETTING_WIRED_SETTING_NAME, NULL);
s_user = NM_SETTING_USER (nm_setting_user_new ());
#define _USER_SET_DATA(s_user, key, val) \
G_STMT_START { \
GError *_error = NULL; \
gboolean _success; \
\
_success = nm_setting_user_set_data ((s_user), (key), (val), &_error); \
nmtst_assert_success (_success, _error); \
} G_STMT_END
#define _USER_SET_DATA_X(s_user, key) \
_USER_SET_DATA (s_user, key, "val="key"")
_USER_SET_DATA (s_user, "my.val1", "");
_USER_SET_DATA_X (s_user, "my.val2");
_USER_SET_DATA_X (s_user, "my.v__al3");
_USER_SET_DATA_X (s_user, "my._v");
_USER_SET_DATA_X (s_user, "my.v+");
_USER_SET_DATA_X (s_user, "my.Av");
_USER_SET_DATA_X (s_user, "MY.AV");
_USER_SET_DATA_X (s_user, "MY.8V");
_USER_SET_DATA_X (s_user, "MY.8-V");
_USER_SET_DATA_X (s_user, "MY.8_V");
_USER_SET_DATA_X (s_user, "MY.8+V");
_USER_SET_DATA_X (s_user, "MY.8/V");
_USER_SET_DATA_X (s_user, "MY.8=V");
_USER_SET_DATA_X (s_user, "MY.-");
_USER_SET_DATA_X (s_user, "MY._");
_USER_SET_DATA_X (s_user, "MY.+");
_USER_SET_DATA_X (s_user, "MY./");
_USER_SET_DATA_X (s_user, "MY.=");
_USER_SET_DATA_X (s_user, "my.keys.1");
_USER_SET_DATA_X (s_user, "my.other.KEY.42");
nm_connection_add_setting (con, NM_SETTING (s_user));
nmtst_connection_normalize (con);
_keyfile_convert (&con, &keyfile, NULL, NULL, NULL, NULL, NULL, NULL, FALSE);
}
/*****************************************************************************/
NMTST_DEFINE ();
int main (int argc, char **argv)
@ -657,6 +725,7 @@ int main (int argc, char **argv)
g_test_add_func ("/core/keyfile/test_8021x_cert_read", test_8021x_cert_read);
g_test_add_func ("/core/keyfile/test_team_conf_read/valid", test_team_conf_read_valid);
g_test_add_func ("/core/keyfile/test_team_conf_read/invalid", test_team_conf_read_invalid);
g_test_add_func ("/core/keyfile/test_user/1", test_user_1);
return g_test_run ();
}