config: parse $nmconfdir/conf.d/*.conf

Add a new configuration directory ($nmconfdir/conf.d by default,
overridable via the --config-dir command-line option) that can contain
".conf" files that will be parsed in asciibetical order to override
the main NetworkManager.conf file.

In addition to simple overrides, the conf files also support appending
to the value of a previously-set list-valued key, by doing, eg,
"plugins+=foo"

https://bugzilla.gnome.org/show_bug.cgi?id=688857
This commit is contained in:
Dan Winship 2013-03-14 14:34:36 -04:00
parent 0186330a4b
commit a2308fcab8
8 changed files with 325 additions and 119 deletions

View file

@ -10,7 +10,7 @@ NetworkManager \- network management daemon
.SH SYNOPSIS
.B NetworkManager [\-\-version] | [\-\-help]
.PP
.B NetworkManager [\-\-no\-daemon] [\-\-pid\-file=<filename>] [\-\-state\-file=<filename>] [\-\-config=<filename>] [\-\-plugins=<plugin1>,plugin2>,...] [\-\-log\-level=<level>] [\-\-log\-domains=<domain1>,<domain2>,...]
.B NetworkManager [\-\-no\-daemon] [\-\-pid\-file=<filename>] [\-\-state\-file=<filename>] [\-\-config=<filename>] [\-\-config-dir=<directory>] [\-\-plugins=<plugin1>,plugin2>,...] [\-\-log\-level=<level>] [\-\-log\-domains=<domain1>,<domain2>,...]
.SH DESCRIPTION
The \fINetworkManager\fP daemon attempts to make networking configuration and
operation as painless and automatic as possible by managing the primary network
@ -102,6 +102,12 @@ the same directory; where <SYSCONFDIR> is dependent on your distribution (usuall
it's /etc). See \fBNetworkManager.conf\fP(5) for more information on configuration
file.
.TP
.I "\-\-config-dir=<directory>"
Specify configuration directory for files that override NetworkManager.conf. If not
specified, the default value of '<SYSCONFDIR>/NetworkManager/conf.d'
is used. See \fBNetworkManager.conf\fP(5) for more information on configuration
file.
.TP
.I "\-\-plugins=<plugin1>,<plugin2>, ...
List plugins used to manage system-wide connection settings. This list has
preference over plugins specified in the configuration file. Currently supported

View file

@ -8,10 +8,14 @@ NetworkManager.conf \- NetworkManager configuration file
.SH SYNOPSIS
/etc/NetworkManager/NetworkManager.conf
.br
/etc/NetworkManager/conf.d/*.conf
.br
or
.br
\fI<SYSCONFDIR>\fP/NetworkManager/NetworkManager.conf
.br
\fI<SYSCONFDIR>\fP/NetworkManager/conf.d/*.conf
.br
where <SYSCONFDIR> depends on your distribution or build.
.SH DESCRIPTION
.P
@ -20,6 +24,17 @@ is a 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 "\-\-config=" argument for
\fBNetworkManager\fP (8).
.P
If a default
.I NetworkManager.conf
is provided by your distribution's packages, you should not modify it,
since your changes may get overwritten by package updates. Instead,
you can add additional
.I .conf
files to the
.I conf.d
directory. These will be read in order, with later files overriding
earlier ones.
.SH "FILE FORMAT"
.P
The configuration file format is so-called key file (sort of ini-style format).
@ -36,6 +51,14 @@ Minimal system settings configuration file looks like this:
plugins=keyfile
.fi
.P
As an extension to the normal keyfile format, you can also append a
value to a previously-set list-valued key by doing:
.P
.nf
[main]
plugins+=another-plugin
.fi
.P
Description of sections and available keys follows:
.SS [main]
This section is the only mandatory section of the configuration file.

View file

@ -27,14 +27,17 @@
#include "nm-logging.h"
#include "nm-utils.h"
#include <gio/gio.h>
#include <glib/gi18n.h>
#define NM_DEFAULT_SYSTEM_CONF_FILE NMCONFDIR "/NetworkManager.conf"
#define NM_DEFAULT_SYSTEM_CONF_DIR NMCONFDIR "/conf.d"
#define NM_OLD_SYSTEM_CONF_FILE NMCONFDIR "/nm-system-settings.conf"
#define NM_NO_AUTO_DEFAULT_STATE_FILE NMSTATEDIR "/no-auto-default.state"
typedef struct {
char *path;
char *nm_conf_path;
char *config_dir;
char *no_auto_default_file;
GKeyFile *keyfile;
@ -62,7 +65,7 @@ nm_config_get_path (NMConfig *config)
{
g_return_val_if_fail (config != NULL, NULL);
return NM_CONFIG_GET_PRIVATE (config)->path;
return NM_CONFIG_GET_PRIVATE (config)->nm_conf_path;
}
const char **
@ -226,6 +229,7 @@ nm_config_set_ethernet_no_auto_default (NMConfig *config, NMConfigDevice *device
/************************************************************************/
static char *cli_config_path;
static char *cli_config_dir;
static char *cli_no_auto_default_file;
static char *cli_plugins;
static char *cli_log_level;
@ -236,6 +240,7 @@ static char *cli_connectivity_response;
static GOptionEntry config_options[] = {
{ "config", 0, 0, G_OPTION_ARG_FILENAME, &cli_config_path, N_("Config file location"), N_("/path/to/config.file") },
{ "config-dir", 0, 0, G_OPTION_ARG_FILENAME, &cli_config_dir, N_("Config directory location"), N_("/path/to/config/dir") },
{ "no-auto-default", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_FILENAME, &cli_no_auto_default_file, "no-auto-default.state location", NULL },
{ "plugins", 0, 0, G_OPTION_ARG_STRING, &cli_plugins, N_("List of plugins separated by ','"), N_("plugin1,plugin2") },
{ "log-level", 0, 0, G_OPTION_ARG_STRING, &cli_log_level, N_("Log level: one of [%s]"), "INFO" },
@ -279,7 +284,9 @@ read_config (NMConfig *config, const char *path, GError **error)
{
NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (config);
GKeyFile *kf;
gboolean success = FALSE;
char **groups, **keys;
gsize ngroups, nkeys;
int g, k;
if (g_file_test (path, G_FILE_TEST_EXISTS) == FALSE) {
g_set_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND, "file %s not found", path);
@ -288,42 +295,102 @@ read_config (NMConfig *config, const char *path, GError **error)
kf = g_key_file_new ();
g_key_file_set_list_separator (kf, ',');
if (g_key_file_load_from_file (kf, path, G_KEY_FILE_NONE, error)) {
priv->path = g_strdup (path);
/* Only set stuff that's not already set, as CLI options override
* config file options.
*/
if (!priv->plugins)
priv->plugins = g_key_file_get_string_list (kf, "main", "plugins", NULL, NULL);
priv->dhcp_client = g_key_file_get_value (kf, "main", "dhcp", NULL);
priv->dns_plugins = g_key_file_get_string_list (kf, "main", "dns", NULL, NULL);
if (!priv->log_level)
priv->log_level = g_key_file_get_value (kf, "logging", "level", NULL);
if (!priv->log_domains)
priv->log_domains = g_key_file_get_value (kf, "logging", "domains", NULL);
if (!priv->connectivity_uri)
priv->connectivity_uri = g_key_file_get_value (kf, "connectivity", "uri", NULL);
if (priv->connectivity_interval < 0)
priv->connectivity_interval = CLAMP (g_key_file_get_integer (kf, "connectivity", "interval", NULL), 0, G_MAXINT32);
if (!priv->connectivity_response)
priv->connectivity_response = g_key_file_get_value (kf, "connectivity", "response", NULL);
if (!priv->no_auto_default)
priv->no_auto_default = g_key_file_get_string_list (kf, "main", "no-auto-default", NULL, NULL);
priv->keyfile = kf;
success = TRUE;
} else
if (!g_key_file_load_from_file (kf, path, G_KEY_FILE_NONE, error)) {
g_key_file_free (kf);
return FALSE;
}
return success;
/* Override the current settings with the new ones */
groups = g_key_file_get_groups (kf, &ngroups);
for (g = 0; groups[g]; g++) {
keys = g_key_file_get_keys (kf, groups[g], &nkeys, NULL);
if (!keys)
continue;
for (k = 0; keys[k]; k++) {
int len = strlen (keys[k]);
if (keys[k][len - 1] == '+') {
char *base_key = g_strndup (keys[k], len - 1);
const char *old_val = g_key_file_get_value (priv->keyfile, groups[g], base_key, NULL);
const char *new_val = g_key_file_get_value (kf, groups[g], keys[k], NULL);
if (old_val && *old_val) {
char *combined = g_strconcat (old_val, ",", new_val, NULL);
g_key_file_set_value (priv->keyfile, groups[g], base_key, combined);
g_free (combined);
} else
g_key_file_set_value (priv->keyfile, groups[g], base_key, new_val);
g_free (base_key);
continue;
}
g_key_file_set_value (priv->keyfile, groups[g], keys[k],
g_key_file_get_value (kf, groups[g], keys[k], NULL));
}
}
g_key_file_free (kf);
return TRUE;
}
static gboolean
find_base_config (NMConfig *config, GError **error)
{
NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (config);
GError *my_error = NULL;
/* Try a user-specified config file first */
if (cli_config_path) {
/* Bad user-specific config file path is a hard error */
if (read_config (config, cli_config_path, error)) {
priv->nm_conf_path = g_strdup (cli_config_path);
return TRUE;
} else
return FALSE;
}
/* Even though we prefer NetworkManager.conf, we need to check the
* old nm-system-settings.conf first to preserve compat with older
* setups. In package managed systems dropping a NetworkManager.conf
* onto the system would make NM use it instead of nm-system-settings.conf,
* changing behavior during an upgrade. We don't want that.
*/
/* Try deprecated nm-system-settings.conf first */
if (read_config (config, NM_OLD_SYSTEM_CONF_FILE, &my_error)) {
priv->nm_conf_path = g_strdup (NM_OLD_SYSTEM_CONF_FILE);
return TRUE;
}
if (!g_error_matches (my_error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND)) {
g_warning ("Default config file %s invalid: %s\n",
NM_OLD_SYSTEM_CONF_FILE,
my_error->message);
}
g_clear_error (&my_error);
/* Try the standard config file location next */
if (read_config (config, NM_DEFAULT_SYSTEM_CONF_FILE, &my_error)) {
priv->nm_conf_path = g_strdup (NM_DEFAULT_SYSTEM_CONF_FILE);
return TRUE;
}
if (!g_error_matches (my_error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND)) {
g_warning ("Default config file %s invalid: %s\n",
NM_DEFAULT_SYSTEM_CONF_FILE,
my_error->message);
g_propagate_error (error, my_error);
return FALSE;
}
/* If for some reason no config file exists, use the default
* config file path.
*/
priv->nm_conf_path = g_strdup (NM_DEFAULT_SYSTEM_CONF_FILE);
g_warning ("No config file found or given; using %s\n",
NM_DEFAULT_SYSTEM_CONF_FILE);
return TRUE;
}
/************************************************************************/
@ -335,107 +402,118 @@ nm_config_get (void)
return singleton;
}
static int
sort_asciibetically (gconstpointer a, gconstpointer b)
{
const char *s1 = *(const char **)a;
const char *s2 = *(const char **)b;
return strcmp (s1, s2);
}
/* call this function only once! */
NMConfig *
nm_config_new (GError **error)
{
GError *local = NULL;
NMConfigPrivate *priv = NULL;
GFile *dir;
GFileEnumerator *direnum;
GFileInfo *info;
GPtrArray *confs;
const char *name;
int i;
g_assert (!singleton);
singleton = NM_CONFIG (g_object_new (NM_TYPE_CONFIG, NULL));
priv = NM_CONFIG_GET_PRIVATE (singleton);
/* Fill with command-line defaults */
if (cli_plugins && cli_plugins[0])
priv->plugins = g_strsplit_set (cli_plugins, ",", 0);
if (cli_log_level && cli_log_level[0])
priv->log_level = g_strdup (cli_log_level);
if (cli_log_domains && cli_log_domains[0])
priv->log_domains = g_strdup (cli_log_domains);
if (cli_connectivity_uri && cli_connectivity_uri[0])
priv->connectivity_uri = g_strdup (cli_connectivity_uri);
if (cli_connectivity_interval >= 0)
priv->connectivity_interval = cli_connectivity_interval;
if (cli_connectivity_response && cli_connectivity_response[0])
priv->connectivity_response = g_strdup (cli_connectivity_response);
/* Try a user-specified config file first */
if (cli_config_path) {
/* Bad user-specific config file path is a hard error */
if (!read_config (singleton, cli_config_path, error)) {
g_object_unref (singleton);
singleton = NULL;
return NULL;
}
goto got_config;
}
/* Even though we prefer NetworkManager.conf, we need to check the
* old nm-system-settings.conf first to preserve compat with older
* setups. In package managed systems dropping a NetworkManager.conf
* onto the system would make NM use it instead of nm-system-settings.conf,
* changing behavior during an upgrade. We don't want that.
*/
/* Try deprecated nm-system-settings.conf first */
if (read_config (singleton, NM_OLD_SYSTEM_CONF_FILE, &local))
goto got_config;
if (g_error_matches (local, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND) == FALSE) {
fprintf (stderr, "Default config file %s invalid: (%d) %s\n",
NM_OLD_SYSTEM_CONF_FILE,
local ? local->code : -1,
(local && local->message) ? local->message : "unknown");
}
g_clear_error (&local);
/* Try the standard config file location next */
if (read_config (singleton, NM_DEFAULT_SYSTEM_CONF_FILE, &local))
goto got_config;
if (g_error_matches (local, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND) == FALSE) {
fprintf (stderr, "Default config file %s invalid: (%d) %s\n",
NM_DEFAULT_SYSTEM_CONF_FILE,
local ? local->code : -1,
(local && local->message) ? local->message : "unknown");
g_propagate_error (error, local);
/* First read the base config file */
if (!find_base_config (singleton, error)) {
g_object_unref (singleton);
singleton = NULL;
return NULL;
}
/* If for some reason no config file exists, and NM wasn't given on on
* the command line, just use the default config file path.
*/
if (priv->path == NULL) {
priv->path = g_strdup (NM_DEFAULT_SYSTEM_CONF_FILE);
fprintf (stderr, "No config file found or given; using %s\n",
NM_DEFAULT_SYSTEM_CONF_FILE);
/* Now read the overrides in the config dir */
if (cli_config_dir)
priv->config_dir = g_strdup (cli_config_dir);
else
priv->config_dir = g_strdup (NM_DEFAULT_SYSTEM_CONF_DIR);
confs = g_ptr_array_new_with_free_func (g_free);
dir = g_file_new_for_path (priv->config_dir);
direnum = g_file_enumerate_children (dir, G_FILE_ATTRIBUTE_STANDARD_NAME, 0, NULL, NULL);
if (direnum) {
while ((info = g_file_enumerator_next_file (direnum, NULL, NULL))) {
name = g_file_info_get_name (info);
if (g_str_has_suffix (name, ".conf"))
g_ptr_array_add (confs, g_build_filename (priv->config_dir, name, NULL));
g_object_unref (info);
}
g_object_unref (direnum);
}
g_object_unref (dir);
/* ignore error if config file not found */
g_clear_error (&local);
g_ptr_array_sort (confs, sort_asciibetically);
for (i = 0; i < confs->len; i++) {
if (!read_config (singleton, confs->pdata[i], error)) {
g_object_unref (singleton);
singleton = NULL;
break;
}
}
g_ptr_array_unref (confs);
if (!singleton)
return FALSE;
got_config:
/* Handle no-auto-default state file */
/* Handle no-auto-default key and state file */
priv->no_auto_default = g_key_file_get_string_list (priv->keyfile, "main", "no-auto-default", NULL, NULL);
if (cli_no_auto_default_file)
priv->no_auto_default_file = g_strdup (cli_no_auto_default_file);
else
priv->no_auto_default_file = g_strdup (NM_NO_AUTO_DEFAULT_STATE_FILE);
merge_no_auto_default_state (singleton);
/* Now let command-line options override the config files, and fill in priv. */
if (cli_plugins && cli_plugins[0])
g_key_file_set_value (priv->keyfile, "main", "plugins", cli_plugins);
priv->plugins = g_key_file_get_string_list (priv->keyfile, "main", "plugins", NULL, NULL);
priv->dhcp_client = g_key_file_get_value (priv->keyfile, "main", "dhcp", NULL);
priv->dns_plugins = g_key_file_get_string_list (priv->keyfile, "main", "dns", NULL, NULL);
if (cli_log_level && cli_log_level[0])
g_key_file_set_value (priv->keyfile, "logging", "level", cli_log_level);
priv->log_level = g_key_file_get_value (priv->keyfile, "logging", "level", NULL);
if (cli_log_domains && cli_log_domains[0])
g_key_file_set_value (priv->keyfile, "logging", "domains", cli_log_domains);
priv->log_domains = g_key_file_get_value (priv->keyfile, "logging", "domains", NULL);
if (cli_connectivity_uri && cli_connectivity_uri[0])
g_key_file_set_value (priv->keyfile, "connectivity", "uri", cli_connectivity_uri);
priv->connectivity_uri = g_key_file_get_value (priv->keyfile, "connectivity", "uri", NULL);
if (cli_connectivity_interval >= 0)
g_key_file_set_integer (priv->keyfile, "connectivity", "interval", cli_connectivity_interval);
priv->connectivity_interval = g_key_file_get_integer (priv->keyfile, "connectivity", "interval", NULL);
if (cli_connectivity_response && cli_connectivity_response[0])
g_key_file_set_value (priv->keyfile, "connectivity", "response", cli_connectivity_response);
priv->connectivity_response = g_key_file_get_value (priv->keyfile, "connectivity", "response", NULL);
return singleton;
}
static void
nm_config_init (NMConfig *config)
{
NM_CONFIG_GET_PRIVATE (config)->connectivity_interval = -1;
NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (config);
priv->keyfile = g_key_file_new ();
g_key_file_set_list_separator (priv->keyfile, ',');
priv->connectivity_interval = -1;
}
static void
@ -443,7 +521,9 @@ finalize (GObject *gobject)
{
NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (gobject);
g_free (priv->path);
g_free (priv->nm_conf_path);
g_free (priv->config_dir);
g_free (priv->no_auto_default_file);
g_clear_pointer (&priv->keyfile, g_key_file_unref);
g_strfreev (priv->plugins);
g_free (priv->dhcp_client);
@ -452,10 +532,13 @@ finalize (GObject *gobject)
g_free (priv->log_domains);
g_free (priv->connectivity_uri);
g_free (priv->connectivity_response);
g_strfreev (priv->no_auto_default);
singleton = NULL;
g_clear_pointer (&cli_config_path, g_free);
g_clear_pointer (&cli_config_dir, g_free);
g_clear_pointer (&cli_no_auto_default_file, g_free);
g_clear_pointer (&cli_plugins, g_free);
g_clear_pointer (&cli_log_level, g_free);
g_clear_pointer (&cli_log_domains, g_free);

View file

@ -27,6 +27,9 @@ check-local: test-config
EXTRA_DIST = \
NetworkManager.conf \
bad.conf
bad.conf \
conf.d/00-overrides.conf \
conf.d/10-more.conf \
conf.d/90-last.conf
endif

View file

@ -0,0 +1,11 @@
[main]
dhcp=dhcpcd
[logging]
domains=PLATFORM,DNS,WIFI
[order]
a=0
b=0
c=0

View file

@ -0,0 +1,11 @@
[main]
extra=hello
new+=something
[connectivity]
uri=http://example.net
[order]
a=10
b=10

View file

@ -0,0 +1,5 @@
[main]
plugins+=one,two
[order]
a=90

View file

@ -28,7 +28,7 @@
#include "nm-test-device.h"
static void
setup_config (const char *config_file, ...)
setup_config (const char *config_file, const char *config_dir, ...)
{
va_list ap;
GPtrArray *args;
@ -40,8 +40,10 @@ setup_config (const char *config_file, ...)
g_ptr_array_add (args, "test-config");
g_ptr_array_add (args, "--config");
g_ptr_array_add (args, (char *)config_file);
g_ptr_array_add (args, "--config-dir");
g_ptr_array_add (args, (char *)config_dir);
va_start (ap, config_file);
va_start (ap, config_dir);
while ((arg = va_arg (ap, char *)))
g_ptr_array_add (args, arg);
va_end (ap);
@ -65,7 +67,7 @@ test_config_simple (void)
const char **plugins;
char *value;
setup_config (SRCDIR "/NetworkManager.conf", NULL);
setup_config (SRCDIR "/NetworkManager.conf", "/no/such/dir", NULL);
config = nm_config_new (&error);
g_assert_no_error (error);
@ -101,7 +103,7 @@ test_config_non_existent (void)
NMConfig *config;
GError *error = NULL;
setup_config (SRCDIR "/no-such-file", NULL);
setup_config (SRCDIR "/no-such-file", "/no/such/dir", NULL);
config = nm_config_new (&error);
g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND);
}
@ -112,7 +114,7 @@ test_config_parse_error (void)
NMConfig *config;
GError *error = NULL;
setup_config (SRCDIR "/bad.conf", NULL);
setup_config (SRCDIR "/bad.conf", "/no/such/dir", NULL);
config = nm_config_new (&error);
g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_PARSE);
}
@ -164,7 +166,7 @@ test_config_no_auto_default (void)
g_assert_cmpint (nwrote, ==, 18);
close (fd);
setup_config (SRCDIR "/NetworkManager.conf",
setup_config (SRCDIR "/NetworkManager.conf", "/no/such/dir",
"--no-auto-default", state_file,
NULL);
config = nm_config_new (&error);
@ -185,7 +187,7 @@ test_config_no_auto_default (void)
g_object_unref (config);
setup_config (SRCDIR "/NetworkManager.conf",
setup_config (SRCDIR "/NetworkManager.conf", "/no/such/dir",
"--no-auto-default", state_file,
NULL);
config = nm_config_new (&error);
@ -207,6 +209,66 @@ test_config_no_auto_default (void)
g_free (state_file);
}
static void
test_config_confdir (void)
{
NMConfig *config;
GError *error = NULL;
const char **plugins;
char *value;
setup_config (SRCDIR "/NetworkManager.conf", SRCDIR "/conf.d", NULL);
config = nm_config_new (&error);
g_assert_no_error (error);
g_assert_cmpstr (nm_config_get_path (config), ==, SRCDIR "/NetworkManager.conf");
g_assert_cmpstr (nm_config_get_dhcp_client (config), ==, "dhcpcd");
g_assert_cmpstr (nm_config_get_log_level (config), ==, "INFO");
g_assert_cmpstr (nm_config_get_log_domains (config), ==, "PLATFORM,DNS,WIFI");
g_assert_cmpstr (nm_config_get_connectivity_uri (config), ==, "http://example.net");
g_assert_cmpint (nm_config_get_connectivity_interval (config), ==, 100);
plugins = nm_config_get_plugins (config);
g_assert_cmpint (g_strv_length ((char **)plugins), ==, 5);
g_assert_cmpstr (plugins[0], ==, "foo");
g_assert_cmpstr (plugins[1], ==, "bar");
g_assert_cmpstr (plugins[2], ==, "baz");
g_assert_cmpstr (plugins[3], ==, "one");
g_assert_cmpstr (plugins[4], ==, "two");
value = nm_config_get_value (config, "main", "extra", NULL);
g_assert_cmpstr (value, ==, "hello");
g_free (value);
value = nm_config_get_value (config, "main", "new", NULL);
g_assert_cmpstr (value, ==, "something"); /* not ",something" */
g_free (value);
value = nm_config_get_value (config, "order", "a", NULL);
g_assert_cmpstr (value, ==, "90");
g_free (value);
value = nm_config_get_value (config, "order", "b", NULL);
g_assert_cmpstr (value, ==, "10");
g_free (value);
value = nm_config_get_value (config, "order", "c", NULL);
g_assert_cmpstr (value, ==, "0");
g_free (value);
g_object_unref (config);
}
static void
test_config_confdir_parse_error (void)
{
NMConfig *config;
GError *error = NULL;
/* Using SRCDIR as the conf dir will pick up bad.conf */
setup_config (SRCDIR "/NetworkManager.conf", SRCDIR, NULL);
config = nm_config_new (&error);
g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_PARSE);
}
int
main (int argc, char **argv)
{
@ -217,6 +279,8 @@ main (int argc, char **argv)
g_test_add_func ("/config/non-existent", test_config_non_existent);
g_test_add_func ("/config/parse-error", test_config_parse_error);
g_test_add_func ("/config/no-auto-default", test_config_no_auto_default);
g_test_add_func ("/config/confdir", test_config_confdir);
g_test_add_func ("/config/confdir-parse-error", test_config_confdir_parse_error);
/* This one has to come last, because it leaves its values in
* nm-config.c's global variables, and there's no way to reset