2008-08-26 Dan Williams <dcbw@redhat.com>

* system-settings/plugins/keyfile/nm-keyfile-connection.c
		- (update): Update filename of the connection if the connection id
			was changed

	* system-settings/plugins/keyfile/plugin.c
		- (dir_changed): first pass at handling connection renames correctly

	* system-settings/plugins/keyfile/writer.c
	  system-settings/plugins/keyfile/writer.h
		- (write_connection): replace '/' with '*' when writing out the filename
			from the connection id



git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@4018 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
This commit is contained in:
Dan Williams
2008-08-27 03:09:14 +00:00
parent 39e0b5fd7b
commit 3d70bc42bf
5 changed files with 195 additions and 55 deletions

View File

@@ -1,3 +1,17 @@
2008-08-26 Dan Williams <dcbw@redhat.com>
* system-settings/plugins/keyfile/nm-keyfile-connection.c
- (update): Update filename of the connection if the connection id
was changed
* system-settings/plugins/keyfile/plugin.c
- (dir_changed): first pass at handling connection renames correctly
* system-settings/plugins/keyfile/writer.c
system-settings/plugins/keyfile/writer.h
- (write_connection): replace '/' with '*' when writing out the filename
from the connection id
2008-08-26 Dan Williams <dcbw@redhat.com> 2008-08-26 Dan Williams <dcbw@redhat.com>
Add connection UUIDs, since connection names can be changed, and since Add connection UUIDs, since connection names can be changed, and since

View File

@@ -1,4 +1,4 @@
/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
#include <string.h> #include <string.h>
#include <glib/gstdio.h> #include <glib/gstdio.h>
@@ -54,11 +54,23 @@ update (NMExportedConnection *exported,
GHashTable *new_settings, GHashTable *new_settings,
GError **error) GError **error)
{ {
NMKeyfileConnectionPrivate *priv = NM_KEYFILE_CONNECTION_GET_PRIVATE (exported);
gboolean success; gboolean success;
success = NM_EXPORTED_CONNECTION_CLASS (nm_keyfile_connection_parent_class)->update (exported, new_settings, error); success = NM_EXPORTED_CONNECTION_CLASS (nm_keyfile_connection_parent_class)->update (exported, new_settings, error);
if (success) if (success) {
success = write_connection (nm_exported_connection_get_connection (exported), error); NMConnection *connection;
char *filename = NULL;
connection = nm_exported_connection_get_connection (exported);
success = write_connection (connection, &filename, error);
if (success && filename && strcmp (priv->filename, filename)) {
/* Update the filename if it changed */
g_free (priv->filename);
priv->filename = filename;
} else
g_free (filename);
}
return success; return success;
} }
@@ -116,7 +128,7 @@ constructor (GType type,
GError *error = NULL; GError *error = NULL;
s_con->uuid = nm_utils_uuid_generate (); s_con->uuid = nm_utils_uuid_generate ();
if (!write_connection (wrapped, &error)) { if (!write_connection (wrapped, NULL, &error)) {
g_warning ("Couldn't update connection %s with a UUID: (%d) %s", g_warning ("Couldn't update connection %s with a UUID: (%d) %s",
s_con->id, error ? error->code : 0, s_con->id, error ? error->code : 0,
error ? error->message : "unknown"); error ? error->message : "unknown");

View File

@@ -4,6 +4,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <sys/types.h> #include <sys/types.h>
#include <string.h>
#include <gmodule.h> #include <gmodule.h>
#include <glib.h> #include <glib.h>
#include <glib/gstdio.h> #include <glib/gstdio.h>
@@ -42,25 +43,10 @@ typedef struct {
gboolean disposed; gboolean disposed;
} SCPluginKeyfilePrivate; } SCPluginKeyfilePrivate;
static NMKeyfileConnection *
read_one_connection (NMSystemConfigInterface *config, const char *filename)
{
SCPluginKeyfilePrivate *priv = SC_PLUGIN_KEYFILE_GET_PRIVATE (config);
NMKeyfileConnection *connection;
connection = nm_keyfile_connection_new (filename);
if (connection) {
g_hash_table_insert (priv->hash,
(gpointer) nm_keyfile_connection_get_filename (connection),
g_object_ref (connection));
}
return connection;
}
static void static void
read_connections (NMSystemConfigInterface *config) read_connections (NMSystemConfigInterface *config)
{ {
SCPluginKeyfilePrivate *priv = SC_PLUGIN_KEYFILE_GET_PRIVATE (config);
GDir *dir; GDir *dir;
GError *err = NULL; GError *err = NULL;
@@ -69,10 +55,16 @@ read_connections (NMSystemConfigInterface *config)
const char *item; const char *item;
while ((item = g_dir_read_name (dir))) { while ((item = g_dir_read_name (dir))) {
NMKeyfileConnection *connection;
char *full_path; char *full_path;
full_path = g_build_filename (KEYFILE_DIR, item, NULL); full_path = g_build_filename (KEYFILE_DIR, item, NULL);
read_one_connection (config, full_path); connection = nm_keyfile_connection_new (full_path);
if (connection) {
g_hash_table_insert (priv->hash,
(gpointer) nm_keyfile_connection_get_filename (connection),
connection);
}
g_free (full_path); g_free (full_path);
} }
@@ -83,6 +75,45 @@ read_connections (NMSystemConfigInterface *config)
} }
} }
typedef struct {
const char *uuid;
NMKeyfileConnection *found;
} FindByUUIDInfo;
static void
find_by_uuid (gpointer key, gpointer data, gpointer user_data)
{
NMKeyfileConnection *keyfile = NM_KEYFILE_CONNECTION (key);
FindByUUIDInfo *info = user_data;
NMConnection *connection;
NMSettingConnection *s_con;
if (info->found)
return;
connection = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (keyfile));
s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
if (s_con && s_con->uuid) {
if (!strcmp (info->uuid, s_con->uuid))
info->found = keyfile;
}
}
static gboolean
update_connection_settings (NMExportedConnection *orig,
NMExportedConnection *new,
GError **error)
{
GHashTable *settings;
gboolean success;
settings = nm_connection_to_hash (nm_exported_connection_get_connection (new));
success = nm_exported_connection_update (orig, settings, error);
g_hash_table_destroy (settings);
return success;
}
/* Monitoring */ /* Monitoring */
static void static void
@@ -103,8 +134,11 @@ dir_changed (GFileMonitor *monitor,
switch (event_type) { switch (event_type) {
case G_FILE_MONITOR_EVENT_DELETED: case G_FILE_MONITOR_EVENT_DELETED:
if (connection) { if (connection) {
/* Removing from the hash table should drop the last reference */
g_object_ref (connection);
g_hash_table_remove (priv->hash, name); g_hash_table_remove (priv->hash, name);
nm_exported_connection_signal_removed (NM_EXPORTED_CONNECTION (connection)); nm_exported_connection_signal_removed (NM_EXPORTED_CONNECTION (connection));
g_object_unref (connection);
} }
break; break;
case G_FILE_MONITOR_EVENT_CREATED: case G_FILE_MONITOR_EVENT_CREATED:
@@ -115,19 +149,76 @@ dir_changed (GFileMonitor *monitor,
tmp = (NMExportedConnection *) nm_keyfile_connection_new (name); tmp = (NMExportedConnection *) nm_keyfile_connection_new (name);
if (tmp) { if (tmp) {
GHashTable *settings; GError *error = NULL;
settings = nm_connection_to_hash (nm_exported_connection_get_connection (tmp)); if (!update_connection_settings (NM_EXPORTED_CONNECTION (connection), tmp, &error)) {
nm_exported_connection_update (NM_EXPORTED_CONNECTION (connection), settings, NULL); g_warning ("%s: couldn't update connection settings: (%d) %s",
g_hash_table_destroy (settings); __func__, error ? error->code : 0,
error ? error->message : "unknown");
g_error_free (error);
}
g_object_unref (tmp); g_object_unref (tmp);
} }
} else { } else {
/* New */ /* New */
connection = read_one_connection (config, name); connection = nm_keyfile_connection_new (name);
if (connection) if (connection) {
NMConnection *tmp;
NMSettingConnection *s_con;
NMKeyfileConnection *found = NULL;
/* Connection renames will show up as different files but with
* the same UUID. Try to find the original connection.
*/
tmp = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (connection));
s_con = (NMSettingConnection *) nm_connection_get_setting (tmp, NM_TYPE_SETTING_CONNECTION);
if (s_con && s_con->uuid) {
FindByUUIDInfo info = { .found = NULL, .uuid = s_con->uuid };
g_hash_table_foreach (priv->hash, find_by_uuid, &info);
found = info.found;
}
/* A connection rename is treated just like an update except
* there's a bit more housekeeping with the hash table.
*/
if (found) {
const char *old_filename = nm_keyfile_connection_get_filename (connection);
GError *error = NULL;
/* Removing from the hash table should drop the last reference,
* but of course we want to keep the connection around.
*/
g_object_ref (found);
g_hash_table_remove (priv->hash, old_filename);
/* Updating settings should update the NMKeyfileConnection's
* filename property too.
*/
if (!update_connection_settings (NM_EXPORTED_CONNECTION (found),
NM_EXPORTED_CONNECTION (connection),
&error)) {
g_warning ("%s: couldn't update connection settings: (%d) %s",
__func__, error ? error->code : 0,
error ? error->message : "unknown");
g_error_free (error);
}
/* Re-insert the connection back into the hash with the new filename */
g_hash_table_insert (priv->hash,
(gpointer) nm_keyfile_connection_get_filename (found),
found);
/* Get rid of the temporary connection */
g_object_unref (connection);
} else {
g_hash_table_insert (priv->hash,
(gpointer) nm_keyfile_connection_get_filename (connection),
connection);
g_signal_emit_by_name (config, "connection-added", connection); g_signal_emit_by_name (config, "connection-added", connection);
} }
}
}
break; break;
default: default:
break; break;
@@ -186,7 +277,7 @@ add_connection (NMSystemConfigInterface *config,
NMConnection *connection, NMConnection *connection,
GError **error) GError **error)
{ {
return write_connection (connection, error); return write_connection (connection, NULL, error);
} }
/* GObject */ /* GObject */

View File

@@ -263,15 +263,38 @@ write_setting_value (NMSetting *setting,
} }
} }
char *
writer_id_to_filename (const char *id)
{
char *filename, *f;
const char *i = id;
f = filename = g_malloc0 (strlen (id) + 1);
/* Convert '/' to '*' */
while (*i) {
if (*i == '/')
*f++ = '*';
else
*f++ = *i;
i++;
}
return filename;
}
gboolean gboolean
write_connection (NMConnection *connection, GError **error) write_connection (NMConnection *connection, char **out_path, GError **error)
{ {
NMSettingConnection *s_con; NMSettingConnection *s_con;
GKeyFile *key_file; GKeyFile *key_file;
char *data; char *data;
gsize len; gsize len;
gboolean success = FALSE; gboolean success = FALSE;
GError *err = NULL; char *filename, *path;
if (out_path)
g_return_val_if_fail (*out_path == NULL, FALSE);
s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION)); s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
if (!s_con) if (!s_con)
@@ -279,30 +302,28 @@ write_connection (NMConnection *connection, GError **error)
key_file = g_key_file_new (); key_file = g_key_file_new ();
nm_connection_for_each_setting_value (connection, write_setting_value, key_file); nm_connection_for_each_setting_value (connection, write_setting_value, key_file);
data = g_key_file_to_data (key_file, &len, &err); data = g_key_file_to_data (key_file, &len, error);
if (!data)
if (!err) { goto out;
char *filename;
filename = g_build_filename (KEYFILE_DIR, s_con->id, NULL);
g_file_set_contents (filename, data, len, &err);
chmod (filename, S_IRUSR | S_IWUSR);
if (chown (filename, 0, 0) < 0) {
g_warning ("Error chowning '%s': %d", filename, errno);
unlink (filename);
} else
success = TRUE;
filename = writer_id_to_filename (s_con->id);
path = g_build_filename (KEYFILE_DIR, filename, NULL);
g_free (filename); g_free (filename);
}
if (err) { g_file_set_contents (path, data, len, error);
g_warning ("Error while saving connection: %s", err->message); chmod (path, S_IRUSR | S_IWUSR);
g_error_free (err); if (chown (path, 0, 0) < 0) {
g_warning ("Error chowning '%s': %d", path, errno);
unlink (path);
} else {
if (out_path)
*out_path = g_strdup (path);
success = TRUE;
} }
g_free (path);
out:
g_free (data); g_free (data);
g_key_file_free (key_file); g_key_file_free (key_file);
return success; return success;
} }

View File

@@ -6,6 +6,8 @@
#include <glib.h> #include <glib.h>
#include <nm-connection.h> #include <nm-connection.h>
gboolean write_connection (NMConnection *connection, GError **error); gboolean write_connection (NMConnection *connection, char **out_path, GError **error);
char *writer_id_to_filename (const char *id);
#endif /* _KEYFILE_PLUGIN_WRITER_H */ #endif /* _KEYFILE_PLUGIN_WRITER_H */