doveadm-mail-index.c revision 6c00502d4ece417ead501db8f0ee3e8287ba4459
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (c) 2010-2011 Dovecot authors, see the included COPYING file */
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch#include "lib.h"
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch#include "str.h"
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch#include "strescape.h"
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch#include "network.h"
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch#include "write-full.h"
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch#include "mail-namespace.h"
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch#include "mail-storage.h"
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch#include "mail-search-build.h"
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch#include "doveadm-settings.h"
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch#include "doveadm-mail.h"
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch
5afe997e79978b7e989aa3b0bfdf4a813ecdc6f6Timo Sirainen#define INDEXER_SOCKET_NAME "indexer"
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch#define INDEXER_HANDSHAKE "VERSION\tindexer\t1\t0\n"
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Boschstruct index_cmd_context {
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch struct doveadm_mail_cmd_context ctx;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch int queue_fd;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch unsigned int queue:1;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch unsigned int have_wildcards:1;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch};
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Boschstatic int
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Boschcmd_index_box(const struct mailbox_info *info)
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch{
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch struct mailbox *box;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch int ret = 0;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen box = mailbox_alloc(info->ns->list, info->name,
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen MAILBOX_FLAG_KEEP_RECENT |
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen MAILBOX_FLAG_IGNORE_ACLS);
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ |
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch MAILBOX_SYNC_FLAG_PRECACHE) < 0) {
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch i_error("Syncing mailbox %s failed: %s", info->name,
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch mail_storage_get_last_error(mailbox_get_storage(box), NULL));
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch ret = -1;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch }
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch
5afe997e79978b7e989aa3b0bfdf4a813ecdc6f6Timo Sirainen mailbox_free(&box);
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch return ret;
5afe997e79978b7e989aa3b0bfdf4a813ecdc6f6Timo Sirainen}
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Boschstatic void cmd_index_queue(struct index_cmd_context *ctx,
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch struct mail_user *user, const char *mailbox)
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch{
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch T_BEGIN {
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch string_t *str = t_str_new(256);
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch str_append(str, "APPEND\t0\t");
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch str_tabescape_write(str, user->username);
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch str_append_c(str, '\t');
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch str_tabescape_write(str, mailbox);
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch str_append_c(str, '\n');
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch if (write_full(ctx->queue_fd, str_data(str), str_len(str)) < 0)
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch i_fatal("write(indexer) failed: %m");
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen } T_END;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen}
9a5980c7bb836f69a63082f4699c30596ea4ee74Timo Sirainen
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainenstatic void
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainencmd_index_run(struct doveadm_mail_cmd_context *_ctx, struct mail_user *user)
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen{
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen struct index_cmd_context *ctx = (struct index_cmd_context *)_ctx;
9a5980c7bb836f69a63082f4699c30596ea4ee74Timo Sirainen const enum mailbox_list_iter_flags iter_flags =
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen MAILBOX_LIST_ITER_RAW_LIST |
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen MAILBOX_LIST_ITER_NO_AUTO_BOXES |
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch MAILBOX_LIST_ITER_RETURN_NO_FLAGS |
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch MAILBOX_LIST_ITER_STAR_WITHIN_NS;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch const enum namespace_type ns_mask =
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch NAMESPACE_PRIVATE | NAMESPACE_SHARED | NAMESPACE_PUBLIC;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch struct mailbox_list_iterate_context *iter;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch const struct mailbox_info *info;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch unsigned int i;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch if (ctx->queue && !ctx->have_wildcards) {
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch /* we can do this quickly without going through the mailboxes */
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch for (i = 0; _ctx->args[i] != NULL; i++)
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch cmd_index_queue(ctx, user, _ctx->args[i]);
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch return;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch }
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch iter = mailbox_list_iter_init_namespaces(user->namespaces, _ctx->args,
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch ns_mask, iter_flags);
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch while ((info = mailbox_list_iter_next(iter)) != NULL) {
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch if ((info->flags & (MAILBOX_NOSELECT |
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch MAILBOX_NONEXISTENT)) == 0) T_BEGIN {
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch if (ctx->queue)
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch cmd_index_queue(ctx, user, info->name);
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch else
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch (void)cmd_index_box(info);
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch } T_END;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch }
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch if (mailbox_list_iter_deinit(&iter) < 0)
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch i_error("Listing mailboxes failed");
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch}
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Boschstatic void cmd_index_init(struct doveadm_mail_cmd_context *_ctx,
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch const char *const args[])
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch{
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch struct index_cmd_context *ctx = (struct index_cmd_context *)_ctx;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch const char *path;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch unsigned int i;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch if (args[0] == NULL)
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch doveadm_mail_help_name("index");
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch for (i = 0; args[i] != NULL; i++) {
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch if (strchr(args[i], '*') != NULL ||
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch strchr(args[i], '%') != NULL) {
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch ctx->have_wildcards = TRUE;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch break;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch }
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch }
5afe997e79978b7e989aa3b0bfdf4a813ecdc6f6Timo Sirainen
5afe997e79978b7e989aa3b0bfdf4a813ecdc6f6Timo Sirainen if (ctx->queue) {
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch path = t_strconcat(doveadm_settings->base_dir,
5afe997e79978b7e989aa3b0bfdf4a813ecdc6f6Timo Sirainen "/"INDEXER_SOCKET_NAME, NULL);
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch ctx->queue_fd = net_connect_unix(path);
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch if (ctx->queue_fd == -1)
d730192e34fbedbc590a5abc7351e5af5e120c5fTimo Sirainen i_fatal("net_connect_unix(%s) failed: %m", path);
d730192e34fbedbc590a5abc7351e5af5e120c5fTimo Sirainen if (write_full(ctx->queue_fd, INDEXER_HANDSHAKE,
d730192e34fbedbc590a5abc7351e5af5e120c5fTimo Sirainen strlen(INDEXER_HANDSHAKE)) < 0)
d730192e34fbedbc590a5abc7351e5af5e120c5fTimo Sirainen i_fatal("write(indexer) failed: %m");
d730192e34fbedbc590a5abc7351e5af5e120c5fTimo Sirainen }
d730192e34fbedbc590a5abc7351e5af5e120c5fTimo Sirainen}
d730192e34fbedbc590a5abc7351e5af5e120c5fTimo Sirainen
d730192e34fbedbc590a5abc7351e5af5e120c5fTimo Sirainenstatic void cmd_index_deinit(struct doveadm_mail_cmd_context *_ctx)
d730192e34fbedbc590a5abc7351e5af5e120c5fTimo Sirainen{
d730192e34fbedbc590a5abc7351e5af5e120c5fTimo Sirainen struct index_cmd_context *ctx = (struct index_cmd_context *)_ctx;
d730192e34fbedbc590a5abc7351e5af5e120c5fTimo Sirainen
d730192e34fbedbc590a5abc7351e5af5e120c5fTimo Sirainen if (ctx->queue_fd != -1) {
d730192e34fbedbc590a5abc7351e5af5e120c5fTimo Sirainen net_disconnect(ctx->queue_fd);
d730192e34fbedbc590a5abc7351e5af5e120c5fTimo Sirainen ctx->queue_fd = -1;
d730192e34fbedbc590a5abc7351e5af5e120c5fTimo Sirainen }
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch}
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Boschstatic bool
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Boschcmd_index_parse_arg(struct doveadm_mail_cmd_context *_ctx, int c)
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch{
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch struct index_cmd_context *ctx = (struct index_cmd_context *)_ctx;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch switch (c) {
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch case 'q':
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch ctx->queue = TRUE;
4afd5082f38342fd688acb5796912329f57dd02cTimo Sirainen break;
4afd5082f38342fd688acb5796912329f57dd02cTimo Sirainen default:
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch return FALSE;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch }
5afe997e79978b7e989aa3b0bfdf4a813ecdc6f6Timo Sirainen return TRUE;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch}
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Boschstatic struct doveadm_mail_cmd_context *cmd_index_alloc(void)
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch{
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch struct index_cmd_context *ctx;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch ctx = doveadm_mail_cmd_alloc(struct index_cmd_context);
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch ctx->queue_fd = -1;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch ctx->ctx.getopt_args = "q";
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch ctx->ctx.v.parse_arg = cmd_index_parse_arg;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch ctx->ctx.v.init = cmd_index_init;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch ctx->ctx.v.deinit = cmd_index_deinit;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch ctx->ctx.v.run = cmd_index_run;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch return &ctx->ctx;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch}
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Boschstruct doveadm_mail_cmd cmd_index = {
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch cmd_index_alloc, "index", "[-q] <mailbox>"
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch};
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch