diff options
Diffstat (limited to 'src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c')
-rw-r--r-- | src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c | 286 |
1 files changed, 183 insertions, 103 deletions
diff --git a/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c b/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c index 04d3d3e45..3db06f17d 100644 --- a/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c +++ b/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c @@ -35,10 +35,12 @@ #include <nm-setting-8021x.h> #include "common.h" +#include "nm-config.h" #include "nm-ifcfg-connection.h" #include "reader.h" #include "writer.h" #include "nm-inotify-helper.h" +#include "utils.h" G_DEFINE_TYPE (NMIfcfgConnection, nm_ifcfg_connection, NM_TYPE_SETTINGS_CONNECTION) @@ -59,12 +61,14 @@ typedef struct { char *route6file; int route6file_wd; - char *unmanaged; + char *unmanaged_spec; + char *unrecognized_spec; } NMIfcfgConnectionPrivate; enum { PROP_0, - PROP_UNMANAGED, + PROP_UNMANAGED_SPEC, + PROP_UNRECOGNIZED_SPEC, LAST_PROP }; @@ -96,86 +100,159 @@ files_changed_cb (NMInotifyHelper *ih, } NMIfcfgConnection * -nm_ifcfg_connection_new (const char *full_path, - NMConnection *source, +nm_ifcfg_connection_new (NMConnection *source, + const char *full_path, GError **error, gboolean *ignore_error) { GObject *object; - NMIfcfgConnectionPrivate *priv; NMConnection *tmp; - char *unmanaged = NULL; - char *keyfile = NULL; - char *routefile = NULL; - char *route6file = NULL; - NMInotifyHelper *ih; + char *unhandled_spec = NULL; + const char *unmanaged_spec = NULL, *unrecognized_spec = NULL; + gboolean update_unsaved = TRUE; - g_return_val_if_fail (full_path != NULL, NULL); + g_assert (source || full_path); /* If we're given a connection already, prefer that instead of re-reading */ if (source) tmp = g_object_ref (source); else { + char *keyfile = NULL, *routefile = NULL, *route6file = NULL; + tmp = connection_from_file (full_path, NULL, NULL, NULL, - &unmanaged, + &unhandled_spec, &keyfile, &routefile, &route6file, error, ignore_error); + g_free (keyfile); + g_free (routefile); + g_free (route6file); if (!tmp) return NULL; + + /* If we just read the connection from disk, it's clearly not Unsaved */ + update_unsaved = FALSE; } + if (unhandled_spec && g_str_has_prefix (unhandled_spec, "unmanaged:")) + unmanaged_spec = unhandled_spec + strlen ("unmanaged:"); + else if (unhandled_spec && g_str_has_prefix (unhandled_spec, "unrecognized:")) + unrecognized_spec = unhandled_spec + strlen ("unrecognized:"); + object = (GObject *) g_object_new (NM_TYPE_IFCFG_CONNECTION, - NM_IFCFG_CONNECTION_UNMANAGED, unmanaged, + NM_IFCFG_CONNECTION_UNMANAGED_SPEC, unmanaged_spec, + NM_IFCFG_CONNECTION_UNRECOGNIZED_SPEC, unrecognized_spec, NULL); - if (!object) - goto out; - - /* Update our settings with what was read from the file */ - if (!nm_settings_connection_replace_settings (NM_SETTINGS_CONNECTION (object), tmp, error)) { - g_object_unref (object); - object = NULL; - goto out; + if (object) { + /* Update our settings with what was read from the file */ + if (nm_settings_connection_replace_settings (NM_SETTINGS_CONNECTION (object), + tmp, + update_unsaved, + error)) { + /* Set the path and start monitoring */ + if (full_path) + nm_ifcfg_connection_set_path (NM_IFCFG_CONNECTION (object), full_path); + } else { + g_object_unref (object); + object = NULL; + } } - priv = NM_IFCFG_CONNECTION_GET_PRIVATE (object); - priv->path = g_strdup (full_path); + g_object_unref (tmp); + g_free (unhandled_spec); + return (NMIfcfgConnection *) object; +} + +const char * +nm_ifcfg_connection_get_path (NMIfcfgConnection *self) +{ + g_return_val_if_fail (NM_IS_IFCFG_CONNECTION (self), NULL); + + return NM_IFCFG_CONNECTION_GET_PRIVATE (self)->path; +} + +static void +path_watch_stop (NMIfcfgConnection *self) +{ + NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (self); + NMInotifyHelper *ih; ih = nm_inotify_helper_get (); - priv->ih_event_id = g_signal_connect (ih, "event", G_CALLBACK (files_changed_cb), object); - priv->file_wd = nm_inotify_helper_add_watch (ih, full_path); + if (priv->ih_event_id) { + g_signal_handler_disconnect (ih, priv->ih_event_id); + priv->ih_event_id = 0; + } - priv->keyfile = keyfile; - priv->keyfile_wd = nm_inotify_helper_add_watch (ih, keyfile); + if (priv->file_wd >= 0) { + nm_inotify_helper_remove_watch (ih, priv->file_wd); + priv->file_wd = -1; + } - priv->routefile = routefile; - priv->routefile_wd = nm_inotify_helper_add_watch (ih, routefile); + g_free (priv->keyfile); + priv->keyfile = NULL; + if (priv->keyfile_wd >= 0) { + nm_inotify_helper_remove_watch (ih, priv->keyfile_wd); + priv->keyfile_wd = -1; + } - priv->route6file = route6file; - priv->route6file_wd = nm_inotify_helper_add_watch (ih, route6file); + g_free (priv->routefile); + priv->routefile = NULL; + if (priv->routefile_wd >= 0) { + nm_inotify_helper_remove_watch (ih, priv->routefile_wd); + priv->routefile_wd = -1; + } -out: - g_object_unref (tmp); - return (NMIfcfgConnection *) object; + g_free (priv->route6file); + priv->route6file = NULL; + if (priv->route6file_wd >= 0) { + nm_inotify_helper_remove_watch (ih, priv->route6file_wd); + priv->route6file_wd = -1; + } +} + +void +nm_ifcfg_connection_set_path (NMIfcfgConnection *self, const char *ifcfg_path) +{ + NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (self); + + g_return_if_fail (ifcfg_path != NULL); + + path_watch_stop (self); + g_free (priv->path); + + priv->path = g_strdup (ifcfg_path); + priv->keyfile = utils_get_keys_path (ifcfg_path); + priv->routefile = utils_get_route_path (ifcfg_path); + priv->route6file = utils_get_route6_path (ifcfg_path); + + if (nm_config_get_monitor_connection_files (nm_config_get ())) { + NMInotifyHelper *ih = nm_inotify_helper_get (); + + priv->ih_event_id = g_signal_connect (ih, "event", G_CALLBACK (files_changed_cb), self); + priv->file_wd = nm_inotify_helper_add_watch (ih, ifcfg_path); + priv->keyfile_wd = nm_inotify_helper_add_watch (ih, priv->keyfile); + priv->routefile_wd = nm_inotify_helper_add_watch (ih, priv->routefile); + priv->route6file_wd = nm_inotify_helper_add_watch (ih, priv->route6file); + } } const char * -nm_ifcfg_connection_get_path (NMIfcfgConnection *self) +nm_ifcfg_connection_get_unmanaged_spec (NMIfcfgConnection *self) { g_return_val_if_fail (NM_IS_IFCFG_CONNECTION (self), NULL); - return NM_IFCFG_CONNECTION_GET_PRIVATE (self)->path; + return NM_IFCFG_CONNECTION_GET_PRIVATE (self)->unmanaged_spec; } const char * -nm_ifcfg_connection_get_unmanaged_spec (NMIfcfgConnection *self) +nm_ifcfg_connection_get_unrecognized_spec (NMIfcfgConnection *self) { g_return_val_if_fail (NM_IS_IFCFG_CONNECTION (self), NULL); - return NM_IFCFG_CONNECTION_GET_PRIVATE (self)->unmanaged; + return NM_IFCFG_CONNECTION_GET_PRIVATE (self)->unrecognized_spec; } static void @@ -186,41 +263,50 @@ commit_changes (NMSettingsConnection *connection, NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (connection); GError *error = NULL; NMConnection *reread; - char *unmanaged = NULL, *keyfile = NULL, *routefile = NULL, *route6file = NULL; - gboolean same = FALSE; + gboolean same = FALSE, success = FALSE; + char *ifcfg_path = NULL; /* To ensure we don't rewrite files that are only changed from other * processes on-disk, read the existing connection back in and only rewrite * it if it's really changed. */ - reread = connection_from_file (priv->path, NULL, NULL, NULL, - &unmanaged, &keyfile, &routefile, &route6file, - NULL, NULL); - g_free (unmanaged); - g_free (keyfile); - g_free (routefile); - g_free (route6file); - - if (reread) { - same = nm_connection_compare (NM_CONNECTION (connection), - reread, - NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS | - NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS); - g_object_unref (reread); - - /* Don't bother writing anything out if in-memory and on-disk data are the same */ - if (same) { - /* But chain up to parent to handle success - emits updated signal */ - NM_SETTINGS_CONNECTION_CLASS (nm_ifcfg_connection_parent_class)->commit_changes (connection, callback, user_data); - return; + if (priv->path) { + reread = connection_from_file (priv->path, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + &error, NULL); + g_clear_error (&error); + if (reread) { + same = nm_connection_compare (NM_CONNECTION (connection), + reread, + NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS | + NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS); + g_object_unref (reread); + + /* Don't bother writing anything out if in-memory and on-disk data are the same */ + if (same) { + /* But chain up to parent to handle success - emits updated signal */ + NM_SETTINGS_CONNECTION_CLASS (nm_ifcfg_connection_parent_class)->commit_changes (connection, callback, user_data); + return; + } + } + + success = writer_update_connection (NM_CONNECTION (connection), + IFCFG_DIR, + priv->path, + priv->keyfile, + &error); + } else { + success = writer_new_connection (NM_CONNECTION (connection), + IFCFG_DIR, + &ifcfg_path, + &error); + if (success) { + nm_ifcfg_connection_set_path (NM_IFCFG_CONNECTION (connection), ifcfg_path); + g_free (ifcfg_path); } } - if (writer_update_connection (NM_CONNECTION (connection), - IFCFG_DIR, - priv->path, - priv->keyfile, - &error)) { + if (success) { /* Chain up to parent to handle success */ NM_SETTINGS_CONNECTION_CLASS (nm_ifcfg_connection_parent_class)->commit_changes (connection, callback, user_data); } else { @@ -237,14 +323,16 @@ do_delete (NMSettingsConnection *connection, { NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (connection); - g_unlink (priv->path); - if (priv->keyfile) - g_unlink (priv->keyfile); - if (priv->routefile) - g_unlink (priv->routefile); + if (priv->path) { + g_unlink (priv->path); + if (priv->keyfile) + g_unlink (priv->keyfile); + if (priv->routefile) + g_unlink (priv->routefile); - if (priv->route6file) - g_unlink (priv->route6file); + if (priv->route6file) + g_unlink (priv->route6file); + } NM_SETTINGS_CONNECTION_CLASS (nm_ifcfg_connection_parent_class)->delete (connection, callback, user_data); } @@ -259,31 +347,10 @@ nm_ifcfg_connection_init (NMIfcfgConnection *connection) static void finalize (GObject *object) { - NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (object); - NMInotifyHelper *ih; - nm_connection_clear_secrets (NM_CONNECTION (object)); - ih = nm_inotify_helper_get (); - - if (priv->ih_event_id) - g_signal_handler_disconnect (ih, priv->ih_event_id); - - g_free (priv->path); - if (priv->file_wd >= 0) - nm_inotify_helper_remove_watch (ih, priv->file_wd); - - g_free (priv->keyfile); - if (priv->keyfile_wd >= 0) - nm_inotify_helper_remove_watch (ih, priv->keyfile_wd); - - g_free (priv->routefile); - if (priv->routefile_wd >= 0) - nm_inotify_helper_remove_watch (ih, priv->routefile_wd); - - g_free (priv->route6file); - if (priv->route6file_wd >= 0) - nm_inotify_helper_remove_watch (ih, priv->route6file_wd); + path_watch_stop (NM_IFCFG_CONNECTION (object)); + g_free (NM_IFCFG_CONNECTION_GET_PRIVATE (object)->path); G_OBJECT_CLASS (nm_ifcfg_connection_parent_class)->finalize (object); } @@ -295,8 +362,11 @@ set_property (GObject *object, guint prop_id, NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (object); switch (prop_id) { - case PROP_UNMANAGED: - priv->unmanaged = g_value_dup_string (value); + case PROP_UNMANAGED_SPEC: + priv->unmanaged_spec = g_value_dup_string (value); + break; + case PROP_UNRECOGNIZED_SPEC: + priv->unrecognized_spec = g_value_dup_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -311,8 +381,11 @@ get_property (GObject *object, guint prop_id, NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (object); switch (prop_id) { - case PROP_UNMANAGED: - g_value_set_string (value, priv->unmanaged); + case PROP_UNMANAGED_SPEC: + g_value_set_string (value, priv->unmanaged_spec); + break; + case PROP_UNRECOGNIZED_SPEC: + g_value_set_string (value, priv->unrecognized_spec); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -337,12 +410,19 @@ nm_ifcfg_connection_class_init (NMIfcfgConnectionClass *ifcfg_connection_class) /* Properties */ g_object_class_install_property - (object_class, PROP_UNMANAGED, - g_param_spec_string (NM_IFCFG_CONNECTION_UNMANAGED, - "Unmanaged", - "Unmanaged", + (object_class, PROP_UNMANAGED_SPEC, + g_param_spec_string (NM_IFCFG_CONNECTION_UNMANAGED_SPEC, + "Unmanaged spec", + "Unmanaged spec", NULL, G_PARAM_READWRITE)); + g_object_class_install_property + (object_class, PROP_UNRECOGNIZED_SPEC, + g_param_spec_string (NM_IFCFG_CONNECTION_UNRECOGNIZED_SPEC, + "Unrecognized spec", + "Unrecognized spec", + NULL, + G_PARAM_READWRITE)); signals[IFCFG_CHANGED] = g_signal_new ("ifcfg-changed", |