From: Timo Sirainen Date: Wed, 28 Apr 2010 21:19:00 +0000 (+0300) Subject: doveadm: Added expunge command. X-Git-Tag: 2.0.beta5~64 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4eecd3e2aadb20768a60f701e329b4345d04430c;p=thirdparty%2Fdovecot%2Fcore.git doveadm: Added expunge command. --HG-- branch : HEAD --- diff --git a/src/doveadm/Makefile.am b/src/doveadm/Makefile.am index c6e5bd6450..b5e66caf4b 100644 --- a/src/doveadm/Makefile.am +++ b/src/doveadm/Makefile.am @@ -53,6 +53,7 @@ doveadm_SOURCES = \ doveadm-kick.c \ doveadm-mail.c \ doveadm-mail-altmove.c \ + doveadm-mail-expunge.c \ doveadm-mail-fetch.c \ doveadm-mail-iter.c \ doveadm-mail-list.c \ diff --git a/src/doveadm/doveadm-mail-expunge.c b/src/doveadm/doveadm-mail-expunge.c new file mode 100644 index 0000000000..0fb14cffa0 --- /dev/null +++ b/src/doveadm/doveadm-mail-expunge.c @@ -0,0 +1,191 @@ +/* Copyright (c) 2010 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "array.h" +#include "mail-index.h" +#include "mail-storage.h" +#include "mail-search.h" +#include "doveadm-mail-list-iter.h" +#include "doveadm-mail-iter.h" +#include "doveadm-mail.h" + +static int +cmd_expunge_box(const struct mailbox_info *info, + struct mail_search_args *search_args) +{ + struct doveadm_mail_iter *iter; + struct mailbox_transaction_context *trans; + struct mail *mail; + + if (doveadm_mail_iter_init(info, search_args, &trans, &iter) < 0) + return -1; + + mail = mail_alloc(trans, 0, NULL); + while (doveadm_mail_iter_next(iter, mail)) { + if (doveadm_debug) { + i_debug("expunge: box=%s uid=%u", + info->name, mail->uid); + } + mail_expunge(mail); + } + mail_free(&mail); + return doveadm_mail_iter_deinit(&iter); +} + +static bool +expunge_search_args_is_mailbox_ok(struct mail_search_arg *args); + +static bool +expunge_search_args_is_mailbox_or_ok(struct mail_search_arg *args) +{ + struct mail_search_arg *arg; + + for (arg = args; arg != NULL; arg = arg->next) { + switch (arg->type) { + case SEARCH_OR: + if (!expunge_search_args_is_mailbox_or_ok(arg->value.subargs)) + return FALSE; + break; + case SEARCH_SUB: + case SEARCH_INTHREAD: + if (!expunge_search_args_is_mailbox_ok(arg->value.subargs)) + return FALSE; + break; + case SEARCH_MAILBOX: + case SEARCH_MAILBOX_GLOB: + break; + default: + return FALSE; + } + } + return TRUE; +} + +static bool +expunge_search_args_is_mailbox_ok(struct mail_search_arg *args) +{ + struct mail_search_arg *arg; + bool have_or = FALSE; + + /* a) we find one mailbox here in the SUB block */ + for (arg = args; arg != NULL; arg = arg->next) { + switch (arg->type) { + case SEARCH_MAILBOX: + case SEARCH_MAILBOX_GLOB: + return TRUE; + case SEARCH_OR: + have_or = TRUE; + break; + case SEARCH_SUB: + case SEARCH_INTHREAD: + if (expunge_search_args_is_mailbox_ok(arg->value.subargs)) + return TRUE; + break; + default: + break; + } + } + + /* b) there is at least one OR block, and all of the ORs must have + mailbox */ + if (!have_or) + return FALSE; + + for (arg = args; arg != NULL; arg = arg->next) { + if (arg->type == SEARCH_OR && + !expunge_search_args_is_mailbox_or_ok(arg->value.subargs)) + return FALSE; + } + return TRUE; +} + +static bool +expunge_search_args_is_msgset_ok(struct mail_search_arg *args); + +static bool +expunge_search_args_is_msgset_or_ok(struct mail_search_arg *args) +{ + struct mail_search_arg *arg; + + /* we're done if all OR branches contain something else besides + MAILBOXes */ + for (arg = args; arg != NULL; arg = arg->next) { + switch (arg->type) { + case SEARCH_MAILBOX: + case SEARCH_MAILBOX_GLOB: + return FALSE; + case SEARCH_OR: + if (!expunge_search_args_is_msgset_or_ok(arg->value.subargs)) + return FALSE; + break; + case SEARCH_SUB: + if (!expunge_search_args_is_msgset_ok(arg->value.subargs)) + return FALSE; + break; + default: + break; + } + } + return TRUE; +} + +static bool +expunge_search_args_is_msgset_ok(struct mail_search_arg *args) +{ + struct mail_search_arg *arg; + + /* all args can't be just MAILBOXes */ + for (arg = args; arg != NULL; arg = arg->next) { + switch (arg->type) { + case SEARCH_MAILBOX: + case SEARCH_MAILBOX_GLOB: + break; + case SEARCH_OR: + /* if each OR branch has something else than just + MAILBOXes, we're ok */ + if (expunge_search_args_is_msgset_or_ok(arg->value.subargs)) + return TRUE; + break; + case SEARCH_SUB: + if (expunge_search_args_is_msgset_ok(arg->value.subargs)) + return TRUE; + break; + default: + return TRUE; + } + } + return FALSE; +} + +void cmd_expunge(struct mail_user *user, const char *const args[]) +{ + const enum mailbox_list_iter_flags iter_flags = + MAILBOX_LIST_ITER_RAW_LIST | + MAILBOX_LIST_ITER_VIRTUAL_NAMES | + MAILBOX_LIST_ITER_NO_AUTO_INBOX | + MAILBOX_LIST_ITER_RETURN_NO_FLAGS; + struct mail_search_args *search_args; + struct doveadm_mail_list_iter *iter; + const struct mailbox_info *info; + + if (args[0] == NULL) + doveadm_mail_help_name("expunge"); + search_args = doveadm_mail_build_search_args(args); + mail_search_args_simplify(search_args); + + if (!expunge_search_args_is_mailbox_ok(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(search_args->args)) { + i_fatal("expunge: To avoid accidents, each branch in " + "search query must contain something else " + "besides MAILBOX"); + } + + iter = doveadm_mail_list_iter_init(user, search_args, iter_flags); + while ((info = doveadm_mail_list_iter_next(iter)) != NULL) T_BEGIN { + (void)cmd_expunge_box(info, search_args); + } T_END; + doveadm_mail_list_iter_deinit(&iter); +} diff --git a/src/doveadm/doveadm-mail.c b/src/doveadm/doveadm-mail.c index ae422781fd..eb3fcae003 100644 --- a/src/doveadm/doveadm-mail.c +++ b/src/doveadm/doveadm-mail.c @@ -329,6 +329,7 @@ void doveadm_mail_help_name(const char *cmd_name) static struct doveadm_mail_cmd mail_commands[] = { { cmd_purge, "purge", NULL }, { cmd_force_resync, "force-resync", "" }, + { cmd_expunge, "expunge", "" }, { cmd_fetch, "fetch", " " }, { cmd_altmove, "altmove", "" }, { cmd_list, "list", "[ [...]]" } diff --git a/src/doveadm/doveadm-mail.h b/src/doveadm/doveadm-mail.h index 2f6eb06f2e..50dcb27336 100644 --- a/src/doveadm/doveadm-mail.h +++ b/src/doveadm/doveadm-mail.h @@ -32,6 +32,7 @@ doveadm_mailbox_find_and_sync(struct mail_user *user, const char *mailbox); struct mail_search_args * doveadm_mail_build_search_args(const char *const args[]); +void cmd_expunge(struct mail_user *user, const char *const args[]); void cmd_fetch(struct mail_user *user, const char *const args[]); void cmd_altmove(struct mail_user *user, const char *const args[]); void cmd_list(struct mail_user *user, const char *const args[]);