aboutsummaryrefslogtreecommitdiffstats
path: root/storage.c
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@samba.org>2005-12-14 00:05:27 +0100
committerJelmer Vernooij <jelmer@samba.org>2005-12-14 00:05:27 +0100
commitb73ac9c35fb53203b8d0668251dfb66096883863 (patch)
treeb5e10b15e55ec9453bf902431a3b9dc24310378c /storage.c
parenta301379c2035d9d0dd86926c4bdeebf95db18fac (diff)
Add support for 'primary' and 'migrate' account storages.
Fix two bugs in the text storage backend that were introduced by my previous changes.
Diffstat (limited to 'storage.c')
-rw-r--r--storage.c114
1 files changed, 108 insertions, 6 deletions
diff --git a/storage.c b/storage.c
index 28ead8ac..b766c9e3 100644
--- a/storage.c
+++ b/storage.c
@@ -37,7 +37,7 @@ void register_storage_backend(storage_t *backend)
storage_backends = g_list_append(storage_backends, backend);
}
-storage_t *storage_init(const char *name)
+static storage_t *storage_init_single(const char *name)
{
GList *gl;
storage_t *st;
@@ -57,27 +57,129 @@ storage_t *storage_init(const char *name)
return st;
}
+GList *storage_init(const char *primary, char **migrate)
+{
+ GList *ret = NULL;
+ int i;
+ storage_t *storage;
+
+ storage = storage_init_single(primary);
+ if (storage == NULL)
+ return NULL;
+
+ ret = g_list_append(ret, storage);
+
+ for (i = 0; migrate && migrate[i]; i++) {
+ storage = storage_init_single(migrate[i]);
+
+ if (storage)
+ ret = g_list_append(ret, storage);
+ }
+
+ return ret;
+}
+
storage_status_t storage_check_pass (const char *nick, const char *password)
{
- return global.storage->check_pass(nick, password);
+ GList *gl;
+
+ /* Loop until we don't get NO_SUCH_USER */
+
+ for (gl = global.storage; gl; gl = gl->next) {
+ storage_t *st = gl->data;
+ storage_status_t status;
+
+ status = st->check_pass(nick, password);
+ if (status != STORAGE_NO_SUCH_USER)
+ return status;
+ }
+
+ return STORAGE_NO_SUCH_USER;
}
storage_status_t storage_load (const char *nick, const char *password, irc_t * irc)
{
- return global.storage->load(nick, password, irc);
+ GList *gl;
+
+ /* Loop until we don't get NO_SUCH_USER */
+ for (gl = global.storage; gl; gl = gl->next) {
+ storage_t *st = gl->data;
+ storage_status_t status;
+
+ status = st->load(nick, password, irc);
+ if (status == STORAGE_OK) {
+ irc_setpass(irc, password);
+ return status;
+ }
+
+ if (status != STORAGE_NO_SUCH_USER)
+ return status;
+ }
+
+ return STORAGE_NO_SUCH_USER;
}
storage_status_t storage_save (irc_t *irc, int overwrite)
{
- return global.storage->save(irc, overwrite);
+ return ((storage_t *)global.storage->data)->save(irc, overwrite);
}
storage_status_t storage_remove (const char *nick, const char *password)
{
- return global.storage->remove(nick, password);
+ GList *gl;
+ storage_status_t ret = STORAGE_OK;
+
+ /* Remove this account from all storage backends. If this isn't
+ * done, the account will still be usable, it'd just be
+ * loaded from a different backend. */
+ for (gl = global.storage; gl; gl = gl->next) {
+ storage_t *st = gl->data;
+ storage_status_t status;
+
+ status = st->remove(nick, password);
+ if (status != STORAGE_NO_SUCH_USER &&
+ status != STORAGE_OK)
+ ret = status;
+ }
+
+ return ret;
}
storage_status_t storage_rename (const char *onick, const char *nnick, const char *password)
{
- return global.storage->rename(onick, nnick, password);
+ storage_status_t status;
+ GList *gl = global.storage;
+ storage_t *primary_storage = gl->data;
+ irc_t *irc;
+
+ /* First, try to rename in the current write backend, assuming onick
+ * is stored there */
+ status = primary_storage->rename(onick, nnick, password);
+ if (status != STORAGE_NO_SUCH_USER)
+ return status;
+
+ /* Try to load from a migration backend and save to the current backend.
+ * Explicitly remove the account from the migration backend as otherwise
+ * it'd still be usable under the old name */
+
+ irc = g_new0(irc_t, 1);
+ status = storage_load(onick, password, irc);
+ if (status != STORAGE_OK) {
+ irc_free(irc);
+ return status;
+ }
+
+ g_free(irc->nick);
+ irc->nick = g_strdup(nnick);
+
+ status = storage_save(irc, FALSE);
+ if (status != STORAGE_OK) {
+ irc_free(irc);
+ return status;
+ }
+ irc_free(irc);
+
+ storage_remove(onick, password);
+
+ return STORAGE_OK;
}