doveadm-mail-altmove.c revision c57ba1788a6598993a9625bbf26a4fedca23815e
89a126810703c666309310d0f3189e9834d70b5bTimo Sirainen/* Copyright (c) 2010-2013 Dovecot authors, see the included COPYING file */
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen#include "lib.h"
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen#include "array.h"
5dd05e966ffd69181ab3067f6939b03ced68ebc3Timo Sirainen#include "mail-index.h"
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen#include "mail-storage.h"
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen#include "mail-namespace.h"
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen#include "doveadm-mailbox-list-iter.h"
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen#include "doveadm-mail-iter.h"
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen#include "doveadm-mail.h"
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainenstruct altmove_cmd_context {
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen struct doveadm_mail_cmd_context ctx;
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen bool reverse;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen};
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen
cd466fe7b84b0223735a6469c7f7bc225f65996dTimo Sirainenstatic int
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainencmd_altmove_box(struct doveadm_mail_cmd_context *ctx,
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen const struct mailbox_info *info,
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen struct mail_search_args *search_args, bool reverse)
d56384d5226c8860079d0d0b08b83404e8c42986Timo Sirainen{
0f66f12eb4cdbf47670975044c88d8f388bf92dfTimo Sirainen struct doveadm_mail_iter *iter;
d56384d5226c8860079d0d0b08b83404e8c42986Timo Sirainen struct mail *mail;
d56384d5226c8860079d0d0b08b83404e8c42986Timo Sirainen enum modify_type modify_type =
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen !reverse ? MODIFY_ADD : MODIFY_REMOVE;
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen if (doveadm_mail_iter_init(ctx, info, search_args, 0, NULL,
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen &iter) < 0)
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen return -1;
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen while (doveadm_mail_iter_next(iter, &mail)) {
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen if (doveadm_debug) {
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen i_debug("altmove: box=%s uid=%u",
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen info->vname, mail->uid);
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen }
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen mail_update_flags(mail, modify_type,
6a9f9a5101b665fd2ef80c9e048a5eace78e01efTimo Sirainen (enum mail_flags)MAIL_INDEX_MAIL_FLAG_BACKEND);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen }
0f66f12eb4cdbf47670975044c88d8f388bf92dfTimo Sirainen return doveadm_mail_iter_deinit_sync(&iter);
6a9f9a5101b665fd2ef80c9e048a5eace78e01efTimo Sirainen}
6a9f9a5101b665fd2ef80c9e048a5eace78e01efTimo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenstatic int
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainenns_purge(struct doveadm_mail_cmd_context *ctx, struct mail_namespace *ns)
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen{
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen if (mail_storage_purge(ns->storage) < 0) {
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen i_error("Purging namespace '%s' failed: %s", ns->prefix,
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen mail_storage_get_last_error(ns->storage, NULL));
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen doveadm_mail_failed_storage(ctx, ns->storage);
a3ea111cfdbfd4f32baeb0bd7f1d72568c60a023Timo Sirainen return -1;
a3ea111cfdbfd4f32baeb0bd7f1d72568c60a023Timo Sirainen }
a3ea111cfdbfd4f32baeb0bd7f1d72568c60a023Timo Sirainen return 0;
a3ea111cfdbfd4f32baeb0bd7f1d72568c60a023Timo Sirainen}
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainenstatic int
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainencmd_altmove_run(struct doveadm_mail_cmd_context *_ctx, struct mail_user *user)
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen{
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen struct altmove_cmd_context *ctx = (struct altmove_cmd_context *)_ctx;
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen const enum mailbox_list_iter_flags iter_flags =
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen MAILBOX_LIST_ITER_NO_AUTO_BOXES |
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen MAILBOX_LIST_ITER_RETURN_NO_FLAGS;
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen struct doveadm_mailbox_list_iter *iter;
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen const struct mailbox_info *info;
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen struct mail_namespace *ns, *prev_ns = NULL;
1f57716285d4c5bc9bf2fd5569e3c85fd496afd9Timo Sirainen ARRAY(struct mail_storage *) purged_storages;
1f57716285d4c5bc9bf2fd5569e3c85fd496afd9Timo Sirainen struct mail_storage *const *storages;
1f57716285d4c5bc9bf2fd5569e3c85fd496afd9Timo Sirainen unsigned int i, count;
1f57716285d4c5bc9bf2fd5569e3c85fd496afd9Timo Sirainen int ret = 0;
1f57716285d4c5bc9bf2fd5569e3c85fd496afd9Timo Sirainen
1f57716285d4c5bc9bf2fd5569e3c85fd496afd9Timo Sirainen t_array_init(&purged_storages, 8);
1f57716285d4c5bc9bf2fd5569e3c85fd496afd9Timo Sirainen iter = doveadm_mailbox_list_iter_init(_ctx, user, _ctx->search_args,
1f57716285d4c5bc9bf2fd5569e3c85fd496afd9Timo Sirainen iter_flags);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen while ((info = doveadm_mailbox_list_iter_next(iter)) != NULL) T_BEGIN {
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen if (info->ns != prev_ns) {
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen if (prev_ns != NULL) {
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen if (ns_purge(_ctx, prev_ns) < 0)
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen ret = -1;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen array_append(&purged_storages,
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen &prev_ns->storage, 1);
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen }
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen prev_ns = info->ns;
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen }
a3ea111cfdbfd4f32baeb0bd7f1d72568c60a023Timo Sirainen if (cmd_altmove_box(_ctx, info, _ctx->search_args, ctx->reverse) < 0)
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen ret = -1;
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen } T_END;
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen if (doveadm_mailbox_list_iter_deinit(&iter) < 0)
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen ret = -1;
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen
a29a5b7520f7b8d6cdaf97e66d184b6a9e4f4ecfTimo Sirainen if (prev_ns != NULL) {
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen if (ns_purge(_ctx, prev_ns) < 0)
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen ret = -1;
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen array_append(&purged_storages, &prev_ns->storage, 1);
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen }
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen /* make sure all private storages have been purged */
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen storages = array_get(&purged_storages, &count);
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen for (ns = user->namespaces; ns != NULL; ns = ns->next) {
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen if (ns->type != MAIL_NAMESPACE_TYPE_PRIVATE)
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen continue;
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen for (i = 0; i < count; i++) {
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen if (ns->storage == storages[i])
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen break;
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen }
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen if (i == count) {
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen if (ns_purge(_ctx, ns) < 0)
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen ret = -1;
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen array_append(&purged_storages, &ns->storage, 1);
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen storages = array_get(&purged_storages, &count);
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen }
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen }
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen return ret;
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen}
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainenstatic void cmd_altmove_init(struct doveadm_mail_cmd_context *ctx,
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen const char *const args[])
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen{
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen if (args[0] == NULL)
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen doveadm_mail_help_name("altmove");
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen ctx->search_args = doveadm_mail_build_search_args(args);
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen}
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainenstatic bool
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainencmd_mailbox_altmove_parse_arg(struct doveadm_mail_cmd_context *_ctx, int c)
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen{
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen struct altmove_cmd_context *ctx = (struct altmove_cmd_context *)_ctx;
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen switch (c) {
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen case 'r':
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen ctx->reverse = TRUE;
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen break;
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen default:
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen return FALSE;
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen }
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen return TRUE;
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen}
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainenstatic struct doveadm_mail_cmd_context *cmd_altmove_alloc(void)
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen{
5dd05e966ffd69181ab3067f6939b03ced68ebc3Timo Sirainen struct altmove_cmd_context *ctx;
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen ctx = doveadm_mail_cmd_alloc(struct altmove_cmd_context);
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen ctx->ctx.getopt_args = "r";
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen ctx->ctx.v.parse_arg = cmd_mailbox_altmove_parse_arg;
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen ctx->ctx.v.init = cmd_altmove_init;
9453e8d75cfd8fab2232cf772e9b120f308fb3eeTimo Sirainen ctx->ctx.v.run = cmd_altmove_run;
9453e8d75cfd8fab2232cf772e9b120f308fb3eeTimo Sirainen return &ctx->ctx;
9453e8d75cfd8fab2232cf772e9b120f308fb3eeTimo Sirainen}
9453e8d75cfd8fab2232cf772e9b120f308fb3eeTimo Sirainen
9453e8d75cfd8fab2232cf772e9b120f308fb3eeTimo Sirainenstruct doveadm_mail_cmd cmd_altmove = {
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen cmd_altmove_alloc, "altmove", "[-r] <search query>"
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen};
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen