diff options
-rw-r--r-- | man/NetworkManager.conf.xml.in | 17 | ||||
-rw-r--r-- | src/devices/nm-device.c | 2 | ||||
-rw-r--r-- | src/nm-config-data.c | 181 | ||||
-rw-r--r-- | src/nm-config-data.h | 24 | ||||
-rw-r--r-- | src/nm-config.c | 468 | ||||
-rw-r--r-- | src/nm-config.h | 11 | ||||
-rw-r--r-- | src/tests/config/test-config.c | 22 |
7 files changed, 677 insertions, 48 deletions
diff --git a/man/NetworkManager.conf.xml.in b/man/NetworkManager.conf.xml.in index 9557d7a9be..bf15c9e8b5 100644 --- a/man/NetworkManager.conf.xml.in +++ b/man/NetworkManager.conf.xml.in @@ -28,16 +28,19 @@ Copyright 2010 - 2014 Red Hat, Inc. <refsynopsisdiv> <para><filename>/etc/NetworkManager/NetworkManager.conf</filename>, <filename>/etc/NetworkManager/conf.d/<replaceable>name</replaceable>.conf</filename>, - <filename>/usr/lib/NetworkManager/conf.d/<replaceable>name</replaceable>.conf</filename> + <filename>/usr/lib/NetworkManager/conf.d/<replaceable>name</replaceable>.conf</filename>, + <filename>/var/lib/NetworkManager/NetworkManager-intern.conf</filename> </para> </refsynopsisdiv> <refsect1> <title>Description</title> - <para>This is a configuration file for NetworkManager. It is used + <para><literal>NetworkManager.conf</literal> is the configuration file for NetworkManager. It is used to set up various aspects of NetworkManager's behavior. The - location of the file may be changed through use of the - <option>--config</option> argument for NetworkManager. + location of the main file and configuration directories may be changed + through use of the <option>--config</option>, <option>--config-dir</option>, + <option>--system-config-dir</option>, and <option>--intern-config</option> + argument for NetworkManager, respectively. </para> <para>If a default <literal>NetworkManager.conf</literal> is provided by your distribution's packages, you should not modify @@ -52,6 +55,12 @@ Copyright 2010 - 2014 Red Hat, Inc. In this case, the file from the etc configuration shadows the file from the system configuration directory. </para> + <para> + NetworkManager can overwrite certain user configuration options via D-Bus or other internal + operations. In this case it writes those changes to <literal>/var/lib/NetworkManager/NetworkManager-intern.conf</literal>. + This file is not intended to be modified by the user, but it is read last and can shadow + user configuration from <literal>NetworkManager.conf</literal>. + </para> </refsect1> diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index dcdd29e440..16d4c48c69 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -3323,7 +3323,7 @@ ip4_config_merge_and_apply (NMDevice *self, if ( !priv->default_route.v4_configure_first_time && !nm_device_uses_assumed_connection (self) && connection_is_never_default) { - /* If the connection is explicitly configured as never-default, we enforce the (absense of the) + /* If the connection is explicitly configured as never-default, we enforce the (absence of the) * default-route only once. That allows the user to configure a connection as never-default, * but he can add default routes externally (via a dispatcher script) and NM will not interfere. */ goto END_ADD_DEFAULT_ROUTE; diff --git a/src/nm-config-data.c b/src/nm-config-data.c index 82c1deab11..c3f279a521 100644 --- a/src/nm-config-data.c +++ b/src/nm-config-data.c @@ -48,6 +48,8 @@ typedef struct { char *config_description; GKeyFile *keyfile; + GKeyFile *keyfile_user; + GKeyFile *keyfile_intern; /* A zero-terminated list of pre-processed information from the * [connection] sections. This is to speed up lookup. */ @@ -77,7 +79,8 @@ enum { PROP_0, PROP_CONFIG_MAIN_FILE, PROP_CONFIG_DESCRIPTION, - PROP_KEYFILE, + PROP_KEYFILE_USER, + PROP_KEYFILE_INTERN, PROP_CONNECTIVITY_URI, PROP_CONNECTIVITY_INTERVAL, PROP_CONNECTIVITY_RESPONSE, @@ -92,6 +95,14 @@ G_DEFINE_TYPE (NMConfigData, nm_config_data, G_TYPE_OBJECT) /************************************************************************/ +#define _HAS_PREFIX(str, prefix) \ + ({ \ + const char *_str = (str); \ + g_str_has_prefix ( _str, ""prefix"") && _str[STRLEN(prefix)] != '\0'; \ + }) + +/************************************************************************/ + const char * nm_config_data_get_config_main_file (const NMConfigData *self) { @@ -238,6 +249,40 @@ nm_config_data_get_assume_ipv6ll_only (const NMConfigData *self, NMDevice *devic return nm_device_spec_match_list (device, NM_CONFIG_DATA_GET_PRIVATE (self)->assume_ipv6ll_only); } +GKeyFile * +nm_config_data_clone_keyfile_intern (const NMConfigData *self) +{ + NMConfigDataPrivate *priv; + GKeyFile *keyfile; + + g_return_val_if_fail (NM_IS_CONFIG_DATA (self), FALSE); + + priv = NM_CONFIG_DATA_GET_PRIVATE (self); + + keyfile = nm_config_create_keyfile (); + if (priv->keyfile_intern) + _nm_keyfile_copy (keyfile, priv->keyfile_intern); + return keyfile; +} + +GKeyFile * +_nm_config_data_get_keyfile (const NMConfigData *self) +{ + return NM_CONFIG_DATA_GET_PRIVATE (self)->keyfile; +} + +GKeyFile * +_nm_config_data_get_keyfile_intern (const NMConfigData *self) +{ + return NM_CONFIG_DATA_GET_PRIVATE (self)->keyfile_intern; +} + +GKeyFile * +_nm_config_data_get_keyfile_user (const NMConfigData *self) +{ + return NM_CONFIG_DATA_GET_PRIVATE (self)->keyfile_user; +} + /************************************************************************/ /** @@ -267,13 +312,80 @@ nm_config_data_get_keys (const NMConfigData *self, const char *group) /************************************************************************/ +static GKeyFile * +_merge_keyfiles (GKeyFile *keyfile_user, GKeyFile *keyfile_intern) +{ + gs_strfreev char **groups = NULL; + guint g, k; + GKeyFile *keyfile; + gsize ngroups; + + keyfile = nm_config_create_keyfile (); + if (keyfile_user) + _nm_keyfile_copy (keyfile, keyfile_user); + if (!keyfile_intern) + return keyfile; + + groups = g_key_file_get_groups (keyfile_intern, &ngroups); + if (!groups) + return keyfile; + + /* we must reverse the order of the connection settings so that we + * have lowest priority last. */ + _nm_config_sort_groups (groups, ngroups); + for (g = 0; groups[g]; g++) { + const char *group = groups[g]; + gs_strfreev char **keys = NULL; + gboolean is_intern; + + keys = g_key_file_get_keys (keyfile_intern, group, NULL, NULL); + if (!keys) + continue; + + is_intern = g_str_has_prefix (group, NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN); + + for (k = 0; keys[k]; k++) { + const char *key = keys[k]; + gs_free char *value = NULL; + + if (!is_intern && _HAS_PREFIX (key, NM_CONFIG_KEYFILE_KEYPREFIX_WAS)) { + const char *key_base = &key[STRLEN (NM_CONFIG_KEYFILE_KEYPREFIX_WAS)]; + + if (!g_key_file_has_key (keyfile_intern, group, key_base, NULL)) + g_key_file_remove_key (keyfile, group, key_base, NULL); + continue; + } + if (!is_intern && _HAS_PREFIX (key, NM_CONFIG_KEYFILE_KEYPREFIX_SET)) + continue; + + value = g_key_file_get_value (keyfile_intern, group, key, NULL); + g_key_file_set_value (keyfile, group, key, value); + } + } + return keyfile; +} + +/************************************************************************/ + static int _nm_config_data_log_sort (const char **pa, const char **pb, gpointer dummy) { gboolean a_is_connection, b_is_connection; + gboolean a_is_intern, b_is_intern; const char *a = *pa; const char *b = *pb; + /* we sort intern groups to the end. */ + a_is_intern = g_str_has_prefix (a, NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN); + b_is_intern = g_str_has_prefix (b, NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN); + + if (a_is_intern && b_is_intern) + return 0; + if (a_is_intern) + return 1; + if (b_is_intern) + return -1; + /* we sort connection groups before intern groups (to the end). */ a_is_connection = a && g_str_has_prefix (a, NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION); b_is_connection = b && g_str_has_prefix (b, NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION); @@ -479,8 +591,11 @@ nm_config_data_diff (NMConfigData *old_data, NMConfigData *new_data) priv_old = NM_CONFIG_DATA_GET_PRIVATE (old_data); priv_new = NM_CONFIG_DATA_GET_PRIVATE (new_data); - if (!_nm_keyfile_equals (priv_old->keyfile, priv_new->keyfile, TRUE)) - changes |= NM_CONFIG_CHANGE_VALUES; + if (!_nm_keyfile_equals (priv_old->keyfile_user, priv_new->keyfile_user, TRUE)) + changes |= NM_CONFIG_CHANGE_VALUES | NM_CONFIG_CHANGE_VALUES_USER; + + if (!_nm_keyfile_equals (priv_old->keyfile_intern, priv_new->keyfile_intern, TRUE)) + changes |= NM_CONFIG_CHANGE_VALUES | NM_CONFIG_CHANGE_VALUES_INTERN; if ( g_strcmp0 (nm_config_data_get_config_main_file (old_data), nm_config_data_get_config_main_file (new_data)) != 0 || g_strcmp0 (nm_config_data_get_config_description (old_data), nm_config_data_get_config_description (new_data)) != 0) @@ -553,10 +668,21 @@ set_property (GObject *object, case PROP_CONFIG_DESCRIPTION: priv->config_description = g_value_dup_string (value); break; - case PROP_KEYFILE: - priv->keyfile = g_value_dup_boxed (value); - if (!priv->keyfile) - priv->keyfile = nm_config_create_keyfile (); + case PROP_KEYFILE_USER: + priv->keyfile_user = g_value_dup_boxed (value); + if ( priv->keyfile_user + && !_nm_keyfile_has_values (priv->keyfile_user)) { + g_key_file_unref (priv->keyfile_user); + priv->keyfile_user = NULL; + } + break; + case PROP_KEYFILE_INTERN: + priv->keyfile_intern = g_value_dup_boxed (value); + if ( priv->keyfile_intern + && !_nm_keyfile_has_values (priv->keyfile_intern)) { + g_key_file_unref (priv->keyfile_intern); + priv->keyfile_intern = NULL; + } break; case PROP_NO_AUTO_DEFAULT: { @@ -620,6 +746,10 @@ finalize (GObject *gobject) } g_key_file_unref (priv->keyfile); + if (priv->keyfile_user) + g_key_file_unref (priv->keyfile_user); + if (priv->keyfile_intern) + g_key_file_unref (priv->keyfile_intern); G_OBJECT_CLASS (nm_config_data_parent_class)->finalize (gobject); } @@ -636,6 +766,8 @@ constructed (GObject *object) NMConfigDataPrivate *priv = NM_CONFIG_DATA_GET_PRIVATE (self); char *interval; + priv->keyfile = _merge_keyfiles (priv->keyfile_user, priv->keyfile_intern); + priv->connection_infos = _get_connection_infos (priv->keyfile); priv->connectivity.uri = nm_strstrip (g_key_file_get_string (priv->keyfile, NM_CONFIG_KEYFILE_GROUP_CONNECTIVITY, "uri", NULL)); @@ -664,17 +796,33 @@ NMConfigData * nm_config_data_new (const char *config_main_file, const char *config_description, const char *const*no_auto_default, - GKeyFile *keyfile) + GKeyFile *keyfile_user, + GKeyFile *keyfile_intern) { return g_object_new (NM_TYPE_CONFIG_DATA, NM_CONFIG_DATA_CONFIG_MAIN_FILE, config_main_file, NM_CONFIG_DATA_CONFIG_DESCRIPTION, config_description, - NM_CONFIG_DATA_KEYFILE, keyfile, + NM_CONFIG_DATA_KEYFILE_USER, keyfile_user, + NM_CONFIG_DATA_KEYFILE_INTERN, keyfile_intern, NM_CONFIG_DATA_NO_AUTO_DEFAULT, no_auto_default, NULL); } NMConfigData * +nm_config_data_new_update_keyfile_intern (const NMConfigData *base, GKeyFile *keyfile_intern) +{ + NMConfigDataPrivate *priv = NM_CONFIG_DATA_GET_PRIVATE (base); + + return g_object_new (NM_TYPE_CONFIG_DATA, + NM_CONFIG_DATA_CONFIG_MAIN_FILE, priv->config_main_file, + NM_CONFIG_DATA_CONFIG_DESCRIPTION, priv->config_description, + NM_CONFIG_DATA_KEYFILE_USER, priv->keyfile_user, /* the keyfile is unchanged. It's safe to share it. */ + NM_CONFIG_DATA_KEYFILE_INTERN, keyfile_intern, + NM_CONFIG_DATA_NO_AUTO_DEFAULT, priv->no_auto_default.arr, + NULL); +} + +NMConfigData * nm_config_data_new_update_no_auto_default (const NMConfigData *base, const char *const*no_auto_default) { @@ -683,7 +831,8 @@ nm_config_data_new_update_no_auto_default (const NMConfigData *base, return g_object_new (NM_TYPE_CONFIG_DATA, NM_CONFIG_DATA_CONFIG_MAIN_FILE, priv->config_main_file, NM_CONFIG_DATA_CONFIG_DESCRIPTION, priv->config_description, - NM_CONFIG_DATA_KEYFILE, priv->keyfile, /* the keyfile is unchanged. It's safe to share it. */ + NM_CONFIG_DATA_KEYFILE_USER, priv->keyfile_user, /* the keyfile is unchanged. It's safe to share it. */ + NM_CONFIG_DATA_KEYFILE_INTERN, priv->keyfile_intern, NM_CONFIG_DATA_NO_AUTO_DEFAULT, no_auto_default, NULL); } @@ -718,8 +867,16 @@ nm_config_data_class_init (NMConfigDataClass *config_class) G_PARAM_STATIC_STRINGS)); g_object_class_install_property - (object_class, PROP_KEYFILE, - g_param_spec_boxed (NM_CONFIG_DATA_KEYFILE, "", "", + (object_class, PROP_KEYFILE_USER, + g_param_spec_boxed (NM_CONFIG_DATA_KEYFILE_USER, "", "", + G_TYPE_KEY_FILE, + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_KEYFILE_INTERN, + g_param_spec_boxed (NM_CONFIG_DATA_KEYFILE_INTERN, "", "", G_TYPE_KEY_FILE, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | diff --git a/src/nm-config-data.h b/src/nm-config-data.h index bd26b9dfbb..d061583540 100644 --- a/src/nm-config-data.h +++ b/src/nm-config-data.h @@ -38,7 +38,8 @@ G_BEGIN_DECLS #define NM_CONFIG_DATA_CONFIG_MAIN_FILE "config-main-file" #define NM_CONFIG_DATA_CONFIG_DESCRIPTION "config-description" -#define NM_CONFIG_DATA_KEYFILE "keyfile" +#define NM_CONFIG_DATA_KEYFILE_USER "keyfile-user" +#define NM_CONFIG_DATA_KEYFILE_INTERN "keyfile-intern" #define NM_CONFIG_DATA_CONNECTIVITY_URI "connectivity-uri" #define NM_CONFIG_DATA_CONNECTIVITY_INTERVAL "connectivity-interval" #define NM_CONFIG_DATA_CONNECTIVITY_RESPONSE "connectivity-response" @@ -71,10 +72,12 @@ typedef enum { /*< flags >*/ NM_CONFIG_CHANGE_CONFIG_FILES = (1L << 3), NM_CONFIG_CHANGE_VALUES = (1L << 4), - NM_CONFIG_CHANGE_CONNECTIVITY = (1L << 5), - NM_CONFIG_CHANGE_NO_AUTO_DEFAULT = (1L << 6), - NM_CONFIG_CHANGE_DNS_MODE = (1L << 7), - NM_CONFIG_CHANGE_RC_MANAGER = (1L << 8), + NM_CONFIG_CHANGE_VALUES_USER = (1L << 5), + NM_CONFIG_CHANGE_VALUES_INTERN = (1L << 6), + NM_CONFIG_CHANGE_CONNECTIVITY = (1L << 7), + NM_CONFIG_CHANGE_NO_AUTO_DEFAULT = (1L << 8), + NM_CONFIG_CHANGE_DNS_MODE = (1L << 9), + NM_CONFIG_CHANGE_RC_MANAGER = (1L << 10), _NM_CONFIG_CHANGE_LAST, NM_CONFIG_CHANGE_ALL = ((_NM_CONFIG_CHANGE_LAST - 1) << 1) - 1, @@ -93,7 +96,9 @@ GType nm_config_data_get_type (void); NMConfigData *nm_config_data_new (const char *config_main_file, const char *config_description, const char *const*no_auto_default, - GKeyFile *keyfile); + GKeyFile *keyfile_user, + GKeyFile *keyfile_intern); +NMConfigData *nm_config_data_new_update_keyfile_intern (const NMConfigData *base, GKeyFile *keyfile_intern); NMConfigData *nm_config_data_new_update_no_auto_default (const NMConfigData *base, const char *const*no_auto_default); NMConfigChangeFlags nm_config_data_diff (NMConfigData *old_data, NMConfigData *new_data); @@ -128,6 +133,13 @@ char *nm_config_data_get_connection_default (const NMConfigData *self, char **nm_config_data_get_groups (const NMConfigData *self); char **nm_config_data_get_keys (const NMConfigData *self, const char *group); +GKeyFile *nm_config_data_clone_keyfile_intern (const NMConfigData *self); + +/* private accessors */ +GKeyFile *_nm_config_data_get_keyfile (const NMConfigData *self); +GKeyFile *_nm_config_data_get_keyfile_user (const NMConfigData *self); +GKeyFile *_nm_config_data_get_keyfile_intern (const NMConfigData *self); + G_END_DECLS #endif /* NM_CONFIG_DATA_H */ diff --git a/src/nm-config.c b/src/nm-config.c index 9e49905954..0c36f7a773 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -33,6 +33,7 @@ #include "gsystem-local-alloc.h" #include "nm-enum-types.h" #include "nm-core-internal.h" +#include "nm-keyfile-internal.h" #include <gio/gio.h> #include <glib/gi18n.h> @@ -42,9 +43,11 @@ #define DEFAULT_CONFIG_MAIN_FILE_OLD NMCONFDIR "/nm-system-settings.conf" #define DEFAULT_SYSTEM_CONFIG_DIR NMLIBDIR "/conf.d" #define DEFAULT_NO_AUTO_DEFAULT_FILE NMSTATEDIR "/no-auto-default.state" +#define DEFAULT_INTERN_CONFIG_FILE NMSTATEDIR "/NetworkManager-intern.conf" struct NMConfigCmdLineOptions { char *config_main_file; + char *intern_config_file; char *config_dir; char *system_config_dir; char *no_auto_default_file; @@ -68,6 +71,7 @@ typedef struct { char *config_dir; char *system_config_dir; char *no_auto_default_file; + char *intern_config_file; char **plugins; gboolean monitor_connection_files; @@ -111,6 +115,14 @@ static void _set_config_data (NMConfig *self, NMConfigData *new_data, int signal /************************************************************************/ +#define _HAS_PREFIX(str, prefix) \ + ({ \ + const char *_str = (str); \ + g_str_has_prefix ( _str, ""prefix"") && _str[STRLEN(prefix)] != '\0'; \ + }) + +/************************************************************************/ + gint nm_config_parse_boolean (const char *str, gint default_value) @@ -362,7 +374,7 @@ nm_config_get_no_auto_default_for_device (NMConfig *self, NMDevice *device) void nm_config_set_no_auto_default_for_device (NMConfig *self, NMDevice *device) { - NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (self); + NMConfigPrivate *priv; GError *error = NULL; NMConfigData *new_data = NULL; const char *hw_address; @@ -373,6 +385,8 @@ nm_config_set_no_auto_default_for_device (NMConfig *self, NMDevice *device) g_return_if_fail (NM_IS_CONFIG (self)); g_return_if_fail (NM_IS_DEVICE (device)); + priv = NM_CONFIG_GET_PRIVATE (self); + hw_address = nm_device_get_hw_address (device); no_auto_default_current = nm_config_data_get_no_auto_default (priv->config_data); @@ -412,6 +426,7 @@ _nm_config_cmd_line_options_clear (NMConfigCmdLineOptions *cli) g_clear_pointer (&cli->config_dir, g_free); g_clear_pointer (&cli->system_config_dir, g_free); g_clear_pointer (&cli->no_auto_default_file, g_free); + g_clear_pointer (&cli->intern_config_file, g_free); g_clear_pointer (&cli->plugins, g_free); cli->configure_and_quit = FALSE; g_clear_pointer (&cli->connectivity_uri, g_free); @@ -431,6 +446,7 @@ _nm_config_cmd_line_options_copy (const NMConfigCmdLineOptions *cli, NMConfigCmd dst->system_config_dir = g_strdup (cli->system_config_dir); dst->config_main_file = g_strdup (cli->config_main_file); dst->no_auto_default_file = g_strdup (cli->no_auto_default_file); + dst->intern_config_file = g_strdup (cli->intern_config_file); dst->plugins = g_strdup (cli->plugins); dst->configure_and_quit = cli->configure_and_quit; dst->connectivity_uri = g_strdup (cli->connectivity_uri); @@ -468,6 +484,7 @@ nm_config_cmd_line_options_add_to_entries (NMConfigCmdLineOptions *cli, { "config", 0, 0, G_OPTION_ARG_FILENAME, &cli->config_main_file, N_("Config file location"), N_(DEFAULT_CONFIG_MAIN_FILE) }, { "config-dir", 0, 0, G_OPTION_ARG_FILENAME, &cli->config_dir, N_("Config directory location"), N_(DEFAULT_CONFIG_DIR) }, { "system-config-dir", 0, 0, G_OPTION_ARG_FILENAME, &cli->system_config_dir, N_("System config directory location"), N_(DEFAULT_SYSTEM_CONFIG_DIR) }, + { "intern-config", 0, 0, G_OPTION_ARG_FILENAME, &cli->intern_config_file, N_("Internal config file location"), N_(DEFAULT_INTERN_CONFIG_FILE) }, { "no-auto-default", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_FILENAME, &cli->no_auto_default_file, N_("State file for no-auto-default devices"), N_(DEFAULT_NO_AUTO_DEFAULT_FILE) }, { "plugins", 0, 0, G_OPTION_ARG_STRING, &cli->plugins, N_("List of plugins separated by ','"), N_(CONFIG_PLUGINS_DEFAULT) }, { "configure-and-quit", 0, 0, G_OPTION_ARG_NONE, &cli->configure_and_quit, N_("Quit after initial configuration"), NULL }, @@ -534,6 +551,18 @@ _sort_groups_cmp (const char **pa, const char **pb, gpointer dummy) return pa > pb ? -1 : 1; } +void +_nm_config_sort_groups (char **groups, gsize ngroups) +{ + if (ngroups > 1) { + g_qsort_with_data (groups, + ngroups, + sizeof (char *), + (GCompareDataFunc) _sort_groups_cmp, + NULL); + } +} + static gboolean _setting_is_device_spec (const char *group, const char *key) { @@ -599,17 +628,15 @@ read_config (GKeyFile *keyfile, const char *dirname, const char *path, GError ** * At the very end, we will revert the order of all sections again and * get thus the right behavior. This final reversing is done in * NMConfigData:_get_connection_infos(). */ - if (ngroups > 1) { - g_qsort_with_data (groups, - ngroups, - sizeof (char *), - (GCompareDataFunc) _sort_groups_cmp, - NULL); - } + _nm_config_sort_groups (groups, ngroups); for (g = 0; groups[g]; g++) { const char *group = groups[g]; + if (g_str_has_prefix (group, NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN)) { + /* internal groups cannot be set by user configuration. */ + continue; + } keys = g_key_file_get_keys (kf, group, &nkeys, NULL); if (!keys) continue; @@ -621,6 +648,13 @@ read_config (GKeyFile *keyfile, const char *dirname, const char *path, GError ** key = keys[k]; g_assert (key && *key); + + if ( _HAS_PREFIX (key, NM_CONFIG_KEYFILE_KEYPREFIX_WAS) + || _HAS_PREFIX (key, NM_CONFIG_KEYFILE_KEYPREFIX_SET)) { + /* these keys are protected. We ignore them if the user sets them. */ + continue; + } + key_len = strlen (key); last_char = key[key_len - 1]; if ( key_len > 1 @@ -832,8 +866,8 @@ read_entire_config (const NMConfigCmdLineOptions *cli, g_return_val_if_fail (config_dir, NULL); g_return_val_if_fail (system_config_dir, NULL); - g_return_val_if_fail (out_config_main_file && !*out_config_main_file, FALSE); - g_return_val_if_fail (out_config_description && !*out_config_description, NULL); + g_return_val_if_fail (!out_config_main_file || !*out_config_main_file, FALSE); + g_return_val_if_fail (!out_config_description || !*out_config_description, NULL); g_return_val_if_fail (!error || !*error, FALSE); /* create a default configuration file. */ @@ -916,13 +950,310 @@ read_entire_config (const NMConfigCmdLineOptions *cli, g_string_append (str, ")"); } - *out_config_main_file = o_config_main_file; - *out_config_description = g_string_free (str, FALSE); + if (out_config_main_file) + *out_config_main_file = o_config_main_file; + else + g_free (o_config_main_file); + if (out_config_description) + *out_config_description = g_string_free (str, FALSE); + else + g_string_free (str, TRUE); o_config_main_file = NULL; return keyfile; } +/** + * intern_config_read: + * @filename: the filename where to store the internal config + * @keyfile_conf: the merged configuration from user (/etc/NM/NetworkManager.conf). + * @out_needs_rewrite: (allow-none): whether the read keyfile contains inconsistent + * data (compared to @keyfile_conf). If %TRUE, you might want to rewrite + * the file. + * + * Does the opposite of intern_config_write(). It reads the internal configuration. + * Note that the actual format of how the configuration is saved in @filename + * is different then what we return here. NMConfig manages what is written internally + * by having it inside a keyfile_intern. But we don't write that to disk as is. + * Especially, we also store parts of @keyfile_conf as ".was" and on read we compare + * what we have, with what ".was". + * + * Returns: a #GKeyFile instance with the internal configuration. + */ +static GKeyFile * +intern_config_read (const char *filename, + GKeyFile *keyfile_conf, + gboolean *out_needs_rewrite) +{ + GKeyFile *keyfile_intern; + GKeyFile *keyfile; + gboolean needs_rewrite = FALSE; + gs_strfreev char **groups = NULL; + guint g, k; + gboolean has_intern = FALSE; + + g_return_val_if_fail (filename, NULL); + + if (!*filename) { + if (out_needs_rewrite) + *out_needs_rewrite = FALSE; + return NULL; + } + + keyfile_intern = nm_config_create_keyfile (); + + keyfile = nm_config_create_keyfile (); + if (!g_key_file_load_from_file (keyfile, filename, G_KEY_FILE_NONE, NULL)) { + needs_rewrite = TRUE; + goto out; + } + + groups = g_key_file_get_groups (keyfile, NULL); + for (g = 0; groups && groups[g]; g++) { + gs_strfreev char **keys = NULL; + const char *group = groups[g]; + gboolean is_intern; + + keys = g_key_file_get_keys (keyfile, group, NULL, NULL); + if (!keys) + continue; + + is_intern = g_str_has_prefix (group, NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN); + + for (k = 0; keys[k]; k++) { + gs_free char *value_set = NULL; + const char *key = keys[k]; + + value_set = g_key_file_get_value (keyfile, group, key, NULL); + + if (is_intern) { + has_intern = TRUE; + g_key_file_set_value (keyfile_intern, group, key, value_set); + } else if (_HAS_PREFIX (key, NM_CONFIG_KEYFILE_KEYPREFIX_SET)) { + const char *key_base = &key[STRLEN (NM_CONFIG_KEYFILE_KEYPREFIX_SET)]; + gs_free char *value_was = NULL; + gs_free char *value_conf = NULL; + gs_free char *key_was = g_strdup_printf (NM_CONFIG_KEYFILE_KEYPREFIX_WAS"%s", key_base); + + if (keyfile_conf) + value_conf = g_key_file_get_value (keyfile_conf, group, key_base, NULL); + value_was = g_key_file_get_value (keyfile, group, key_was, NULL); + + if (g_strcmp0 (value_conf, value_was) != 0) { + /* if value_was is no longer the same as @value_conf, it means the user + * changed the configuration since the last write. In this case, we + * drop the value. It also means our file is out-of-date, and we should + * rewrite it. */ + needs_rewrite = TRUE; + continue; + } + has_intern = TRUE; + g_key_file_set_value (keyfile_intern, group, key_base, value_set); + } else if (_HAS_PREFIX (key, NM_CONFIG_KEYFILE_KEYPREFIX_WAS)) { + const char *key_base = &key[STRLEN (NM_CONFIG_KEYFILE_KEYPREFIX_WAS)]; + gs_free char *key_set = g_strdup_printf (NM_CONFIG_KEYFILE_KEYPREFIX_SET"%s", key_base); + gs_free char *value_was = NULL; + gs_free char *value_conf = NULL; + + if (g_key_file_has_key (keyfile, group, key_set, NULL)) { + /* we have a matching "set" key too. Handle the "was" key there. */ + continue; + } + + if (keyfile_conf) + value_conf = g_key_file_get_value (keyfile_conf, group, key_base, NULL); + value_was = g_key_file_get_value (keyfile, group, key, NULL); + + if (g_strcmp0 (value_conf, value_was) != 0) { + /* if value_was is no longer the same as @value_conf, it means the user + * changed the configuration since the last write. In this case, we + * don't overwrite the user-provided value. It also means our file is + * out-of-date, and we should rewrite it. */ + needs_rewrite = TRUE; + continue; + } + has_intern = TRUE; + /* signal the absence of the value. That means, we must propagate the + * "was" key to NMConfigData, so that it knows to hide the corresponding + * user key. */ + g_key_file_set_value (keyfile_intern, group, key, ""); + } else + needs_rewrite = TRUE; + } + } + +out: + g_key_file_unref (keyfile); + + if (out_needs_rewrite) + *out_needs_rewrite = needs_rewrite; + + nm_log_dbg (LOGD_CORE, "intern config file \"%s\"", filename); + + if (!has_intern) { + g_key_file_unref (keyfile_intern); + return NULL; + } + return keyfile_intern; +} + +static int +_intern_config_write_sort_fcn (const char **a, const char **b, gpointer dummy) +{ + const char *g_a = (a ? *a : NULL); + const char *g_b = (b ? *b : NULL); + gboolean a_is, b_is; + + a_is = g_str_has_prefix (g_a, NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN); + b_is = g_str_has_prefix (g_b, NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN); + + if (a_is != b_is) { + if (a_is) + return 1; + return -1; + } + return g_strcmp0 (g_a, g_b); +} + +static gboolean +intern_config_write (const char *filename, + GKeyFile *keyfile_intern, + GKeyFile *keyfile_conf, + GError **error) +{ + GKeyFile *keyfile; + gs_strfreev char **groups = NULL; + guint g, k; + gboolean has_intern = FALSE; + gboolean success = FALSE; + GError *local = NULL; + + g_return_val_if_fail (filename, FALSE); + + if (!*filename) { + g_set_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND, "no filename to write (use --intern-config?)"); + return FALSE; + } + + keyfile = nm_config_create_keyfile (); + + if (keyfile_intern) { + groups = g_key_file_get_groups (keyfile_intern, NULL); + if (groups && groups[0]) { + g_qsort_with_data (groups, + g_strv_length (groups), + sizeof (char *), + (GCompareDataFunc) _intern_config_write_sort_fcn, + NULL); + } + } + for (g = 0; groups && groups[g]; g++) { + gs_strfreev char **keys = NULL; + const char *group = groups[g]; + gboolean is_intern; + + keys = g_key_file_get_keys (keyfile_intern, group, NULL, NULL); + if (!keys) + continue; + + is_intern = g_str_has_prefix (group, NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN); + + for (k = 0; keys[k]; k++) { + const char *key = keys[k]; + gs_free char *value_set = NULL; + gs_free char *key_set = NULL; + + value_set = g_key_file_get_value (keyfile_intern, group, key, NULL); + + if (is_intern) { + has_intern = TRUE; + g_key_file_set_value (keyfile, group, key, value_set); + } else { + gs_free char *value_was = NULL; + + if (_HAS_PREFIX (key, NM_CONFIG_KEYFILE_KEYPREFIX_SET)) { + /* Setting a key with .set prefix has no meaning, as these keys + * are protected. Just set the value you want to set instead. + * Why did this happen?? */ + g_warn_if_reached (); + } else if (_HAS_PREFIX (key, NM_CONFIG_KEYFILE_KEYPREFIX_WAS)) { + const char *key_base = &key[STRLEN (NM_CONFIG_KEYFILE_KEYPREFIX_WAS)]; + + if ( _HAS_PREFIX (key_base, NM_CONFIG_KEYFILE_KEYPREFIX_SET) + || _HAS_PREFIX (key_base, NM_CONFIG_KEYFILE_KEYPREFIX_WAS)) { + g_warn_if_reached (); + continue; + } + + if (g_key_file_has_key (keyfile_intern, group, key_base, NULL)) { + /* There is also a matching key_base entry. Skip processing + * the .was. key ad handle the key_base in the other else branch. */ + continue; + } + + if (keyfile_conf) { + value_was = g_key_file_get_value (keyfile_conf, group, key_base, NULL); + if (value_was) + g_key_file_set_value (keyfile, group, key, value_was); + } + } else { + if (keyfile_conf) { + value_was = g_key_file_get_value (keyfile_conf, group, key, NULL); + if (g_strcmp0 (value_set, value_was) == 0) { + /* there is no point in storing the identical value as we have via + * user configuration. Skip it. */ + continue; + } + if (value_was) { + gs_free char *key_was = NULL; + + key_was = g_strdup_printf (NM_CONFIG_KEYFILE_KEYPREFIX_WAS"%s", key); + g_key_file_set_value (keyfile, group, key_was, value_was); + } + } + key = key_set = g_strdup_printf (NM_CONFIG_KEYFILE_KEYPREFIX_SET"%s", key); + g_key_file_set_value (keyfile, group, key, value_set); + } + } + } + if ( is_intern + && g_key_file_has_group (keyfile, group)) { + g_key_file_set_comment (keyfile, group, NULL, + " Internal section. Not overwritable via user configuration in 'NetworkManager.conf'", + NULL); + } + } + + g_key_file_set_comment (keyfile, NULL, NULL, + " Internal configuration file. This file is written and read\n" + " by NetworkManager and its configuration values are merged\n" + " with the configuration from 'NetworkManager.conf'.\n" + "\n" + " Keys with a \""NM_CONFIG_KEYFILE_KEYPREFIX_SET"\" prefix specify the value to set.\n" + " A corresponding key with a \""NM_CONFIG_KEYFILE_KEYPREFIX_WAS"\" prefix records the value\n" + " of the user configuration at the time of storing the file.\n" + " The value from internal configuration is rejected if the corresponding\n" + " \""NM_CONFIG_KEYFILE_KEYPREFIX_WAS"\" key no longer matches the configuration from 'NetworkManager.conf'.\n" + " That means, if you modify a value in 'NetworkManager.conf', the internal\n" + " overwrite no longer matches and is ignored.\n" + "\n" + " Internal sections of the form [" NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN "*] cannot\n" + " be set by user configuration.\n" + "\n" + " CHANGES TO THIS FILE WILL BE OVERWRITTEN", + NULL); + + success = g_key_file_save_to_file (keyfile, filename, &local); + + nm_log_dbg (LOGD_CORE, "write intern config file \"%s\"%s%s", filename, success ? "" : ": ", success ? "" : local->message); + g_key_file_unref (keyfile); + if (!success) + g_propagate_error (error, local); + return success; +} + +/************************************************************************/ + GSList * nm_config_get_device_match_spec (const GKeyFile *keyfile, const char *group, const char *key, gboolean *out_has_key) { @@ -939,16 +1270,97 @@ nm_config_get_device_match_spec (const GKeyFile *keyfile, const char *group, con /************************************************************************/ +/** + * nm_config_set_values: + * @self: the NMConfig instance + * @keyfile_intern_new: (allow-none): the new internal settings to set. + * If %NULL, it is equal to an empty keyfile. + * @allow_write: only if %TRUE, allow writing the changes to file. Otherwise, + * do the changes in-memory only. + * @force_rewrite: if @allow_write is %FALSE, this has no effect. If %FALSE, + * only write the configuration to file, if there are any actual changes. + * If %TRUE, always write the configuration to file, even if tere are seemingly + * no changes. + * + * This is the most flexible function to set values. It all depends on the + * keys and values you set in @keyfile_intern_new. You basically reset all + * internal configuration values to what is in @keyfile_intern_new. + * + * There are 2 types of settings: + * - all groups/sections with a prefix [.intern.*] are taken as is. As these + * groups are separate from user configuration, there is no conflict. You set + * them, that's it. + * - otherwise you can overwrite individual values from user-configuration. + * Just set the value. Keys with a prefix NM_CONFIG_KEYFILE_KEYPREFIX_* + * are protected -- as they are not value user keys. + * You can also hide a certain user setting by putting only a key + * NM_CONFIG_KEYFILE_KEYPREFIX_WAS"keyname" into the keyfile. + */ +void +nm_config_set_values (NMConfig *self, + GKeyFile *keyfile_intern_new, + gboolean allow_write, + gboolean force_rewrite) +{ + NMConfigPrivate *priv; + GKeyFile *keyfile_intern_current; + GKeyFile *keyfile_user; + GKeyFile *keyfile_new; + GError *local = NULL; + NMConfigData *new_data = NULL; + + g_return_if_fail (NM_IS_CONFIG (self)); + + priv = NM_CONFIG_GET_PRIVATE (self); + + keyfile_intern_current = _nm_config_data_get_keyfile_intern (priv->config_data); + + keyfile_new = nm_config_create_keyfile (); + if (keyfile_intern_new) + _nm_keyfile_copy (keyfile_new, keyfile_intern_new); + + if (!_nm_keyfile_equals (keyfile_intern_current, keyfile_new, TRUE)) + new_data = nm_config_data_new_update_keyfile_intern (priv->config_data, keyfile_new); + + nm_log_dbg (LOGD_CORE, "set values(): %s", new_data ? "has changes" : "no changes"); + + if (allow_write + && (new_data || force_rewrite)) { + /* We write the internal config file based on the user configuration from + * the last load/reload. That is correct, because the intern properties might + * be in accordance to what NM thinks is currently configured. Even if the files + * on disk changed in the meantime. + * But if they changed, on the next reload with might throw away our just + * written data. That is correct, because from NM's point of view, those + * changes on disk happened in any case *after* now. */ + if (*priv->intern_config_file) { + keyfile_user = _nm_config_data_get_keyfile_user (priv->config_data); + if (!intern_config_write (priv->intern_config_file, keyfile_new, keyfile_user, &local)) { + nm_log_warn (LOGD_CORE, "error saving internal configuration \"%s\": %s", priv->intern_config_file, local->message); + g_clear_error (&local); + } + } else + nm_log_dbg (LOGD_CORE, "don't persistate internal configuration (no file set, use --intern-config?)"); + } + if (new_data) + _set_config_data (self, new_data, 0); + + g_key_file_unref (keyfile_new); +} + +/************************************************************************/ + void nm_config_reload (NMConfig *self, int signal) { NMConfigPrivate *priv; GError *error = NULL; - GKeyFile *keyfile; + GKeyFile *keyfile, *keyfile_intern; NMConfigData *new_data = NULL; char *config_main_file = NULL; char *config_description = NULL; gs_strfreev char **no_auto_default = NULL; + gboolean intern_config_needs_rewrite; g_return_if_fail (NM_IS_CONFIG (self)); @@ -975,12 +1387,19 @@ nm_config_reload (NMConfig *self, int signal) _set_config_data (self, NULL, signal); return; } + no_auto_default = no_auto_default_from_file (priv->no_auto_default_file); - new_data = nm_config_data_new (config_main_file, config_description, (const char *const*) no_auto_default, keyfile); + keyfile_intern = intern_config_read (priv->intern_config_file, keyfile, &intern_config_needs_rewrite); + if (intern_config_needs_rewrite) + intern_config_write (priv->intern_config_file, keyfile_intern, keyfile, NULL); + + new_data = nm_config_data_new (config_main_file, config_description, (const char *const*) no_auto_default, keyfile, keyfile_intern); g_free (config_main_file); g_free (config_description); g_key_file_unref (keyfile); + if (keyfile_intern) + g_key_file_unref (keyfile_intern); _set_config_data (self, new_data, signal); } @@ -999,6 +1418,10 @@ _change_flags_one_to_string (NMConfigChangeFlags flag) return "config-files"; case NM_CONFIG_CHANGE_VALUES: return "values"; + case NM_CONFIG_CHANGE_VALUES_USER: + return "values-user"; + case NM_CONFIG_CHANGE_VALUES_INTERN: + return "values-intern"; case NM_CONFIG_CHANGE_CONNECTIVITY: return "connectivity"; case NM_CONFIG_CHANGE_NO_AUTO_DEFAULT: @@ -1107,10 +1530,11 @@ init_sync (GInitable *initable, GCancellable *cancellable, GError **error) { NMConfig *self = NM_CONFIG (initable); NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (self); - GKeyFile *keyfile; + GKeyFile *keyfile, *keyfile_intern; char *config_main_file = NULL; char *config_description = NULL; gs_strfreev char **no_auto_default = NULL; + gboolean intern_config_needs_rewrite; if (priv->config_dir) { /* Object is already initialized. */ @@ -1137,6 +1561,11 @@ init_sync (GInitable *initable, GCancellable *cancellable, GError **error) priv->system_config_dir = g_strdup (""); } + if (priv->cli.intern_config_file) + priv->intern_config_file = g_strdup (priv->cli.intern_config_file); + else + priv->intern_config_file = g_strdup (DEFAULT_INTERN_CONFIG_FILE); + keyfile = read_entire_config (&priv->cli, priv->config_dir, priv->system_config_dir, @@ -1173,13 +1602,19 @@ init_sync (GInitable *initable, GCancellable *cancellable, GError **error) no_auto_default = no_auto_default_from_file (priv->no_auto_default_file); - priv->config_data_orig = nm_config_data_new (config_main_file, config_description, (const char *const*) no_auto_default, keyfile); + keyfile_intern = intern_config_read (priv->intern_config_file, keyfile, &intern_config_needs_rewrite); + if (intern_config_needs_rewrite) + intern_config_write (priv->intern_config_file, keyfile_intern, keyfile, NULL); + + priv->config_data_orig = nm_config_data_new (config_main_file, config_description, (const char *const*) no_auto_default, keyfile, keyfile_intern); priv->config_data = g_object_ref (priv->config_data_orig); g_free (config_main_file); g_free (config_description); g_key_file_unref (keyfile); + if (keyfile_intern) + g_key_file_unref (keyfile_intern); return TRUE; } @@ -1209,6 +1644,7 @@ finalize (GObject *gobject) g_free (priv->config_dir); g_free (priv->system_config_dir); g_free (priv->no_auto_default_file); + g_free (priv->intern_config_file); g_strfreev (priv->plugins); g_free (priv->dhcp_client); g_free (priv->log_level); diff --git a/src/nm-config.h b/src/nm-config.h index 5b096f165d..d4ff887ba3 100644 --- a/src/nm-config.h +++ b/src/nm-config.h @@ -48,6 +48,7 @@ G_BEGIN_DECLS #define NM_CONFIG_KEYFILE_LIST_SEPARATOR ',' +#define NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN ".intern." #define NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION "connection" #define NM_CONFIG_KEYFILE_GROUPPREFIX_TEST_APPEND_STRINGLIST ".test-append-stringlist" @@ -63,6 +64,9 @@ G_BEGIN_DECLS #define NM_CONFIG_KEYFILE_KEY_IFNET_MANAGED "managed" #define NM_CONFIG_KEYFILE_KEY_IFUPDOWN_MANAGED "managed" +#define NM_CONFIG_KEYFILE_KEYPREFIX_WAS ".was." +#define NM_CONFIG_KEYFILE_KEYPREFIX_SET ".set." + typedef struct NMConfigCmdLineOptions NMConfigCmdLineOptions; struct _NMConfig { @@ -97,6 +101,11 @@ const char *nm_config_get_log_domains (NMConfig *config); const char *nm_config_get_debug (NMConfig *config); gboolean nm_config_get_configure_and_quit (NMConfig *config); +void nm_config_set_values (NMConfig *self, + GKeyFile *keyfile_intern_new, + gboolean allow_write, + gboolean force_rewrite); + /* for main.c only */ NMConfigCmdLineOptions *nm_config_cmd_line_options_new (void); void nm_config_cmd_line_options_free (NMConfigCmdLineOptions *cli); @@ -128,6 +137,8 @@ void nm_config_keyfile_set_string_list (GKeyFile *keyfile, gssize len); GSList *nm_config_get_device_match_spec (const GKeyFile *keyfile, const char *group, const char *key, gboolean *out_has_key); +void _nm_config_sort_groups (char **groups, gsize ngroups); + G_END_DECLS #endif /* __NETWORKMANAGER_CONFIG_H__ */ diff --git a/src/tests/config/test-config.c b/src/tests/config/test-config.c index bc4944e021..82fb73dad2 100644 --- a/src/tests/config/test-config.c +++ b/src/tests/config/test-config.c @@ -33,7 +33,7 @@ #include "nm-test-utils.h" static NMConfig * -setup_config (GError **error, const char *config_file, const char *config_dir, const char *system_config_dir, ...) +setup_config (GError **error, const char *config_file, const char *intern_config, const char *config_dir, const char *system_config_dir, ...) { va_list ap; GPtrArray *args; @@ -51,6 +51,10 @@ setup_config (GError **error, const char *config_file, const char *config_dir, c g_ptr_array_add (args, "test-config"); g_ptr_array_add (args, "--config"); g_ptr_array_add (args, (char *)config_file); + if (intern_config) { + g_ptr_array_add (args, "--intern-config"); + g_ptr_array_add (args, (char *)intern_config); + } g_ptr_array_add (args, "--config-dir"); g_ptr_array_add (args, (char *)config_dir); if (system_config_dir) { @@ -101,7 +105,7 @@ test_config_simple (void) gs_unref_object NMDevice *dev51 = nm_test_device_new ("00:00:00:00:00:51"); gs_unref_object NMDevice *dev52 = nm_test_device_new ("00:00:00:00:00:52"); - config = setup_config (NULL, SRCDIR "/NetworkManager.conf", "/no/such/dir", "", NULL); + config = setup_config (NULL, SRCDIR "/NetworkManager.conf", "", "/no/such/dir", "", NULL); g_assert_cmpstr (nm_config_data_get_config_main_file (nm_config_get_data_orig (config)), ==, SRCDIR "/NetworkManager.conf"); g_assert_cmpstr (nm_config_get_dhcp_client (config), ==, "dhclient"); @@ -180,7 +184,7 @@ test_config_non_existent (void) { GError *error = NULL; - setup_config (&error, SRCDIR "/no-such-file", "/no/such/dir", "", NULL); + setup_config (&error, SRCDIR "/no-such-file", "", "/no/such/dir", "", NULL); g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND); g_clear_error (&error); } @@ -190,7 +194,7 @@ test_config_parse_error (void) { GError *error = NULL; - setup_config (&error, SRCDIR "/bad.conf", "/no/such/dir", "", NULL); + setup_config (&error, SRCDIR "/bad.conf", "", "/no/such/dir", "", NULL); g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_PARSE); g_clear_error (&error); } @@ -201,7 +205,7 @@ test_config_override (void) NMConfig *config; const char **plugins; - config = setup_config (NULL, SRCDIR "/NetworkManager.conf", "/no/such/dir", "", + config = setup_config (NULL, SRCDIR "/NetworkManager.conf", "", "/no/such/dir", "", "--plugins", "alpha,beta,gamma,delta", "--connectivity-interval", "12", NULL); @@ -239,7 +243,7 @@ test_config_no_auto_default (void) g_assert_cmpint (nwrote, ==, 18); close (fd); - config = setup_config (NULL, SRCDIR "/NetworkManager.conf", "/no/such/dir", "", + config = setup_config (NULL, SRCDIR "/NetworkManager.conf", "", "/no/such/dir", "", "--no-auto-default", state_file, NULL); @@ -261,7 +265,7 @@ test_config_no_auto_default (void) g_object_unref (config); - config = setup_config (NULL, SRCDIR "/NetworkManager.conf", "/no/such/dir", "", + config = setup_config (NULL, SRCDIR "/NetworkManager.conf", "", "/no/such/dir", "", "--no-auto-default", state_file, NULL); @@ -289,7 +293,7 @@ test_config_confdir (void) char *value; GSList *specs; - config = setup_config (NULL, SRCDIR "/NetworkManager.conf", SRCDIR "/conf.d", "", NULL); + config = setup_config (NULL, SRCDIR "/NetworkManager.conf", "", SRCDIR "/conf.d", "", NULL); g_assert_cmpstr (nm_config_data_get_config_main_file (nm_config_get_data_orig (config)), ==, SRCDIR "/NetworkManager.conf"); g_assert_cmpstr (nm_config_get_dhcp_client (config), ==, "dhcpcd"); @@ -395,7 +399,7 @@ test_config_confdir_parse_error (void) GError *error = NULL; /* Using SRCDIR as the conf dir will pick up bad.conf */ - setup_config (&error, SRCDIR "/NetworkManager.conf", SRCDIR, "", NULL); + setup_config (&error, SRCDIR "/NetworkManager.conf", "", SRCDIR, "", NULL); g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_PARSE); g_clear_error (&error); } |