[dovecot-cvs] dovecot/src/plugins/convert .cvsignore, NONE,
1.1 convert-plugin.c, NONE, 1.1 convert-plugin.h, NONE,
1.1 convert-storage.c, NONE, 1.1 convert-storage.h, NONE,
1.1 convert-tool.c, NONE, 1.1
cras at dovecot.org
cras at dovecot.org
Thu Feb 2 22:42:46 EET 2006
Update of /var/lib/cvs/dovecot/src/plugins/convert
In directory talvi:/tmp/cvs-serv2477/src/plugins/convert
Added Files:
.cvsignore convert-plugin.c convert-plugin.h convert-storage.c
convert-storage.h convert-tool.c
Log Message:
Added "mail storage conversion" plugin. It can be used with IMAP, POP3
and/or LDA to convert one complete mail storage to another format. Also
included a convert-tool command line tool to do it manually. Currently
doesn't support preserving UID/UIDVALIDITY.
--- NEW FILE: .cvsignore ---
*.la
*.lo
*.o
.deps
.libs
Makefile
Makefile.in
so_locations
convert-tool
--- NEW FILE: convert-plugin.c ---
/* Copyright (C) 2006 Timo Sirainen */
#include "lib.h"
#include "convert-storage.h"
#include "convert-plugin.h"
#include <stdlib.h>
void convert_plugin_init(void)
{
const char *convert_mail, *mail, *home, *user;
convert_mail = getenv("CONVERT_MAIL");
if (convert_mail == NULL)
return;
mail = getenv("MAIL");
if (mail == NULL)
i_fatal("convert plugin: MAIL unset");
user = getenv("USER");
if (mail == NULL)
i_fatal("convert plugin: USER unset");
home = getenv("HOME");
if (mail == NULL)
i_fatal("convert plugin: HOME unset");
if (convert_storage(user, home, convert_mail, mail) < 0)
exit(FATAL_DEFAULT);
}
void convert_plugin_deinit(void)
{
}
--- NEW FILE: convert-plugin.h ---
#ifndef __CONVERT_PLUGIN_H
#define __CONVERT_PLUGIN_H
void convert_plugin_init(void);
void convert_plugin_deinit(void);
#endif
--- NEW FILE: convert-storage.c ---
/* Copyright (C) 2006 Timo Sirainen */
#include "lib.h"
#include "file-dotlock.h"
#include "index-storage.h"
#include "mail-search.h"
#include "convert-storage.h"
#include <stdio.h>
#define CONVERT_LOCK_FILENAME ".dovecot-convert.lock"
const struct dotlock_settings dotlock_settings = {
NULL,
NULL,
60*5,
0,
60*5,
NULL,
NULL,
FALSE
};
static int sync_mailbox(struct mailbox *box)
{
struct mailbox_sync_context *ctx;
struct mailbox_sync_rec sync_rec;
struct mailbox_status status;
ctx = mailbox_sync_init(box, MAILBOX_SYNC_FLAG_FULL_READ);
while (mailbox_sync_next(ctx, &sync_rec) > 0)
;
return mailbox_sync_deinit(&ctx, &status);
}
static int mailbox_copy_mails(struct mailbox *srcbox, struct mailbox *destbox)
{
struct mail_search_context *ctx;
struct mailbox_transaction_context *src_trans, *dest_trans;
struct mail *mail;
struct mail_search_arg search_arg;
int ret = 0;
if (sync_mailbox(srcbox) < 0)
return -1;
memset(&search_arg, 0, sizeof(search_arg));
search_arg.type = SEARCH_ALL;
src_trans = mailbox_transaction_begin(srcbox, 0);
dest_trans = mailbox_transaction_begin(destbox,
MAILBOX_TRANSACTION_FLAG_EXTERNAL);
ctx = mailbox_search_init(src_trans, NULL, &search_arg, NULL);
mail = mail_alloc(src_trans,
MAIL_FETCH_FLAGS | MAIL_FETCH_RECEIVED_DATE |
MAIL_FETCH_STREAM_HEADER | MAIL_FETCH_STREAM_BODY |
MAIL_FETCH_FROM_ENVELOPE, NULL);
while (mailbox_search_next(ctx, mail) > 0) {
struct mail_keywords *keywords;
const char *const *keywords_list;
keywords_list = mail_get_keywords(mail);
keywords = strarray_length(keywords_list) == 0 ? NULL :
mailbox_keywords_create(dest_trans, keywords_list);
ret = mailbox_copy(dest_trans, mail, mail_get_flags(mail),
keywords, NULL);
mailbox_keywords_free(dest_trans, &keywords);
if (ret < 0)
break;
}
mail_free(&mail);
if (mailbox_search_deinit(&ctx) < 0)
ret = -1;
if (ret < 0)
mailbox_transaction_rollback(&dest_trans);
else
ret = mailbox_transaction_commit(&dest_trans, 0);
/* source transaction committing isn't all that important.
ignore if it fails. */
if (ret < 0)
mailbox_transaction_rollback(&src_trans);
else
(void)mailbox_transaction_commit(&src_trans, 0);
return ret;
}
static int mailbox_convert_list_item(struct mail_storage *source_storage,
struct mail_storage *dest_storage,
struct mailbox_list *list)
{
struct mailbox *srcbox, *destbox;
int ret = 0;
if ((list->flags & (MAILBOX_NONEXISTENT|MAILBOX_PLACEHOLDER)) != 0)
return 0;
if ((list->flags & MAILBOX_NOSELECT) != 0) {
if (mail_storage_mailbox_create(dest_storage,
list->name, TRUE) < 0) {
i_error("Mailbox conversion: Couldn't create mailbox "
"directory %s", list->name);
return -1;
}
return 0;
}
/* It's a real mailbox. First create the destination mailbox. */
if (mail_storage_mailbox_create(dest_storage, list->name, FALSE) < 0) {
i_error("Mailbox conversion: Couldn't create mailbox %s",
list->name);
return -1;
}
/* Open both the mailboxes.. */
srcbox = mailbox_open(source_storage, list->name, NULL,
MAILBOX_OPEN_READONLY | MAILBOX_OPEN_KEEP_RECENT);
if (srcbox == NULL) {
i_error("Mailbox conversion: Couldn't open source mailbox %s",
list->name);
return -1;
}
destbox = mailbox_open(dest_storage, list->name, NULL,
MAILBOX_OPEN_KEEP_RECENT);
if (destbox == NULL) {
i_error("Mailbox conversion: Couldn't open dest mailbox %s",
list->name);
mailbox_close(&srcbox);
return -1;
}
if (mailbox_copy_mails(srcbox, destbox) < 0) {
i_error("Mailbox conversion: Couldn't copy mailbox %s",
mailbox_get_name(srcbox));
}
mailbox_close(&srcbox);
mailbox_close(&destbox);
return ret;
}
static int mailbox_list_copy(struct mail_storage *source_storage,
struct mail_storage *dest_storage)
{
struct mailbox_list_context *iter;
struct mailbox_list *list;
int ret = 0;
iter = mail_storage_mailbox_list_init(source_storage, "", "*",
MAILBOX_LIST_FAST_FLAGS);
while ((list = mail_storage_mailbox_list_next(iter)) != NULL) {
if (mailbox_convert_list_item(source_storage, dest_storage,
list) < 0) {
ret = -1;
break;
}
}
if (mail_storage_mailbox_list_deinit(&iter) < 0)
ret = -1;
return ret;
}
int convert_storage(const char *user, const char *home_dir,
const char *source_data, const char *dest_data)
{
struct mail_storage *source_storage, *dest_storage;
struct dotlock *dotlock;
enum mail_storage_flags flags;
enum mail_storage_lock_method lock_method;
const char *path;
int ret;
mail_storage_parse_env(&flags, &lock_method);
source_storage = mail_storage_create_with_data(source_data, user,
flags, lock_method);
if (source_storage == NULL) {
/* No need for conversion. */
return 0;
}
path = t_strconcat(home_dir, "/"CONVERT_LOCK_FILENAME, NULL);
ret = file_dotlock_create(&dotlock_settings, path, 0, &dotlock);
if (ret <= 0) {
if (ret == 0)
i_error("Mailbox conversion: Lock creation timeouted");
return -1;
}
dest_storage = mail_storage_create_with_data(dest_data, user,
flags, lock_method);
if (dest_storage == NULL) {
i_error("Mailbox conversion: Failed to create destination "
"storage with data: %s", dest_data);
}
ret = mailbox_list_copy(source_storage, dest_storage);
if (ret == 0) {
/* all finished. rename the source directory to mark the
move as finished. FIXME: kind of kludgy way to get the
directory.. */
struct index_storage *index_storage =
(struct index_storage *)source_storage;
const char *dest;
dest = t_strconcat(index_storage->dir, "-converted", NULL);
if (rename(index_storage->dir, dest) < 0) {
i_error("Mailbox conversion: rename(%s, %s) failed: %m",
index_storage->dir, dest);
/* return success anyway */
}
ret = 1;
}
mail_storage_destroy(&source_storage);
mail_storage_destroy(&dest_storage);
return ret;
}
--- NEW FILE: convert-storage.h ---
#ifndef __CONVERT_STORAGE_H
#define __CONVERT_STORAGE_H
int convert_storage(const char *user, const char *home_dir,
const char *source_data, const char *dest_data);
#endif
--- NEW FILE: convert-tool.c ---
/* Copyright (C) 2006 Timo Sirainen */
#include "lib.h"
#include "ioloop.h"
#include "randgen.h"
#include "lib-signals.h"
#include "convert-storage.h"
/* ugly, but automake doesn't like having it built as both static and
dynamic object.. */
#include "convert-storage.c"
int main(int argc, const char *argv[])
{
struct ioloop *ioloop;
int ret = 0;
lib_init();
lib_signals_init();
random_init();
mail_storage_init();
mail_storage_register_all();
if (argc <= 4) {
i_fatal("Usage: <username> <home dir> "
"<source mail env> <dest mail env>");
}
ioloop = io_loop_create(system_pool);
ret = convert_storage(argv[1], argv[2], argv[3], argv[4]);
if (ret > 0)
i_info("Successfully converted");
else if (ret == 0)
i_error("Source storage not found");
else
i_error("Internal failure");
io_loop_destroy(&ioloop);
mail_storage_deinit();
lib_signals_deinit();
lib_deinit();
return ret;
}
More information about the dovecot-cvs
mailing list