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:
14
ChangeLog
14
ChangeLog
@@ -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>
|
||||
|
||||
Add connection UUIDs, since connection names can be changed, and since
|
||||
|
@@ -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 <glib/gstdio.h>
|
||||
@@ -54,11 +54,23 @@ update (NMExportedConnection *exported,
|
||||
GHashTable *new_settings,
|
||||
GError **error)
|
||||
{
|
||||
NMKeyfileConnectionPrivate *priv = NM_KEYFILE_CONNECTION_GET_PRIVATE (exported);
|
||||
gboolean success;
|
||||
|
||||
success = NM_EXPORTED_CONNECTION_CLASS (nm_keyfile_connection_parent_class)->update (exported, new_settings, error);
|
||||
if (success)
|
||||
success = write_connection (nm_exported_connection_get_connection (exported), error);
|
||||
if (success) {
|
||||
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;
|
||||
}
|
||||
@@ -116,7 +128,7 @@ constructor (GType type,
|
||||
GError *error = NULL;
|
||||
|
||||
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",
|
||||
s_con->id, error ? error->code : 0,
|
||||
error ? error->message : "unknown");
|
||||
|
@@ -4,6 +4,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <gmodule.h>
|
||||
#include <glib.h>
|
||||
#include <glib/gstdio.h>
|
||||
@@ -42,25 +43,10 @@ typedef struct {
|
||||
gboolean disposed;
|
||||
} 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
|
||||
read_connections (NMSystemConfigInterface *config)
|
||||
{
|
||||
SCPluginKeyfilePrivate *priv = SC_PLUGIN_KEYFILE_GET_PRIVATE (config);
|
||||
GDir *dir;
|
||||
GError *err = NULL;
|
||||
|
||||
@@ -69,10 +55,16 @@ read_connections (NMSystemConfigInterface *config)
|
||||
const char *item;
|
||||
|
||||
while ((item = g_dir_read_name (dir))) {
|
||||
NMKeyfileConnection *connection;
|
||||
char *full_path;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
static void
|
||||
@@ -103,8 +134,11 @@ dir_changed (GFileMonitor *monitor,
|
||||
switch (event_type) {
|
||||
case G_FILE_MONITOR_EVENT_DELETED:
|
||||
if (connection) {
|
||||
/* Removing from the hash table should drop the last reference */
|
||||
g_object_ref (connection);
|
||||
g_hash_table_remove (priv->hash, name);
|
||||
nm_exported_connection_signal_removed (NM_EXPORTED_CONNECTION (connection));
|
||||
g_object_unref (connection);
|
||||
}
|
||||
break;
|
||||
case G_FILE_MONITOR_EVENT_CREATED:
|
||||
@@ -115,19 +149,76 @@ dir_changed (GFileMonitor *monitor,
|
||||
|
||||
tmp = (NMExportedConnection *) nm_keyfile_connection_new (name);
|
||||
if (tmp) {
|
||||
GHashTable *settings;
|
||||
GError *error = NULL;
|
||||
|
||||
settings = nm_connection_to_hash (nm_exported_connection_get_connection (tmp));
|
||||
nm_exported_connection_update (NM_EXPORTED_CONNECTION (connection), settings, NULL);
|
||||
g_hash_table_destroy (settings);
|
||||
if (!update_connection_settings (NM_EXPORTED_CONNECTION (connection), tmp, &error)) {
|
||||
g_warning ("%s: couldn't update connection settings: (%d) %s",
|
||||
__func__, error ? error->code : 0,
|
||||
error ? error->message : "unknown");
|
||||
g_error_free (error);
|
||||
}
|
||||
g_object_unref (tmp);
|
||||
}
|
||||
} else {
|
||||
/* New */
|
||||
connection = read_one_connection (config, name);
|
||||
if (connection)
|
||||
connection = nm_keyfile_connection_new (name);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -186,7 +277,7 @@ add_connection (NMSystemConfigInterface *config,
|
||||
NMConnection *connection,
|
||||
GError **error)
|
||||
{
|
||||
return write_connection (connection, error);
|
||||
return write_connection (connection, NULL, error);
|
||||
}
|
||||
|
||||
/* GObject */
|
||||
|
@@ -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
|
||||
write_connection (NMConnection *connection, GError **error)
|
||||
write_connection (NMConnection *connection, char **out_path, GError **error)
|
||||
{
|
||||
NMSettingConnection *s_con;
|
||||
GKeyFile *key_file;
|
||||
char *data;
|
||||
gsize len;
|
||||
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));
|
||||
if (!s_con)
|
||||
@@ -279,30 +302,28 @@ write_connection (NMConnection *connection, GError **error)
|
||||
|
||||
key_file = g_key_file_new ();
|
||||
nm_connection_for_each_setting_value (connection, write_setting_value, key_file);
|
||||
data = g_key_file_to_data (key_file, &len, &err);
|
||||
|
||||
if (!err) {
|
||||
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;
|
||||
data = g_key_file_to_data (key_file, &len, error);
|
||||
if (!data)
|
||||
goto out;
|
||||
|
||||
filename = writer_id_to_filename (s_con->id);
|
||||
path = g_build_filename (KEYFILE_DIR, filename, NULL);
|
||||
g_free (filename);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
g_warning ("Error while saving connection: %s", err->message);
|
||||
g_error_free (err);
|
||||
g_file_set_contents (path, data, len, error);
|
||||
chmod (path, S_IRUSR | S_IWUSR);
|
||||
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_key_file_free (key_file);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
@@ -6,6 +6,8 @@
|
||||
#include <glib.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 */
|
||||
|
Reference in New Issue
Block a user