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