]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
doveadm: Added expunge command.
authorTimo Sirainen <tss@iki.fi>
Wed, 28 Apr 2010 21:19:00 +0000 (00:19 +0300)
committerTimo Sirainen <tss@iki.fi>
Wed, 28 Apr 2010 21:19:00 +0000 (00:19 +0300)
--HG--
branch : HEAD

src/doveadm/Makefile.am
src/doveadm/doveadm-mail-expunge.c [new file with mode: 0644]
src/doveadm/doveadm-mail.c
src/doveadm/doveadm-mail.h

index c6e5bd645036d22274f9f1eac8ab31ea03c0041b..b5e66caf4b406d0553dd9ca4226e7283e165bc3f 100644 (file)
@@ -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 (file)
index 0000000..0fb14cf
--- /dev/null
@@ -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);
+}
index ae422781fd84e73b755ae33bb6ee5516f8e2ab4e..eb3fcae003cbfa57b560eec0d8560dfae582e49b 100644 (file)
@@ -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", "<mailbox>" },
+       { cmd_expunge, "expunge", "<search query>" },
        { cmd_fetch, "fetch", "<fields> <search query>" },
        { cmd_altmove, "altmove", "<search query>" },
        { cmd_list, "list", "[<mailbox> [...]]" }
index 2f6eb06f2e37fdca8d05f92d287d28b87c41db41..50dcb27336be786deb1e87b967dd47086f8fd6e8 100644 (file)
@@ -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[]);