dovecot-2.0: doveadm: Added "move" command for moving mails betw...
dovecot at dovecot.org
dovecot at dovecot.org
Wed Mar 23 22:16:27 EET 2011
details: http://hg.dovecot.org/dovecot-2.0/rev/d7a02077d91f
changeset: 12697:d7a02077d91f
user: Timo Sirainen <tss at iki.fi>
date: Wed Mar 23 22:16:24 2011 +0200
description:
doveadm: Added "move" command for moving mails between mailboxes.
diffstat:
src/doveadm/Makefile.am | 1 +
src/doveadm/doveadm-mail-expunge.c | 26 +++--
src/doveadm/doveadm-mail-iter.c | 31 +++++--
src/doveadm/doveadm-mail-iter.h | 1 +
src/doveadm/doveadm-mail-move.c | 137 ++++++++++++++++++++++++++++++++++
src/doveadm/doveadm-mail.c | 1 +
src/doveadm/doveadm-mail.h | 3 +
7 files changed, 179 insertions(+), 21 deletions(-)
diffs (truncated from 308 to 300 lines):
diff -r a94abbccea0f -r d7a02077d91f src/doveadm/Makefile.am
--- a/src/doveadm/Makefile.am Tue Mar 22 23:03:41 2011 +0200
+++ b/src/doveadm/Makefile.am Wed Mar 23 22:16:24 2011 +0200
@@ -66,6 +66,7 @@
doveadm-mail-iter.c \
doveadm-mail-mailbox.c \
doveadm-mail-mailbox-status.c \
+ doveadm-mail-move.c \
doveadm-mail-list-iter.c \
doveadm-mail-search.c \
doveadm-print.c \
diff -r a94abbccea0f -r d7a02077d91f src/doveadm/doveadm-mail-expunge.c
--- a/src/doveadm/doveadm-mail-expunge.c Tue Mar 22 23:03:41 2011 +0200
+++ b/src/doveadm/doveadm-mail-expunge.c Wed Mar 23 22:16:24 2011 +0200
@@ -178,6 +178,20 @@
doveadm_mail_list_iter_deinit(&iter);
}
+void expunge_search_args_check(struct mail_search_args *args, const char *cmd)
+{
+ mail_search_args_simplify(args);
+ if (!expunge_search_args_is_mailbox_ok(args->args)) {
+ i_fatal("%s: To avoid accidents, search query "
+ "must contain MAILBOX in all search branches", cmd);
+ }
+ if (!expunge_search_args_is_msgset_ok(args->args)) {
+ i_fatal("%s: To avoid accidents, each branch in "
+ "search query must contain something else "
+ "besides MAILBOX", cmd);
+ }
+}
+
static void cmd_expunge_init(struct doveadm_mail_cmd_context *ctx,
const char *const args[])
{
@@ -185,17 +199,7 @@
doveadm_mail_help_name("expunge");
ctx->search_args = doveadm_mail_build_search_args(args);
- mail_search_args_simplify(ctx->search_args);
-
- if (!expunge_search_args_is_mailbox_ok(ctx->search_args->args)) {
- i_fatal("expunge: To avoid accidents, search query "
- "must contain MAILBOX in all search branches");
- }
- if (!expunge_search_args_is_msgset_ok(ctx->search_args->args)) {
- i_fatal("expunge: To avoid accidents, each branch in "
- "search query must contain something else "
- "besides MAILBOX");
- }
+ expunge_search_args_check(ctx->search_args, "expunge");
}
static struct doveadm_mail_cmd_context *cmd_expunge_alloc(void)
diff -r a94abbccea0f -r d7a02077d91f src/doveadm/doveadm-mail-iter.c
--- a/src/doveadm/doveadm-mail-iter.c Tue Mar 22 23:03:41 2011 +0200
+++ b/src/doveadm/doveadm-mail-iter.c Wed Mar 23 22:16:24 2011 +0200
@@ -50,7 +50,8 @@
}
static int
-doveadm_mail_iter_deinit_transaction(struct doveadm_mail_iter *iter)
+doveadm_mail_iter_deinit_transaction(struct doveadm_mail_iter *iter,
+ bool commit)
{
int ret = 0;
@@ -60,25 +61,30 @@
mail_storage_get_last_error(iter->storage, NULL));
ret = -1;
}
- if (mailbox_transaction_commit(&iter->t) < 0) {
- i_error("Commiting mailbox %s failed: %s",
- mailbox_get_vname(iter->box),
- mail_storage_get_last_error(iter->storage, NULL));
- ret = -1;
+ if (commit) {
+ if (mailbox_transaction_commit(&iter->t) < 0) {
+ i_error("Commiting mailbox %s failed: %s",
+ mailbox_get_vname(iter->box),
+ mail_storage_get_last_error(iter->storage, NULL));
+ ret = -1;
+ }
+ } else {
+ mailbox_transaction_rollback(&iter->t);
}
mail_search_args_deinit(iter->search_args);
return ret;
}
static int
-doveadm_mail_iter_deinit_full(struct doveadm_mail_iter **_iter, bool sync)
+doveadm_mail_iter_deinit_full(struct doveadm_mail_iter **_iter,
+ bool sync, bool commit)
{
struct doveadm_mail_iter *iter = *_iter;
int ret;
*_iter = NULL;
- ret = doveadm_mail_iter_deinit_transaction(iter);
+ ret = doveadm_mail_iter_deinit_transaction(iter, commit);
if (ret == 0 && sync)
ret = mailbox_sync(iter->box, 0);
mailbox_free(&iter->box);
@@ -88,12 +94,17 @@
int doveadm_mail_iter_deinit(struct doveadm_mail_iter **_iter)
{
- return doveadm_mail_iter_deinit_full(_iter, FALSE);
+ return doveadm_mail_iter_deinit_full(_iter, FALSE, TRUE);
}
int doveadm_mail_iter_deinit_sync(struct doveadm_mail_iter **_iter)
{
- return doveadm_mail_iter_deinit_full(_iter, TRUE);
+ return doveadm_mail_iter_deinit_full(_iter, TRUE, TRUE);
+}
+
+void doveadm_mail_iter_deinit_rollback(struct doveadm_mail_iter **_iter)
+{
+ (void)doveadm_mail_iter_deinit_full(_iter, FALSE, FALSE);
}
bool doveadm_mail_iter_next(struct doveadm_mail_iter *iter, struct mail *mail)
diff -r a94abbccea0f -r d7a02077d91f src/doveadm/doveadm-mail-iter.h
--- a/src/doveadm/doveadm-mail-iter.h Tue Mar 22 23:03:41 2011 +0200
+++ b/src/doveadm/doveadm-mail-iter.h Wed Mar 23 22:16:24 2011 +0200
@@ -9,6 +9,7 @@
struct doveadm_mail_iter **iter_r);
int doveadm_mail_iter_deinit(struct doveadm_mail_iter **iter);
int doveadm_mail_iter_deinit_sync(struct doveadm_mail_iter **iter);
+void doveadm_mail_iter_deinit_rollback(struct doveadm_mail_iter **iter);
bool doveadm_mail_iter_next(struct doveadm_mail_iter *iter, struct mail *mail);
diff -r a94abbccea0f -r d7a02077d91f src/doveadm/doveadm-mail-move.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/doveadm/doveadm-mail-move.c Wed Mar 23 22:16:24 2011 +0200
@@ -0,0 +1,137 @@
+/* Copyright (c) 2011 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "mail-storage.h"
+#include "mail-namespace.h"
+#include "doveadm-print.h"
+#include "doveadm-mail-list-iter.h"
+#include "doveadm-mail-iter.h"
+#include "doveadm-mail.h"
+
+#include <stdio.h>
+
+struct move_cmd_context {
+ struct doveadm_mail_cmd_context ctx;
+
+ const char *destname;
+};
+
+static int
+cmd_move_box(struct move_cmd_context *ctx, struct mailbox *destbox,
+ const struct mailbox_info *info)
+{
+ struct doveadm_mail_iter *iter;
+ struct mailbox_transaction_context *trans;
+ struct mailbox_transaction_context *desttrans;
+ struct mail_storage *deststorage = mailbox_get_storage(destbox);
+ struct mail_save_context *save_ctx;
+ struct mail *mail;
+ int ret = 0;
+
+ if (doveadm_mail_iter_init(info, ctx->ctx.search_args,
+ &trans, &iter) < 0)
+ return -1;
+
+ /* use a separately committed transaction for each mailbox.
+ this guarantees that mails aren't expunged without actually having
+ been copied. */
+ desttrans = mailbox_transaction_begin(destbox,
+ MAILBOX_TRANSACTION_FLAG_EXTERNAL);
+
+ mail = mail_alloc(trans, 0, NULL);
+ while (doveadm_mail_iter_next(iter, mail)) {
+ save_ctx = mailbox_save_alloc(desttrans);
+ mailbox_save_copy_flags(save_ctx, mail);
+ if (mailbox_copy(&save_ctx, mail) == 0)
+ mail_expunge(mail);
+ else {
+ i_error("Copying messsage UID %u from '%s' failed: %s",
+ mail->uid, info->name,
+ mail_storage_get_last_error(deststorage, NULL));
+ ret = -1;
+ }
+ }
+ mail_free(&mail);
+
+ if (mailbox_transaction_commit(&desttrans) < 0) {
+ i_error("Committing moved mails failed: %s",
+ mail_storage_get_last_error(deststorage, NULL));
+ /* rollback expunges */
+ doveadm_mail_iter_deinit_rollback(&iter);
+ ret = -1;
+ } else {
+ if (doveadm_mail_iter_deinit_sync(&iter) < 0)
+ ret = -1;
+ }
+ return ret;
+}
+
+static void
+cmd_move_run(struct doveadm_mail_cmd_context *_ctx, struct mail_user *user)
+{
+ struct move_cmd_context *ctx = (struct move_cmd_context *)_ctx;
+ const enum mailbox_list_iter_flags iter_flags =
+ MAILBOX_LIST_ITER_RAW_LIST |
+ MAILBOX_LIST_ITER_NO_AUTO_INBOX |
+ MAILBOX_LIST_ITER_RETURN_NO_FLAGS;
+ struct doveadm_mail_list_iter *iter;
+ struct mail_namespace *ns;
+ struct mailbox *destbox;
+ struct mail_storage *storage;
+ const struct mailbox_info *info;
+ const char *storage_name = ctx->destname;
+
+ ns = mail_namespace_find(user->namespaces, &storage_name);
+ if (ns == NULL)
+ i_fatal("Can't find namespace for: %s", ctx->destname);
+
+ destbox = mailbox_alloc(ns->list, storage_name,
+ MAILBOX_FLAG_SAVEONLY |
+ MAILBOX_FLAG_KEEP_RECENT);
+ storage = mailbox_get_storage(destbox);
+ if (mailbox_open(destbox) < 0) {
+ i_error("Can't open mailbox '%s': %s", ctx->destname,
+ mail_storage_get_last_error(storage, NULL));
+ mailbox_free(&destbox);
+ return;
+ }
+
+ iter = doveadm_mail_list_iter_init(user, _ctx->search_args, iter_flags);
+ while ((info = doveadm_mail_list_iter_next(iter)) != NULL) T_BEGIN {
+ (void)cmd_move_box(ctx, destbox, info);
+ } T_END;
+ doveadm_mail_list_iter_deinit(&iter);
+
+ (void)mailbox_sync(destbox, 0);
+ mailbox_free(&destbox);
+
+}
+
+static void cmd_move_init(struct doveadm_mail_cmd_context *_ctx,
+ const char *const args[])
+{
+ struct move_cmd_context *ctx = (struct move_cmd_context *)_ctx;
+ const char *destname = args[0];
+
+ if (destname == NULL || args[1] == NULL)
+ doveadm_mail_help_name("move");
+
+ ctx->destname = p_strdup(ctx->ctx.pool, destname);
+ ctx->ctx.search_args = doveadm_mail_build_search_args(args + 1);
+ expunge_search_args_check(ctx->ctx.search_args, "move");
+}
+
+static struct doveadm_mail_cmd_context *cmd_move_alloc(void)
+{
+ struct move_cmd_context *ctx;
+
+ ctx = doveadm_mail_cmd_alloc(struct move_cmd_context);
+ ctx->ctx.v.init = cmd_move_init;
+ ctx->ctx.v.run = cmd_move_run;
+ doveadm_print_init(DOVEADM_PRINT_TYPE_FLOW);
+ return &ctx->ctx;
+}
+
+struct doveadm_mail_cmd cmd_move = {
+ cmd_move_alloc, "move", "<destination> <search query>"
+};
diff -r a94abbccea0f -r d7a02077d91f src/doveadm/doveadm-mail.c
--- a/src/doveadm/doveadm-mail.c Tue Mar 22 23:03:41 2011 +0200
+++ b/src/doveadm/doveadm-mail.c Wed Mar 23 22:16:24 2011 +0200
@@ -566,6 +566,7 @@
&cmd_fetch,
&cmd_import,
&cmd_altmove,
+ &cmd_move,
&cmd_mailbox_list,
&cmd_mailbox_create,
&cmd_mailbox_delete,
diff -r a94abbccea0f -r d7a02077d91f src/doveadm/doveadm-mail.h
--- a/src/doveadm/doveadm-mail.h Tue Mar 22 23:03:41 2011 +0200
+++ b/src/doveadm/doveadm-mail.h Wed Mar 23 22:16:24 2011 +0200
@@ -97,6 +97,8 @@
struct mail_search_args *
doveadm_mail_mailbox_search_args_build(const char *const args[]);
+void expunge_search_args_check(struct mail_search_args *args, const char *cmd);
+
struct doveadm_mail_cmd_context *
doveadm_mail_cmd_alloc_size(size_t size);
#define doveadm_mail_cmd_alloc(type) \
More information about the dovecot-cvs
mailing list