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>
|
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
|
||||||
|
@@ -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");
|
||||||
|
@@ -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 */
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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 */
|
||||||
|
Reference in New Issue
Block a user