From 72d06eb9c8f0339d266318d27add724c52ce1645 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 10 Jul 2014 00:00:56 +0200 Subject: [PATCH 01/31] connectivity: add code comment to nm_connectivity_check_cb() (cherry picked from commit 6cb5db60de292fc4493b9f799819641bb56942c6) --- src/nm-connectivity.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/nm-connectivity.c b/src/nm-connectivity.c index 85bd70aed4..15ac9d799a 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 5929a4cbec622901a8dddcc442a2e35b8b282ddd Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 9 Jul 2014 22:22:48 +0200 Subject: [PATCH 02/31] connectivity: make NMConnectivity:dispose() reentrant (cherry picked from commit 3dce101f6b28887dc6e8851525d6a52c2d8e341a) --- 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 15ac9d799a..5b730bd5fa 100644 --- a/src/nm-connectivity.c +++ b/src/nm-connectivity.c @@ -397,8 +397,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 da87866882f5e20b45323e92a0310ec258464762 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 14 Jul 2014 12:52:08 +0200 Subject: [PATCH 03/31] connectivity/trivial: fix white space and line-break in nm-connectivity.c (cherry picked from commit 7aab5bc81ccd1eeb6dbf7d67d84861ab9d117cd1) --- 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 5b730bd5fa..11f1545fde 100644 --- a/src/nm-connectivity.c +++ b/src/nm-connectivity.c @@ -427,31 +427,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 6f4bf2818a2abc80e23994f4c00faeddf717f6cc Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 19 Jan 2015 17:41:22 +0100 Subject: [PATCH 04/31] connectivity: add missing G_PARAM_CONSTRUCT for NM_CONNECTIVITY_URI property (cherry picked from commit a79e9fdbb0081cd296f3cf34feaf72d62ce91f1d) --- src/nm-connectivity.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/nm-connectivity.c b/src/nm-connectivity.c index 11f1545fde..959d359eff 100644 --- a/src/nm-connectivity.c +++ b/src/nm-connectivity.c @@ -431,6 +431,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 fc6f45e42af3798498da737087c5391068048b4f Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 14 Jul 2014 17:45:37 +0200 Subject: [PATCH 05/31] connectivity: refactor converting connectivity states to string (cherry picked from commit 78e3b4866aead808e48af1845e3ef25d1b454d19) --- 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 959d359eff..9d37338ebe 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 c1fd1dde13..111095bb0e 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -4271,12 +4271,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 b4d7ac70f2f832de18a5f2cd16e8e44554c32e4d Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 14 Jul 2014 13:40:30 +0200 Subject: [PATCH 06/31] 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. (cherry picked from commit 5ee18c124b2c8e79477b846c216d3ca9f1aa8dc5) --- 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 9d37338ebe..38e96016ff 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,33 +138,49 @@ 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_object_unref (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, @@ -186,39 +212,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 @@ -227,38 +268,44 @@ 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); /* Disable HTTP/1.1 keepalive; the connection should not persist */ soup_message_headers_append (msg->request_headers, "Connection", "close"); + 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); @@ -281,38 +328,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 @@ -321,32 +351,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); @@ -369,7 +415,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); @@ -384,11 +433,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 9d5b4baf364ccbfc045e1363a3e7c38cec9cf7b6 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 19 Jan 2015 19:06:27 +0100 Subject: [PATCH 07/31] connectivity: add logging macros to nm-connectivity.c They add a common prefix to all logging lines. (cherry picked from commit 3ed4aa271aa7db403a0dcaf8548a9b0c72b805fe) --- 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 38e96016ff..89f09d40e6 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; } @@ -191,7 +206,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); } } @@ -256,7 +271,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); } @@ -298,14 +313,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); @@ -364,7 +379,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 0799617515e20a39e3de1b904c0cd104db121acf Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 12 Dec 2014 13:44:37 +0100 Subject: [PATCH 08/31] config: forward declare NMConfig in nm-types.h (cherry picked from commit 86ac1ad7bd185e7d8838676bde74458719833ca2) --- 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 4a93567e11..471fe4d7fd 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 d165559ef276e36fc645026b8bd1dedd8b7e3802 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 15 Jan 2015 15:46:19 +0100 Subject: [PATCH 09/31] config/trivial: fix returning FALSE instead of NULL in nm_config_new() (cherry picked from commit 9387e8e8a7a76732ae0eed7732d1f284cf82148a) --- 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 4626ae2642..8e0be25c2d 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -580,7 +580,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 b4ad7434a87c165a77b615accbe1868a9df9221b Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 9 Jul 2014 15:17:01 +0200 Subject: [PATCH 10/31] 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. (cherry picked from commit 1ff5154369f69f1e266521dd5f2ed53c37baa84f) --- src/main-utils.c | 7 +- src/main-utils.h | 3 +- src/main.c | 14 ++- src/nm-config.c | 207 ++++++++++++++++++++++----------- src/nm-config.h | 11 +- src/nm-iface-helper.c | 1 + src/tests/config/test-config.c | 81 ++++++------- 7 files changed, 203 insertions(+), 121 deletions(-) diff --git a/src/main-utils.c b/src/main-utils.c index c4d0eeb902..132b708916 100644 --- a/src/main-utils.c +++ b/src/main-utils.c @@ -231,7 +231,8 @@ nm_main_utils_early_setup (const char *progname, int *argc, char **argv[], 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; @@ -276,9 +277,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 1fceb35006..4242ce4d01 100644 --- a/src/main-utils.h +++ b/src/main-utils.h @@ -37,7 +37,8 @@ gboolean nm_main_utils_early_setup (const char *progname, int *argc, char **argv[], 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 53e829cd72..f7742de223 100644 --- a/src/main.c +++ b/src/main.c @@ -217,7 +217,7 @@ manager_configure_quit (NMManager *manager, gpointer user_data) } static void -do_early_setup (int *argc, char **argv[]) +do_early_setup (int *argc, char **argv[], NMConfigCmdLineOptions *config_cli) { GOptionEntry options[] = { { "version", 'V', 0, G_OPTION_ARG_NONE, &global_opt.show_version, N_("Print NetworkManager version and exit"), NULL }, @@ -234,11 +234,13 @@ do_early_setup (int *argc, char **argv[]) {NULL} }; + config_cli = nm_config_cmd_line_options_new (); if (!nm_main_utils_early_setup ("NetworkManager", argc, argv, 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); @@ -267,6 +269,7 @@ main (int argc, char *argv[]) GError *error = NULL; gboolean wrote_pidfile = FALSE; char *bad_domains = NULL; + NMConfigCmdLineOptions *config_cli; #if !GLIB_CHECK_VERSION (2, 35, 0) g_type_init (); @@ -276,7 +279,8 @@ main (int argc, char *argv[]) main_loop = g_main_loop_new (NULL, FALSE); - do_early_setup (&argc, &argv); + config_cli = nm_config_cmd_line_options_new (); + do_early_setup (&argc, &argv, config_cli); if (global_opt.g_fatal_warnings) _set_g_fatal_warnings (); @@ -338,7 +342,9 @@ main (int argc, char *argv[]) } /* 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 8e0be25c2d..7f3960b376 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); + } } /************************************************************************/ @@ -447,10 +504,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; @@ -502,11 +559,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 @@ -518,9 +589,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; @@ -530,21 +600,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); @@ -572,27 +646,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); @@ -609,23 +683,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 @@ -637,8 +711,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 @@ -662,14 +734,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 97e1708e3c..d53f8b43b8 100644 --- a/src/nm-iface-helper.c +++ b/src/nm-iface-helper.c @@ -320,6 +320,7 @@ do_early_setup (int *argc, char **argv[]) argv, 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 e027eab84e..2973bcc284 100644 --- a/src/tests/config/test-config.c +++ b/src/tests/config/test-config.c @@ -32,8 +32,8 @@ #include "nm-test-utils.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; @@ -41,6 +41,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"); @@ -57,8 +62,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); @@ -66,6 +73,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 @@ -76,9 +95,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"); @@ -111,40 +128,33 @@ test_config_simple (void) static void test_config_non_existent (void) { - NMConfig *config; gs_free_error 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; gs_free_error 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"); @@ -179,11 +189,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"); @@ -200,11 +208,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)); @@ -226,13 +232,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"); @@ -273,14 +276,12 @@ test_config_confdir (void) static void test_config_confdir_parse_error (void) { - NMConfig *config; - gs_free_error GError *error = NULL; + 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); } NMTST_DEFINE (); From 5a7506a4053635ca5445582cd3f6e355f71b0d62 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 11 Jul 2014 17:57:20 +0200 Subject: [PATCH 11/31] 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. (cherry picked from commit 076478505dd1c278898d64d389184d7fb2b6c158) --- 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 a24ac6c4f2..369c9a6957 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -285,6 +285,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 471fe4d7fd..8d613a22cc 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 a56fe5ae0c1e87a38e41324dd54166844b245dc8 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 11 Jul 2014 18:54:18 +0200 Subject: [PATCH 12/31] config: use NMConfigData in NMConfig (cherry picked from commit 50fce5a860479016470117ded4fb7ea947c27c1c) --- 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 7f3960b376..ea145ff804 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) { @@ -601,6 +595,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); @@ -685,20 +681,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; } @@ -729,13 +734,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 89f09d40e6..229d68fdb6 100644 --- a/src/nm-connectivity.c +++ b/src/nm-connectivity.c @@ -348,15 +348,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 2973bcc284..827fde1841 100644 --- a/src/tests/config/test-config.c +++ b/src/tests/config/test-config.c @@ -100,7 +100,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); @@ -159,7 +159,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); @@ -241,8 +241,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 3a5fb56b6024034f7d331edcaad36c21d7cdfb71 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 9 Jul 2014 18:36:20 +0200 Subject: [PATCH 13/31] config: add handler for SIGHUP and a reload-configuration stub (cherry picked from commit d62022e28a508070e3d5ef089ab4e17dd45d3b23) --- src/main-utils.c | 2 +- src/main-utils.h | 5 +++++ src/main.c | 6 ++++++ src/nm-iface-helper.c | 6 ++++++ 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/main-utils.c b/src/main-utils.c index 132b708916..8d806e40b2 100644 --- a/src/main-utils.c +++ b/src/main-utils.c @@ -67,7 +67,7 @@ signal_handling_thread (void *arg) break; case SIGHUP: /* Reread config stuff like system config files, VPN service files, etc */ - nm_log_info (LOGD_CORE, "caught signal %d, not supported yet.", signo); + nm_main_config_reload (); break; case SIGPIPE: /* silently ignore signal */ diff --git a/src/main-utils.h b/src/main-utils.h index 4242ce4d01..a34a6df40e 100644 --- a/src/main-utils.h +++ b/src/main-utils.h @@ -41,4 +41,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 f7742de223..e82e4d3501 100644 --- a/src/main.c +++ b/src/main.c @@ -208,6 +208,12 @@ _init_nm_debug (const char *debug) _set_g_fatal_warnings (); } +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 d53f8b43b8..1e32524356 100644 --- a/src/nm-iface-helper.c +++ b/src/nm-iface-helper.c @@ -510,6 +510,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 63293bba19829c203c974ce6121ea6e52896e798 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 9 Jul 2014 18:54:47 +0200 Subject: [PATCH 14/31] 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. (cherry picked from commit 82cfd5ad47b43de640dfa2dd60c4b84f0857e6a5) --- 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 e82e4d3501..a8964c0834 100644 --- a/src/main.c +++ b/src/main.c @@ -211,7 +211,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 ea145ff804..5507da18bf 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)) @@ -553,6 +562,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); @@ -753,5 +815,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 b18de2309a7db1e764579e10552393b259f73b28 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 29 Jan 2015 15:28:03 +0100 Subject: [PATCH 15/31] connectivity: make NMConnectivity independent of NMConfig (cherry picked from commit ac9dd4c8324c2f8c8d06cada245496c4c3511379) --- 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 229d68fdb6..ecb9c0f5c1 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) @@ -346,17 +345,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 111095bb0e..c9b4448881 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -4716,6 +4716,7 @@ nm_manager_new (NMSettings *settings, NMManagerPrivate *priv; DBusGConnection *bus; DBusConnection *dbus_connection; + NMConfigData *config_data; g_assert (settings); @@ -4747,7 +4748,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); @@ -5068,7 +5072,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 244cc0171ae1563703cb52cf887ae4377a48997f Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 30 Jan 2015 19:52:53 +0100 Subject: [PATCH 16/31] config: implement reloading of connectivity parameters (cherry picked from commit b814c3122acbf9105effd54976cb675672264930) --- 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 5507da18bf..8f63892066 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -596,7 +596,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 c9b4448881..3281de13b9 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; @@ -464,6 +465,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) { @@ -4748,7 +4761,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)); @@ -5072,6 +5091,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 67c4398170a5f96442c3704bc32b5bdef1273e94 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 16 Dec 2014 10:53:58 +0100 Subject: [PATCH 17/31] config: refactor read_config() to make it independent from NMConfig (cherry picked from commit 3c7f71e44aadb65a8a661b7d57f08e653851fef5) --- 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 8f63892066..a1489512f7 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,16 +472,16 @@ read_config (NMConfig *config, const char *path, GError **error) if (keys[k][len - 1] == '+') { char *base_key = g_strndup (keys[k], len - 1); - char *old_val = g_key_file_get_value (priv->keyfile, groups[g], base_key, NULL); + char *old_val = g_key_file_get_value (keyfile, groups[g], base_key, NULL); 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); g_free (old_val); @@ -488,7 +489,7 @@ read_config (NMConfig *config, const char *path, GError **error) 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); } @@ -501,16 +502,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; @@ -524,8 +531,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; } @@ -537,8 +544,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; } @@ -554,7 +561,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; @@ -673,18 +680,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); @@ -709,7 +716,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 83edb5aee308e09569b7cef906b85268fa728cb0 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 16 Dec 2014 11:02:57 +0100 Subject: [PATCH 18/31] 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". (cherry picked from commit 3714a6c7bd0f22328ac769926732af3f4746f68b) --- 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 a8964c0834..3ab78e66e3 100644 --- a/src/main.c +++ b/src/main.c @@ -424,7 +424,7 @@ main (int argc, char *argv[]) */ dbus_glib_global_set_disable_legacy_property_access (); - 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 a1489512f7..c844575461 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") }, @@ -503,21 +503,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; @@ -532,7 +532,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; } @@ -545,7 +545,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; } @@ -561,7 +561,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; @@ -687,13 +687,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) { @@ -797,7 +797,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 827fde1841..55bf2730b1 100644 --- a/src/tests/config/test-config.c +++ b/src/tests/config/test-config.c @@ -97,7 +97,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); @@ -156,7 +156,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); @@ -237,7 +237,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 cfc435be0b60ceb5cc3cf85664b210300d19815f Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 16 Dec 2014 11:35:58 +0100 Subject: [PATCH 19/31] config: refactor nm_config_new() by extracting function _get_config_dir_files() (cherry picked from commit ef5782844280b3ca2605559f938795425cd12a91) --- 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 c844575461..39bc3af666 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -567,6 +567,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 @@ -648,29 +700,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); @@ -692,29 +730,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 ca6f06d06970a72cde59f6edd85222164373faf2 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 16 Dec 2014 12:14:30 +0100 Subject: [PATCH 20/31] config: refactor nm_config_new() by extracting function read_entire_config() (cherry picked from commit 40dc4c3242c0276d5ac9fc6bf15afc1392cc10be) --- 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 39bc3af666..53786f0e52 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; @@ -619,6 +630,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 @@ -704,11 +762,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); @@ -724,23 +781,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); @@ -804,8 +855,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 f166c007fbf389582af642f1579d12090b5398de Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 16 Dec 2014 15:10:24 +0100 Subject: [PATCH 21/31] config: refactor to inject NMConfigCmdLineOptions to NMConfig constructor (cherry picked from commit 4429f8aea5bf24fc12add15554ad49183439a069) --- 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 53786f0e52..e3841c0b4e 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, @@ -767,15 +773,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 @@ -885,6 +887,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) @@ -893,6 +917,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 8ba5e062b2b6127314fb46f0a7d5ac10869fcd97 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 16 Dec 2014 15:36:56 +0100 Subject: [PATCH 22/31] config: refactor read_entire_config() to merge command line options (cherry picked from commit 64520b7ba4aec12d4750d5351f2bba8317d3fa1b) --- 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 e3841c0b4e..cc27761a49 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -648,6 +648,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); @@ -667,19 +668,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; } @@ -795,7 +812,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); @@ -803,12 +821,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); @@ -822,22 +837,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 c2d7454760ec09b65fb785ebd713593b76561cdc Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 16 Dec 2014 15:47:04 +0100 Subject: [PATCH 23/31] config: minor refactoring to highlight mutable property no_auto_default of NMConfig (cherry picked from commit 83996c621cb7c55d17872fcbd4d2fae51977d839) --- 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 cc27761a49..9d67102e29 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 { @@ -814,12 +817,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) @@ -854,6 +856,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; } @@ -883,6 +888,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 30a47864684729483341460627fca8f099291148 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 16 Dec 2014 16:52:34 +0100 Subject: [PATCH 24/31] config: refactor reloading not to create a second NMConfig instance (cherry picked from commit 699b12ddc9ca502ad75077722d4af4f675377b40) --- 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 9d67102e29..d9a3196dc5 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -709,36 +709,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))) { @@ -746,20 +755,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); } @@ -789,8 +794,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, @@ -843,18 +846,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 0ca82739d5a73515ee4115ec1dcf44c91bf4e2dc Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 6 Jan 2015 20:16:10 +0100 Subject: [PATCH 25/31] config: move main_file and description to NMConfigData Every reload might change the main_file and description. Move those properties to NMConfigData. (cherry picked from commit 56f5fba72353e55db554c359af00376d3959009d) --- 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 3ab78e66e3..c315663bb7 100644 --- a/src/main.c +++ b/src/main.c @@ -424,7 +424,7 @@ main (int argc, char *argv[]) */ dbus_glib_global_set_disable_legacy_property_access (); - 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 d9a3196dc5..a676c0898a 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) { @@ -731,14 +713,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); @@ -755,12 +737,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); @@ -795,6 +798,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, @@ -808,8 +813,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); @@ -846,7 +851,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. */ @@ -855,6 +860,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; } @@ -873,9 +880,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 55bf2730b1..4ffdccea3a 100644 --- a/src/tests/config/test-config.c +++ b/src/tests/config/test-config.c @@ -97,7 +97,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); @@ -156,7 +156,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); @@ -237,7 +237,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 c9aca6f36bade0de07bc3bc31146d2825f2946ed Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 7 Jan 2015 14:30:14 +0100 Subject: [PATCH 26/31] config: add new function nm_config_data_diff() (cherry picked from commit 045a576a7ab8dac3f7aa9302532fa94e790c1f05) --- 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 a676c0898a..10a63bca34 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -723,28 +723,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 9809eb4da1b12635d35de2cb6b7094df723ad0dc Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 7 Jan 2015 13:25:41 +0100 Subject: [PATCH 27/31] config: move keyfile values to NMConfigData (cherry picked from commit ba74f9d2428c937014c3bcd02ac25591bbc1abc5) --- 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 10a63bca34..bddfe0f620 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) { @@ -721,7 +712,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); @@ -802,8 +793,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 */ @@ -811,29 +800,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. */ @@ -844,6 +833,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; } @@ -853,8 +843,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 @@ -864,7 +852,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 4ffdccea3a..e677243103 100644 --- a/src/tests/config/test-config.c +++ b/src/tests/config/test-config.c @@ -108,16 +108,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); @@ -252,21 +252,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 b85c3c4d6bb8165c739d4fc2ddf52e55d2dedd3b Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 7 Jan 2015 16:12:01 +0100 Subject: [PATCH 28/31] config: refactor merging no_auto_default (cherry picked from commit 49b3f5b8d9e3b01cfd23bf72f9df2a6e76006bbe) --- 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 bddfe0f620..e6f8a38632 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; } /************************************************************************/ @@ -828,8 +826,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 41598c1f1ad68c3ff8d3e923000ce4278d648feb Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 7 Jan 2015 17:09:52 +0100 Subject: [PATCH 29/31] 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. (cherry picked from commit 13c7f6a56db55db47d31a181c85913f1d183f95a) --- 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 | 23 +++++----- 7 files changed, 137 insertions(+), 46 deletions(-) diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c index ac408d3d9f..22d2bfa923 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 e6f8a38632..3d93edc9b0 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); } /************************************************************************/ @@ -681,9 +682,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; @@ -692,7 +691,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. @@ -707,12 +705,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) { @@ -771,6 +778,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, @@ -798,7 +807,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) @@ -820,13 +828,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); @@ -855,8 +868,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 fe3f9eeece..3a586b747e 100644 --- a/src/settings/nm-settings.c +++ b/src/settings/nm-settings.c @@ -1687,7 +1687,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 e677243103..67ba5904ec 100644 --- a/src/tests/config/test-config.c +++ b/src/tests/config/test-config.c @@ -198,13 +198,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); @@ -212,10 +215,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); From 0efcf3c680214f2ea7d5cc1080d05239d7fa211a Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 12 Jan 2015 15:35:52 +0100 Subject: [PATCH 30/31] config: make NMConfig implement GInitable (cherry picked from commit cc46b182ed779110f93b5df19f2f9d43dc476d1e) --- 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 3d93edc9b0..a20dfb4bc3 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)) @@ -770,21 +775,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); @@ -796,10 +804,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 */ @@ -836,15 +842,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 @@ -926,3 +939,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 d9f372f439b5b61576c6ab90d5ddf3f342a7c35a Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 21 Jan 2015 12:58:32 +0100 Subject: [PATCH 31/31] config: use flags argument in config-changed signal instead of a hash table (cherry picked from commit 5b47462f32489c726d6f79dfed431864d31f8dd2) --- 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 a20dfb4bc3..012b872aca 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 @@ -718,40 +720,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); @@ -936,7 +958,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 3281de13b9..54b4429a5c 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -466,7 +466,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),