From 6cb5db60de292fc4493b9f799819641bb56942c6 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 10 Jul 2014 00:00:56 +0200 Subject: [PATCH 01/32] connectivity: add code comment to nm_connectivity_check_cb() --- src/nm-connectivity.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/nm-connectivity.c b/src/nm-connectivity.c index d21626735f..7f99f92f93 100644 --- a/src/nm-connectivity.c +++ b/src/nm-connectivity.c @@ -112,6 +112,7 @@ nm_connectivity_check_cb (SoupSession *session, SoupMessage *msg, gpointer user_ const char *nm_header; self = NM_CONNECTIVITY (g_async_result_get_source_object (G_ASYNC_RESULT (simple))); + /* it is safe to unref @self here, @simple holds yet another reference. */ g_object_unref (self); priv = NM_CONNECTIVITY_GET_PRIVATE (self); priv->pending_checks--; From 3dce101f6b28887dc6e8851525d6a52c2d8e341a Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 9 Jul 2014 22:22:48 +0200 Subject: [PATCH 02/32] connectivity: make NMConnectivity:dispose() reentrant --- src/nm-connectivity.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nm-connectivity.c b/src/nm-connectivity.c index 7f99f92f93..e049de42d8 100644 --- a/src/nm-connectivity.c +++ b/src/nm-connectivity.c @@ -393,8 +393,8 @@ dispose (GObject *object) NMConnectivity *self = NM_CONNECTIVITY (object); NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self); - g_free (priv->uri); - g_free (priv->response); + g_clear_pointer (&priv->uri, g_free); + g_clear_pointer (&priv->response, g_free); #if WITH_CONCHECK if (priv->soup_session) { From 7aab5bc81ccd1eeb6dbf7d67d84861ab9d117cd1 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 14 Jul 2014 12:52:08 +0200 Subject: [PATCH 03/32] connectivity/trivial: fix white space and line-break in nm-connectivity.c --- src/nm-connectivity.c | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/nm-connectivity.c b/src/nm-connectivity.c index e049de42d8..609ed988c9 100644 --- a/src/nm-connectivity.c +++ b/src/nm-connectivity.c @@ -423,31 +423,33 @@ nm_connectivity_class_init (NMConnectivityClass *klass) /* properties */ g_object_class_install_property - (object_class, PROP_URI, - g_param_spec_string (NM_CONNECTIVITY_URI, "", "", - NULL, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + (object_class, PROP_URI, + g_param_spec_string (NM_CONNECTIVITY_URI, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); g_object_class_install_property - (object_class, PROP_INTERVAL, - g_param_spec_uint (NM_CONNECTIVITY_INTERVAL, "", "", - 0, G_MAXUINT, 300, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); + (object_class, PROP_INTERVAL, + g_param_spec_uint (NM_CONNECTIVITY_INTERVAL, "", "", + 0, G_MAXUINT, 300, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); g_object_class_install_property - (object_class, PROP_RESPONSE, - g_param_spec_string (NM_CONNECTIVITY_RESPONSE, "", "", - DEFAULT_RESPONSE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); + (object_class, PROP_RESPONSE, + g_param_spec_string (NM_CONNECTIVITY_RESPONSE, "", "", + DEFAULT_RESPONSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); g_object_class_install_property - (object_class, PROP_STATE, - g_param_spec_uint (NM_CONNECTIVITY_STATE, "", "", - NM_CONNECTIVITY_UNKNOWN, NM_CONNECTIVITY_FULL, NM_CONNECTIVITY_UNKNOWN, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); + (object_class, PROP_STATE, + g_param_spec_uint (NM_CONNECTIVITY_STATE, "", "", + NM_CONNECTIVITY_UNKNOWN, NM_CONNECTIVITY_FULL, NM_CONNECTIVITY_UNKNOWN, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); } From a79e9fdbb0081cd296f3cf34feaf72d62ce91f1d Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 19 Jan 2015 17:41:22 +0100 Subject: [PATCH 04/32] connectivity: add missing G_PARAM_CONSTRUCT for NM_CONNECTIVITY_URI property --- src/nm-connectivity.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/nm-connectivity.c b/src/nm-connectivity.c index 609ed988c9..204044d024 100644 --- a/src/nm-connectivity.c +++ b/src/nm-connectivity.c @@ -427,6 +427,7 @@ nm_connectivity_class_init (NMConnectivityClass *klass) g_param_spec_string (NM_CONNECTIVITY_URI, "", "", NULL, G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); g_object_class_install_property From 78e3b4866aead808e48af1845e3ef25d1b454d19 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 14 Jul 2014 17:45:37 +0200 Subject: [PATCH 05/32] connectivity: refactor converting connectivity states to string --- src/nm-connectivity.c | 9 +++++---- src/nm-connectivity.h | 2 ++ src/nm-manager.c | 5 +---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/nm-connectivity.c b/src/nm-connectivity.c index 204044d024..62db360af4 100644 --- a/src/nm-connectivity.c +++ b/src/nm-connectivity.c @@ -69,8 +69,8 @@ nm_connectivity_get_state (NMConnectivity *connectivity) return NM_CONNECTIVITY_GET_PRIVATE (connectivity)->state; } -static const char * -state_name (NMConnectivityState state) +const char * +nm_connectivity_state_to_string (NMConnectivityState state) { switch (state) { case NM_CONNECTIVITY_UNKNOWN: @@ -84,7 +84,7 @@ state_name (NMConnectivityState state) case NM_CONNECTIVITY_FULL: return "FULL"; default: - return "???"; + g_return_val_if_reached ("???"); } } @@ -95,7 +95,8 @@ update_state (NMConnectivity *self, NMConnectivityState state) if (priv->state != state) { nm_log_dbg (LOGD_CONCHECK, "Connectivity state changed from %s to %s", - state_name (priv->state), state_name (state)); + nm_connectivity_state_to_string (priv->state), + nm_connectivity_state_to_string (state)); priv->state = state; g_object_notify (G_OBJECT (self), NM_CONNECTIVITY_STATE); } diff --git a/src/nm-connectivity.h b/src/nm-connectivity.h index 771abdc237..a61af5c190 100644 --- a/src/nm-connectivity.h +++ b/src/nm-connectivity.h @@ -51,6 +51,8 @@ typedef struct { GType nm_connectivity_get_type (void); +const char *nm_connectivity_state_to_string (NMConnectivityState state); + NMConnectivity *nm_connectivity_new (void); void nm_connectivity_set_online (NMConnectivity *self, diff --git a/src/nm-manager.c b/src/nm-manager.c index 0d0686319c..4ef0722644 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -4274,12 +4274,9 @@ connectivity_changed (NMConnectivity *connectivity, gpointer user_data) { NMManager *self = NM_MANAGER (user_data); - NMConnectivityState state; - static const char *connectivity_states[] = { "UNKNOWN", "NONE", "PORTAL", "LIMITED", "FULL" }; - state = nm_connectivity_get_state (connectivity); nm_log_dbg (LOGD_CORE, "connectivity checking indicates %s", - connectivity_states[state]); + nm_connectivity_state_to_string (nm_connectivity_get_state (connectivity))); nm_manager_update_state (self); g_object_notify (G_OBJECT (self), NM_MANAGER_CONNECTIVITY); From 5ee18c124b2c8e79477b846c216d3ca9f1aa8dc5 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 14 Jul 2014 13:40:30 +0200 Subject: [PATCH 06/32] connectivity: refactor handling parameters of NMConnectivity Currently the three parameters for the connectivity check (uri, interval, response) don't get reset. Soon they might be modified at any time when reloading the configuration. When calling the asynchronous HTTP connectivity check, we want to preserve the original parameters so that the result callback still can access them later. Pass the uri and response parameter on as ConCheckCbData. --- src/nm-connectivity.c | 206 ++++++++++++++++++++++++++---------------- 1 file changed, 128 insertions(+), 78 deletions(-) diff --git a/src/nm-connectivity.c b/src/nm-connectivity.c index 62db360af4..406f41e329 100644 --- a/src/nm-connectivity.c +++ b/src/nm-connectivity.c @@ -41,10 +41,11 @@ typedef struct { char *uri; char *response; guint interval; + gboolean online; /* whether periodic connectivity checking is enabled. */ #if WITH_CONCHECK SoupSession *soup_session; - guint pending_checks; + gboolean initial_check_obsoleted; guint check_id; #endif @@ -103,24 +104,33 @@ update_state (NMConnectivity *self, NMConnectivityState state) } #if WITH_CONCHECK +typedef struct { + GSimpleAsyncResult *simple; + char *uri; + char *response; + guint check_id_when_scheduled; +} ConCheckCbData; + static void nm_connectivity_check_cb (SoupSession *session, SoupMessage *msg, gpointer user_data) { - GSimpleAsyncResult *simple = user_data; NMConnectivity *self; NMConnectivityPrivate *priv; + ConCheckCbData *cb_data = user_data; + GSimpleAsyncResult *simple = cb_data->simple; NMConnectivityState new_state; const char *nm_header; + const char *uri = cb_data->uri; + const char *response = cb_data->response ? cb_data->response : DEFAULT_RESPONSE; self = NM_CONNECTIVITY (g_async_result_get_source_object (G_ASYNC_RESULT (simple))); /* it is safe to unref @self here, @simple holds yet another reference. */ g_object_unref (self); priv = NM_CONNECTIVITY_GET_PRIVATE (self); - priv->pending_checks--; if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)) { nm_log_info (LOGD_CONCHECK, "Connectivity check for uri '%s' failed with '%s'.", - priv->uri, msg->reason_phrase); + uri, msg->reason_phrase); new_state = NM_CONNECTIVITY_LIMITED; goto done; } @@ -128,32 +138,48 @@ nm_connectivity_check_cb (SoupSession *session, SoupMessage *msg, gpointer user_ /* Check headers; if we find the NM-specific one we're done */ nm_header = soup_message_headers_get_one (msg->response_headers, "X-NetworkManager-Status"); if (g_strcmp0 (nm_header, "online") == 0) { - nm_log_dbg (LOGD_CONCHECK, "Connectivity check for uri '%s' with Status header successful.", priv->uri); + nm_log_dbg (LOGD_CONCHECK, "Connectivity check for uri '%s' with Status header successful.", uri); new_state = NM_CONNECTIVITY_FULL; } else if (msg->status_code == SOUP_STATUS_OK) { /* check response */ - if (msg->response_body->data && (g_str_has_prefix (msg->response_body->data, priv->response))) { + if (msg->response_body->data && g_str_has_prefix (msg->response_body->data, response)) { nm_log_dbg (LOGD_CONCHECK, "Connectivity check for uri '%s' successful.", - priv->uri); + uri); new_state = NM_CONNECTIVITY_FULL; } else { nm_log_info (LOGD_CONCHECK, "Connectivity check for uri '%s' did not match expected response '%s'; assuming captive portal.", - priv->uri, priv->response); + uri, response); new_state = NM_CONNECTIVITY_PORTAL; } } else { nm_log_info (LOGD_CONCHECK, "Connectivity check for uri '%s' returned status '%d %s'; assuming captive portal.", - priv->uri, msg->status_code, msg->reason_phrase); + uri, msg->status_code, msg->reason_phrase); new_state = NM_CONNECTIVITY_PORTAL; } done: - update_state (self, new_state); + /* Only update the state, if the call was done from external, or if the periodic check + * is still the one that called this async check. */ + if (!cb_data->check_id_when_scheduled || cb_data->check_id_when_scheduled == priv->check_id) { + /* Only update the state, if the URI and response parameters did not change + * since invocation. + * The interval does not matter for exernal calls, and for internal calls + * we don't reach this line if the interval changed. */ + if ( !g_strcmp0 (cb_data->uri, priv->uri) + && !g_strcmp0 (cb_data->response, priv->response)) + update_state (self, new_state); + } g_simple_async_result_set_op_res_gssize (simple, new_state); g_simple_async_result_complete (simple); + + g_free (cb_data->uri); + g_free (cb_data->response); + g_slice_free (ConCheckCbData, cb_data); } +#define IS_PERIODIC_CHECK(callback) (callback == run_check_complete) + static void run_check_complete (GObject *object, GAsyncResult *result, @@ -185,39 +211,54 @@ idle_start_periodic_checks (gpointer user_data) NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self); priv->check_id = g_timeout_add_seconds (priv->interval, run_check, self); - if (!priv->pending_checks) + if (!priv->initial_check_obsoleted) run_check (self); return FALSE; } #endif -void -nm_connectivity_set_online (NMConnectivity *self, - gboolean online) +static void +_reschedule_periodic_checks (NMConnectivity *self, gboolean force_reschedule) { -#if WITH_CONCHECK NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self); -#endif - - nm_log_dbg (LOGD_CONCHECK, "nm_connectivity_set_online(%s)", online ? "TRUE" : "FALSE"); #if WITH_CONCHECK - if (online && priv->uri && priv->interval) { - if (!priv->check_id) + if (priv->online && priv->uri && priv->interval) { + if (force_reschedule || !priv->check_id) { + if (priv->check_id) + g_source_remove (priv->check_id); priv->check_id = g_timeout_add (0, idle_start_periodic_checks, self); - - return; - } else if (priv->check_id) { - g_source_remove (priv->check_id); - priv->check_id = 0; + priv->initial_check_obsoleted = FALSE; + } + } else { + if (priv->check_id) { + g_source_remove (priv->check_id); + priv->check_id = 0; + } } + if (priv->check_id) + return; #endif /* Either @online is %TRUE but we aren't checking connectivity, or * @online is %FALSE. Either way we can update our status immediately. */ - update_state (self, online ? NM_CONNECTIVITY_FULL : NM_CONNECTIVITY_NONE); + update_state (self, priv->online ? NM_CONNECTIVITY_FULL : NM_CONNECTIVITY_NONE); +} + +void +nm_connectivity_set_online (NMConnectivity *self, + gboolean online) +{ + NMConnectivityPrivate *priv= NM_CONNECTIVITY_GET_PRIVATE (self); + + online = !!online; + if (priv->online != online) { + nm_log_dbg (LOGD_CONCHECK, "connectivity: set %s", online ? "online" : "offline"); + priv->online = online; + _reschedule_periodic_checks (self, FALSE); + } } void @@ -226,36 +267,42 @@ nm_connectivity_check_async (NMConnectivity *self, gpointer user_data) { NMConnectivityPrivate *priv; -#if WITH_CONCHECK - SoupMessage *msg; -#endif GSimpleAsyncResult *simple; g_return_if_fail (NM_IS_CONNECTIVITY (self)); priv = NM_CONNECTIVITY_GET_PRIVATE (self); -#if WITH_CONCHECK - if (callback == run_check_complete) - nm_log_dbg (LOGD_CONCHECK, "Periodic connectivity check started with uri '%s'.", priv->uri); - else -#endif - nm_log_dbg (LOGD_CONCHECK, "Connectivity check started with uri '%s'.", priv->uri); - simple = g_simple_async_result_new (G_OBJECT (self), callback, user_data, nm_connectivity_check_async); #if WITH_CONCHECK if (priv->uri && priv->interval) { + SoupMessage *msg; + ConCheckCbData *cb_data = g_slice_new (ConCheckCbData); + msg = soup_message_new ("GET", priv->uri); soup_message_set_flags (msg, SOUP_MESSAGE_NO_REDIRECT); + cb_data->simple = simple; + cb_data->uri = g_strdup (priv->uri); + cb_data->response = g_strdup (priv->response); + + /* For internal calls (periodic), remember the check-id at time of scheduling. */ + cb_data->check_id_when_scheduled = IS_PERIODIC_CHECK (callback) ? priv->check_id : 0; + soup_session_queue_message (priv->soup_session, msg, nm_connectivity_check_cb, - simple); - priv->pending_checks++; + cb_data); + priv->initial_check_obsoleted = TRUE; + nm_log_dbg (LOGD_CONCHECK, "%sconnectivity check: send request to '%s'", IS_PERIODIC_CHECK (callback) ? "periodic " : "", priv->uri); return; + } else { + g_warn_if_fail (!IS_PERIODIC_CHECK (callback)); + nm_log_dbg (LOGD_CONCHECK, "connectivity check: faking request. Connectivity check disabled"); } +#else + nm_log_dbg (LOGD_CONCHECK, "connectivity check: faking request. Compiled without connectivity-check support"); #endif g_simple_async_result_set_op_res_gssize (simple, priv->state); @@ -277,38 +324,21 @@ nm_connectivity_check_finish (NMConnectivity *self, return (NMConnectivityState) g_simple_async_result_get_op_res_gssize (simple); } +/**************************************************************************/ NMConnectivity * nm_connectivity_new (void) { - NMConnectivity *self; - NMConfig *config; - const char *check_response; + NMConfig *config = nm_config_get (); - config = nm_config_get (); - check_response = nm_config_get_connectivity_response (config); - - self = g_object_new (NM_TYPE_CONNECTIVITY, + /* NMConnectivity is (almost) independent from NMConfig and works + * fine without it. As convenience, the default constructor nm_connectivity_new() + * uses the parameters from NMConfig to create an instance. */ + return g_object_new (NM_TYPE_CONNECTIVITY, NM_CONNECTIVITY_URI, nm_config_get_connectivity_uri (config), NM_CONNECTIVITY_INTERVAL, nm_config_get_connectivity_interval (config), - NM_CONNECTIVITY_RESPONSE, check_response ? check_response : DEFAULT_RESPONSE, + NM_CONNECTIVITY_RESPONSE, nm_config_get_connectivity_response (config), NULL); - g_return_val_if_fail (self != NULL, NULL); - update_state (self, NM_CONNECTIVITY_NONE); - - return self; -} - -static char * -get_non_empty_string_value (const GValue *val) -{ - const char *s; - - s = g_value_get_string (val); - if (s && s[0]) - return g_strdup (s); - else - return NULL; } static void @@ -317,32 +347,48 @@ set_property (GObject *object, guint property_id, { NMConnectivity *self = NM_CONNECTIVITY (object); NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self); + const char *uri, *response; + guint interval; switch (property_id) { case PROP_URI: - g_free (priv->uri); - priv->uri = get_non_empty_string_value (value); - + uri = g_value_get_string (value); + if (uri && !*uri) + uri = NULL; #if WITH_CONCHECK - if (priv->uri) { - SoupURI *uri = soup_uri_new (priv->uri); + if (uri) { + SoupURI *soup_uri = soup_uri_new (uri); - if (!uri || !SOUP_URI_VALID_FOR_HTTP (uri)) { - nm_log_err (LOGD_CONCHECK, "Invalid uri '%s' for connectivity check.", priv->uri); - g_free (priv->uri); - priv->uri = NULL; + if (!soup_uri || !SOUP_URI_VALID_FOR_HTTP (soup_uri)) { + nm_log_err (LOGD_CONCHECK, "Invalid uri '%s' for connectivity check.", uri); + uri = NULL; } - if (uri) - soup_uri_free (uri); + if (soup_uri) + soup_uri_free (soup_uri); } #endif + if (g_strcmp0 (uri, priv->uri) != 0) { + g_free (priv->uri); + priv->uri = g_strdup (uri); + _reschedule_periodic_checks (self, TRUE); + } break; case PROP_INTERVAL: - priv->interval = g_value_get_uint (value); + interval = g_value_get_uint (value); + if (priv->interval != interval) { + priv->interval = interval; + _reschedule_periodic_checks (self, TRUE); + } break; case PROP_RESPONSE: - g_free (priv->response); - priv->response = get_non_empty_string_value (value); + response = g_value_get_string (value); + if (g_strcmp0 (response, priv->response) != 0) { + /* a response %NULL means, DEFAULT_RESPONSE. Any other response + * (including "") is accepted. */ + g_free (priv->response); + priv->response = g_strdup (response); + _reschedule_periodic_checks (self, TRUE); + } break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -365,7 +411,10 @@ get_property (GObject *object, guint property_id, g_value_set_uint (value, priv->interval); break; case PROP_RESPONSE: - g_value_set_string (value, priv->response); + if (priv->response) + g_value_set_string (value, priv->response); + else + g_value_set_static_string (value, DEFAULT_RESPONSE); break; case PROP_STATE: g_value_set_uint (value, priv->state); @@ -380,11 +429,12 @@ get_property (GObject *object, guint property_id, static void nm_connectivity_init (NMConnectivity *self) { -#if WITH_CONCHECK NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self); +#if WITH_CONCHECK priv->soup_session = soup_session_async_new_with_options (SOUP_SESSION_TIMEOUT, 15, NULL); #endif + priv->state = NM_CONNECTIVITY_NONE; } From 3ed4aa271aa7db403a0dcaf8548a9b0c72b805fe Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 19 Jan 2015 19:06:27 +0100 Subject: [PATCH 07/32] connectivity: add logging macros to nm-connectivity.c They add a common prefix to all logging lines. --- src/nm-connectivity.c | 51 ++++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/src/nm-connectivity.c b/src/nm-connectivity.c index 406f41e329..21d4433d32 100644 --- a/src/nm-connectivity.c +++ b/src/nm-connectivity.c @@ -37,6 +37,23 @@ G_DEFINE_TYPE (NMConnectivity, nm_connectivity, G_TYPE_OBJECT) #define DEFAULT_RESPONSE "NetworkManager is online" /* NOT LOCALIZED */ +#define _LOG_DEFAULT_DOMAIN LOGD_CONCHECK + +#define _LOG(level, domain, ...) \ + G_STMT_START { \ + nm_log ((level), (domain), \ + "%s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + "connectivity: " \ + _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } G_STMT_END + +#define _LOGT(...) _LOG (LOGL_TRACE, _LOG_DEFAULT_DOMAIN, __VA_ARGS__) +#define _LOGD(...) _LOG (LOGL_DEBUG, _LOG_DEFAULT_DOMAIN, __VA_ARGS__) +#define _LOGI(...) _LOG (LOGL_INFO, _LOG_DEFAULT_DOMAIN, __VA_ARGS__) +#define _LOGW(...) _LOG (LOGL_WARN, _LOG_DEFAULT_DOMAIN, __VA_ARGS__) +#define _LOGE(...) _LOG (LOGL_ERR, _LOG_DEFAULT_DOMAIN, __VA_ARGS__) + + typedef struct { char *uri; char *response; @@ -95,9 +112,9 @@ update_state (NMConnectivity *self, NMConnectivityState state) NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self); if (priv->state != state) { - nm_log_dbg (LOGD_CONCHECK, "Connectivity state changed from %s to %s", - nm_connectivity_state_to_string (priv->state), - nm_connectivity_state_to_string (state)); + _LOGD ("state changed from %s to %s", + nm_connectivity_state_to_string (priv->state), + nm_connectivity_state_to_string (state)); priv->state = state; g_object_notify (G_OBJECT (self), NM_CONNECTIVITY_STATE); } @@ -129,8 +146,7 @@ nm_connectivity_check_cb (SoupSession *session, SoupMessage *msg, gpointer user_ priv = NM_CONNECTIVITY_GET_PRIVATE (self); if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)) { - nm_log_info (LOGD_CONCHECK, "Connectivity check for uri '%s' failed with '%s'.", - uri, msg->reason_phrase); + _LOGI ("check for uri '%s' failed with '%s'", uri, msg->reason_phrase); new_state = NM_CONNECTIVITY_LIMITED; goto done; } @@ -138,22 +154,21 @@ nm_connectivity_check_cb (SoupSession *session, SoupMessage *msg, gpointer user_ /* Check headers; if we find the NM-specific one we're done */ nm_header = soup_message_headers_get_one (msg->response_headers, "X-NetworkManager-Status"); if (g_strcmp0 (nm_header, "online") == 0) { - nm_log_dbg (LOGD_CONCHECK, "Connectivity check for uri '%s' with Status header successful.", uri); + _LOGD ("check for uri '%s' with Status header successful.", uri); new_state = NM_CONNECTIVITY_FULL; } else if (msg->status_code == SOUP_STATUS_OK) { /* check response */ if (msg->response_body->data && g_str_has_prefix (msg->response_body->data, response)) { - nm_log_dbg (LOGD_CONCHECK, "Connectivity check for uri '%s' successful.", - uri); + _LOGD ("check for uri '%s' successful.", uri); new_state = NM_CONNECTIVITY_FULL; } else { - nm_log_info (LOGD_CONCHECK, "Connectivity check for uri '%s' did not match expected response '%s'; assuming captive portal.", - uri, response); + _LOGI ("check for uri '%s' did not match expected response '%s'; assuming captive portal.", + uri, response); new_state = NM_CONNECTIVITY_PORTAL; } } else { - nm_log_info (LOGD_CONCHECK, "Connectivity check for uri '%s' returned status '%d %s'; assuming captive portal.", - uri, msg->status_code, msg->reason_phrase); + _LOGI ("check for uri '%s' returned status '%d %s'; assuming captive portal.", + uri, msg->status_code, msg->reason_phrase); new_state = NM_CONNECTIVITY_PORTAL; } @@ -190,7 +205,7 @@ run_check_complete (GObject *object, nm_connectivity_check_finish (self, result, &error); if (error) { - nm_log_err (LOGD_CONCHECK, "Connectivity check failed: %s", error->message); + _LOGE ("check failed: %s", error->message); g_error_free (error); } } @@ -255,7 +270,7 @@ nm_connectivity_set_online (NMConnectivity *self, online = !!online; if (priv->online != online) { - nm_log_dbg (LOGD_CONCHECK, "connectivity: set %s", online ? "online" : "offline"); + _LOGD ("set %s", online ? "online" : "offline"); priv->online = online; _reschedule_periodic_checks (self, FALSE); } @@ -295,14 +310,14 @@ nm_connectivity_check_async (NMConnectivity *self, cb_data); priv->initial_check_obsoleted = TRUE; - nm_log_dbg (LOGD_CONCHECK, "%sconnectivity check: send request to '%s'", IS_PERIODIC_CHECK (callback) ? "periodic " : "", priv->uri); + _LOGD ("check: send %srequest to '%s'", IS_PERIODIC_CHECK (callback) ? "periodic " : "", priv->uri); return; } else { g_warn_if_fail (!IS_PERIODIC_CHECK (callback)); - nm_log_dbg (LOGD_CONCHECK, "connectivity check: faking request. Connectivity check disabled"); + _LOGD ("check: faking request. Connectivity check disabled"); } #else - nm_log_dbg (LOGD_CONCHECK, "connectivity check: faking request. Compiled without connectivity-check support"); + _LOGD ("check: faking request. Compiled without connectivity-check support"); #endif g_simple_async_result_set_op_res_gssize (simple, priv->state); @@ -360,7 +375,7 @@ set_property (GObject *object, guint property_id, SoupURI *soup_uri = soup_uri_new (uri); if (!soup_uri || !SOUP_URI_VALID_FOR_HTTP (soup_uri)) { - nm_log_err (LOGD_CONCHECK, "Invalid uri '%s' for connectivity check.", uri); + _LOGE ("invalid uri '%s' for connectivity check.", uri); uri = NULL; } if (soup_uri) From 86ac1ad7bd185e7d8838676bde74458719833ca2 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 12 Dec 2014 13:44:37 +0100 Subject: [PATCH 08/32] config: forward declare NMConfig in nm-types.h --- src/nm-config.h | 4 ++-- src/nm-types.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/nm-config.h b/src/nm-config.h index 56f75fb5f6..ca9d3640f3 100644 --- a/src/nm-config.h +++ b/src/nm-config.h @@ -36,9 +36,9 @@ G_BEGIN_DECLS #define NM_IS_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_CONFIG)) #define NM_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_CONFIG, NMConfigClass)) -typedef struct { +struct _NMConfig { GObject parent; -} NMConfig; +}; typedef struct { GObjectClass parent; diff --git a/src/nm-types.h b/src/nm-types.h index 73a11e7567..bbdfce9b79 100644 --- a/src/nm-types.h +++ b/src/nm-types.h @@ -26,6 +26,7 @@ typedef struct _NMActiveConnection NMActiveConnection; typedef struct _NMVpnConnection NMVpnConnection; typedef struct _NMActRequest NMActRequest; typedef struct _NMAuthSubject NMAuthSubject; +typedef struct _NMConfig NMConfig; typedef struct _NMConnectionProvider NMConnectionProvider; typedef struct _NMConnectivity NMConnectivity; typedef struct _NMDBusManager NMDBusManager; From 643f042b9b181655fda6989ecf297b65c615f66c Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 15 Jan 2015 14:11:26 +0100 Subject: [PATCH 09/32] config: fix memory leak in merge_no_auto_default_state() --- src/nm-config.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/nm-config.c b/src/nm-config.c index fa9a894429..d3da01ba56 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -276,13 +276,17 @@ merge_no_auto_default_state (NMConfig *config) list = g_strsplit (data, "\n", -1); for (i = 0; list[i]; i++) { if (!*list[i]) - continue; - for (j = 0; j < updated->len; j++) { - if (!strcmp (list[i], updated->pdata[j])) - break; + g_free (list[i]); + else { + for (j = 0; j < updated->len; j++) { + if (!strcmp (list[i], updated->pdata[j])) + break; + } + if (j == updated->len) + g_ptr_array_add (updated, list[i]); + else + g_free (list[i]); } - if (j == updated->len) - g_ptr_array_add (updated, list[i]); } g_free (list); g_free (data); From 9387e8e8a7a76732ae0eed7732d1f284cf82148a Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 15 Jan 2015 15:46:19 +0100 Subject: [PATCH 10/32] config/trivial: fix returning FALSE instead of NULL in nm_config_new() --- src/nm-config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nm-config.c b/src/nm-config.c index d3da01ba56..be06955f64 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -578,7 +578,7 @@ nm_config_new (GError **error) } g_ptr_array_unref (confs); if (!singleton) - return FALSE; + return NULL; /* 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); From 1ff5154369f69f1e266521dd5f2ed53c37baa84f Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 9 Jul 2014 15:17:01 +0200 Subject: [PATCH 11/32] config: add nm_config_setup() to initialize config singleton Make nm_config_new() usable without accessing static/singleton data. nm_config_setup() is now used to initialize the singleton. Still, you must not call nm_config_get() before calling nm_config_setup() or after freeing the provided singleton instance. --- src/main-utils.c | 7 +- src/main-utils.h | 3 +- src/main.c | 9 +- src/nm-config.c | 207 ++++++++++++++++++++++----------- src/nm-config.h | 11 +- src/nm-iface-helper.c | 1 + src/tests/config/test-config.c | 79 ++++++------- 7 files changed, 199 insertions(+), 118 deletions(-) diff --git a/src/main-utils.c b/src/main-utils.c index 0825a7f01d..909ef28ad1 100644 --- a/src/main-utils.c +++ b/src/main-utils.c @@ -177,7 +177,8 @@ nm_main_utils_early_setup (const char *progname, char **argv[], int *argc, GOptionEntry *options, - GOptionEntry *more_options, + void (*option_context_hook) (gpointer user_data, GOptionContext *opt_ctx), + gpointer option_context_hook_data, const char *summary) { GOptionContext *opt_ctx = NULL; @@ -220,9 +221,9 @@ nm_main_utils_early_setup (const char *progname, g_option_context_set_ignore_unknown_options (opt_ctx, FALSE); g_option_context_set_help_enabled (opt_ctx, TRUE); g_option_context_add_main_entries (opt_ctx, options, NULL); - if (more_options) - g_option_context_add_main_entries (opt_ctx, more_options, NULL); g_option_context_set_summary (opt_ctx, summary); + if (option_context_hook) + option_context_hook (option_context_hook_data, opt_ctx); success = g_option_context_parse (opt_ctx, argc, argv, &error); if (!success) { diff --git a/src/main-utils.h b/src/main-utils.h index 30c8213ed3..432833f31d 100644 --- a/src/main-utils.h +++ b/src/main-utils.h @@ -33,7 +33,8 @@ gboolean nm_main_utils_early_setup (const char *progname, char **argv[], int *argc, GOptionEntry *options, - GOptionEntry *more_options, + void (*option_context_hook) (gpointer user_data, GOptionContext *opt_ctx), + gpointer option_context_hook_data, const char *summary); #endif /* __MAIN_UTILS_H__ */ diff --git a/src/main.c b/src/main.c index 2d6af01594..5432e1f3e8 100644 --- a/src/main.c +++ b/src/main.c @@ -204,6 +204,7 @@ main (int argc, char *argv[]) GError *error = NULL; gboolean wrote_pidfile = FALSE; char *bad_domains = NULL; + NMConfigCmdLineOptions *config_cli; GOptionEntry options[] = { { "version", 'V', 0, G_OPTION_ARG_NONE, &show_version, N_("Print NetworkManager version and exit"), NULL }, @@ -224,11 +225,13 @@ main (int argc, char *argv[]) main_loop = g_main_loop_new (NULL, FALSE); + config_cli = nm_config_cmd_line_options_new (); if (!nm_main_utils_early_setup ("NetworkManager", &argv, &argc, options, - nm_config_get_options (), + (void (*)(gpointer, GOptionContext *)) nm_config_cmd_line_options_add_to_entries, + config_cli, _("NetworkManager monitors all network connections and automatically\nchooses the best connection to use. It also allows the user to\nspecify wireless access points which wireless cards in the computer\nshould associate with."))) exit (1); @@ -290,7 +293,9 @@ main (int argc, char *argv[]) exit (1); /* Read the config file and CLI overrides */ - config = nm_config_new (&error); + config = nm_config_setup (config_cli, &error); + nm_config_cmd_line_options_free (config_cli); + config_cli = NULL; if (config == NULL) { fprintf (stderr, _("Failed to read configuration: (%d) %s\n"), error ? error->code : -1, diff --git a/src/nm-config.c b/src/nm-config.c index be06955f64..dd5b2a6d10 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -38,7 +38,23 @@ #define NM_OLD_SYSTEM_CONF_FILE NMCONFDIR "/nm-system-settings.conf" #define NM_NO_AUTO_DEFAULT_STATE_FILE NMSTATEDIR "/no-auto-default.state" +struct NMConfigCmdLineOptions { + char *config_path; + char *config_dir; + char *no_auto_default_file; + char *plugins; + char *connectivity_uri; + + /* We store interval as signed internally to track whether it's + * set or not via GOptionEntry + */ + int connectivity_interval; + char *connectivity_response; +}; + typedef struct { + NMConfigCmdLineOptions cli; + char *nm_conf_path; char *config_dir; char *config_description; @@ -57,7 +73,7 @@ typedef struct { char *debug; char *connectivity_uri; - gint connectivity_interval; + guint connectivity_interval; char *connectivity_response; char **no_auto_default; @@ -66,8 +82,6 @@ typedef struct { gboolean configure_and_quit; } NMConfigPrivate; -static NMConfig *singleton = NULL; - G_DEFINE_TYPE (NMConfig, nm_config, G_TYPE_OBJECT) #define NM_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_CONFIG, NMConfigPrivate)) @@ -202,10 +216,7 @@ nm_config_get_connectivity_interval (NMConfig *config) { g_return_val_if_fail (config != NULL, 0); - /* We store interval as signed internally to track whether it's - * set or not, but report as unsigned to callers. - */ - return MAX (NM_CONFIG_GET_PRIVATE (config)->connectivity_interval, 0); + return NM_CONFIG_GET_PRIVATE (config)->connectivity_interval; } const char * @@ -348,30 +359,76 @@ nm_config_set_ethernet_no_auto_default (NMConfig *config, NMDevice *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_connectivity_uri; -static int cli_connectivity_interval = -1; -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") }, - - /* These three are hidden for now, and should eventually just go away. */ - { "connectivity-uri", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &cli_connectivity_uri, N_("An http(s) address for checking internet connectivity"), "http://example.com" }, - { "connectivity-interval", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_INT, &cli_connectivity_interval, N_("The interval between connectivity checks (in seconds)"), "60" }, - { "connectivity-response", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &cli_connectivity_response, N_("The expected start of the response"), N_("Bingo!") }, - {NULL} -}; -GOptionEntry * -nm_config_get_options (void) +static void +_nm_config_cmd_line_options_clear (NMConfigCmdLineOptions *cli) { - return config_options; + 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->connectivity_uri, g_free); + g_clear_pointer (&cli->connectivity_response, g_free); + cli->connectivity_interval = -1; +} + +static void +_nm_config_cmd_line_options_copy (const NMConfigCmdLineOptions *cli, NMConfigCmdLineOptions *dst) +{ + g_return_if_fail (cli); + g_return_if_fail (dst); + g_return_if_fail (cli != dst); + + _nm_config_cmd_line_options_clear (dst); + dst->config_dir = g_strdup (cli->config_dir); + dst->config_path = g_strdup (cli->config_path); + dst->no_auto_default_file = g_strdup (cli->no_auto_default_file); + dst->plugins = g_strdup (cli->plugins); + dst->connectivity_uri = g_strdup (cli->connectivity_uri); + dst->connectivity_response = g_strdup (cli->connectivity_response); + dst->connectivity_interval = cli->connectivity_interval; +} + +NMConfigCmdLineOptions * +nm_config_cmd_line_options_new () +{ + NMConfigCmdLineOptions *cli = g_new0 (NMConfigCmdLineOptions, 1); + + _nm_config_cmd_line_options_clear (cli); + return cli; +} + +void +nm_config_cmd_line_options_free (NMConfigCmdLineOptions *cli) +{ + g_return_if_fail (cli); + + _nm_config_cmd_line_options_clear (cli); + g_free (cli); +} + +void +nm_config_cmd_line_options_add_to_entries (NMConfigCmdLineOptions *cli, + GOptionContext *opt_ctx) +{ + g_return_if_fail (opt_ctx); + g_return_if_fail (cli); + + { + 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") }, + + /* These three are hidden for now, and should eventually just go away. */ + { "connectivity-uri", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &cli->connectivity_uri, N_("An http(s) address for checking internet connectivity"), "http://example.com" }, + { "connectivity-interval", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_INT, &cli->connectivity_interval, N_("The interval between connectivity checks (in seconds)"), "60" }, + { "connectivity-response", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &cli->connectivity_response, N_("The expected start of the response"), N_("Bingo!") }, + { 0 }, + }; + + g_option_context_add_main_entries (opt_ctx, config_options, NULL); + } } /************************************************************************/ @@ -445,10 +502,10 @@ find_base_config (NMConfig *config, GError **error) GError *my_error = NULL; /* Try a user-specified config file first */ - if (cli_config_path) { + if (priv->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); + if (read_config (config, priv->cli.config_path, error)) { + priv->nm_conf_path = g_strdup (priv->cli.config_path); return TRUE; } else return FALSE; @@ -500,11 +557,25 @@ find_base_config (NMConfig *config, GError **error) /************************************************************************/ +NM_DEFINE_SINGLETON_DESTRUCTOR (NMConfig); +NM_DEFINE_SINGLETON_WEAK_REF (NMConfig); + NMConfig * nm_config_get (void) { - g_assert (singleton); - return singleton; + g_assert (singleton_instance); + return singleton_instance; +} + +NMConfig * +nm_config_setup (const NMConfigCmdLineOptions *cli, GError **error) +{ + g_assert (!singleton_instance); + + singleton_instance = nm_config_new (cli, error); + if (singleton_instance) + nm_singleton_instance_weak_ref_register (); + return singleton_instance; } static int @@ -516,9 +587,8 @@ sort_asciibetically (gconstpointer a, gconstpointer b) return strcmp (s1, s2); } -/* call this function only once! */ NMConfig * -nm_config_new (GError **error) +nm_config_new (const NMConfigCmdLineOptions *cli, GError **error) { NMConfigPrivate *priv = NULL; GFile *dir; @@ -528,21 +598,25 @@ nm_config_new (GError **error) const char *name; int i; GString *config_description; + NMConfig *self; - g_assert (!singleton); - singleton = NM_CONFIG (g_object_new (NM_TYPE_CONFIG, NULL)); - priv = NM_CONFIG_GET_PRIVATE (singleton); + self = NM_CONFIG (g_object_new (NM_TYPE_CONFIG, NULL)); + priv = NM_CONFIG_GET_PRIVATE (self); + + if (!cli) + _nm_config_cmd_line_options_clear (&priv->cli); + else + _nm_config_cmd_line_options_copy (cli, &priv->cli); /* First read the base config file */ - if (!find_base_config (singleton, error)) { - g_object_unref (singleton); - singleton = NULL; + if (!find_base_config (self, error)) { + g_object_unref (self); return NULL; } /* Now read the overrides in the config dir */ - if (cli_config_dir) - priv->config_dir = g_strdup (cli_config_dir); + if (priv->cli.config_dir) + priv->config_dir = g_strdup (priv->cli.config_dir); else priv->config_dir = g_strdup (NM_DEFAULT_SYSTEM_CONF_DIR); @@ -570,27 +644,27 @@ nm_config_new (GError **error) g_ptr_array_sort (confs, sort_asciibetically); priv->config_description = g_string_free (config_description, FALSE); for (i = 0; i < confs->len; i++) { - if (!read_config (singleton, confs->pdata[i], error)) { - g_object_unref (singleton); - singleton = NULL; + if (!read_config (self, confs->pdata[i], error)) { + g_object_unref (self); + self = NULL; break; } } g_ptr_array_unref (confs); - if (!singleton) + if (!self) return NULL; /* 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); + if (priv->cli.no_auto_default_file) + priv->no_auto_default_file = g_strdup (priv->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); + merge_no_auto_default_state (self); /* 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); + if (priv->cli.plugins && priv->cli.plugins[0]) + g_key_file_set_value (priv->keyfile, "main", "plugins", priv->cli.plugins); priv->plugins = g_key_file_get_string_list (priv->keyfile, "main", "plugins", NULL, NULL); if (!priv->plugins && STRLEN (CONFIG_PLUGINS_DEFAULT) > 0) priv->plugins = g_strsplit (CONFIG_PLUGINS_DEFAULT, ",", -1); @@ -607,23 +681,23 @@ nm_config_new (GError **error) priv->debug = g_key_file_get_value (priv->keyfile, "main", "debug", NULL); - if (cli_connectivity_uri && cli_connectivity_uri[0]) - g_key_file_set_value (priv->keyfile, "connectivity", "uri", cli_connectivity_uri); + if (priv->cli.connectivity_uri && priv->cli.connectivity_uri[0]) + g_key_file_set_value (priv->keyfile, "connectivity", "uri", priv->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); + if (priv->cli.connectivity_interval >= 0) + g_key_file_set_integer (priv->keyfile, "connectivity", "interval", priv->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); + if (priv->cli.connectivity_response && priv->cli.connectivity_response[0]) + g_key_file_set_value (priv->keyfile, "connectivity", "response", priv->cli.connectivity_response); priv->connectivity_response = g_key_file_get_value (priv->keyfile, "connectivity", "response", NULL); priv->ignore_carrier = g_key_file_get_string_list (priv->keyfile, "main", "ignore-carrier", NULL, NULL); priv->configure_and_quit = _get_bool_value (priv->keyfile, "main", "configure-and-quit", FALSE); - return singleton; + return self; } static void @@ -635,8 +709,6 @@ nm_config_init (NMConfig *config) priv->keyfile = g_key_file_new (); g_key_file_set_list_separator (priv->keyfile, ','); - - priv->connectivity_interval = -1; } static void @@ -660,14 +732,7 @@ finalize (GObject *gobject) g_strfreev (priv->no_auto_default); g_strfreev (priv->ignore_carrier); - 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_connectivity_uri, g_free); - g_clear_pointer (&cli_connectivity_response, g_free); + _nm_config_cmd_line_options_clear (&priv->cli); G_OBJECT_CLASS (nm_config_parent_class)->finalize (gobject); } diff --git a/src/nm-config.h b/src/nm-config.h index ca9d3640f3..e62edd7a59 100644 --- a/src/nm-config.h +++ b/src/nm-config.h @@ -36,6 +36,8 @@ G_BEGIN_DECLS #define NM_IS_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_CONFIG)) #define NM_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_CONFIG, NMConfigClass)) +typedef struct NMConfigCmdLineOptions NMConfigCmdLineOptions; + struct _NMConfig { GObject parent; }; @@ -71,8 +73,13 @@ gboolean nm_config_get_ignore_carrier (NMConfig *config, NMDevice *device); char *nm_config_get_value (NMConfig *config, const char *group, const char *key, GError **error); /* for main.c only */ -GOptionEntry *nm_config_get_options (void); -NMConfig *nm_config_new (GError **error); +NMConfigCmdLineOptions *nm_config_cmd_line_options_new (void); +void nm_config_cmd_line_options_free (NMConfigCmdLineOptions *cli); +void nm_config_cmd_line_options_add_to_entries (NMConfigCmdLineOptions *cli, + GOptionContext *opt_ctx); + +NMConfig *nm_config_new (const NMConfigCmdLineOptions *cli, GError **error); +NMConfig *nm_config_setup (const NMConfigCmdLineOptions *cli, GError **error); G_END_DECLS diff --git a/src/nm-iface-helper.c b/src/nm-iface-helper.c index 2d3768beb6..8b61b5252f 100644 --- a/src/nm-iface-helper.c +++ b/src/nm-iface-helper.c @@ -315,6 +315,7 @@ main (int argc, char *argv[]) &argc, options, NULL, + NULL, _("nm-iface-helper is a small, standalone process that manages a single network interface."))) exit (1); diff --git a/src/tests/config/test-config.c b/src/tests/config/test-config.c index 808fc670b3..e47be92af4 100644 --- a/src/tests/config/test-config.c +++ b/src/tests/config/test-config.c @@ -28,8 +28,8 @@ #include "nm-test-device.h" #include "nm-fake-platform.h" -static void -setup_config (const char *config_file, const char *config_dir, ...) +static NMConfig * +setup_config (GError **error, const char *config_file, const char *config_dir, ...) { va_list ap; GPtrArray *args; @@ -37,6 +37,11 @@ setup_config (const char *config_file, const char *config_dir, ...) int argc; GOptionContext *context; gboolean success; + NMConfig *config; + GError *local_error = NULL; + NMConfigCmdLineOptions *cli; + + g_assert (!error || !*error); args = g_ptr_array_new (); g_ptr_array_add (args, "test-config"); @@ -53,8 +58,10 @@ setup_config (const char *config_file, const char *config_dir, ...) argv = (char **)args->pdata; argc = args->len; + cli = nm_config_cmd_line_options_new (); + context = g_option_context_new (NULL); - g_option_context_add_main_entries (context, nm_config_get_options (), NULL); + nm_config_cmd_line_options_add_to_entries (cli, context); success = g_option_context_parse (context, &argc, &argv, NULL); g_option_context_free (context); @@ -62,6 +69,18 @@ setup_config (const char *config_file, const char *config_dir, ...) g_printerr ("Invalid options.\n"); g_ptr_array_free (args, TRUE); + + config = nm_config_setup (cli, &local_error); + if (error) { + g_assert (!config); + g_assert (local_error); + g_propagate_error (error, local_error); + } else { + g_assert (config); + g_assert_no_error (local_error); + } + nm_config_cmd_line_options_free (cli); + return config; } static void @@ -72,9 +91,7 @@ test_config_simple (void) const char **plugins; char *value; - setup_config (SRCDIR "/NetworkManager.conf", "/no/such/dir", NULL); - config = nm_config_new (&error); - g_assert_no_error (error); + config = setup_config (NULL, SRCDIR "/NetworkManager.conf", "/no/such/dir", NULL); g_assert_cmpstr (nm_config_get_path (config), ==, SRCDIR "/NetworkManager.conf"); g_assert_cmpstr (nm_config_get_dhcp_client (config), ==, "dhclient"); @@ -107,40 +124,33 @@ test_config_simple (void) static void test_config_non_existent (void) { - NMConfig *config; GError *error = NULL; - setup_config (SRCDIR "/no-such-file", "/no/such/dir", NULL); - config = nm_config_new (&error); - g_assert (!config); + 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); } static void test_config_parse_error (void) { - NMConfig *config; GError *error = NULL; - setup_config (SRCDIR "/bad.conf", "/no/such/dir", NULL); - config = nm_config_new (&error); - g_assert (!config); + 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); } static void test_config_override (void) { NMConfig *config; - GError *error = NULL; const char **plugins; - setup_config (SRCDIR "/NetworkManager.conf", "/no/such/dir", - "--plugins", "alpha,beta,gamma,delta", - "--connectivity-interval", "12", - NULL); - config = nm_config_new (&error); - g_assert_no_error (error); + config = setup_config (NULL, SRCDIR "/NetworkManager.conf", "/no/such/dir", + "--plugins", "alpha,beta,gamma,delta", + "--connectivity-interval", "12", + NULL); g_assert_cmpstr (nm_config_get_path (config), ==, SRCDIR "/NetworkManager.conf"); g_assert_cmpstr (nm_config_get_dhcp_client (config), ==, "dhclient"); @@ -175,11 +185,9 @@ test_config_no_auto_default (void) g_assert_cmpint (nwrote, ==, 18); close (fd); - setup_config (SRCDIR "/NetworkManager.conf", "/no/such/dir", - "--no-auto-default", state_file, - NULL); - config = nm_config_new (&error); - g_assert_no_error (error); + config = setup_config (NULL, SRCDIR "/NetworkManager.conf", "/no/such/dir", + "--no-auto-default", state_file, + NULL); dev1 = nm_test_device_new ("11:11:11:11:11:11"); dev2 = nm_test_device_new ("22:22:22:22:22:22"); @@ -196,11 +204,9 @@ test_config_no_auto_default (void) g_object_unref (config); - setup_config (SRCDIR "/NetworkManager.conf", "/no/such/dir", - "--no-auto-default", state_file, - NULL); - config = nm_config_new (&error); - g_assert_no_error (error); + config = setup_config (NULL, SRCDIR "/NetworkManager.conf", "/no/such/dir", + "--no-auto-default", state_file, + NULL); g_assert (!nm_config_get_ethernet_can_auto_default (config, dev1)); g_assert (!nm_config_get_ethernet_can_auto_default (config, dev2)); @@ -222,13 +228,10 @@ 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); + config = setup_config (NULL, SRCDIR "/NetworkManager.conf", SRCDIR "/conf.d", NULL); g_assert_cmpstr (nm_config_get_path (config), ==, SRCDIR "/NetworkManager.conf"); g_assert_cmpstr (nm_config_get_dhcp_client (config), ==, "dhcpcd"); @@ -269,14 +272,12 @@ test_config_confdir (void) 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 (!config); + 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); } int From 076478505dd1c278898d64d389184d7fb2b6c158 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 11 Jul 2014 17:57:20 +0200 Subject: [PATCH 12/32] config: add new NMConfigData class The NMConfig class should be immutable and its properties should not change, with one exception: the NMConfigData property. Later, when changing/reloading a configuration, NMConfig will only swap the NMConfigData instance. The NMConfigData instance itself is also immutable. --- src/Makefile.am | 2 + src/nm-config-data.c | 183 +++++++++++++++++++++++++++++++++++++++++++ src/nm-config-data.h | 65 +++++++++++++++ src/nm-types.h | 1 + 4 files changed, 251 insertions(+) create mode 100644 src/nm-config-data.c create mode 100644 src/nm-config-data.h diff --git a/src/Makefile.am b/src/Makefile.am index a5a40fba35..e0ed6f3f66 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -287,6 +287,8 @@ nm_sources = \ nm-active-connection.h \ nm-config.c \ nm-config.h \ + nm-config-data.c \ + nm-config-data.h \ nm-connection-provider.c \ nm-connection-provider.h \ nm-connectivity.c \ diff --git a/src/nm-config-data.c b/src/nm-config-data.c new file mode 100644 index 0000000000..a5722453ed --- /dev/null +++ b/src/nm-config-data.c @@ -0,0 +1,183 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2011 Red Hat, Inc. + * Copyright (C) 2013 Thomas Bechtold + */ + +#include "nm-config-data.h" + +typedef struct { + struct { + char *uri; + char *response; + guint interval; + } connectivity; +} NMConfigDataPrivate; + + +enum { + PROP_0, + PROP_CONNECTIVITY_URI, + PROP_CONNECTIVITY_INTERVAL, + PROP_CONNECTIVITY_RESPONSE, + + LAST_PROP +}; + +G_DEFINE_TYPE (NMConfigData, nm_config_data, G_TYPE_OBJECT) + +#define NM_CONFIG_DATA_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_CONFIG_DATA, NMConfigDataPrivate)) + +/************************************************************************/ + +const char * +nm_config_data_get_connectivity_uri (const NMConfigData *self) +{ + g_return_val_if_fail (self, NULL); + + return NM_CONFIG_DATA_GET_PRIVATE (self)->connectivity.uri; +} + +const guint +nm_config_data_get_connectivity_interval (const NMConfigData *self) +{ + g_return_val_if_fail (self, 0); + + return MAX (NM_CONFIG_DATA_GET_PRIVATE (self)->connectivity.interval, 0); +} + +const char * +nm_config_data_get_connectivity_response (const NMConfigData *self) +{ + g_return_val_if_fail (self != NULL, NULL); + + return NM_CONFIG_DATA_GET_PRIVATE (self)->connectivity.response; +} + + +/************************************************************************/ + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMConfigData *self = NM_CONFIG_DATA (object); + + switch (prop_id) { + case PROP_CONNECTIVITY_URI: + g_value_set_string (value, nm_config_data_get_connectivity_uri (self)); + break; + case PROP_CONNECTIVITY_INTERVAL: + g_value_set_uint (value, nm_config_data_get_connectivity_interval (self)); + break; + case PROP_CONNECTIVITY_RESPONSE: + g_value_set_string (value, nm_config_data_get_connectivity_response (self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + NMConfigData *self = NM_CONFIG_DATA (object); + NMConfigDataPrivate *priv = NM_CONFIG_DATA_GET_PRIVATE (self); + + /* This type is immutable. All properties are construct only. */ + switch (prop_id) { + case PROP_CONNECTIVITY_URI: + priv->connectivity.uri = g_value_dup_string (value); + break; + case PROP_CONNECTIVITY_INTERVAL: + priv->connectivity.interval = g_value_get_uint (value); + break; + case PROP_CONNECTIVITY_RESPONSE: + priv->connectivity.response = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +dispose (GObject *object) +{ +} + +static void +finalize (GObject *gobject) +{ + NMConfigDataPrivate *priv = NM_CONFIG_DATA_GET_PRIVATE (gobject); + + g_free (priv->connectivity.uri); + g_free (priv->connectivity.response); + + G_OBJECT_CLASS (nm_config_data_parent_class)->finalize (gobject); +} + +static void +nm_config_data_init (NMConfigData *self) +{ +} + +static void +nm_config_data_class_init (NMConfigDataClass *config_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (config_class); + + g_type_class_add_private (config_class, sizeof (NMConfigDataPrivate)); + + object_class->dispose = dispose; + object_class->finalize = finalize; + object_class->get_property = get_property; + object_class->set_property = set_property; + + g_object_class_install_property + (object_class, PROP_CONNECTIVITY_URI, + g_param_spec_string (NM_CONFIG_DATA_CONNECTIVITY_URI, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_CONNECTIVITY_INTERVAL, + g_param_spec_uint (NM_CONFIG_DATA_CONNECTIVITY_INTERVAL, "", "", + 0, G_MAXUINT, 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_CONNECTIVITY_RESPONSE, + g_param_spec_string (NM_CONFIG_DATA_CONNECTIVITY_RESPONSE, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + +} + diff --git a/src/nm-config-data.h b/src/nm-config-data.h new file mode 100644 index 0000000000..1437781e7d --- /dev/null +++ b/src/nm-config-data.h @@ -0,0 +1,65 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2014 Red Hat, Inc. + */ + +#ifndef NM_CONFIG_DATA_H +#define NM_CONFIG_DATA_H + +#include +#include + +#include "nm-types.h" + +G_BEGIN_DECLS + +#define NM_TYPE_CONFIG_DATA (nm_config_data_get_type ()) +#define NM_CONFIG_DATA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_CONFIG_DATA, NMConfigData)) +#define NM_CONFIG_DATA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_CONFIG_DATA, NMConfigDataClass)) +#define NM_IS_CONFIG_DATA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_CONFIG_DATA)) +#define NM_IS_CONFIG_DATA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_CONFIG_DATA)) +#define NM_CONFIG_DATA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_CONFIG_DATA, NMConfigDataClass)) + + +#define NM_CONFIG_DATA_CONNECTIVITY_URI "connectivity-uri" +#define NM_CONFIG_DATA_CONNECTIVITY_INTERVAL "connectivity-interval" +#define NM_CONFIG_DATA_CONNECTIVITY_RESPONSE "connectivity-response" + +struct _NMConfigData { + GObject parent; +}; + +typedef struct { + GObjectClass parent; +} NMConfigDataClass; + +GType nm_config_data_get_type (void); + +const char *nm_config_data_get_connectivity_uri (const NMConfigData *config_data); +const guint nm_config_data_get_connectivity_interval (const NMConfigData *config_data); +const char *nm_config_data_get_connectivity_response (const NMConfigData *config_data); + +#include "nm-config.h" + +/* private function: internal use only */ +void _nm_config_data_set_config (NMConfigData *config_data, NMConfig *config); + +G_END_DECLS + +#endif /* NM_CONFIG_DATA_H */ + diff --git a/src/nm-types.h b/src/nm-types.h index bbdfce9b79..7229eba8b0 100644 --- a/src/nm-types.h +++ b/src/nm-types.h @@ -27,6 +27,7 @@ typedef struct _NMVpnConnection NMVpnConnection; typedef struct _NMActRequest NMActRequest; typedef struct _NMAuthSubject NMAuthSubject; typedef struct _NMConfig NMConfig; +typedef struct _NMConfigData NMConfigData; typedef struct _NMConnectionProvider NMConnectionProvider; typedef struct _NMConnectivity NMConnectivity; typedef struct _NMDBusManager NMDBusManager; From 50fce5a860479016470117ded4fb7ea947c27c1c Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 11 Jul 2014 18:54:18 +0200 Subject: [PATCH 13/32] config: use NMConfigData in NMConfig --- src/nm-config.c | 72 ++++++++++++++++++---------------- src/nm-config.h | 6 +-- src/nm-connectivity.c | 8 ++-- src/tests/config/test-config.c | 8 ++-- 4 files changed, 50 insertions(+), 44 deletions(-) diff --git a/src/nm-config.c b/src/nm-config.c index dd5b2a6d10..742a72e38c 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -55,6 +55,9 @@ struct NMConfigCmdLineOptions { typedef struct { NMConfigCmdLineOptions cli; + NMConfigData *config_data; + NMConfigData *config_data_orig; + char *nm_conf_path; char *config_dir; char *config_description; @@ -72,10 +75,6 @@ typedef struct { char *debug; - char *connectivity_uri; - guint connectivity_interval; - char *connectivity_response; - char **no_auto_default; char **ignore_carrier; @@ -123,6 +122,25 @@ _get_bool_value (GKeyFile *keyfile, /************************************************************************/ +NMConfigData * +nm_config_get_data (NMConfig *config) +{ + g_return_val_if_fail (config != NULL, NULL); + + return NM_CONFIG_GET_PRIVATE (config)->config_data; +} + +/* The NMConfigData instance is reloadable and will be swapped on reload. + * nm_config_get_data_orig() returns the original configuration, when the NMConfig + * instance was created. */ +NMConfigData * +nm_config_get_data_orig (NMConfig *config) +{ + g_return_val_if_fail (config != NULL, NULL); + + return NM_CONFIG_GET_PRIVATE (config)->config_data_orig; +} + const char * nm_config_get_path (NMConfig *config) { @@ -203,30 +221,6 @@ nm_config_get_debug (NMConfig *config) return NM_CONFIG_GET_PRIVATE (config)->debug; } -const char * -nm_config_get_connectivity_uri (NMConfig *config) -{ - g_return_val_if_fail (config != NULL, NULL); - - return NM_CONFIG_GET_PRIVATE (config)->connectivity_uri; -} - -guint -nm_config_get_connectivity_interval (NMConfig *config) -{ - g_return_val_if_fail (config != NULL, 0); - - return NM_CONFIG_GET_PRIVATE (config)->connectivity_interval; -} - -const char * -nm_config_get_connectivity_response (NMConfig *config) -{ - g_return_val_if_fail (config != NULL, NULL); - - return NM_CONFIG_GET_PRIVATE (config)->connectivity_response; -} - gboolean nm_config_get_configure_and_quit (NMConfig *config) { @@ -599,6 +593,8 @@ nm_config_new (const NMConfigCmdLineOptions *cli, GError **error) int i; GString *config_description; NMConfig *self; + char *connectivity_uri, *connectivity_response; + guint connectivity_interval; self = NM_CONFIG (g_object_new (NM_TYPE_CONFIG, NULL)); priv = NM_CONFIG_GET_PRIVATE (self); @@ -683,20 +679,29 @@ nm_config_new (const NMConfigCmdLineOptions *cli, GError **error) if (priv->cli.connectivity_uri && priv->cli.connectivity_uri[0]) g_key_file_set_value (priv->keyfile, "connectivity", "uri", priv->cli.connectivity_uri); - priv->connectivity_uri = g_key_file_get_value (priv->keyfile, "connectivity", "uri", NULL); + connectivity_uri = g_key_file_get_value (priv->keyfile, "connectivity", "uri", NULL); if (priv->cli.connectivity_interval >= 0) g_key_file_set_integer (priv->keyfile, "connectivity", "interval", priv->cli.connectivity_interval); - priv->connectivity_interval = g_key_file_get_integer (priv->keyfile, "connectivity", "interval", NULL); + connectivity_interval = g_key_file_get_integer (priv->keyfile, "connectivity", "interval", NULL); if (priv->cli.connectivity_response && priv->cli.connectivity_response[0]) g_key_file_set_value (priv->keyfile, "connectivity", "response", priv->cli.connectivity_response); - priv->connectivity_response = g_key_file_get_value (priv->keyfile, "connectivity", "response", NULL); + connectivity_response = g_key_file_get_value (priv->keyfile, "connectivity", "response", NULL); priv->ignore_carrier = g_key_file_get_string_list (priv->keyfile, "main", "ignore-carrier", NULL, NULL); priv->configure_and_quit = _get_bool_value (priv->keyfile, "main", "configure-and-quit", FALSE); + priv->config_data = g_object_new (NM_TYPE_CONFIG_DATA, + NM_CONFIG_DATA_CONNECTIVITY_URI, connectivity_uri, + NM_CONFIG_DATA_CONNECTIVITY_INTERVAL, connectivity_interval, + NM_CONFIG_DATA_CONNECTIVITY_RESPONSE, connectivity_response, + NULL); + priv->config_data_orig = g_object_ref (priv->config_data); + g_free (connectivity_uri); + g_free (connectivity_response); + return self; } @@ -727,13 +732,14 @@ finalize (GObject *gobject) g_free (priv->log_level); g_free (priv->log_domains); g_free (priv->debug); - g_free (priv->connectivity_uri); - g_free (priv->connectivity_response); g_strfreev (priv->no_auto_default); g_strfreev (priv->ignore_carrier); _nm_config_cmd_line_options_clear (&priv->cli); + g_clear_object (&priv->config_data); + g_clear_object (&priv->config_data_orig); + G_OBJECT_CLASS (nm_config_parent_class)->finalize (gobject); } diff --git a/src/nm-config.h b/src/nm-config.h index e62edd7a59..3b0ee6cfae 100644 --- a/src/nm-config.h +++ b/src/nm-config.h @@ -26,6 +26,7 @@ #include #include "nm-types.h" +#include "nm-config-data.h" G_BEGIN_DECLS @@ -50,6 +51,8 @@ GType nm_config_get_type (void); NMConfig *nm_config_get (void); +NMConfigData *nm_config_get_data (NMConfig *config); +NMConfigData *nm_config_get_data_orig (NMConfig *config); const char *nm_config_get_path (NMConfig *config); const char *nm_config_get_description (NMConfig *config); const char **nm_config_get_plugins (NMConfig *config); @@ -60,9 +63,6 @@ const char *nm_config_get_dns_mode (NMConfig *config); const char *nm_config_get_log_level (NMConfig *config); const char *nm_config_get_log_domains (NMConfig *config); const char *nm_config_get_debug (NMConfig *config); -const char *nm_config_get_connectivity_uri (NMConfig *config); -guint nm_config_get_connectivity_interval (NMConfig *config); -const char *nm_config_get_connectivity_response (NMConfig *config); gboolean nm_config_get_configure_and_quit (NMConfig *config); gboolean nm_config_get_ethernet_can_auto_default (NMConfig *config, NMDevice *device); diff --git a/src/nm-connectivity.c b/src/nm-connectivity.c index 21d4433d32..a96f47abf8 100644 --- a/src/nm-connectivity.c +++ b/src/nm-connectivity.c @@ -344,15 +344,15 @@ nm_connectivity_check_finish (NMConnectivity *self, NMConnectivity * nm_connectivity_new (void) { - NMConfig *config = nm_config_get (); + NMConfigData *config_data = nm_config_get_data (nm_config_get ()); /* NMConnectivity is (almost) independent from NMConfig and works * fine without it. As convenience, the default constructor nm_connectivity_new() * uses the parameters from NMConfig to create an instance. */ return g_object_new (NM_TYPE_CONNECTIVITY, - NM_CONNECTIVITY_URI, nm_config_get_connectivity_uri (config), - NM_CONNECTIVITY_INTERVAL, nm_config_get_connectivity_interval (config), - NM_CONNECTIVITY_RESPONSE, nm_config_get_connectivity_response (config), + NM_CONNECTIVITY_URI, nm_config_data_get_connectivity_uri (config_data), + NM_CONNECTIVITY_INTERVAL, nm_config_data_get_connectivity_interval (config_data), + NM_CONNECTIVITY_RESPONSE, nm_config_data_get_connectivity_response (config_data), NULL); } diff --git a/src/tests/config/test-config.c b/src/tests/config/test-config.c index e47be92af4..bd934373b1 100644 --- a/src/tests/config/test-config.c +++ b/src/tests/config/test-config.c @@ -96,7 +96,7 @@ test_config_simple (void) g_assert_cmpstr (nm_config_get_path (config), ==, SRCDIR "/NetworkManager.conf"); g_assert_cmpstr (nm_config_get_dhcp_client (config), ==, "dhclient"); g_assert_cmpstr (nm_config_get_log_level (config), ==, "INFO"); - g_assert_cmpint (nm_config_get_connectivity_interval (config), ==, 100); + g_assert_cmpint (nm_config_data_get_connectivity_interval (nm_config_get_data_orig (config)), ==, 100); plugins = nm_config_get_plugins (config); g_assert_cmpint (g_strv_length ((char **)plugins), ==, 3); @@ -155,7 +155,7 @@ test_config_override (void) g_assert_cmpstr (nm_config_get_path (config), ==, SRCDIR "/NetworkManager.conf"); g_assert_cmpstr (nm_config_get_dhcp_client (config), ==, "dhclient"); g_assert_cmpstr (nm_config_get_log_level (config), ==, "INFO"); - g_assert_cmpint (nm_config_get_connectivity_interval (config), ==, 12); + g_assert_cmpint (nm_config_data_get_connectivity_interval (nm_config_get_data_orig (config)), ==, 12); plugins = nm_config_get_plugins (config); g_assert_cmpint (g_strv_length ((char **)plugins), ==, 4); @@ -237,8 +237,8 @@ test_config_confdir (void) 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); + g_assert_cmpstr (nm_config_data_get_connectivity_uri (nm_config_get_data_orig (config)), ==, "http://example.net"); + g_assert_cmpint (nm_config_data_get_connectivity_interval (nm_config_get_data_orig (config)), ==, 100); plugins = nm_config_get_plugins (config); g_assert_cmpint (g_strv_length ((char **)plugins), ==, 5); From d62022e28a508070e3d5ef089ab4e17dd45d3b23 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 9 Jul 2014 18:36:20 +0200 Subject: [PATCH 14/32] config: add handler for SIGHUP and a reload-configuration stub --- src/main-utils.c | 4 +--- src/main-utils.h | 5 +++++ src/main.c | 6 ++++++ src/nm-iface-helper.c | 6 ++++++ 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/main-utils.c b/src/main-utils.c index 909ef28ad1..164dc84a99 100644 --- a/src/main-utils.c +++ b/src/main-utils.c @@ -40,9 +40,7 @@ static gboolean sighup_handler (gpointer user_data) { - /* Reread config stuff like system config files, VPN service files, etc */ - nm_log_info (LOGD_CORE, "caught SIGHUP, not supported yet."); - + nm_main_config_reload (); return G_SOURCE_CONTINUE; } diff --git a/src/main-utils.h b/src/main-utils.h index 432833f31d..9b29866be0 100644 --- a/src/main-utils.h +++ b/src/main-utils.h @@ -37,4 +37,9 @@ gboolean nm_main_utils_early_setup (const char *progname, gpointer option_context_hook_data, const char *summary); +/* The following functions are not implemented inside nm-main-utils.c, instead + * main.c and nm-iface-helper.c */ + +void nm_main_config_reload (void); + #endif /* __MAIN_UTILS_H__ */ diff --git a/src/main.c b/src/main.c index 5432e1f3e8..89cfeb1cda 100644 --- a/src/main.c +++ b/src/main.c @@ -175,6 +175,12 @@ _init_nm_debug (const char *debug) } } +void +nm_main_config_reload () +{ + nm_log_info (LOGD_CORE, "reloading configuration not supported."); +} + static void manager_configure_quit (NMManager *manager, gpointer user_data) { diff --git a/src/nm-iface-helper.c b/src/nm-iface-helper.c index 8b61b5252f..97678aa1e8 100644 --- a/src/nm-iface-helper.c +++ b/src/nm-iface-helper.c @@ -481,6 +481,12 @@ main (int argc, char *argv[]) /*******************************************************/ /* Stub functions */ +void +nm_main_config_reload () +{ + nm_log_info (LOGD_CORE, "reloading configuration not supported"); +} + gconstpointer nm_config_get (void); const char *nm_config_get_dhcp_client (gpointer unused); gboolean nm_config_get_configure_and_quit (gpointer unused); From 82cfd5ad47b43de640dfa2dd60c4b84f0857e6a5 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 9 Jul 2014 18:54:47 +0200 Subject: [PATCH 15/32] config: add support for reloading of configuration No actual reloading is yet implemented. Later we will decide on specific configuration parameters where we support reloading. They must be then implemented one-by-one. Some configuration parameters can be set via command line. If a parameter is set from command line, the original value from command line will still be preserved after reloading. --- src/main.c | 9 ++++++- src/nm-config.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++ src/nm-config.h | 7 +++++ 3 files changed, 85 insertions(+), 1 deletion(-) diff --git a/src/main.c b/src/main.c index 89cfeb1cda..d60c67e38b 100644 --- a/src/main.c +++ b/src/main.c @@ -178,7 +178,14 @@ _init_nm_debug (const char *debug) void nm_main_config_reload () { - nm_log_info (LOGD_CORE, "reloading configuration not supported."); + nm_log_info (LOGD_CORE, "reload configuration..."); + /* The signal handler thread is only installed after + * creating NMConfig instance, and on shut down we + * no longer run the mainloop (to reach this point). + * + * Hence, a NMConfig singleton instance must always be + * available. */ + nm_config_reload (nm_config_get ()); } static void diff --git a/src/nm-config.c b/src/nm-config.c index 742a72e38c..4362ea3cdf 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -29,6 +29,7 @@ #include "nm-utils.h" #include "nm-glib-compat.h" #include "nm-device.h" +#include "NetworkManagerUtils.h" #include #include @@ -81,6 +82,14 @@ typedef struct { gboolean configure_and_quit; } NMConfigPrivate; +enum { + SIGNAL_CONFIG_CHANGED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + G_DEFINE_TYPE (NMConfig, nm_config, G_TYPE_OBJECT) #define NM_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_CONFIG, NMConfigPrivate)) @@ -551,6 +560,59 @@ find_base_config (NMConfig *config, GError **error) /************************************************************************/ +void +nm_config_reload (NMConfig *self) +{ + NMConfigPrivate *priv; + NMConfig *new; + GError *error = NULL; + GHashTable *changes; + NMConfigData *old_data; + NMConfigData *new_data = NULL; + + g_return_if_fail (NM_IS_CONFIG (self)); + + priv = NM_CONFIG_GET_PRIVATE (self); + + /* pass on the original command line options. This means, that + * options specified at command line cannot ever be reloaded from + * file. That seems desirable. + */ + new = nm_config_new (&priv->cli, &error); + + if (!new) { + nm_log_err (LOGD_CORE, "Failed to reload the configuration: %s", error->message); + g_clear_error (&error); + return; + } + + old_data = priv->config_data; + new_data = nm_config_get_data (new); + + changes = g_hash_table_new (g_str_hash, g_str_equal); + + /* reloading configuration means we have to carefully check every single option + * that we want to support and take specific actions. */ + + /* FIXME: no actual reloading implemented yet */ + + if (g_hash_table_size (changes)) + new_data = g_object_ref (new_data); + else + new_data = NULL; + + g_object_unref (new); + + if (new_data) { + old_data = priv->config_data; + priv->config_data = new_data; + g_signal_emit (self, signals[SIGNAL_CONFIG_CHANGED], 0, new_data, changes, old_data); + g_object_unref (old_data); + } + + g_hash_table_destroy (changes); +} + NM_DEFINE_SINGLETON_DESTRUCTOR (NMConfig); NM_DEFINE_SINGLETON_WEAK_REF (NMConfig); @@ -751,5 +813,13 @@ nm_config_class_init (NMConfigClass *config_class) g_type_class_add_private (config_class, sizeof (NMConfigPrivate)); object_class->finalize = finalize; + + signals[SIGNAL_CONFIG_CHANGED] = + g_signal_new (NM_CONFIG_SIGNAL_CONFIG_CHANGED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMConfigClass, config_changed), + NULL, NULL, NULL, + G_TYPE_NONE, 3, NM_TYPE_CONFIG_DATA, G_TYPE_HASH_TABLE, NM_TYPE_CONFIG_DATA); } diff --git a/src/nm-config.h b/src/nm-config.h index 3b0ee6cfae..68f1a4ed30 100644 --- a/src/nm-config.h +++ b/src/nm-config.h @@ -37,6 +37,9 @@ G_BEGIN_DECLS #define NM_IS_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_CONFIG)) #define NM_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_CONFIG, NMConfigClass)) +/* Signals */ +#define NM_CONFIG_SIGNAL_CONFIG_CHANGED "config-changed" + typedef struct NMConfigCmdLineOptions NMConfigCmdLineOptions; struct _NMConfig { @@ -45,6 +48,9 @@ struct _NMConfig { typedef struct { GObjectClass parent; + + /* Signals */ + void (*config_changed) (NMConfig *config, GHashTable *changes, NMConfigData *old_data); } NMConfigClass; GType nm_config_get_type (void); @@ -80,6 +86,7 @@ void nm_config_cmd_line_options_add_to_entries (NMConfigCmdLi NMConfig *nm_config_new (const NMConfigCmdLineOptions *cli, GError **error); NMConfig *nm_config_setup (const NMConfigCmdLineOptions *cli, GError **error); +void nm_config_reload (NMConfig *config); G_END_DECLS From ac9dd4c8324c2f8c8d06cada245496c4c3511379 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 29 Jan 2015 15:28:03 +0100 Subject: [PATCH 16/32] connectivity: make NMConnectivity independent of NMConfig --- src/nm-connectivity.c | 16 ++++++---------- src/nm-connectivity.h | 4 +++- src/nm-manager.c | 11 +++++++++-- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/nm-connectivity.c b/src/nm-connectivity.c index a96f47abf8..804e3935fe 100644 --- a/src/nm-connectivity.c +++ b/src/nm-connectivity.c @@ -28,7 +28,6 @@ #include "nm-connectivity.h" #include "nm-logging.h" -#include "nm-config.h" G_DEFINE_TYPE (NMConnectivity, nm_connectivity, G_TYPE_OBJECT) @@ -342,17 +341,14 @@ nm_connectivity_check_finish (NMConnectivity *self, /**************************************************************************/ NMConnectivity * -nm_connectivity_new (void) +nm_connectivity_new (const char *uri, + guint interval, + const char *response) { - NMConfigData *config_data = nm_config_get_data (nm_config_get ()); - - /* NMConnectivity is (almost) independent from NMConfig and works - * fine without it. As convenience, the default constructor nm_connectivity_new() - * uses the parameters from NMConfig to create an instance. */ return g_object_new (NM_TYPE_CONNECTIVITY, - NM_CONNECTIVITY_URI, nm_config_data_get_connectivity_uri (config_data), - NM_CONNECTIVITY_INTERVAL, nm_config_data_get_connectivity_interval (config_data), - NM_CONNECTIVITY_RESPONSE, nm_config_data_get_connectivity_response (config_data), + NM_CONNECTIVITY_URI, uri, + NM_CONNECTIVITY_INTERVAL, interval, + NM_CONNECTIVITY_RESPONSE, response, NULL); } diff --git a/src/nm-connectivity.h b/src/nm-connectivity.h index a61af5c190..fc584d5fed 100644 --- a/src/nm-connectivity.h +++ b/src/nm-connectivity.h @@ -53,7 +53,9 @@ GType nm_connectivity_get_type (void); const char *nm_connectivity_state_to_string (NMConnectivityState state); -NMConnectivity *nm_connectivity_new (void); +NMConnectivity *nm_connectivity_new (const char *uri, + guint interval, + const char *response); void nm_connectivity_set_online (NMConnectivity *self, gboolean online); diff --git a/src/nm-manager.c b/src/nm-manager.c index 4ef0722644..e10c173543 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -4719,6 +4719,7 @@ nm_manager_new (NMSettings *settings, NMManagerPrivate *priv; DBusGConnection *bus; DBusConnection *dbus_connection; + NMConfigData *config_data; g_assert (settings); @@ -4750,7 +4751,10 @@ nm_manager_new (NMSettings *settings, g_signal_connect (priv->policy, "notify::" NM_POLICY_ACTIVATING_IP6_DEVICE, G_CALLBACK (policy_activating_device_changed), singleton); - priv->connectivity = nm_connectivity_new (); + config_data = nm_config_get_data (nm_config_get ()); + priv->connectivity = nm_connectivity_new (nm_config_data_get_connectivity_uri (config_data), + nm_config_data_get_connectivity_interval (config_data), + nm_config_data_get_connectivity_response (config_data)); g_signal_connect (priv->connectivity, "notify::" NM_CONNECTIVITY_STATE, G_CALLBACK (connectivity_changed), singleton); @@ -5071,7 +5075,10 @@ dispose (GObject *object) g_clear_object (&priv->primary_connection); g_clear_object (&priv->activating_connection); - g_clear_object (&priv->connectivity); + if (priv->connectivity) { + g_signal_handlers_disconnect_by_func (priv->connectivity, connectivity_changed, manager); + g_clear_object (&priv->connectivity); + } g_free (priv->hostname); From b814c3122acbf9105effd54976cb675672264930 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 30 Jan 2015 19:52:53 +0100 Subject: [PATCH 17/32] config: implement reloading of connectivity parameters --- src/nm-config.c | 7 ++++++- src/nm-config.h | 2 ++ src/nm-manager.c | 25 ++++++++++++++++++++++++- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/nm-config.c b/src/nm-config.c index 4362ea3cdf..5ecfc0bbfc 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -594,7 +594,12 @@ nm_config_reload (NMConfig *self) /* reloading configuration means we have to carefully check every single option * that we want to support and take specific actions. */ - /* FIXME: no actual reloading implemented yet */ + if ( nm_config_data_get_connectivity_interval (old_data) != nm_config_data_get_connectivity_interval (new_data) + || g_strcmp0 (nm_config_data_get_connectivity_uri (old_data), nm_config_data_get_connectivity_uri (new_data)) + || g_strcmp0 (nm_config_data_get_connectivity_response (old_data), nm_config_data_get_connectivity_response (new_data))) { + nm_log_dbg (LOGD_CORE, "config: reload: change '" NM_CONFIG_CHANGES_CONNECTIVITY "'"); + g_hash_table_insert (changes, NM_CONFIG_CHANGES_CONNECTIVITY, NULL); + } if (g_hash_table_size (changes)) new_data = g_object_ref (new_data); diff --git a/src/nm-config.h b/src/nm-config.h index 68f1a4ed30..8e8bca3406 100644 --- a/src/nm-config.h +++ b/src/nm-config.h @@ -40,6 +40,8 @@ G_BEGIN_DECLS /* Signals */ #define NM_CONFIG_SIGNAL_CONFIG_CHANGED "config-changed" +#define NM_CONFIG_CHANGES_CONNECTIVITY "connectivity" + typedef struct NMConfigCmdLineOptions NMConfigCmdLineOptions; struct _NMConfig { diff --git a/src/nm-manager.c b/src/nm-manager.c index e10c173543..ad76da7c4d 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -167,6 +167,7 @@ typedef struct { GSList *devices; NMState state; + NMConfig *config; NMConnectivity *connectivity; int ignore_link_added_cb; @@ -463,6 +464,18 @@ active_connection_get_by_path (NMManager *manager, const char *path) /************************************************************************/ +static void +_config_changed_cb (NMConfig *config, NMConfigData *config_data, GHashTable *changes, NMConfigData *old_data, NMManager *self) +{ + g_object_set (NM_MANAGER_GET_PRIVATE (self)->connectivity, + NM_CONNECTIVITY_URI, nm_config_data_get_connectivity_uri (config_data), + NM_CONNECTIVITY_INTERVAL, nm_config_data_get_connectivity_interval (config_data), + NM_CONNECTIVITY_RESPONSE, nm_config_data_get_connectivity_response (config_data), + NULL); +} + +/************************************************************************/ + static NMDevice * nm_manager_get_device_by_udi (NMManager *manager, const char *udi) { @@ -4751,7 +4764,13 @@ nm_manager_new (NMSettings *settings, g_signal_connect (priv->policy, "notify::" NM_POLICY_ACTIVATING_IP6_DEVICE, G_CALLBACK (policy_activating_device_changed), singleton); - config_data = nm_config_get_data (nm_config_get ()); + priv->config = g_object_ref (nm_config_get ()); + g_signal_connect (G_OBJECT (priv->config), + NM_CONFIG_SIGNAL_CONFIG_CHANGED, + G_CALLBACK (_config_changed_cb), + singleton); + + config_data = nm_config_get_data (priv->config); priv->connectivity = nm_connectivity_new (nm_config_data_get_connectivity_uri (config_data), nm_config_data_get_connectivity_interval (config_data), nm_config_data_get_connectivity_response (config_data)); @@ -5075,6 +5094,10 @@ dispose (GObject *object) g_clear_object (&priv->primary_connection); g_clear_object (&priv->activating_connection); + if (priv->config) { + g_signal_handlers_disconnect_by_func (priv->config, _config_changed_cb, manager); + g_clear_object (&priv->config); + } if (priv->connectivity) { g_signal_handlers_disconnect_by_func (priv->connectivity, connectivity_changed, manager); g_clear_object (&priv->connectivity); From 3c7f71e44aadb65a8a661b7d57f08e653851fef5 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 16 Dec 2014 10:53:58 +0100 Subject: [PATCH 18/32] config: refactor read_config() to make it independent from NMConfig --- src/nm-config.c | 53 ++++++++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/src/nm-config.c b/src/nm-config.c index 5ecfc0bbfc..c6eaa6559d 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -437,14 +437,15 @@ nm_config_cmd_line_options_add_to_entries (NMConfigCmdLineOptions *cli, /************************************************************************/ static gboolean -read_config (NMConfig *config, const char *path, GError **error) +read_config (GKeyFile *keyfile, const char *path, GError **error) { - NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (config); GKeyFile *kf; char **groups, **keys; gsize ngroups, nkeys; int g, k; + g_return_val_if_fail (keyfile, FALSE); + 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); return FALSE; @@ -471,22 +472,22 @@ read_config (NMConfig *config, const char *path, GError **error) 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 *old_val = g_key_file_get_value (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_key_file_set_value (keyfile, groups[g], base_key, combined); g_free (combined); } else - g_key_file_set_value (priv->keyfile, groups[g], base_key, new_val); + g_key_file_set_value (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_set_value (keyfile, groups[g], keys[k], v = g_key_file_get_value (kf, groups[g], keys[k], NULL)); g_free (v); } @@ -499,16 +500,22 @@ read_config (NMConfig *config, const char *path, GError **error) } static gboolean -find_base_config (NMConfig *config, GError **error) +read_base_config (GKeyFile *keyfile, + const char *cli_config_path, + char **out_config_path, + GError **error) { - NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (config); GError *my_error = NULL; + g_return_val_if_fail (keyfile, FALSE); + g_return_val_if_fail (out_config_path && !*out_config_path, FALSE); + g_return_val_if_fail (!error || !*error, FALSE); + /* Try a user-specified config file first */ - if (priv->cli.config_path) { + if (cli_config_path) { /* Bad user-specific config file path is a hard error */ - if (read_config (config, priv->cli.config_path, error)) { - priv->nm_conf_path = g_strdup (priv->cli.config_path); + if (read_config (keyfile, cli_config_path, error)) { + *out_config_path = g_strdup (cli_config_path); return TRUE; } else return FALSE; @@ -522,8 +529,8 @@ find_base_config (NMConfig *config, GError **error) */ /* 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); + if (read_config (keyfile, NM_OLD_SYSTEM_CONF_FILE, &my_error)) { + *out_config_path = g_strdup (NM_OLD_SYSTEM_CONF_FILE); return TRUE; } @@ -535,8 +542,8 @@ find_base_config (NMConfig *config, GError **error) 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); + if (read_config (keyfile, NM_DEFAULT_SYSTEM_CONF_FILE, &my_error)) { + *out_config_path = g_strdup (NM_DEFAULT_SYSTEM_CONF_FILE); return TRUE; } @@ -552,7 +559,7 @@ find_base_config (NMConfig *config, GError **error) /* 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); + *out_config_path = g_strdup (NM_DEFAULT_SYSTEM_CONF_FILE); nm_log_info (LOGD_CORE, "No config file found or given; using %s\n", NM_DEFAULT_SYSTEM_CONF_FILE); return TRUE; @@ -671,18 +678,18 @@ nm_config_new (const NMConfigCmdLineOptions *cli, GError **error) else _nm_config_cmd_line_options_copy (cli, &priv->cli); - /* First read the base config file */ - if (!find_base_config (self, error)) { - g_object_unref (self); - return NULL; - } - /* Now read the overrides in the config dir */ if (priv->cli.config_dir) priv->config_dir = g_strdup (priv->cli.config_dir); else priv->config_dir = g_strdup (NM_DEFAULT_SYSTEM_CONF_DIR); + /* First read the base config file */ + if (!read_base_config (priv->keyfile, priv->cli.config_path, &priv->nm_conf_path, error)) { + g_object_unref (self); + return NULL; + } + confs = g_ptr_array_new_with_free_func (g_free); config_description = g_string_new (priv->nm_conf_path); dir = g_file_new_for_path (priv->config_dir); @@ -707,7 +714,7 @@ nm_config_new (const NMConfigCmdLineOptions *cli, GError **error) g_ptr_array_sort (confs, sort_asciibetically); priv->config_description = g_string_free (config_description, FALSE); for (i = 0; i < confs->len; i++) { - if (!read_config (self, confs->pdata[i], error)) { + if (!read_config (priv->keyfile, confs->pdata[i], error)) { g_object_unref (self); self = NULL; break; From 3714a6c7bd0f22328ac769926732af3f4746f68b Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 16 Dec 2014 11:02:57 +0100 Subject: [PATCH 19/32] config/trivial: rename variables for configuration file The name "nm_conf_path" and cli.config_path" were not consistent. Rename them both to "config_main_file". --- src/main.c | 2 +- src/nm-config.c | 40 +++++++++++++------------- src/nm-config.h | 4 +-- src/settings/plugins/example/plugin.c | 2 +- src/settings/plugins/ifupdown/plugin.c | 2 +- src/settings/plugins/keyfile/plugin.c | 2 +- src/tests/config/test-config.c | 6 ++-- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/main.c b/src/main.c index d60c67e38b..e1d2805a5c 100644 --- a/src/main.c +++ b/src/main.c @@ -387,7 +387,7 @@ main (int argc, char *argv[]) nm_log_info (LOGD_CORE, "NetworkManager (version " NM_DIST_VERSION ") is starting..."); success = FALSE; - nm_log_info (LOGD_CORE, "Read config: %s", nm_config_get_description (config)); + nm_log_info (LOGD_CORE, "Read config: %s", nm_config_get_config_description (config)); nm_log_info (LOGD_CORE, "WEXT support is %s", #if HAVE_WEXT "enabled" diff --git a/src/nm-config.c b/src/nm-config.c index c6eaa6559d..78ece59831 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -40,7 +40,7 @@ #define NM_NO_AUTO_DEFAULT_STATE_FILE NMSTATEDIR "/no-auto-default.state" struct NMConfigCmdLineOptions { - char *config_path; + char *config_main_file; char *config_dir; char *no_auto_default_file; char *plugins; @@ -59,7 +59,7 @@ typedef struct { NMConfigData *config_data; NMConfigData *config_data_orig; - char *nm_conf_path; + char *config_main_file; char *config_dir; char *config_description; char *no_auto_default_file; @@ -151,15 +151,15 @@ nm_config_get_data_orig (NMConfig *config) } const char * -nm_config_get_path (NMConfig *config) +nm_config_get_config_main_file (NMConfig *config) { g_return_val_if_fail (config != NULL, NULL); - return NM_CONFIG_GET_PRIVATE (config)->nm_conf_path; + return NM_CONFIG_GET_PRIVATE (config)->config_main_file; } const char * -nm_config_get_description (NMConfig *config) +nm_config_get_config_description (NMConfig *config) { g_return_val_if_fail (config != NULL, NULL); @@ -365,7 +365,7 @@ nm_config_set_ethernet_no_auto_default (NMConfig *config, NMDevice *device) static void _nm_config_cmd_line_options_clear (NMConfigCmdLineOptions *cli) { - g_clear_pointer (&cli->config_path, g_free); + g_clear_pointer (&cli->config_main_file, 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); @@ -383,7 +383,7 @@ _nm_config_cmd_line_options_copy (const NMConfigCmdLineOptions *cli, NMConfigCmd _nm_config_cmd_line_options_clear (dst); dst->config_dir = g_strdup (cli->config_dir); - dst->config_path = g_strdup (cli->config_path); + dst->config_main_file = g_strdup (cli->config_main_file); dst->no_auto_default_file = g_strdup (cli->no_auto_default_file); dst->plugins = g_strdup (cli->plugins); dst->connectivity_uri = g_strdup (cli->connectivity_uri); @@ -418,7 +418,7 @@ nm_config_cmd_line_options_add_to_entries (NMConfigCmdLineOptions *cli, { GOptionEntry config_options[] = { - { "config", 0, 0, G_OPTION_ARG_FILENAME, &cli->config_path, N_("Config file location"), N_("/path/to/config.file") }, + { "config", 0, 0, G_OPTION_ARG_FILENAME, &cli->config_main_file, 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") }, @@ -501,21 +501,21 @@ read_config (GKeyFile *keyfile, const char *path, GError **error) static gboolean read_base_config (GKeyFile *keyfile, - const char *cli_config_path, - char **out_config_path, + const char *cli_config_main_file, + char **out_config_main_file, GError **error) { GError *my_error = NULL; g_return_val_if_fail (keyfile, FALSE); - g_return_val_if_fail (out_config_path && !*out_config_path, FALSE); + g_return_val_if_fail (out_config_main_file && !*out_config_main_file, FALSE); g_return_val_if_fail (!error || !*error, FALSE); /* Try a user-specified config file first */ - if (cli_config_path) { + if (cli_config_main_file) { /* Bad user-specific config file path is a hard error */ - if (read_config (keyfile, cli_config_path, error)) { - *out_config_path = g_strdup (cli_config_path); + if (read_config (keyfile, cli_config_main_file, error)) { + *out_config_main_file = g_strdup (cli_config_main_file); return TRUE; } else return FALSE; @@ -530,7 +530,7 @@ read_base_config (GKeyFile *keyfile, /* Try deprecated nm-system-settings.conf first */ if (read_config (keyfile, NM_OLD_SYSTEM_CONF_FILE, &my_error)) { - *out_config_path = g_strdup (NM_OLD_SYSTEM_CONF_FILE); + *out_config_main_file = g_strdup (NM_OLD_SYSTEM_CONF_FILE); return TRUE; } @@ -543,7 +543,7 @@ read_base_config (GKeyFile *keyfile, /* Try the standard config file location next */ if (read_config (keyfile, NM_DEFAULT_SYSTEM_CONF_FILE, &my_error)) { - *out_config_path = g_strdup (NM_DEFAULT_SYSTEM_CONF_FILE); + *out_config_main_file = g_strdup (NM_DEFAULT_SYSTEM_CONF_FILE); return TRUE; } @@ -559,7 +559,7 @@ read_base_config (GKeyFile *keyfile, /* If for some reason no config file exists, use the default * config file path. */ - *out_config_path = g_strdup (NM_DEFAULT_SYSTEM_CONF_FILE); + *out_config_main_file = g_strdup (NM_DEFAULT_SYSTEM_CONF_FILE); nm_log_info (LOGD_CORE, "No config file found or given; using %s\n", NM_DEFAULT_SYSTEM_CONF_FILE); return TRUE; @@ -685,13 +685,13 @@ nm_config_new (const NMConfigCmdLineOptions *cli, GError **error) priv->config_dir = g_strdup (NM_DEFAULT_SYSTEM_CONF_DIR); /* First read the base config file */ - if (!read_base_config (priv->keyfile, priv->cli.config_path, &priv->nm_conf_path, error)) { + if (!read_base_config (priv->keyfile, priv->cli.config_main_file, &priv->config_main_file, error)) { g_object_unref (self); return NULL; } confs = g_ptr_array_new_with_free_func (g_free); - config_description = g_string_new (priv->nm_conf_path); + config_description = g_string_new (priv->config_main_file); 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) { @@ -795,7 +795,7 @@ finalize (GObject *gobject) { NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (gobject); - g_free (priv->nm_conf_path); + g_free (priv->config_main_file); g_free (priv->config_dir); g_free (priv->config_description); g_free (priv->no_auto_default_file); diff --git a/src/nm-config.h b/src/nm-config.h index 8e8bca3406..14ae511633 100644 --- a/src/nm-config.h +++ b/src/nm-config.h @@ -61,8 +61,8 @@ NMConfig *nm_config_get (void); NMConfigData *nm_config_get_data (NMConfig *config); NMConfigData *nm_config_get_data_orig (NMConfig *config); -const char *nm_config_get_path (NMConfig *config); -const char *nm_config_get_description (NMConfig *config); +const char *nm_config_get_config_main_file (NMConfig *config); +const char *nm_config_get_config_description (NMConfig *config); const char **nm_config_get_plugins (NMConfig *config); gboolean nm_config_get_monitor_connection_files (NMConfig *config); gboolean nm_config_get_auth_polkit (NMConfig *config); diff --git a/src/settings/plugins/example/plugin.c b/src/settings/plugins/example/plugin.c index 9945e13b56..b93b1dfb46 100644 --- a/src/settings/plugins/example/plugin.c +++ b/src/settings/plugins/example/plugin.c @@ -847,7 +847,7 @@ nm_system_config_factory (void) priv = SC_PLUGIN_EXAMPLE_GET_PRIVATE (singleton); /* Cache the config file path */ - priv->conf_file = nm_config_get_path (nm_config_get ()); + priv->conf_file = nm_config_get_config_main_file (nm_config_get ()); } else { /* This function should never be called twice */ g_assert_not_reached (); diff --git a/src/settings/plugins/ifupdown/plugin.c b/src/settings/plugins/ifupdown/plugin.c index 1b5642afb4..61b9dcef07 100644 --- a/src/settings/plugins/ifupdown/plugin.c +++ b/src/settings/plugins/ifupdown/plugin.c @@ -461,7 +461,7 @@ SCPluginIfupdown_init (NMSystemConfigInterface *config) &error); if (error) { nm_log_info (LOGD_SETTINGS, "loading system config file (%s) caused error: %s", - nm_config_get_path (nm_config_get ()), + nm_config_get_config_main_file (nm_config_get ()), error->message); } else { gboolean manage_well_known; diff --git a/src/settings/plugins/keyfile/plugin.c b/src/settings/plugins/keyfile/plugin.c index fcdb3c3cf0..869af6a1c5 100644 --- a/src/settings/plugins/keyfile/plugin.c +++ b/src/settings/plugins/keyfile/plugin.c @@ -843,7 +843,7 @@ nm_settings_keyfile_plugin_new (void) singleton = SC_PLUGIN_KEYFILE (g_object_new (SC_TYPE_PLUGIN_KEYFILE, NULL)); priv = SC_PLUGIN_KEYFILE_GET_PRIVATE (singleton); - priv->conf_file = nm_config_get_path (nm_config_get ()); + priv->conf_file = nm_config_get_config_main_file (nm_config_get ()); /* plugin_set_hostname() has to be called *after* priv->conf_file is set */ priv->hostname = plugin_get_hostname (singleton); diff --git a/src/tests/config/test-config.c b/src/tests/config/test-config.c index bd934373b1..a6f921c750 100644 --- a/src/tests/config/test-config.c +++ b/src/tests/config/test-config.c @@ -93,7 +93,7 @@ test_config_simple (void) config = setup_config (NULL, SRCDIR "/NetworkManager.conf", "/no/such/dir", NULL); - g_assert_cmpstr (nm_config_get_path (config), ==, SRCDIR "/NetworkManager.conf"); + g_assert_cmpstr (nm_config_get_config_main_file (config), ==, SRCDIR "/NetworkManager.conf"); g_assert_cmpstr (nm_config_get_dhcp_client (config), ==, "dhclient"); g_assert_cmpstr (nm_config_get_log_level (config), ==, "INFO"); g_assert_cmpint (nm_config_data_get_connectivity_interval (nm_config_get_data_orig (config)), ==, 100); @@ -152,7 +152,7 @@ test_config_override (void) "--connectivity-interval", "12", NULL); - g_assert_cmpstr (nm_config_get_path (config), ==, SRCDIR "/NetworkManager.conf"); + g_assert_cmpstr (nm_config_get_config_main_file (config), ==, SRCDIR "/NetworkManager.conf"); g_assert_cmpstr (nm_config_get_dhcp_client (config), ==, "dhclient"); g_assert_cmpstr (nm_config_get_log_level (config), ==, "INFO"); g_assert_cmpint (nm_config_data_get_connectivity_interval (nm_config_get_data_orig (config)), ==, 12); @@ -233,7 +233,7 @@ test_config_confdir (void) config = setup_config (NULL, SRCDIR "/NetworkManager.conf", SRCDIR "/conf.d", NULL); - g_assert_cmpstr (nm_config_get_path (config), ==, SRCDIR "/NetworkManager.conf"); + g_assert_cmpstr (nm_config_get_config_main_file (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"); From ef5782844280b3ca2605559f938795425cd12a91 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 16 Dec 2014 11:35:58 +0100 Subject: [PATCH 20/32] config: refactor nm_config_new() by extracting function _get_config_dir_files() --- src/nm-config.c | 92 +++++++++++++++++++++++++++++-------------------- 1 file changed, 54 insertions(+), 38 deletions(-) diff --git a/src/nm-config.c b/src/nm-config.c index 78ece59831..8fed763399 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -565,6 +565,58 @@ read_base_config (GKeyFile *keyfile, return TRUE; } +static int +sort_asciibetically (gconstpointer a, gconstpointer b) +{ + const char *s1 = *(const char **)a; + const char *s2 = *(const char **)b; + + return strcmp (s1, s2); +} + +static GPtrArray * +_get_config_dir_files (const char *config_main_file, + const char *config_dir, + char **out_config_description) +{ + GFile *dir; + GFileEnumerator *direnum; + GFileInfo *info; + GPtrArray *confs; + GString *config_description; + const char *name; + + g_return_val_if_fail (config_main_file, NULL); + g_return_val_if_fail (config_dir, NULL); + g_return_val_if_fail (out_config_description && !*out_config_description, NULL); + + confs = g_ptr_array_new_with_free_func (g_free); + config_description = g_string_new (config_main_file); + dir = g_file_new_for_path (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 (config_dir, name, NULL)); + if (confs->len == 1) + g_string_append (config_description, " and conf.d: "); + else + g_string_append (config_description, ", "); + g_string_append (config_description, name); + } + g_object_unref (info); + } + g_object_unref (direnum); + } + g_object_unref (dir); + + g_ptr_array_sort (confs, sort_asciibetically); + + *out_config_description = g_string_free (config_description, FALSE); + return confs; +} + /************************************************************************/ void @@ -646,29 +698,15 @@ nm_config_setup (const NMConfigCmdLineOptions *cli, GError **error) return singleton_instance; } -static int -sort_asciibetically (gconstpointer a, gconstpointer b) -{ - const char *s1 = *(const char **)a; - const char *s2 = *(const char **)b; - - return strcmp (s1, s2); -} - NMConfig * nm_config_new (const NMConfigCmdLineOptions *cli, GError **error) { NMConfigPrivate *priv = NULL; - GFile *dir; - GFileEnumerator *direnum; - GFileInfo *info; - GPtrArray *confs; - const char *name; int i; - GString *config_description; NMConfig *self; char *connectivity_uri, *connectivity_response; guint connectivity_interval; + GPtrArray *confs; self = NM_CONFIG (g_object_new (NM_TYPE_CONFIG, NULL)); priv = NM_CONFIG_GET_PRIVATE (self); @@ -690,29 +728,7 @@ nm_config_new (const NMConfigCmdLineOptions *cli, GError **error) return NULL; } - confs = g_ptr_array_new_with_free_func (g_free); - config_description = g_string_new (priv->config_main_file); - 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)); - if (confs->len == 1) - g_string_append (config_description, " and conf.d: "); - else - g_string_append (config_description, ", "); - g_string_append (config_description, name); - } - g_object_unref (info); - } - g_object_unref (direnum); - } - g_object_unref (dir); - - g_ptr_array_sort (confs, sort_asciibetically); - priv->config_description = g_string_free (config_description, FALSE); + confs = _get_config_dir_files (priv->config_main_file, priv->config_dir, &priv->config_description); for (i = 0; i < confs->len; i++) { if (!read_config (priv->keyfile, confs->pdata[i], error)) { g_object_unref (self); From 40dc4c3242c0276d5ac9fc6bf15afc1392cc10be Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 16 Dec 2014 12:14:30 +0100 Subject: [PATCH 21/32] config: refactor nm_config_new() by extracting function read_entire_config() --- src/nm-config.c | 90 ++++++++++++++++++++++++++++++++++++++----------- src/nm-config.h | 2 ++ 2 files changed, 72 insertions(+), 20 deletions(-) diff --git a/src/nm-config.c b/src/nm-config.c index 8fed763399..eb801dab1a 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -436,6 +436,16 @@ nm_config_cmd_line_options_add_to_entries (NMConfigCmdLineOptions *cli, /************************************************************************/ +GKeyFile * +nm_config_create_keyfile () +{ + GKeyFile *keyfile; + + keyfile = g_key_file_new (); + g_key_file_set_list_separator (keyfile, ','); + return keyfile; +} + static gboolean read_config (GKeyFile *keyfile, const char *path, GError **error) { @@ -445,6 +455,8 @@ read_config (GKeyFile *keyfile, const char *path, GError **error) int g, k; g_return_val_if_fail (keyfile, FALSE); + g_return_val_if_fail (path, FALSE); + g_return_val_if_fail (!error || !*error, FALSE); 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); @@ -453,8 +465,7 @@ read_config (GKeyFile *keyfile, const char *path, GError **error) nm_log_dbg (LOGD_SETTINGS, "Reading config file '%s'", path); - kf = g_key_file_new (); - g_key_file_set_list_separator (kf, ','); + kf = nm_config_create_keyfile (); if (!g_key_file_load_from_file (kf, path, G_KEY_FILE_NONE, error)) { g_key_file_free (kf); return FALSE; @@ -617,6 +628,53 @@ _get_config_dir_files (const char *config_main_file, return confs; } +static GKeyFile * +read_entire_config (const NMConfigCmdLineOptions *cli, + const char *config_dir, + char **out_config_main_file, + char **out_config_description, + GError **error) +{ + GKeyFile *keyfile = nm_config_create_keyfile (); + GPtrArray *confs; + guint i; + char *o_config_main_file = NULL; + char *o_config_description = NULL; + + g_return_val_if_fail (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 (!error || !*error, FALSE); + + /* First read the base config file */ + if ( cli + && !read_base_config (keyfile, cli->config_main_file, &o_config_main_file, error)) { + g_key_file_free (keyfile); + return NULL; + } + + g_assert (o_config_main_file); + + confs = _get_config_dir_files (o_config_main_file, config_dir, &o_config_description); + for (i = 0; i < confs->len; i++) { + if (!read_config (keyfile, confs->pdata[i], error)) { + g_key_file_free (keyfile); + keyfile = NULL; + break; + } + } + g_ptr_array_unref (confs); + + if (keyfile) { + *out_config_main_file = o_config_main_file; + *out_config_description = o_config_description; + } else { + g_free (o_config_main_file); + g_free (o_config_description); + } + return keyfile; +} + /************************************************************************/ void @@ -702,11 +760,10 @@ NMConfig * nm_config_new (const NMConfigCmdLineOptions *cli, GError **error) { NMConfigPrivate *priv = NULL; - int i; NMConfig *self; char *connectivity_uri, *connectivity_response; guint connectivity_interval; - GPtrArray *confs; + GKeyFile *keyfile; self = NM_CONFIG (g_object_new (NM_TYPE_CONFIG, NULL)); priv = NM_CONFIG_GET_PRIVATE (self); @@ -722,23 +779,17 @@ nm_config_new (const NMConfigCmdLineOptions *cli, GError **error) else priv->config_dir = g_strdup (NM_DEFAULT_SYSTEM_CONF_DIR); - /* First read the base config file */ - if (!read_base_config (priv->keyfile, priv->cli.config_main_file, &priv->config_main_file, error)) { + keyfile = read_entire_config (&priv->cli, + priv->config_dir, + &priv->config_main_file, + &priv->config_description, + error); + if (!keyfile) { g_object_unref (self); return NULL; } - - confs = _get_config_dir_files (priv->config_main_file, priv->config_dir, &priv->config_description); - for (i = 0; i < confs->len; i++) { - if (!read_config (priv->keyfile, confs->pdata[i], error)) { - g_object_unref (self); - self = NULL; - break; - } - } - g_ptr_array_unref (confs); - if (!self) - return NULL; + g_key_file_free (priv->keyfile); + priv->keyfile = keyfile; /* 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); @@ -802,8 +853,7 @@ nm_config_init (NMConfig *config) priv->auth_polkit = NM_CONFIG_DEFAULT_AUTH_POLKIT; - priv->keyfile = g_key_file_new (); - g_key_file_set_list_separator (priv->keyfile, ','); + priv->keyfile = nm_config_create_keyfile (); } static void diff --git a/src/nm-config.h b/src/nm-config.h index 14ae511633..4b726495b1 100644 --- a/src/nm-config.h +++ b/src/nm-config.h @@ -90,6 +90,8 @@ NMConfig *nm_config_new (const NMConfigCmdLineOptions *cli, GError **error); NMConfig *nm_config_setup (const NMConfigCmdLineOptions *cli, GError **error); void nm_config_reload (NMConfig *config); +GKeyFile *nm_config_create_keyfile (void); + G_END_DECLS #endif /* __NETWORKMANAGER_CONFIG_H__ */ From 4429f8aea5bf24fc12add15554ad49183439a069 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 16 Dec 2014 15:10:24 +0100 Subject: [PATCH 22/32] config: refactor to inject NMConfigCmdLineOptions to NMConfig constructor --- src/nm-config.c | 46 +++++++++++++++++++++++++++++++++++++++------- src/nm-config.h | 3 +++ 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/src/nm-config.c b/src/nm-config.c index eb801dab1a..0466f3d982 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -82,6 +82,12 @@ typedef struct { gboolean configure_and_quit; } NMConfigPrivate; +enum { + PROP_0, + PROP_CMD_LINE_OPTIONS, + LAST_PROP, +}; + enum { SIGNAL_CONFIG_CHANGED, @@ -765,15 +771,11 @@ nm_config_new (const NMConfigCmdLineOptions *cli, GError **error) guint connectivity_interval; GKeyFile *keyfile; - self = NM_CONFIG (g_object_new (NM_TYPE_CONFIG, NULL)); + self = NM_CONFIG (g_object_new (NM_TYPE_CONFIG, + NM_CONFIG_CMD_LINE_OPTIONS, cli, + NULL)); priv = NM_CONFIG_GET_PRIVATE (self); - if (!cli) - _nm_config_cmd_line_options_clear (&priv->cli); - else - _nm_config_cmd_line_options_copy (cli, &priv->cli); - - /* Now read the overrides in the config dir */ if (priv->cli.config_dir) priv->config_dir = g_strdup (priv->cli.config_dir); else @@ -883,6 +885,28 @@ finalize (GObject *gobject) G_OBJECT_CLASS (nm_config_parent_class)->finalize (gobject); } +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMConfig *self = NM_CONFIG (object); + NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (self); + NMConfigCmdLineOptions *cli; + + switch (prop_id) { + case PROP_CMD_LINE_OPTIONS: + /* construct only */ + cli = g_value_get_pointer (value); + if (!cli) + _nm_config_cmd_line_options_clear (&priv->cli); + else + _nm_config_cmd_line_options_copy (cli, &priv->cli); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} static void nm_config_class_init (NMConfigClass *config_class) @@ -891,6 +915,14 @@ nm_config_class_init (NMConfigClass *config_class) g_type_class_add_private (config_class, sizeof (NMConfigPrivate)); object_class->finalize = finalize; + object_class->set_property = set_property; + + g_object_class_install_property + (object_class, PROP_CMD_LINE_OPTIONS, + g_param_spec_pointer (NM_CONFIG_CMD_LINE_OPTIONS, "", "", + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); signals[SIGNAL_CONFIG_CHANGED] = g_signal_new (NM_CONFIG_SIGNAL_CONFIG_CHANGED, diff --git a/src/nm-config.h b/src/nm-config.h index 4b726495b1..f4994a1f52 100644 --- a/src/nm-config.h +++ b/src/nm-config.h @@ -37,6 +37,9 @@ G_BEGIN_DECLS #define NM_IS_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_CONFIG)) #define NM_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_CONFIG, NMConfigClass)) +/* Properties */ +#define NM_CONFIG_CMD_LINE_OPTIONS "cmd-line-options" + /* Signals */ #define NM_CONFIG_SIGNAL_CONFIG_CHANGED "config-changed" From 64520b7ba4aec12d4750d5351f2bba8317d3fa1b Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 16 Dec 2014 15:36:56 +0100 Subject: [PATCH 23/32] config: refactor read_entire_config() to merge command line options --- src/nm-config.c | 61 +++++++++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/src/nm-config.c b/src/nm-config.c index 0466f3d982..592979aa25 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -646,6 +646,7 @@ read_entire_config (const NMConfigCmdLineOptions *cli, guint i; char *o_config_main_file = NULL; char *o_config_description = NULL; + char **plugins_tmp; g_return_val_if_fail (config_dir, NULL); g_return_val_if_fail (out_config_main_file && !*out_config_main_file, FALSE); @@ -665,19 +666,35 @@ read_entire_config (const NMConfigCmdLineOptions *cli, for (i = 0; i < confs->len; i++) { if (!read_config (keyfile, confs->pdata[i], error)) { g_key_file_free (keyfile); - keyfile = NULL; - break; + g_free (o_config_main_file); + g_free (o_config_description); + g_ptr_array_unref (confs); + return NULL; } } g_ptr_array_unref (confs); - if (keyfile) { - *out_config_main_file = o_config_main_file; - *out_config_description = o_config_description; - } else { - g_free (o_config_main_file); - g_free (o_config_description); - } + /* Merge settings from command line. They overwrite everything read from + * config files. */ + + if (cli && cli->plugins && cli->plugins[0]) + g_key_file_set_value (keyfile, "main", "plugins", cli->plugins); + plugins_tmp = g_key_file_get_string_list (keyfile, "main", "plugins", NULL, NULL); + if (!plugins_tmp) { + if (STRLEN (CONFIG_PLUGINS_DEFAULT) > 0) + g_key_file_set_value (keyfile, "main", "plugins", CONFIG_PLUGINS_DEFAULT); + } else + g_strfreev (plugins_tmp); + + if (cli && cli->connectivity_uri && cli->connectivity_uri[0]) + g_key_file_set_value (keyfile, "connectivity", "uri", cli->connectivity_uri); + if (cli && cli->connectivity_interval >= 0) + g_key_file_set_integer (keyfile, "connectivity", "interval", cli->connectivity_interval); + if (cli && cli->connectivity_response && cli->connectivity_response[0]) + g_key_file_set_value (keyfile, "connectivity", "response", cli->connectivity_response); + + *out_config_main_file = o_config_main_file; + *out_config_description = o_config_description; return keyfile; } @@ -793,7 +810,8 @@ nm_config_new (const NMConfigCmdLineOptions *cli, GError **error) g_key_file_free (priv->keyfile); priv->keyfile = keyfile; - /* Handle no-auto-default key and state file */ + /* Initialize read only private members */ + priv->no_auto_default = g_key_file_get_string_list (priv->keyfile, "main", "no-auto-default", NULL, NULL); if (priv->cli.no_auto_default_file) priv->no_auto_default_file = g_strdup (priv->cli.no_auto_default_file); @@ -801,12 +819,9 @@ nm_config_new (const NMConfigCmdLineOptions *cli, GError **error) priv->no_auto_default_file = g_strdup (NM_NO_AUTO_DEFAULT_STATE_FILE); merge_no_auto_default_state (self); - /* Now let command-line options override the config files, and fill in priv. */ - if (priv->cli.plugins && priv->cli.plugins[0]) - g_key_file_set_value (priv->keyfile, "main", "plugins", priv->cli.plugins); priv->plugins = g_key_file_get_string_list (priv->keyfile, "main", "plugins", NULL, NULL); - if (!priv->plugins && STRLEN (CONFIG_PLUGINS_DEFAULT) > 0) - priv->plugins = g_strsplit (CONFIG_PLUGINS_DEFAULT, ",", -1); + if (!priv->plugins) + priv->plugins = g_new0 (char *, 1); priv->monitor_connection_files = _get_bool_value (priv->keyfile, "main", "monitor-connection-files", FALSE); @@ -820,22 +835,14 @@ nm_config_new (const NMConfigCmdLineOptions *cli, GError **error) priv->debug = g_key_file_get_value (priv->keyfile, "main", "debug", NULL); - if (priv->cli.connectivity_uri && priv->cli.connectivity_uri[0]) - g_key_file_set_value (priv->keyfile, "connectivity", "uri", priv->cli.connectivity_uri); - connectivity_uri = g_key_file_get_value (priv->keyfile, "connectivity", "uri", NULL); - - if (priv->cli.connectivity_interval >= 0) - g_key_file_set_integer (priv->keyfile, "connectivity", "interval", priv->cli.connectivity_interval); - connectivity_interval = g_key_file_get_integer (priv->keyfile, "connectivity", "interval", NULL); - - if (priv->cli.connectivity_response && priv->cli.connectivity_response[0]) - g_key_file_set_value (priv->keyfile, "connectivity", "response", priv->cli.connectivity_response); - connectivity_response = g_key_file_get_value (priv->keyfile, "connectivity", "response", NULL); - priv->ignore_carrier = g_key_file_get_string_list (priv->keyfile, "main", "ignore-carrier", NULL, NULL); priv->configure_and_quit = _get_bool_value (priv->keyfile, "main", "configure-and-quit", FALSE); + connectivity_uri = g_key_file_get_value (priv->keyfile, "connectivity", "uri", NULL); + connectivity_interval = g_key_file_get_integer (priv->keyfile, "connectivity", "interval", NULL); + connectivity_response = g_key_file_get_value (priv->keyfile, "connectivity", "response", NULL); + priv->config_data = g_object_new (NM_TYPE_CONFIG_DATA, NM_CONFIG_DATA_CONNECTIVITY_URI, connectivity_uri, NM_CONFIG_DATA_CONNECTIVITY_INTERVAL, connectivity_interval, From 83996c621cb7c55d17872fcbd4d2fae51977d839 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 16 Dec 2014 15:47:04 +0100 Subject: [PATCH 24/32] config: minor refactoring to highlight mutable property no_auto_default of NMConfig --- src/nm-config.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/nm-config.c b/src/nm-config.c index 592979aa25..95a75edd9a 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -76,10 +76,13 @@ typedef struct { char *debug; - char **no_auto_default; + char **no_auto_default_orig; char **ignore_carrier; gboolean configure_and_quit; + + /* MUTABLE properties: */ + char **no_auto_default; /* mutable via merge_no_auto_default_state() */ } NMConfigPrivate; enum { @@ -812,12 +815,11 @@ nm_config_new (const NMConfigCmdLineOptions *cli, GError **error) /* Initialize read only private members */ - priv->no_auto_default = g_key_file_get_string_list (priv->keyfile, "main", "no-auto-default", NULL, NULL); if (priv->cli.no_auto_default_file) priv->no_auto_default_file = g_strdup (priv->cli.no_auto_default_file); else priv->no_auto_default_file = g_strdup (NM_NO_AUTO_DEFAULT_STATE_FILE); - merge_no_auto_default_state (self); + priv->no_auto_default_orig = g_key_file_get_string_list (priv->keyfile, "main", "no-auto-default", NULL, NULL); priv->plugins = g_key_file_get_string_list (priv->keyfile, "main", "plugins", NULL, NULL); if (!priv->plugins) @@ -852,6 +854,9 @@ nm_config_new (const NMConfigCmdLineOptions *cli, GError **error) g_free (connectivity_uri); g_free (connectivity_response); + priv->no_auto_default = g_strdupv (priv->no_auto_default_orig); + merge_no_auto_default_state (self); + return self; } @@ -881,6 +886,7 @@ finalize (GObject *gobject) g_free (priv->log_level); g_free (priv->log_domains); g_free (priv->debug); + g_strfreev (priv->no_auto_default_orig); g_strfreev (priv->no_auto_default); g_strfreev (priv->ignore_carrier); From 699b12ddc9ca502ad75077722d4af4f675377b40 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 16 Dec 2014 16:52:34 +0100 Subject: [PATCH 25/32] config: refactor reloading not to create a second NMConfig instance --- src/nm-config-data.c | 22 +++++++++++++++++ src/nm-config-data.h | 7 ++---- src/nm-config.c | 58 +++++++++++++++++++++----------------------- 3 files changed, 51 insertions(+), 36 deletions(-) diff --git a/src/nm-config-data.c b/src/nm-config-data.c index a5722453ed..a4799f76c6 100644 --- a/src/nm-config-data.c +++ b/src/nm-config-data.c @@ -143,6 +143,28 @@ nm_config_data_init (NMConfigData *self) { } +NMConfigData * +nm_config_data_new (GKeyFile *keyfile) +{ + char *connectivity_uri, *connectivity_response; + guint connectivity_interval; + NMConfigData *config_data; + + connectivity_uri = g_key_file_get_value (keyfile, "connectivity", "uri", NULL); + connectivity_interval = g_key_file_get_integer (keyfile, "connectivity", "interval", NULL); + connectivity_response = g_key_file_get_value (keyfile, "connectivity", "response", NULL); + + config_data = g_object_new (NM_TYPE_CONFIG_DATA, + NM_CONFIG_DATA_CONNECTIVITY_URI, connectivity_uri, + NM_CONFIG_DATA_CONNECTIVITY_INTERVAL, connectivity_interval, + NM_CONFIG_DATA_CONNECTIVITY_RESPONSE, connectivity_response, + NULL); + g_free (connectivity_uri); + g_free (connectivity_response); + + return config_data; +} + static void nm_config_data_class_init (NMConfigDataClass *config_class) { diff --git a/src/nm-config-data.h b/src/nm-config-data.h index 1437781e7d..042ce98164 100644 --- a/src/nm-config-data.h +++ b/src/nm-config-data.h @@ -50,15 +50,12 @@ typedef struct { GType nm_config_data_get_type (void); +NMConfigData *nm_config_data_new (GKeyFile *keyfile); + const char *nm_config_data_get_connectivity_uri (const NMConfigData *config_data); const guint nm_config_data_get_connectivity_interval (const NMConfigData *config_data); const char *nm_config_data_get_connectivity_response (const NMConfigData *config_data); -#include "nm-config.h" - -/* private function: internal use only */ -void _nm_config_data_set_config (NMConfigData *config_data, NMConfig *config); - G_END_DECLS #endif /* NM_CONFIG_DATA_H */ diff --git a/src/nm-config.c b/src/nm-config.c index 95a75edd9a..4573b7c050 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -707,36 +707,45 @@ void nm_config_reload (NMConfig *self) { NMConfigPrivate *priv; - NMConfig *new; GError *error = NULL; GHashTable *changes; + GKeyFile *keyfile; NMConfigData *old_data; NMConfigData *new_data = NULL; + char *config_main_file = NULL; + char *config_description = NULL; g_return_if_fail (NM_IS_CONFIG (self)); priv = NM_CONFIG_GET_PRIVATE (self); + /* pass on the original command line options. This means, that * options specified at command line cannot ever be reloaded from * file. That seems desirable. */ - new = nm_config_new (&priv->cli, &error); - - if (!new) { + keyfile = read_entire_config (&priv->cli, + priv->config_dir, + &config_main_file, + &config_description, + &error); + g_free (config_main_file); + g_free (config_description); + if (!keyfile) { nm_log_err (LOGD_CORE, "Failed to reload the configuration: %s", error->message); g_clear_error (&error); return; } + new_data = nm_config_data_new (keyfile); + g_key_file_free (keyfile); - old_data = priv->config_data; - new_data = nm_config_get_data (new); changes = g_hash_table_new (g_str_hash, g_str_equal); /* reloading configuration means we have to carefully check every single option * that we want to support and take specific actions. */ + old_data = priv->config_data; if ( nm_config_data_get_connectivity_interval (old_data) != nm_config_data_get_connectivity_interval (new_data) || g_strcmp0 (nm_config_data_get_connectivity_uri (old_data), nm_config_data_get_connectivity_uri (new_data)) || g_strcmp0 (nm_config_data_get_connectivity_response (old_data), nm_config_data_get_connectivity_response (new_data))) { @@ -744,20 +753,16 @@ nm_config_reload (NMConfig *self) g_hash_table_insert (changes, NM_CONFIG_CHANGES_CONNECTIVITY, NULL); } - if (g_hash_table_size (changes)) - new_data = g_object_ref (new_data); - else - new_data = NULL; - - g_object_unref (new); - - if (new_data) { - old_data = priv->config_data; - priv->config_data = new_data; - g_signal_emit (self, signals[SIGNAL_CONFIG_CHANGED], 0, new_data, changes, old_data); - g_object_unref (old_data); + if (!g_hash_table_size (changes)) { + g_hash_table_destroy (changes); + g_object_unref (new_data); + return; } + priv->config_data = new_data; + g_signal_emit (self, signals[SIGNAL_CONFIG_CHANGED], 0, new_data, changes, old_data); + g_object_unref (old_data); + g_hash_table_destroy (changes); } @@ -787,8 +792,6 @@ nm_config_new (const NMConfigCmdLineOptions *cli, GError **error) { NMConfigPrivate *priv = NULL; NMConfig *self; - char *connectivity_uri, *connectivity_response; - guint connectivity_interval; GKeyFile *keyfile; self = NM_CONFIG (g_object_new (NM_TYPE_CONFIG, @@ -841,18 +844,11 @@ nm_config_new (const NMConfigCmdLineOptions *cli, GError **error) priv->configure_and_quit = _get_bool_value (priv->keyfile, "main", "configure-and-quit", FALSE); - connectivity_uri = g_key_file_get_value (priv->keyfile, "connectivity", "uri", NULL); - connectivity_interval = g_key_file_get_integer (priv->keyfile, "connectivity", "interval", NULL); - connectivity_response = g_key_file_get_value (priv->keyfile, "connectivity", "response", NULL); + priv->config_data_orig = nm_config_data_new (priv->keyfile); - priv->config_data = g_object_new (NM_TYPE_CONFIG_DATA, - NM_CONFIG_DATA_CONNECTIVITY_URI, connectivity_uri, - NM_CONFIG_DATA_CONNECTIVITY_INTERVAL, connectivity_interval, - NM_CONFIG_DATA_CONNECTIVITY_RESPONSE, connectivity_response, - NULL); - priv->config_data_orig = g_object_ref (priv->config_data); - g_free (connectivity_uri); - g_free (connectivity_response); + /* Initialize mutable members. */ + + priv->config_data = g_object_ref (priv->config_data_orig); priv->no_auto_default = g_strdupv (priv->no_auto_default_orig); merge_no_auto_default_state (self); From 56f5fba72353e55db554c359af00376d3959009d Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 6 Jan 2015 20:16:10 +0100 Subject: [PATCH 26/32] config: move main_file and description to NMConfigData Every reload might change the main_file and description. Move those properties to NMConfigData. --- src/main.c | 2 +- src/nm-config-data.c | 58 +++++++++++++++++++++++++- src/nm-config-data.h | 9 +++- src/nm-config.c | 57 +++++++++++++------------ src/nm-config.h | 3 +- src/settings/plugins/example/plugin.c | 2 +- src/settings/plugins/ifupdown/plugin.c | 2 +- src/settings/plugins/keyfile/plugin.c | 2 +- src/tests/config/test-config.c | 6 +-- 9 files changed, 104 insertions(+), 37 deletions(-) diff --git a/src/main.c b/src/main.c index e1d2805a5c..11ecffca98 100644 --- a/src/main.c +++ b/src/main.c @@ -387,7 +387,7 @@ main (int argc, char *argv[]) nm_log_info (LOGD_CORE, "NetworkManager (version " NM_DIST_VERSION ") is starting..."); success = FALSE; - nm_log_info (LOGD_CORE, "Read config: %s", nm_config_get_config_description (config)); + nm_log_info (LOGD_CORE, "Read config: %s", nm_config_data_get_config_description (nm_config_get_data (config))); nm_log_info (LOGD_CORE, "WEXT support is %s", #if HAVE_WEXT "enabled" diff --git a/src/nm-config-data.c b/src/nm-config-data.c index a4799f76c6..03d3811065 100644 --- a/src/nm-config-data.c +++ b/src/nm-config-data.c @@ -22,6 +22,9 @@ #include "nm-config-data.h" typedef struct { + char *config_main_file; + char *config_description; + struct { char *uri; char *response; @@ -32,6 +35,8 @@ typedef struct { enum { PROP_0, + PROP_CONFIG_MAIN_FILE, + PROP_CONFIG_DESCRIPTION, PROP_CONNECTIVITY_URI, PROP_CONNECTIVITY_INTERVAL, PROP_CONNECTIVITY_RESPONSE, @@ -45,6 +50,22 @@ G_DEFINE_TYPE (NMConfigData, nm_config_data, G_TYPE_OBJECT) /************************************************************************/ +const char * +nm_config_data_get_config_main_file (const NMConfigData *self) +{ + g_return_val_if_fail (self, NULL); + + return NM_CONFIG_DATA_GET_PRIVATE (self)->config_main_file; +} + +const char * +nm_config_data_get_config_description (const NMConfigData *self) +{ + g_return_val_if_fail (self, NULL); + + return NM_CONFIG_DATA_GET_PRIVATE (self)->config_description; +} + const char * nm_config_data_get_connectivity_uri (const NMConfigData *self) { @@ -81,6 +102,12 @@ get_property (GObject *object, NMConfigData *self = NM_CONFIG_DATA (object); switch (prop_id) { + case PROP_CONFIG_MAIN_FILE: + g_value_set_string (value, nm_config_data_get_config_main_file (self)); + break; + case PROP_CONFIG_DESCRIPTION: + g_value_set_string (value, nm_config_data_get_config_description (self)); + break; case PROP_CONNECTIVITY_URI: g_value_set_string (value, nm_config_data_get_connectivity_uri (self)); break; @@ -107,6 +134,12 @@ set_property (GObject *object, /* This type is immutable. All properties are construct only. */ switch (prop_id) { + case PROP_CONFIG_MAIN_FILE: + priv->config_main_file = g_value_dup_string (value); + break; + case PROP_CONFIG_DESCRIPTION: + priv->config_description = g_value_dup_string (value); + break; case PROP_CONNECTIVITY_URI: priv->connectivity.uri = g_value_dup_string (value); break; @@ -132,6 +165,9 @@ finalize (GObject *gobject) { NMConfigDataPrivate *priv = NM_CONFIG_DATA_GET_PRIVATE (gobject); + g_free (priv->config_main_file); + g_free (priv->config_description); + g_free (priv->connectivity.uri); g_free (priv->connectivity.response); @@ -144,7 +180,9 @@ nm_config_data_init (NMConfigData *self) } NMConfigData * -nm_config_data_new (GKeyFile *keyfile) +nm_config_data_new (const char *config_main_file, + const char *config_description, + GKeyFile *keyfile) { char *connectivity_uri, *connectivity_response; guint connectivity_interval; @@ -155,6 +193,8 @@ nm_config_data_new (GKeyFile *keyfile) connectivity_response = g_key_file_get_value (keyfile, "connectivity", "response", NULL); config_data = 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_CONNECTIVITY_URI, connectivity_uri, NM_CONFIG_DATA_CONNECTIVITY_INTERVAL, connectivity_interval, NM_CONFIG_DATA_CONNECTIVITY_RESPONSE, connectivity_response, @@ -177,6 +217,22 @@ nm_config_data_class_init (NMConfigDataClass *config_class) object_class->get_property = get_property; object_class->set_property = set_property; + g_object_class_install_property + (object_class, PROP_CONFIG_MAIN_FILE, + g_param_spec_string (NM_CONFIG_DATA_CONFIG_MAIN_FILE, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_CONFIG_DESCRIPTION, + g_param_spec_string (NM_CONFIG_DATA_CONFIG_DESCRIPTION, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_CONNECTIVITY_URI, g_param_spec_string (NM_CONFIG_DATA_CONNECTIVITY_URI, "", "", diff --git a/src/nm-config-data.h b/src/nm-config-data.h index 042ce98164..c690f08b97 100644 --- a/src/nm-config-data.h +++ b/src/nm-config-data.h @@ -36,6 +36,8 @@ G_BEGIN_DECLS #define NM_CONFIG_DATA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_CONFIG_DATA, NMConfigDataClass)) +#define NM_CONFIG_DATA_CONFIG_MAIN_FILE "config-main-file" +#define NM_CONFIG_DATA_CONFIG_DESCRIPTION "config-description" #define NM_CONFIG_DATA_CONNECTIVITY_URI "connectivity-uri" #define NM_CONFIG_DATA_CONNECTIVITY_INTERVAL "connectivity-interval" #define NM_CONFIG_DATA_CONNECTIVITY_RESPONSE "connectivity-response" @@ -50,7 +52,12 @@ typedef struct { GType nm_config_data_get_type (void); -NMConfigData *nm_config_data_new (GKeyFile *keyfile); +NMConfigData *nm_config_data_new (const char *config_main_file, + const char *config_description, + GKeyFile *keyfile); + +const char *nm_config_data_get_config_main_file (const NMConfigData *config_data); +const char *nm_config_data_get_config_description (const NMConfigData *config_data); const char *nm_config_data_get_connectivity_uri (const NMConfigData *config_data); const guint nm_config_data_get_connectivity_interval (const NMConfigData *config_data); diff --git a/src/nm-config.c b/src/nm-config.c index 4573b7c050..6fb7335133 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -59,9 +59,7 @@ typedef struct { NMConfigData *config_data; NMConfigData *config_data_orig; - char *config_main_file; char *config_dir; - char *config_description; char *no_auto_default_file; GKeyFile *keyfile; @@ -159,22 +157,6 @@ nm_config_get_data_orig (NMConfig *config) return NM_CONFIG_GET_PRIVATE (config)->config_data_orig; } -const char * -nm_config_get_config_main_file (NMConfig *config) -{ - g_return_val_if_fail (config != NULL, NULL); - - return NM_CONFIG_GET_PRIVATE (config)->config_main_file; -} - -const char * -nm_config_get_config_description (NMConfig *config) -{ - g_return_val_if_fail (config != NULL, NULL); - - return NM_CONFIG_GET_PRIVATE (config)->config_description; -} - const char ** nm_config_get_plugins (NMConfig *config) { @@ -729,14 +711,14 @@ nm_config_reload (NMConfig *self) &config_main_file, &config_description, &error); - g_free (config_main_file); - g_free (config_description); if (!keyfile) { nm_log_err (LOGD_CORE, "Failed to reload the configuration: %s", error->message); g_clear_error (&error); return; } - new_data = nm_config_data_new (keyfile); + new_data = nm_config_data_new (config_main_file, config_description, keyfile); + g_free (config_main_file); + g_free (config_description); g_key_file_free (keyfile); @@ -753,12 +735,33 @@ nm_config_reload (NMConfig *self) g_hash_table_insert (changes, NM_CONFIG_CHANGES_CONNECTIVITY, NULL); } + 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) { + nm_log_dbg (LOGD_CORE, "config: reload: change '" NM_CONFIG_CHANGES_CONFIG_FILES "'"); + g_hash_table_insert (changes, NM_CONFIG_CHANGES_CONFIG_FILES, NULL); + } + if (!g_hash_table_size (changes)) { g_hash_table_destroy (changes); g_object_unref (new_data); return; } + if (nm_logging_enabled (LOGL_INFO, LOGD_CORE)) { + GString *str = g_string_new (NULL); + GHashTableIter iter; + const char *key; + + g_hash_table_iter_init (&iter, changes); + while (g_hash_table_iter_next (&iter, (gpointer) &key, NULL)) { + if (str->len) + g_string_append (str, ","); + g_string_append (str, key); + } + nm_log_info (LOGD_CORE, "config: update %s (%s)", nm_config_data_get_config_description (new_data), str->str); + g_string_free (str, TRUE); + } + priv->config_data = new_data; g_signal_emit (self, signals[SIGNAL_CONFIG_CHANGED], 0, new_data, changes, old_data); g_object_unref (old_data); @@ -793,6 +796,8 @@ nm_config_new (const NMConfigCmdLineOptions *cli, GError **error) NMConfigPrivate *priv = NULL; NMConfig *self; GKeyFile *keyfile; + char *config_main_file = NULL; + char *config_description = NULL; self = NM_CONFIG (g_object_new (NM_TYPE_CONFIG, NM_CONFIG_CMD_LINE_OPTIONS, cli, @@ -806,8 +811,8 @@ nm_config_new (const NMConfigCmdLineOptions *cli, GError **error) keyfile = read_entire_config (&priv->cli, priv->config_dir, - &priv->config_main_file, - &priv->config_description, + &config_main_file, + &config_description, error); if (!keyfile) { g_object_unref (self); @@ -844,7 +849,7 @@ nm_config_new (const NMConfigCmdLineOptions *cli, GError **error) priv->configure_and_quit = _get_bool_value (priv->keyfile, "main", "configure-and-quit", FALSE); - priv->config_data_orig = nm_config_data_new (priv->keyfile); + priv->config_data_orig = nm_config_data_new (config_main_file, config_description, priv->keyfile); /* Initialize mutable members. */ @@ -853,6 +858,8 @@ nm_config_new (const NMConfigCmdLineOptions *cli, GError **error) priv->no_auto_default = g_strdupv (priv->no_auto_default_orig); merge_no_auto_default_state (self); + g_free (config_main_file); + g_free (config_description); return self; } @@ -871,9 +878,7 @@ finalize (GObject *gobject) { NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (gobject); - g_free (priv->config_main_file); g_free (priv->config_dir); - g_free (priv->config_description); g_free (priv->no_auto_default_file); g_clear_pointer (&priv->keyfile, g_key_file_unref); g_strfreev (priv->plugins); diff --git a/src/nm-config.h b/src/nm-config.h index f4994a1f52..a961199499 100644 --- a/src/nm-config.h +++ b/src/nm-config.h @@ -43,6 +43,7 @@ G_BEGIN_DECLS /* Signals */ #define NM_CONFIG_SIGNAL_CONFIG_CHANGED "config-changed" +#define NM_CONFIG_CHANGES_CONFIG_FILES "config-files" #define NM_CONFIG_CHANGES_CONNECTIVITY "connectivity" typedef struct NMConfigCmdLineOptions NMConfigCmdLineOptions; @@ -64,8 +65,6 @@ NMConfig *nm_config_get (void); NMConfigData *nm_config_get_data (NMConfig *config); NMConfigData *nm_config_get_data_orig (NMConfig *config); -const char *nm_config_get_config_main_file (NMConfig *config); -const char *nm_config_get_config_description (NMConfig *config); const char **nm_config_get_plugins (NMConfig *config); gboolean nm_config_get_monitor_connection_files (NMConfig *config); gboolean nm_config_get_auth_polkit (NMConfig *config); diff --git a/src/settings/plugins/example/plugin.c b/src/settings/plugins/example/plugin.c index b93b1dfb46..0bcb38fcf3 100644 --- a/src/settings/plugins/example/plugin.c +++ b/src/settings/plugins/example/plugin.c @@ -847,7 +847,7 @@ nm_system_config_factory (void) priv = SC_PLUGIN_EXAMPLE_GET_PRIVATE (singleton); /* Cache the config file path */ - priv->conf_file = nm_config_get_config_main_file (nm_config_get ()); + priv->conf_file = nm_config_data_get_config_main_file (nm_config_get_data (nm_config_get ())); } else { /* This function should never be called twice */ g_assert_not_reached (); diff --git a/src/settings/plugins/ifupdown/plugin.c b/src/settings/plugins/ifupdown/plugin.c index 61b9dcef07..fbd3dd2379 100644 --- a/src/settings/plugins/ifupdown/plugin.c +++ b/src/settings/plugins/ifupdown/plugin.c @@ -461,7 +461,7 @@ SCPluginIfupdown_init (NMSystemConfigInterface *config) &error); if (error) { nm_log_info (LOGD_SETTINGS, "loading system config file (%s) caused error: %s", - nm_config_get_config_main_file (nm_config_get ()), + nm_config_data_get_config_main_file (nm_config_get_data (nm_config_get ())), error->message); } else { gboolean manage_well_known; diff --git a/src/settings/plugins/keyfile/plugin.c b/src/settings/plugins/keyfile/plugin.c index 869af6a1c5..edaa7d4566 100644 --- a/src/settings/plugins/keyfile/plugin.c +++ b/src/settings/plugins/keyfile/plugin.c @@ -843,7 +843,7 @@ nm_settings_keyfile_plugin_new (void) singleton = SC_PLUGIN_KEYFILE (g_object_new (SC_TYPE_PLUGIN_KEYFILE, NULL)); priv = SC_PLUGIN_KEYFILE_GET_PRIVATE (singleton); - priv->conf_file = nm_config_get_config_main_file (nm_config_get ()); + priv->conf_file = nm_config_data_get_config_main_file (nm_config_get_data (nm_config_get ())); /* plugin_set_hostname() has to be called *after* priv->conf_file is set */ priv->hostname = plugin_get_hostname (singleton); diff --git a/src/tests/config/test-config.c b/src/tests/config/test-config.c index a6f921c750..d63fff4613 100644 --- a/src/tests/config/test-config.c +++ b/src/tests/config/test-config.c @@ -93,7 +93,7 @@ test_config_simple (void) config = setup_config (NULL, SRCDIR "/NetworkManager.conf", "/no/such/dir", NULL); - g_assert_cmpstr (nm_config_get_config_main_file (config), ==, SRCDIR "/NetworkManager.conf"); + 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"); g_assert_cmpstr (nm_config_get_log_level (config), ==, "INFO"); g_assert_cmpint (nm_config_data_get_connectivity_interval (nm_config_get_data_orig (config)), ==, 100); @@ -152,7 +152,7 @@ test_config_override (void) "--connectivity-interval", "12", NULL); - g_assert_cmpstr (nm_config_get_config_main_file (config), ==, SRCDIR "/NetworkManager.conf"); + 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"); g_assert_cmpstr (nm_config_get_log_level (config), ==, "INFO"); g_assert_cmpint (nm_config_data_get_connectivity_interval (nm_config_get_data_orig (config)), ==, 12); @@ -233,7 +233,7 @@ test_config_confdir (void) config = setup_config (NULL, SRCDIR "/NetworkManager.conf", SRCDIR "/conf.d", NULL); - g_assert_cmpstr (nm_config_get_config_main_file (config), ==, SRCDIR "/NetworkManager.conf"); + 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"); g_assert_cmpstr (nm_config_get_log_level (config), ==, "INFO"); g_assert_cmpstr (nm_config_get_log_domains (config), ==, "PLATFORM,DNS,WIFI"); From 045a576a7ab8dac3f7aa9302532fa94e790c1f05 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 7 Jan 2015 14:30:14 +0100 Subject: [PATCH 27/32] config: add new function nm_config_data_diff() --- src/nm-config-data.c | 30 ++++++++++++++++++++++++++++++ src/nm-config-data.h | 2 ++ src/nm-config.c | 22 ++-------------------- 3 files changed, 34 insertions(+), 20 deletions(-) diff --git a/src/nm-config-data.c b/src/nm-config-data.c index 03d3811065..8683696e81 100644 --- a/src/nm-config-data.c +++ b/src/nm-config-data.c @@ -21,6 +21,8 @@ #include "nm-config-data.h" +#include "nm-config.h" + typedef struct { char *config_main_file; char *config_description; @@ -91,6 +93,34 @@ nm_config_data_get_connectivity_response (const NMConfigData *self) } +/************************************************************************/ + +GHashTable * +nm_config_data_diff (NMConfigData *old_data, NMConfigData *new_data) +{ + GHashTable *changes; + + g_return_val_if_fail (NM_IS_CONFIG_DATA (old_data), NULL); + g_return_val_if_fail (NM_IS_CONFIG_DATA (new_data), NULL); + + changes = g_hash_table_new (g_str_hash, g_str_equal); + + 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) + g_hash_table_insert (changes, NM_CONFIG_CHANGES_CONFIG_FILES, NULL); + + if ( nm_config_data_get_connectivity_interval (old_data) != nm_config_data_get_connectivity_interval (new_data) + || g_strcmp0 (nm_config_data_get_connectivity_uri (old_data), nm_config_data_get_connectivity_uri (new_data)) + || g_strcmp0 (nm_config_data_get_connectivity_response (old_data), nm_config_data_get_connectivity_response (new_data))) + g_hash_table_insert (changes, NM_CONFIG_CHANGES_CONNECTIVITY, NULL); + + if (!g_hash_table_size (changes)) { + g_hash_table_destroy (changes); + return NULL; + } + return changes; +} + /************************************************************************/ static void diff --git a/src/nm-config-data.h b/src/nm-config-data.h index c690f08b97..cd6313cdf7 100644 --- a/src/nm-config-data.h +++ b/src/nm-config-data.h @@ -56,6 +56,8 @@ NMConfigData *nm_config_data_new (const char *config_main_file, const char *config_description, GKeyFile *keyfile); +GHashTable *nm_config_data_diff (NMConfigData *old_data, NMConfigData *new_data); + const char *nm_config_data_get_config_main_file (const NMConfigData *config_data); const char *nm_config_data_get_config_description (const NMConfigData *config_data); diff --git a/src/nm-config.c b/src/nm-config.c index 6fb7335133..0eb3c08b7c 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -721,28 +721,10 @@ nm_config_reload (NMConfig *self) g_free (config_description); g_key_file_free (keyfile); - - changes = g_hash_table_new (g_str_hash, g_str_equal); - - /* reloading configuration means we have to carefully check every single option - * that we want to support and take specific actions. */ - old_data = priv->config_data; - if ( nm_config_data_get_connectivity_interval (old_data) != nm_config_data_get_connectivity_interval (new_data) - || g_strcmp0 (nm_config_data_get_connectivity_uri (old_data), nm_config_data_get_connectivity_uri (new_data)) - || g_strcmp0 (nm_config_data_get_connectivity_response (old_data), nm_config_data_get_connectivity_response (new_data))) { - nm_log_dbg (LOGD_CORE, "config: reload: change '" NM_CONFIG_CHANGES_CONNECTIVITY "'"); - g_hash_table_insert (changes, NM_CONFIG_CHANGES_CONNECTIVITY, NULL); - } + changes = nm_config_data_diff (old_data, new_data); - 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) { - nm_log_dbg (LOGD_CORE, "config: reload: change '" NM_CONFIG_CHANGES_CONFIG_FILES "'"); - g_hash_table_insert (changes, NM_CONFIG_CHANGES_CONFIG_FILES, NULL); - } - - if (!g_hash_table_size (changes)) { - g_hash_table_destroy (changes); + if (!changes) { g_object_unref (new_data); return; } From ba74f9d2428c937014c3bcd02ac25591bbc1abc5 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 7 Jan 2015 13:25:41 +0100 Subject: [PATCH 28/32] config: move keyfile values to NMConfigData --- src/nm-config-data.c | 119 ++++++++++++++++++------- src/nm-config-data.h | 3 + src/nm-config.c | 41 +++------ src/nm-config.h | 3 +- src/settings/plugins/ifnet/plugin.c | 12 +-- src/settings/plugins/ifupdown/plugin.c | 6 +- src/tests/config/test-config.c | 16 ++-- 7 files changed, 121 insertions(+), 79 deletions(-) diff --git a/src/nm-config-data.c b/src/nm-config-data.c index 8683696e81..93a56df1e3 100644 --- a/src/nm-config-data.c +++ b/src/nm-config-data.c @@ -21,12 +21,17 @@ #include "nm-config-data.h" +#include + #include "nm-config.h" +#include "gsystem-local-alloc.h" typedef struct { char *config_main_file; char *config_description; + GKeyFile *keyfile; + struct { char *uri; char *response; @@ -39,6 +44,7 @@ enum { PROP_0, PROP_CONFIG_MAIN_FILE, PROP_CONFIG_DESCRIPTION, + PROP_KEYFILE, PROP_CONNECTIVITY_URI, PROP_CONNECTIVITY_INTERVAL, PROP_CONNECTIVITY_RESPONSE, @@ -68,6 +74,14 @@ nm_config_data_get_config_description (const NMConfigData *self) return NM_CONFIG_DATA_GET_PRIVATE (self)->config_description; } +char * +nm_config_data_get_value (const NMConfigData *self, const char *group, const char *key, GError **error) +{ + g_return_val_if_fail (self, NULL); + + return g_key_file_get_string (NM_CONFIG_DATA_GET_PRIVATE (self)->keyfile, group, key, error); +} + const char * nm_config_data_get_connectivity_uri (const NMConfigData *self) { @@ -95,16 +109,51 @@ nm_config_data_get_connectivity_response (const NMConfigData *self) /************************************************************************/ +static gboolean +_keyfile_a_contains_all_in_b (GKeyFile *kf_a, GKeyFile *kf_b) +{ + gs_strfreev char **groups = NULL; + guint i, j; + + if (kf_a == kf_b) + return TRUE; + + groups = g_key_file_get_groups (kf_a, NULL); + for (i = 0; groups && groups[i]; i++) { + gs_strfreev char **keys = NULL; + + keys = g_key_file_get_keys (kf_a, groups[i], NULL, NULL); + if (keys) { + for (j = 0; keys[j]; j++) { + gs_free char *key_a = g_key_file_get_value (kf_a, groups[i], keys[j], NULL); + gs_free char *key_b = g_key_file_get_value (kf_b, groups[i], keys[j], NULL); + + if (g_strcmp0 (key_a, key_b) != 0) + return FALSE; + } + } + } + return TRUE; +} + GHashTable * nm_config_data_diff (NMConfigData *old_data, NMConfigData *new_data) { GHashTable *changes; + NMConfigDataPrivate *priv_old, *priv_new; g_return_val_if_fail (NM_IS_CONFIG_DATA (old_data), NULL); g_return_val_if_fail (NM_IS_CONFIG_DATA (new_data), NULL); changes = g_hash_table_new (g_str_hash, g_str_equal); + priv_old = NM_CONFIG_DATA_GET_PRIVATE (old_data); + priv_new = NM_CONFIG_DATA_GET_PRIVATE (new_data); + + if ( !_keyfile_a_contains_all_in_b (priv_old->keyfile, priv_new->keyfile) + || !_keyfile_a_contains_all_in_b (priv_new->keyfile, priv_old->keyfile)) + g_hash_table_insert (changes, NM_CONFIG_CHANGES_VALUES, NULL); + 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) g_hash_table_insert (changes, NM_CONFIG_CHANGES_CONFIG_FILES, NULL); @@ -170,14 +219,10 @@ set_property (GObject *object, case PROP_CONFIG_DESCRIPTION: priv->config_description = g_value_dup_string (value); break; - case PROP_CONNECTIVITY_URI: - priv->connectivity.uri = g_value_dup_string (value); - break; - case PROP_CONNECTIVITY_INTERVAL: - priv->connectivity.interval = g_value_get_uint (value); - break; - case PROP_CONNECTIVITY_RESPONSE: - priv->connectivity.response = g_value_dup_string (value); + case PROP_KEYFILE: + priv->keyfile = g_value_dup_boxed (value); + if (!priv->keyfile) + priv->keyfile = nm_config_create_keyfile (); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -209,30 +254,32 @@ nm_config_data_init (NMConfigData *self) { } +static void +constructed (GObject *object) +{ + NMConfigData *self = NM_CONFIG_DATA (object); + NMConfigDataPrivate *priv = NM_CONFIG_DATA_GET_PRIVATE (self); + int interval; + + priv->connectivity.uri = g_key_file_get_value (priv->keyfile, "connectivity", "uri", NULL); + priv->connectivity.response = g_key_file_get_value (priv->keyfile, "connectivity", "response", NULL); + + interval = g_key_file_get_integer (priv->keyfile, "connectivity", "interval", NULL); + priv->connectivity.interval = MAX (0, interval); + + G_OBJECT_CLASS (nm_config_data_parent_class)->constructed (object); +} + NMConfigData * nm_config_data_new (const char *config_main_file, const char *config_description, GKeyFile *keyfile) { - char *connectivity_uri, *connectivity_response; - guint connectivity_interval; - NMConfigData *config_data; - - connectivity_uri = g_key_file_get_value (keyfile, "connectivity", "uri", NULL); - connectivity_interval = g_key_file_get_integer (keyfile, "connectivity", "interval", NULL); - connectivity_response = g_key_file_get_value (keyfile, "connectivity", "response", NULL); - - config_data = 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_CONNECTIVITY_URI, connectivity_uri, - NM_CONFIG_DATA_CONNECTIVITY_INTERVAL, connectivity_interval, - NM_CONFIG_DATA_CONNECTIVITY_RESPONSE, connectivity_response, - NULL); - g_free (connectivity_uri); - g_free (connectivity_response); - - return config_data; + 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, + NULL); } static void @@ -242,6 +289,7 @@ nm_config_data_class_init (NMConfigDataClass *config_class) g_type_class_add_private (config_class, sizeof (NMConfigDataPrivate)); + object_class->constructed = constructed; object_class->dispose = dispose; object_class->finalize = finalize; object_class->get_property = get_property; @@ -263,28 +311,33 @@ nm_config_data_class_init (NMConfigDataClass *config_class) G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property + (object_class, PROP_KEYFILE, + g_param_spec_boxed (NM_CONFIG_DATA_KEYFILE, "", "", + G_TYPE_KEY_FILE, + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_CONNECTIVITY_URI, g_param_spec_string (NM_CONFIG_DATA_CONNECTIVITY_URI, "", "", NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_CONNECTIVITY_INTERVAL, g_param_spec_uint (NM_CONFIG_DATA_CONNECTIVITY_INTERVAL, "", "", 0, G_MAXUINT, 0, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_CONNECTIVITY_RESPONSE, g_param_spec_string (NM_CONFIG_DATA_CONNECTIVITY_RESPONSE, "", "", NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); } diff --git a/src/nm-config-data.h b/src/nm-config-data.h index cd6313cdf7..d3425632b0 100644 --- a/src/nm-config-data.h +++ b/src/nm-config-data.h @@ -38,6 +38,7 @@ 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_CONNECTIVITY_URI "connectivity-uri" #define NM_CONFIG_DATA_CONNECTIVITY_INTERVAL "connectivity-interval" #define NM_CONFIG_DATA_CONNECTIVITY_RESPONSE "connectivity-response" @@ -61,6 +62,8 @@ GHashTable *nm_config_data_diff (NMConfigData *old_data, NMConfigData *new_data) const char *nm_config_data_get_config_main_file (const NMConfigData *config_data); const char *nm_config_data_get_config_description (const NMConfigData *config_data); +char *nm_config_data_get_value (const NMConfigData *config_data, const char *group, const char *key, GError **error); + const char *nm_config_data_get_connectivity_uri (const NMConfigData *config_data); const guint nm_config_data_get_connectivity_interval (const NMConfigData *config_data); const char *nm_config_data_get_connectivity_response (const NMConfigData *config_data); diff --git a/src/nm-config.c b/src/nm-config.c index 0eb3c08b7c..501f431f01 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -61,7 +61,6 @@ typedef struct { char *config_dir; char *no_auto_default_file; - GKeyFile *keyfile; char **plugins; gboolean monitor_connection_files; @@ -227,14 +226,6 @@ nm_config_get_configure_and_quit (NMConfig *config) return NM_CONFIG_GET_PRIVATE (config)->configure_and_quit; } -char * -nm_config_get_value (NMConfig *config, const char *group, const char *key, GError **error) -{ - NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (config); - - return g_key_file_get_string (priv->keyfile, group, key, error); -} - gboolean nm_config_get_ignore_carrier (NMConfig *config, NMDevice *device) { @@ -719,7 +710,7 @@ nm_config_reload (NMConfig *self) new_data = nm_config_data_new (config_main_file, config_description, keyfile); g_free (config_main_file); g_free (config_description); - g_key_file_free (keyfile); + g_key_file_unref (keyfile); old_data = priv->config_data; changes = nm_config_data_diff (old_data, new_data); @@ -800,8 +791,6 @@ nm_config_new (const NMConfigCmdLineOptions *cli, GError **error) g_object_unref (self); return NULL; } - g_key_file_free (priv->keyfile); - priv->keyfile = keyfile; /* Initialize read only private members */ @@ -809,29 +798,29 @@ nm_config_new (const NMConfigCmdLineOptions *cli, GError **error) priv->no_auto_default_file = g_strdup (priv->cli.no_auto_default_file); else priv->no_auto_default_file = g_strdup (NM_NO_AUTO_DEFAULT_STATE_FILE); - priv->no_auto_default_orig = g_key_file_get_string_list (priv->keyfile, "main", "no-auto-default", NULL, NULL); + priv->no_auto_default_orig = g_key_file_get_string_list (keyfile, "main", "no-auto-default", NULL, NULL); - priv->plugins = g_key_file_get_string_list (priv->keyfile, "main", "plugins", NULL, NULL); + priv->plugins = g_key_file_get_string_list (keyfile, "main", "plugins", NULL, NULL); if (!priv->plugins) priv->plugins = g_new0 (char *, 1); - priv->monitor_connection_files = _get_bool_value (priv->keyfile, "main", "monitor-connection-files", FALSE); + priv->monitor_connection_files = _get_bool_value (keyfile, "main", "monitor-connection-files", FALSE); - priv->auth_polkit = _get_bool_value (priv->keyfile, "main", "auth-polkit", NM_CONFIG_DEFAULT_AUTH_POLKIT); + priv->auth_polkit = _get_bool_value (keyfile, "main", "auth-polkit", NM_CONFIG_DEFAULT_AUTH_POLKIT); - priv->dhcp_client = g_key_file_get_value (priv->keyfile, "main", "dhcp", NULL); - priv->dns_mode = g_key_file_get_value (priv->keyfile, "main", "dns", NULL); + priv->dhcp_client = g_key_file_get_value (keyfile, "main", "dhcp", NULL); + priv->dns_mode = g_key_file_get_value (keyfile, "main", "dns", NULL); - priv->log_level = g_key_file_get_value (priv->keyfile, "logging", "level", NULL); - priv->log_domains = g_key_file_get_value (priv->keyfile, "logging", "domains", NULL); + priv->log_level = g_key_file_get_value (keyfile, "logging", "level", NULL); + priv->log_domains = g_key_file_get_value (keyfile, "logging", "domains", NULL); - priv->debug = g_key_file_get_value (priv->keyfile, "main", "debug", NULL); + priv->debug = g_key_file_get_value (keyfile, "main", "debug", NULL); - priv->ignore_carrier = g_key_file_get_string_list (priv->keyfile, "main", "ignore-carrier", NULL, NULL); + priv->ignore_carrier = g_key_file_get_string_list (keyfile, "main", "ignore-carrier", NULL, NULL); - priv->configure_and_quit = _get_bool_value (priv->keyfile, "main", "configure-and-quit", FALSE); + priv->configure_and_quit = _get_bool_value (keyfile, "main", "configure-and-quit", FALSE); - priv->config_data_orig = nm_config_data_new (config_main_file, config_description, priv->keyfile); + priv->config_data_orig = nm_config_data_new (config_main_file, config_description, keyfile); /* Initialize mutable members. */ @@ -842,6 +831,7 @@ nm_config_new (const NMConfigCmdLineOptions *cli, GError **error) g_free (config_main_file); g_free (config_description); + g_key_file_unref (keyfile); return self; } @@ -851,8 +841,6 @@ nm_config_init (NMConfig *config) NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (config); priv->auth_polkit = NM_CONFIG_DEFAULT_AUTH_POLKIT; - - priv->keyfile = nm_config_create_keyfile (); } static void @@ -862,7 +850,6 @@ finalize (GObject *gobject) 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); g_free (priv->dns_mode); diff --git a/src/nm-config.h b/src/nm-config.h index a961199499..98a9d2af6d 100644 --- a/src/nm-config.h +++ b/src/nm-config.h @@ -44,6 +44,7 @@ G_BEGIN_DECLS #define NM_CONFIG_SIGNAL_CONFIG_CHANGED "config-changed" #define NM_CONFIG_CHANGES_CONFIG_FILES "config-files" +#define NM_CONFIG_CHANGES_VALUES "values" #define NM_CONFIG_CHANGES_CONNECTIVITY "connectivity" typedef struct NMConfigCmdLineOptions NMConfigCmdLineOptions; @@ -80,8 +81,6 @@ void nm_config_set_ethernet_no_auto_default (NMConfig *config, NMDevice *de gboolean nm_config_get_ignore_carrier (NMConfig *config, NMDevice *device); -char *nm_config_get_value (NMConfig *config, const char *group, const char *key, GError **error); - /* for main.c only */ NMConfigCmdLineOptions *nm_config_cmd_line_options_new (void); void nm_config_cmd_line_options_free (NMConfigCmdLineOptions *cli); diff --git a/src/settings/plugins/ifnet/plugin.c b/src/settings/plugins/ifnet/plugin.c index 33711639da..7f1eb4ff93 100644 --- a/src/settings/plugins/ifnet/plugin.c +++ b/src/settings/plugins/ifnet/plugin.c @@ -123,9 +123,9 @@ is_managed_plugin (void) { char *result = NULL; - result = nm_config_get_value (nm_config_get (), - IFNET_KEY_FILE_GROUP, IFNET_KEY_FILE_KEY_MANAGED, - NULL); + result = nm_config_data_get_value (nm_config_get_data_orig (nm_config_get ()), + IFNET_KEY_FILE_GROUP, IFNET_KEY_FILE_KEY_MANAGED, + NULL); if (result) { gboolean ret = is_true (result); g_free (result); @@ -264,9 +264,9 @@ reload_connections (NMSystemConfigInterface *config) nm_log_info (LOGD_SETTINGS, "Loading connections"); - str_auto_refresh = nm_config_get_value (nm_config_get (), - IFNET_KEY_FILE_GROUP, "auto_refresh", - NULL); + str_auto_refresh = nm_config_data_get_value (nm_config_get_data_orig (nm_config_get ()), + IFNET_KEY_FILE_GROUP, "auto_refresh", + NULL); if (str_auto_refresh && is_true (str_auto_refresh)) auto_refresh = TRUE; g_free (str_auto_refresh); diff --git a/src/settings/plugins/ifupdown/plugin.c b/src/settings/plugins/ifupdown/plugin.c index fbd3dd2379..1cbff29b3d 100644 --- a/src/settings/plugins/ifupdown/plugin.c +++ b/src/settings/plugins/ifupdown/plugin.c @@ -456,9 +456,9 @@ SCPluginIfupdown_init (NMSystemConfigInterface *config) g_hash_table_destroy (auto_ifaces); /* Check the config file to find out whether to manage interfaces */ - value = nm_config_get_value (nm_config_get (), - IFUPDOWN_KEY_FILE_GROUP, IFUPDOWN_KEY_FILE_KEY_MANAGED, - &error); + value = nm_config_data_get_value (nm_config_get_data_orig (nm_config_get ()), + IFUPDOWN_KEY_FILE_GROUP, IFUPDOWN_KEY_FILE_KEY_MANAGED, + &error); if (error) { nm_log_info (LOGD_SETTINGS, "loading system config file (%s) caused error: %s", nm_config_data_get_config_main_file (nm_config_get_data (nm_config_get ())), diff --git a/src/tests/config/test-config.c b/src/tests/config/test-config.c index d63fff4613..8c52031c25 100644 --- a/src/tests/config/test-config.c +++ b/src/tests/config/test-config.c @@ -104,16 +104,16 @@ test_config_simple (void) g_assert_cmpstr (plugins[1], ==, "bar"); g_assert_cmpstr (plugins[2], ==, "baz"); - value = nm_config_get_value (config, "extra-section", "extra-key", NULL); + value = nm_config_data_get_value (nm_config_get_data_orig (config), "extra-section", "extra-key", NULL); g_assert_cmpstr (value, ==, "some value"); g_free (value); - value = nm_config_get_value (config, "extra-section", "no-key", &error); + value = nm_config_data_get_value (nm_config_get_data_orig (config), "extra-section", "no-key", &error); g_assert (!value); g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND); g_clear_error (&error); - value = nm_config_get_value (config, "no-section", "no-key", &error); + value = nm_config_data_get_value (nm_config_get_data_orig (config), "no-section", "no-key", &error); g_assert (!value); g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND); g_clear_error (&error); @@ -248,21 +248,21 @@ test_config_confdir (void) g_assert_cmpstr (plugins[3], ==, "one"); g_assert_cmpstr (plugins[4], ==, "two"); - value = nm_config_get_value (config, "main", "extra", NULL); + value = nm_config_data_get_value (nm_config_get_data_orig (config), "main", "extra", NULL); g_assert_cmpstr (value, ==, "hello"); g_free (value); - value = nm_config_get_value (config, "main", "new", NULL); + value = nm_config_data_get_value (nm_config_get_data_orig (config), "main", "new", NULL); g_assert_cmpstr (value, ==, "something"); /* not ",something" */ g_free (value); - value = nm_config_get_value (config, "order", "a", NULL); + value = nm_config_data_get_value (nm_config_get_data_orig (config), "order", "a", NULL); g_assert_cmpstr (value, ==, "90"); g_free (value); - value = nm_config_get_value (config, "order", "b", NULL); + value = nm_config_data_get_value (nm_config_get_data_orig (config), "order", "b", NULL); g_assert_cmpstr (value, ==, "10"); g_free (value); - value = nm_config_get_value (config, "order", "c", NULL); + value = nm_config_data_get_value (nm_config_get_data_orig (config), "order", "c", NULL); g_assert_cmpstr (value, ==, "0"); g_free (value); From 49b3f5b8d9e3b01cfd23bf72f9df2a6e76006bbe Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 7 Jan 2015 16:12:01 +0100 Subject: [PATCH 29/32] config: refactor merging no_auto_default --- src/nm-config.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/src/nm-config.c b/src/nm-config.c index 501f431f01..a295d1d520 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -248,27 +248,22 @@ nm_config_get_ignore_carrier (NMConfig *config, NMDevice *device) /************************************************************************/ -static void -merge_no_auto_default_state (NMConfig *config) +static char ** +no_auto_default_merge_from_file (const char *no_auto_default_file, const char *const* no_auto_default) { - NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (config); GPtrArray *updated; char **list; int i, j; char *data; - /* If the config already matches everything, we don't need to do anything else. */ - if (priv->no_auto_default && !g_strcmp0 (priv->no_auto_default[0], "*")) - return; - updated = g_ptr_array_new (); - if (priv->no_auto_default) { - for (i = 0; priv->no_auto_default[i]; i++) - g_ptr_array_add (updated, priv->no_auto_default[i]); - g_free (priv->no_auto_default); + if (no_auto_default) { + for (i = 0; no_auto_default[i]; i++) + g_ptr_array_add (updated, g_strdup (no_auto_default[i])); } - if (g_file_get_contents (priv->no_auto_default_file, &data, NULL, NULL)) { + if ( no_auto_default_file + && g_file_get_contents (no_auto_default_file, &data, NULL, NULL)) { list = g_strsplit (data, "\n", -1); for (i = 0; list[i]; i++) { if (!*list[i]) @@ -289,7 +284,7 @@ merge_no_auto_default_state (NMConfig *config) } g_ptr_array_add (updated, NULL); - priv->no_auto_default = (char **) g_ptr_array_free (updated, FALSE); + return (char **) g_ptr_array_free (updated, FALSE); } gboolean @@ -316,6 +311,7 @@ nm_config_set_ethernet_no_auto_default (NMConfig *config, NMDevice *device) char *current; GString *updated; GError *error = NULL; + char **no_auto_default; if (!nm_config_get_ethernet_can_auto_default (config, device)) return; @@ -339,7 +335,9 @@ nm_config_set_ethernet_no_auto_default (NMConfig *config, NMDevice *device) g_string_free (updated, TRUE); - merge_no_auto_default_state (config); + no_auto_default = no_auto_default_merge_from_file (priv->no_auto_default_file, (const char *const *) priv->no_auto_default); + g_strfreev (priv->no_auto_default); + priv->no_auto_default = no_auto_default; } /************************************************************************/ @@ -826,8 +824,7 @@ nm_config_new (const NMConfigCmdLineOptions *cli, GError **error) priv->config_data = g_object_ref (priv->config_data_orig); - priv->no_auto_default = g_strdupv (priv->no_auto_default_orig); - merge_no_auto_default_state (self); + priv->no_auto_default = no_auto_default_merge_from_file (priv->no_auto_default_file, (const char *const *) priv->no_auto_default_orig); g_free (config_main_file); g_free (config_description); From 13c7f6a56db55db47d31a181c85913f1d183f95a Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 7 Jan 2015 17:09:52 +0100 Subject: [PATCH 30/32] config: move no-auto-default to NMConfigData With this change, NMConfig is really immutable and all modifyable parts migrated to NMConfigData. Another advantage is that components can now subscribe to NMConfig changes to pickup changes to no-auto-default. --- src/devices/nm-device-ethernet.c | 2 +- src/nm-config-data.c | 70 ++++++++++++++++++++++++++++++ src/nm-config-data.h | 6 +++ src/nm-config.c | 73 ++++++++++++++++++-------------- src/nm-config.h | 7 +-- src/settings/nm-settings.c | 2 +- src/tests/config/test-config.c | 34 ++++++++------- 7 files changed, 143 insertions(+), 51 deletions(-) diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c index 0027958c38..af24f8be6d 100644 --- a/src/devices/nm-device-ethernet.c +++ b/src/devices/nm-device-ethernet.c @@ -1463,7 +1463,7 @@ new_default_connection (NMDevice *self) const char *hw_address; char *defname, *uuid; - if (!nm_config_get_ethernet_can_auto_default (nm_config_get (), self)) + if (nm_config_get_no_auto_default_for_device (nm_config_get (), self)) return NULL; hw_address = nm_device_get_hw_address (self); diff --git a/src/nm-config-data.c b/src/nm-config-data.c index 93a56df1e3..cf140739fc 100644 --- a/src/nm-config-data.c +++ b/src/nm-config-data.c @@ -37,6 +37,11 @@ typedef struct { char *response; guint interval; } connectivity; + + struct { + char **arr; + GSList *specs; + } no_auto_default; } NMConfigDataPrivate; @@ -48,6 +53,7 @@ enum { PROP_CONNECTIVITY_URI, PROP_CONNECTIVITY_INTERVAL, PROP_CONNECTIVITY_RESPONSE, + PROP_NO_AUTO_DEFAULT, LAST_PROP }; @@ -106,6 +112,21 @@ nm_config_data_get_connectivity_response (const NMConfigData *self) return NM_CONFIG_DATA_GET_PRIVATE (self)->connectivity.response; } +const char *const* +nm_config_data_get_no_auto_default (const NMConfigData *self) +{ + g_return_val_if_fail (self, FALSE); + + return (const char *const*) NM_CONFIG_DATA_GET_PRIVATE (self)->no_auto_default.arr; +} + +const GSList * +nm_config_data_get_no_auto_default_list (const NMConfigData *self) +{ + g_return_val_if_fail (self, NULL); + + return NM_CONFIG_DATA_GET_PRIVATE (self)->no_auto_default.specs; +} /************************************************************************/ @@ -141,6 +162,7 @@ nm_config_data_diff (NMConfigData *old_data, NMConfigData *new_data) { GHashTable *changes; NMConfigDataPrivate *priv_old, *priv_new; + GSList *spec_old, *spec_new; g_return_val_if_fail (NM_IS_CONFIG_DATA (old_data), NULL); g_return_val_if_fail (NM_IS_CONFIG_DATA (new_data), NULL); @@ -163,6 +185,15 @@ nm_config_data_diff (NMConfigData *old_data, NMConfigData *new_data) || g_strcmp0 (nm_config_data_get_connectivity_response (old_data), nm_config_data_get_connectivity_response (new_data))) g_hash_table_insert (changes, NM_CONFIG_CHANGES_CONNECTIVITY, NULL); + spec_old = priv_old->no_auto_default.specs; + spec_new = priv_new->no_auto_default.specs; + while (spec_old && spec_new && strcmp (spec_old->data, spec_new->data) == 0) { + spec_old = spec_old->next; + spec_new = spec_new->next; + } + if (spec_old || spec_new) + g_hash_table_insert (changes, NM_CONFIG_CHANGES_NO_AUTO_DEFAULT, NULL); + if (!g_hash_table_size (changes)) { g_hash_table_destroy (changes); return NULL; @@ -187,6 +218,9 @@ get_property (GObject *object, case PROP_CONFIG_DESCRIPTION: g_value_set_string (value, nm_config_data_get_config_description (self)); break; + case PROP_NO_AUTO_DEFAULT: + g_value_take_boxed (value, g_strdupv ((char **) nm_config_data_get_no_auto_default (self))); + break; case PROP_CONNECTIVITY_URI: g_value_set_string (value, nm_config_data_get_connectivity_uri (self)); break; @@ -210,6 +244,7 @@ set_property (GObject *object, { NMConfigData *self = NM_CONFIG_DATA (object); NMConfigDataPrivate *priv = NM_CONFIG_DATA_GET_PRIVATE (self); + guint i; /* This type is immutable. All properties are construct only. */ switch (prop_id) { @@ -224,6 +259,14 @@ set_property (GObject *object, if (!priv->keyfile) priv->keyfile = nm_config_create_keyfile (); break; + case PROP_NO_AUTO_DEFAULT: + priv->no_auto_default.arr = g_strdupv (g_value_get_boxed (value)); + if (!priv->no_auto_default.arr) + priv->no_auto_default.arr = g_new0 (char *, 1); + for (i = 0; priv->no_auto_default.arr[i]; i++) + priv->no_auto_default.specs = g_slist_prepend (priv->no_auto_default.specs, priv->no_auto_default.arr[i]); + priv->no_auto_default.specs = g_slist_reverse (priv->no_auto_default.specs); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -246,6 +289,9 @@ finalize (GObject *gobject) g_free (priv->connectivity.uri); g_free (priv->connectivity.response); + g_slist_free (priv->no_auto_default.specs); + g_strfreev (priv->no_auto_default.arr); + G_OBJECT_CLASS (nm_config_data_parent_class)->finalize (gobject); } @@ -273,12 +319,28 @@ constructed (GObject *object) NMConfigData * nm_config_data_new (const char *config_main_file, const char *config_description, + const char *const*no_auto_default, GKeyFile *keyfile) { 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_NO_AUTO_DEFAULT, no_auto_default, + NULL); +} + +NMConfigData * +nm_config_data_new_update_no_auto_default (const NMConfigData *base, + const char *const*no_auto_default) +{ + 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, priv->keyfile, /* the keyfile is unchanged. It's safe to share it. */ + NM_CONFIG_DATA_NO_AUTO_DEFAULT, no_auto_default, NULL); } @@ -340,5 +402,13 @@ nm_config_data_class_init (NMConfigDataClass *config_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property + (object_class, PROP_NO_AUTO_DEFAULT, + g_param_spec_boxed (NM_CONFIG_DATA_NO_AUTO_DEFAULT, "", "", + G_TYPE_STRV, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + } diff --git a/src/nm-config-data.h b/src/nm-config-data.h index d3425632b0..59b2806ccd 100644 --- a/src/nm-config-data.h +++ b/src/nm-config-data.h @@ -42,6 +42,7 @@ G_BEGIN_DECLS #define NM_CONFIG_DATA_CONNECTIVITY_URI "connectivity-uri" #define NM_CONFIG_DATA_CONNECTIVITY_INTERVAL "connectivity-interval" #define NM_CONFIG_DATA_CONNECTIVITY_RESPONSE "connectivity-response" +#define NM_CONFIG_DATA_NO_AUTO_DEFAULT "no-auto-default" struct _NMConfigData { GObject parent; @@ -55,7 +56,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); +NMConfigData *nm_config_data_new_update_no_auto_default (const NMConfigData *base, const char *const*no_auto_default); GHashTable *nm_config_data_diff (NMConfigData *old_data, NMConfigData *new_data); @@ -68,6 +71,9 @@ const char *nm_config_data_get_connectivity_uri (const NMConfigData *config_data const guint nm_config_data_get_connectivity_interval (const NMConfigData *config_data); const char *nm_config_data_get_connectivity_response (const NMConfigData *config_data); +const char *const*nm_config_data_get_no_auto_default (const NMConfigData *config_data); +const GSList * nm_config_data_get_no_auto_default_list (const NMConfigData *config_data); + G_END_DECLS #endif /* NM_CONFIG_DATA_H */ diff --git a/src/nm-config.c b/src/nm-config.c index a295d1d520..42cda6605b 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -73,13 +73,9 @@ typedef struct { char *debug; - char **no_auto_default_orig; char **ignore_carrier; gboolean configure_and_quit; - - /* MUTABLE properties: */ - char **no_auto_default; /* mutable via merge_no_auto_default_state() */ } NMConfigPrivate; enum { @@ -102,6 +98,10 @@ G_DEFINE_TYPE (NMConfig, nm_config, G_TYPE_OBJECT) /************************************************************************/ +static void _set_config_data (NMConfig *self, NMConfigData *new_data); + +/************************************************************************/ + static gboolean _get_bool_value (GKeyFile *keyfile, const char *section, @@ -288,32 +288,31 @@ no_auto_default_merge_from_file (const char *no_auto_default_file, const char *c } gboolean -nm_config_get_ethernet_can_auto_default (NMConfig *config, NMDevice *device) +nm_config_get_no_auto_default_for_device (NMConfig *self, NMDevice *device) { - NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (config); - GSList *specs = NULL; - int i; - gboolean match; + NMConfigData *config_data; - for (i = 0; priv->no_auto_default[i]; i++) - specs = g_slist_prepend (specs, priv->no_auto_default[i]); + g_return_val_if_fail (NM_IS_CONFIG (self), FALSE); + g_return_val_if_fail (NM_IS_DEVICE (device), FALSE); - match = nm_device_spec_match_list (device, specs); - - g_slist_free (specs); - return !match; + config_data = NM_CONFIG_GET_PRIVATE (self)->config_data; + return nm_device_spec_match_list (device, nm_config_data_get_no_auto_default_list (config_data)); } void -nm_config_set_ethernet_no_auto_default (NMConfig *config, NMDevice *device) +nm_config_set_no_auto_default_for_device (NMConfig *self, NMDevice *device) { - NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (config); + NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (self); char *current; GString *updated; GError *error = NULL; char **no_auto_default; + NMConfigData *new_data = NULL; - if (!nm_config_get_ethernet_can_auto_default (config, device)) + g_return_if_fail (NM_IS_CONFIG (self)); + g_return_if_fail (NM_IS_DEVICE (device)); + + if (nm_config_get_no_auto_default_for_device (self, device)) return; updated = g_string_new (NULL); @@ -335,9 +334,11 @@ nm_config_set_ethernet_no_auto_default (NMConfig *config, NMDevice *device) g_string_free (updated, TRUE); - no_auto_default = no_auto_default_merge_from_file (priv->no_auto_default_file, (const char *const *) priv->no_auto_default); - g_strfreev (priv->no_auto_default); - priv->no_auto_default = no_auto_default; + no_auto_default = no_auto_default_merge_from_file (priv->no_auto_default_file, nm_config_data_get_no_auto_default (priv->config_data)); + new_data = nm_config_data_new_update_no_auto_default (priv->config_data, (const char *const*) no_auto_default); + g_strfreev (no_auto_default); + + _set_config_data (self, new_data); } /************************************************************************/ @@ -679,9 +680,7 @@ nm_config_reload (NMConfig *self) { NMConfigPrivate *priv; GError *error = NULL; - GHashTable *changes; GKeyFile *keyfile; - NMConfigData *old_data; NMConfigData *new_data = NULL; char *config_main_file = NULL; char *config_description = NULL; @@ -690,7 +689,6 @@ nm_config_reload (NMConfig *self) priv = NM_CONFIG_GET_PRIVATE (self); - /* pass on the original command line options. This means, that * options specified at command line cannot ever be reloaded from * file. That seems desirable. @@ -705,12 +703,21 @@ nm_config_reload (NMConfig *self) g_clear_error (&error); return; } - new_data = nm_config_data_new (config_main_file, config_description, keyfile); + new_data = nm_config_data_new (config_main_file, config_description, nm_config_data_get_no_auto_default (priv->config_data), keyfile); g_free (config_main_file); g_free (config_description); g_key_file_unref (keyfile); - old_data = priv->config_data; + _set_config_data (self, new_data); +} + +static void +_set_config_data (NMConfig *self, NMConfigData *new_data) +{ + NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (self); + NMConfigData *old_data = priv->config_data; + GHashTable *changes; + changes = nm_config_data_diff (old_data, new_data); if (!changes) { @@ -769,6 +776,8 @@ nm_config_new (const NMConfigCmdLineOptions *cli, GError **error) GKeyFile *keyfile; char *config_main_file = NULL; char *config_description = NULL; + char **no_auto_default; + char **no_auto_default_orig; self = NM_CONFIG (g_object_new (NM_TYPE_CONFIG, NM_CONFIG_CMD_LINE_OPTIONS, cli, @@ -796,7 +805,6 @@ nm_config_new (const NMConfigCmdLineOptions *cli, GError **error) priv->no_auto_default_file = g_strdup (priv->cli.no_auto_default_file); else priv->no_auto_default_file = g_strdup (NM_NO_AUTO_DEFAULT_STATE_FILE); - priv->no_auto_default_orig = g_key_file_get_string_list (keyfile, "main", "no-auto-default", NULL, NULL); priv->plugins = g_key_file_get_string_list (keyfile, "main", "plugins", NULL, NULL); if (!priv->plugins) @@ -818,13 +826,18 @@ nm_config_new (const NMConfigCmdLineOptions *cli, GError **error) priv->configure_and_quit = _get_bool_value (keyfile, "main", "configure-and-quit", FALSE); - priv->config_data_orig = nm_config_data_new (config_main_file, config_description, keyfile); + no_auto_default_orig = g_key_file_get_string_list (keyfile, "main", "no-auto-default", NULL, NULL); + no_auto_default = no_auto_default_merge_from_file (priv->no_auto_default_file, (const char *const *) no_auto_default_orig); + + priv->config_data_orig = nm_config_data_new (config_main_file, config_description, (const char *const*) no_auto_default, keyfile); + + g_strfreev (no_auto_default); + g_strfreev (no_auto_default_orig); /* Initialize mutable members. */ priv->config_data = g_object_ref (priv->config_data_orig); - priv->no_auto_default = no_auto_default_merge_from_file (priv->no_auto_default_file, (const char *const *) priv->no_auto_default_orig); g_free (config_main_file); g_free (config_description); @@ -853,8 +866,6 @@ finalize (GObject *gobject) g_free (priv->log_level); g_free (priv->log_domains); g_free (priv->debug); - g_strfreev (priv->no_auto_default_orig); - g_strfreev (priv->no_auto_default); g_strfreev (priv->ignore_carrier); _nm_config_cmd_line_options_clear (&priv->cli); diff --git a/src/nm-config.h b/src/nm-config.h index 98a9d2af6d..b52a6b58f8 100644 --- a/src/nm-config.h +++ b/src/nm-config.h @@ -46,6 +46,7 @@ G_BEGIN_DECLS #define NM_CONFIG_CHANGES_CONFIG_FILES "config-files" #define NM_CONFIG_CHANGES_VALUES "values" #define NM_CONFIG_CHANGES_CONNECTIVITY "connectivity" +#define NM_CONFIG_CHANGES_NO_AUTO_DEFAULT "no-auto-default" typedef struct NMConfigCmdLineOptions NMConfigCmdLineOptions; @@ -76,9 +77,6 @@ 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); -gboolean nm_config_get_ethernet_can_auto_default (NMConfig *config, NMDevice *device); -void nm_config_set_ethernet_no_auto_default (NMConfig *config, NMDevice *device); - gboolean nm_config_get_ignore_carrier (NMConfig *config, NMDevice *device); /* for main.c only */ @@ -87,6 +85,9 @@ void nm_config_cmd_line_options_free (NMConfigCmdLineOptions void nm_config_cmd_line_options_add_to_entries (NMConfigCmdLineOptions *cli, GOptionContext *opt_ctx); +gboolean nm_config_get_no_auto_default_for_device (NMConfig *config, NMDevice *device); +void nm_config_set_no_auto_default_for_device (NMConfig *config, NMDevice *device); + NMConfig *nm_config_new (const NMConfigCmdLineOptions *cli, GError **error); NMConfig *nm_config_setup (const NMConfigCmdLineOptions *cli, GError **error); void nm_config_reload (NMConfig *config); diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c index 36611938ef..3f7d6abf02 100644 --- a/src/settings/nm-settings.c +++ b/src/settings/nm-settings.c @@ -1669,7 +1669,7 @@ default_wired_clear_tag (NMSettings *self, g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (default_wired_connection_updated_by_user_cb), self); if (add_to_no_auto_default) - nm_config_set_ethernet_no_auto_default (NM_SETTINGS_GET_PRIVATE (self)->config, device); + nm_config_set_no_auto_default_for_device (NM_SETTINGS_GET_PRIVATE (self)->config, device); } void diff --git a/src/tests/config/test-config.c b/src/tests/config/test-config.c index 8c52031c25..e5ac0dde4a 100644 --- a/src/tests/config/test-config.c +++ b/src/tests/config/test-config.c @@ -27,6 +27,9 @@ #include #include "nm-test-device.h" #include "nm-fake-platform.h" +#include "nm-logging.h" + +#include "nm-test-utils.h" static NMConfig * setup_config (GError **error, const char *config_file, const char *config_dir, ...) @@ -194,13 +197,16 @@ test_config_no_auto_default (void) dev3 = nm_test_device_new ("33:33:33:33:33:33"); dev4 = nm_test_device_new ("44:44:44:44:44:44"); - g_assert (!nm_config_get_ethernet_can_auto_default (config, dev1)); - g_assert (!nm_config_get_ethernet_can_auto_default (config, dev2)); - g_assert (nm_config_get_ethernet_can_auto_default (config, dev3)); - g_assert (!nm_config_get_ethernet_can_auto_default (config, dev4)); + g_assert (nm_config_get_no_auto_default_for_device (config, dev1)); + g_assert (nm_config_get_no_auto_default_for_device (config, dev2)); + g_assert (!nm_config_get_no_auto_default_for_device (config, dev3)); + g_assert (nm_config_get_no_auto_default_for_device (config, dev4)); - nm_config_set_ethernet_no_auto_default (config, dev3); - g_assert (!nm_config_get_ethernet_can_auto_default (config, dev3)); + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*config: update * (no-auto-default)*"); + nm_config_set_no_auto_default_for_device (config, dev3); + g_test_assert_expected_messages (); + + g_assert (nm_config_get_no_auto_default_for_device (config, dev3)); g_object_unref (config); @@ -208,10 +214,10 @@ test_config_no_auto_default (void) "--no-auto-default", state_file, NULL); - g_assert (!nm_config_get_ethernet_can_auto_default (config, dev1)); - g_assert (!nm_config_get_ethernet_can_auto_default (config, dev2)); - g_assert (!nm_config_get_ethernet_can_auto_default (config, dev3)); - g_assert (!nm_config_get_ethernet_can_auto_default (config, dev4)); + g_assert (nm_config_get_no_auto_default_for_device (config, dev1)); + g_assert (nm_config_get_no_auto_default_for_device (config, dev2)); + g_assert (nm_config_get_no_auto_default_for_device (config, dev3)); + g_assert (nm_config_get_no_auto_default_for_device (config, dev4)); g_object_unref (config); @@ -280,14 +286,12 @@ test_config_confdir_parse_error (void) g_clear_error (&error); } +NMTST_DEFINE (); + int main (int argc, char **argv) { -#if !GLIB_CHECK_VERSION (2, 35, 0) - g_type_init (); -#endif - - g_test_init (&argc, &argv, NULL); + nmtst_init_assert_logging (&argc, &argv); nm_fake_platform_setup (); From cc46b182ed779110f93b5df19f2f9d43dc476d1e Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 12 Jan 2015 15:35:52 +0100 Subject: [PATCH 31/32] config: make NMConfig implement GInitable --- src/nm-config.c | 53 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/src/nm-config.c b/src/nm-config.c index 42cda6605b..a325b4c86a 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -92,7 +92,12 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; -G_DEFINE_TYPE (NMConfig, nm_config, G_TYPE_OBJECT) +static void nm_config_initable_iface_init (GInitableIface *iface); + +G_DEFINE_TYPE_WITH_CODE (NMConfig, nm_config, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_config_initable_iface_init); + ) + #define NM_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_CONFIG, NMConfigPrivate)) @@ -768,21 +773,24 @@ nm_config_setup (const NMConfigCmdLineOptions *cli, GError **error) return singleton_instance; } -NMConfig * -nm_config_new (const NMConfigCmdLineOptions *cli, GError **error) +static gboolean +init_sync (GInitable *initable, GCancellable *cancellable, GError **error) { - NMConfigPrivate *priv = NULL; - NMConfig *self; + NMConfig *self = NM_CONFIG (initable); + NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (self); GKeyFile *keyfile; char *config_main_file = NULL; char *config_description = NULL; char **no_auto_default; char **no_auto_default_orig; - self = NM_CONFIG (g_object_new (NM_TYPE_CONFIG, - NM_CONFIG_CMD_LINE_OPTIONS, cli, - NULL)); - priv = NM_CONFIG_GET_PRIVATE (self); + if (priv->config_dir) { + /* Object is already initialized. */ + if (priv->config_data) + return TRUE; + g_set_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND, "unspecified error"); + return FALSE; + } if (priv->cli.config_dir) priv->config_dir = g_strdup (priv->cli.config_dir); @@ -794,10 +802,8 @@ nm_config_new (const NMConfigCmdLineOptions *cli, GError **error) &config_main_file, &config_description, error); - if (!keyfile) { - g_object_unref (self); - return NULL; - } + if (!keyfile) + return FALSE; /* Initialize read only private members */ @@ -834,15 +840,22 @@ nm_config_new (const NMConfigCmdLineOptions *cli, GError **error) g_strfreev (no_auto_default); g_strfreev (no_auto_default_orig); - /* Initialize mutable members. */ - priv->config_data = g_object_ref (priv->config_data_orig); - g_free (config_main_file); g_free (config_description); g_key_file_unref (keyfile); - return self; + return TRUE; +} + +NMConfig * +nm_config_new (const NMConfigCmdLineOptions *cli, GError **error) +{ + return NM_CONFIG (g_initable_new (NM_TYPE_CONFIG, + NULL, + error, + NM_CONFIG_CMD_LINE_OPTIONS, cli, + NULL)); } static void @@ -924,3 +937,9 @@ nm_config_class_init (NMConfigClass *config_class) G_TYPE_NONE, 3, NM_TYPE_CONFIG_DATA, G_TYPE_HASH_TABLE, NM_TYPE_CONFIG_DATA); } +static void +nm_config_initable_iface_init (GInitableIface *iface) +{ + iface->init = init_sync; +} + From 5b47462f32489c726d6f79dfed431864d31f8dd2 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 21 Jan 2015 12:58:32 +0100 Subject: [PATCH 32/32] config: use flags argument in config-changed signal instead of a hash table --- src/nm-config-data.c | 22 ++++++--------- src/nm-config-data.h | 13 ++++++++- src/nm-config.c | 64 +++++++++++++++++++++++++++++--------------- src/nm-config.h | 7 ++--- src/nm-manager.c | 2 +- 5 files changed, 66 insertions(+), 42 deletions(-) diff --git a/src/nm-config-data.c b/src/nm-config-data.c index cf140739fc..f1a7bcfc62 100644 --- a/src/nm-config-data.c +++ b/src/nm-config-data.c @@ -157,33 +157,31 @@ _keyfile_a_contains_all_in_b (GKeyFile *kf_a, GKeyFile *kf_b) return TRUE; } -GHashTable * +NMConfigChangeFlags nm_config_data_diff (NMConfigData *old_data, NMConfigData *new_data) { - GHashTable *changes; + NMConfigChangeFlags changes = NM_CONFIG_CHANGE_NONE; NMConfigDataPrivate *priv_old, *priv_new; GSList *spec_old, *spec_new; - g_return_val_if_fail (NM_IS_CONFIG_DATA (old_data), NULL); - g_return_val_if_fail (NM_IS_CONFIG_DATA (new_data), NULL); - - changes = g_hash_table_new (g_str_hash, g_str_equal); + g_return_val_if_fail (NM_IS_CONFIG_DATA (old_data), NM_CONFIG_CHANGE_NONE); + g_return_val_if_fail (NM_IS_CONFIG_DATA (new_data), NM_CONFIG_CHANGE_NONE); priv_old = NM_CONFIG_DATA_GET_PRIVATE (old_data); priv_new = NM_CONFIG_DATA_GET_PRIVATE (new_data); if ( !_keyfile_a_contains_all_in_b (priv_old->keyfile, priv_new->keyfile) || !_keyfile_a_contains_all_in_b (priv_new->keyfile, priv_old->keyfile)) - g_hash_table_insert (changes, NM_CONFIG_CHANGES_VALUES, NULL); + changes |= NM_CONFIG_CHANGE_VALUES; 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) - g_hash_table_insert (changes, NM_CONFIG_CHANGES_CONFIG_FILES, NULL); + changes |= NM_CONFIG_CHANGE_CONFIG_FILES; if ( nm_config_data_get_connectivity_interval (old_data) != nm_config_data_get_connectivity_interval (new_data) || g_strcmp0 (nm_config_data_get_connectivity_uri (old_data), nm_config_data_get_connectivity_uri (new_data)) || g_strcmp0 (nm_config_data_get_connectivity_response (old_data), nm_config_data_get_connectivity_response (new_data))) - g_hash_table_insert (changes, NM_CONFIG_CHANGES_CONNECTIVITY, NULL); + changes |= NM_CONFIG_CHANGE_CONNECTIVITY; spec_old = priv_old->no_auto_default.specs; spec_new = priv_new->no_auto_default.specs; @@ -192,12 +190,8 @@ nm_config_data_diff (NMConfigData *old_data, NMConfigData *new_data) spec_new = spec_new->next; } if (spec_old || spec_new) - g_hash_table_insert (changes, NM_CONFIG_CHANGES_NO_AUTO_DEFAULT, NULL); + changes |= NM_CONFIG_CHANGE_NO_AUTO_DEFAULT; - if (!g_hash_table_size (changes)) { - g_hash_table_destroy (changes); - return NULL; - } return changes; } diff --git a/src/nm-config-data.h b/src/nm-config-data.h index 59b2806ccd..bb88bf7ea2 100644 --- a/src/nm-config-data.h +++ b/src/nm-config-data.h @@ -44,6 +44,17 @@ G_BEGIN_DECLS #define NM_CONFIG_DATA_CONNECTIVITY_RESPONSE "connectivity-response" #define NM_CONFIG_DATA_NO_AUTO_DEFAULT "no-auto-default" +typedef enum { /*< flags >*/ + NM_CONFIG_CHANGE_NONE = 0, + NM_CONFIG_CHANGE_CONFIG_FILES = (1L << 0), + NM_CONFIG_CHANGE_VALUES = (1L << 1), + NM_CONFIG_CHANGE_CONNECTIVITY = (1L << 2), + NM_CONFIG_CHANGE_NO_AUTO_DEFAULT = (1L << 3), + + _NM_CONFIG_CHANGE_LAST, + NM_CONFIG_CHANGE_ALL = ((_NM_CONFIG_CHANGE_LAST - 1) << 1) - 1, +} NMConfigChangeFlags; + struct _NMConfigData { GObject parent; }; @@ -60,7 +71,7 @@ NMConfigData *nm_config_data_new (const char *config_main_file, GKeyFile *keyfile); NMConfigData *nm_config_data_new_update_no_auto_default (const NMConfigData *base, const char *const*no_auto_default); -GHashTable *nm_config_data_diff (NMConfigData *old_data, NMConfigData *new_data); +NMConfigChangeFlags nm_config_data_diff (NMConfigData *old_data, NMConfigData *new_data); const char *nm_config_data_get_config_main_file (const NMConfigData *config_data); const char *nm_config_data_get_config_description (const NMConfigData *config_data); diff --git a/src/nm-config.c b/src/nm-config.c index a325b4c86a..03fca56b73 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -30,6 +30,8 @@ #include "nm-glib-compat.h" #include "nm-device.h" #include "NetworkManagerUtils.h" +#include "gsystem-local-alloc.h" +#include "nm-enum-types.h" #include #include @@ -716,40 +718,60 @@ nm_config_reload (NMConfig *self) _set_config_data (self, new_data); } +static const char * +_change_flags_one_to_string (NMConfigChangeFlags flag) +{ + switch (flag) { + case NM_CONFIG_CHANGE_CONFIG_FILES: + return "config-files"; + case NM_CONFIG_CHANGE_VALUES: + return "values"; + case NM_CONFIG_CHANGE_CONNECTIVITY: + return "connectivity"; + case NM_CONFIG_CHANGE_NO_AUTO_DEFAULT: + return "no-auto-default"; + default: + g_return_val_if_reached ("unknown"); + } +} + +char * +nm_config_change_flags_to_string (NMConfigChangeFlags flags) +{ + GString *str = g_string_new (""); + NMConfigChangeFlags s = 0x01; + + while (flags) { + if (NM_FLAGS_HAS (flags, s)) { + if (str->len) + g_string_append_c (str, ','); + g_string_append (str, _change_flags_one_to_string (s)); + } + flags = flags & ~s; + s <<= 1; + } + return g_string_free (str, FALSE); +} + static void _set_config_data (NMConfig *self, NMConfigData *new_data) { NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (self); NMConfigData *old_data = priv->config_data; - GHashTable *changes; + NMConfigChangeFlags changes; + gs_free char *log_str = NULL; changes = nm_config_data_diff (old_data, new_data); - - if (!changes) { + if (changes == NM_CONFIG_CHANGE_NONE) { g_object_unref (new_data); return; } - if (nm_logging_enabled (LOGL_INFO, LOGD_CORE)) { - GString *str = g_string_new (NULL); - GHashTableIter iter; - const char *key; - - g_hash_table_iter_init (&iter, changes); - while (g_hash_table_iter_next (&iter, (gpointer) &key, NULL)) { - if (str->len) - g_string_append (str, ","); - g_string_append (str, key); - } - nm_log_info (LOGD_CORE, "config: update %s (%s)", nm_config_data_get_config_description (new_data), str->str); - g_string_free (str, TRUE); - } - + nm_log_info (LOGD_CORE, "config: update %s (%s)", nm_config_data_get_config_description (new_data), + (log_str = nm_config_change_flags_to_string (changes))); priv->config_data = new_data; g_signal_emit (self, signals[SIGNAL_CONFIG_CHANGED], 0, new_data, changes, old_data); g_object_unref (old_data); - - g_hash_table_destroy (changes); } NM_DEFINE_SINGLETON_DESTRUCTOR (NMConfig); @@ -934,7 +956,7 @@ nm_config_class_init (NMConfigClass *config_class) G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (NMConfigClass, config_changed), NULL, NULL, NULL, - G_TYPE_NONE, 3, NM_TYPE_CONFIG_DATA, G_TYPE_HASH_TABLE, NM_TYPE_CONFIG_DATA); + G_TYPE_NONE, 3, NM_TYPE_CONFIG_DATA, NM_TYPE_CONFIG_CHANGE_FLAGS, NM_TYPE_CONFIG_DATA); } static void diff --git a/src/nm-config.h b/src/nm-config.h index b52a6b58f8..530cbade98 100644 --- a/src/nm-config.h +++ b/src/nm-config.h @@ -43,11 +43,6 @@ G_BEGIN_DECLS /* Signals */ #define NM_CONFIG_SIGNAL_CONFIG_CHANGED "config-changed" -#define NM_CONFIG_CHANGES_CONFIG_FILES "config-files" -#define NM_CONFIG_CHANGES_VALUES "values" -#define NM_CONFIG_CHANGES_CONNECTIVITY "connectivity" -#define NM_CONFIG_CHANGES_NO_AUTO_DEFAULT "no-auto-default" - typedef struct NMConfigCmdLineOptions NMConfigCmdLineOptions; struct _NMConfig { @@ -65,6 +60,8 @@ GType nm_config_get_type (void); NMConfig *nm_config_get (void); +char *nm_config_change_flags_to_string (NMConfigChangeFlags flags); + NMConfigData *nm_config_get_data (NMConfig *config); NMConfigData *nm_config_get_data_orig (NMConfig *config); const char **nm_config_get_plugins (NMConfig *config); diff --git a/src/nm-manager.c b/src/nm-manager.c index ad76da7c4d..d16a912880 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -465,7 +465,7 @@ active_connection_get_by_path (NMManager *manager, const char *path) /************************************************************************/ static void -_config_changed_cb (NMConfig *config, NMConfigData *config_data, GHashTable *changes, NMConfigData *old_data, NMManager *self) +_config_changed_cb (NMConfig *config, NMConfigData *config_data, NMConfigChangeFlags changes, NMConfigData *old_data, NMManager *self) { g_object_set (NM_MANAGER_GET_PRIVATE (self)->connectivity, NM_CONNECTIVITY_URI, nm_config_data_get_connectivity_uri (config_data),