doveadm-mail-mailbox-status.c revision 57434d8add2f13b6d6dbd39b941e9e80c64be74e
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2010-2013 Dovecot authors, see the included COPYING file */
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody#include "lib.h"
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody#include "str.h"
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody#include "mail-namespace.h"
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody#include "mail-storage.h"
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody#include "mail-search.h"
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody#include "doveadm-print.h"
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody#include "doveadm-mail.h"
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody#include "doveadm-mailbox-list-iter.h"
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody#define ALL_STATUS_ITEMS \
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody (STATUS_MESSAGES | STATUS_RECENT | \
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody STATUS_UIDNEXT | STATUS_UIDVALIDITY | \
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody STATUS_UNSEEN | STATUS_HIGHESTMODSEQ)
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody#define ALL_METADATA_ITEMS \
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody (MAILBOX_METADATA_VIRTUAL_SIZE | MAILBOX_METADATA_GUID)
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody#define TOTAL_STATUS_ITEMS \
c398eca6b0fc6583687bd6fe2ee2dbcca2ae9387Timo Sirainen (STATUS_MESSAGES | STATUS_RECENT | STATUS_UNSEEN)
c398eca6b0fc6583687bd6fe2ee2dbcca2ae9387Timo Sirainen#define TOTAL_METADATA_ITEMS \
c398eca6b0fc6583687bd6fe2ee2dbcca2ae9387Timo Sirainen (MAILBOX_METADATA_VIRTUAL_SIZE)
c398eca6b0fc6583687bd6fe2ee2dbcca2ae9387Timo Sirainen
c398eca6b0fc6583687bd6fe2ee2dbcca2ae9387Timo Sirainenstruct status_cmd_context {
c398eca6b0fc6583687bd6fe2ee2dbcca2ae9387Timo Sirainen struct doveadm_mail_cmd_context ctx;
c398eca6b0fc6583687bd6fe2ee2dbcca2ae9387Timo Sirainen struct mail_search_args *search_args;
c398eca6b0fc6583687bd6fe2ee2dbcca2ae9387Timo Sirainen
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody enum mailbox_status_items status_items;
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody enum mailbox_metadata_items metadata_items;
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody struct mailbox_status total_status;
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody struct mailbox_metadata total_metadata;
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody unsigned int total_sum:1;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen};
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmodystatic void status_parse_fields(struct status_cmd_context *ctx,
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody const char *const *fields)
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody{
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody if (*fields == NULL)
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody i_fatal_status(EX_USAGE, "No status fields");
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody for (; *fields != NULL; fields++) {
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody const char *field = *fields;
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody if (strcmp(field, "all") == 0) {
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody if (ctx->total_sum) {
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody ctx->status_items |= TOTAL_STATUS_ITEMS;
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody ctx->metadata_items |= TOTAL_METADATA_ITEMS;
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody } else {
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody ctx->status_items |= ALL_STATUS_ITEMS;
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody ctx->metadata_items |= ALL_METADATA_ITEMS;
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody }
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody } else if (strcmp(field, "messages") == 0)
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody ctx->status_items |= STATUS_MESSAGES;
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody else if (strcmp(field, "recent") == 0)
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody ctx->status_items |= STATUS_RECENT;
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody else if (strcmp(field, "uidnext") == 0)
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody ctx->status_items |= STATUS_UIDNEXT;
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody else if (strcmp(field, "uidvalidity") == 0)
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody ctx->status_items |= STATUS_UIDVALIDITY;
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody else if (strcmp(field, "unseen") == 0)
98c59517ebce19556221065e9231f007bbdd0038Timo Sirainen ctx->status_items |= STATUS_UNSEEN;
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody else if (strcmp(field, "highestmodseq") == 0)
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody ctx->status_items |= STATUS_HIGHESTMODSEQ;
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody else if (strcmp(field, "vsize") == 0)
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen ctx->metadata_items |= MAILBOX_METADATA_VIRTUAL_SIZE;
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody else if (strcmp(field, "guid") == 0)
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody ctx->metadata_items |= MAILBOX_METADATA_GUID;
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody else {
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody i_fatal_status(EX_USAGE,
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody "Unknown status field: %s", field);
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody }
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody if (ctx->total_sum &&
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody ((ctx->status_items & ~TOTAL_STATUS_ITEMS) != 0 ||
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody (ctx->metadata_items & ~TOTAL_METADATA_ITEMS) != 0)) {
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody i_fatal_status(EX_USAGE,
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody "Status field %s can't be used with -t", field);
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody }
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody }
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody}
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmodystatic void ATTR_NULL(2)
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmodystatus_output(struct status_cmd_context *ctx, struct mailbox *box,
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody const struct mailbox_status *status,
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody const struct mailbox_metadata *metadata)
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody{
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody if (box != NULL)
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody doveadm_print(mailbox_get_vname(box));
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody if ((ctx->status_items & STATUS_MESSAGES) != 0)
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody doveadm_print_num(status->messages);
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody if ((ctx->status_items & STATUS_RECENT) != 0)
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody doveadm_print_num(status->recent);
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody if ((ctx->status_items & STATUS_UIDNEXT) != 0)
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody doveadm_print_num(status->uidnext);
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody if ((ctx->status_items & STATUS_UIDVALIDITY) != 0)
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody doveadm_print_num(status->uidvalidity);
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody if ((ctx->status_items & STATUS_UNSEEN) != 0)
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody doveadm_print_num(status->unseen);
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody if ((ctx->status_items & STATUS_HIGHESTMODSEQ) != 0)
8bec19723b39071a1794e76dec35d151473cae5fPhil Carmody doveadm_print_num(status->highest_modseq);
8bec19723b39071a1794e76dec35d151473cae5fPhil Carmody if ((ctx->metadata_items & MAILBOX_METADATA_VIRTUAL_SIZE) != 0)
8bec19723b39071a1794e76dec35d151473cae5fPhil Carmody doveadm_print_num(metadata->virtual_size);
957d34edbe3599fbb4e7c0bcf3785bd7fd4862c4Timo Sirainen if ((ctx->metadata_items & MAILBOX_METADATA_GUID) != 0)
8bec19723b39071a1794e76dec35d151473cae5fPhil Carmody doveadm_print(guid_128_to_string(metadata->guid));
8bec19723b39071a1794e76dec35d151473cae5fPhil Carmody}
8bec19723b39071a1794e76dec35d151473cae5fPhil Carmody
4baf980b75800ad3595c39dc3b8d913f2686affdTimo Sirainenstatic void
8bec19723b39071a1794e76dec35d151473cae5fPhil Carmodystatus_sum(struct status_cmd_context *ctx,
8bec19723b39071a1794e76dec35d151473cae5fPhil Carmody const struct mailbox_status *status,
8bec19723b39071a1794e76dec35d151473cae5fPhil Carmody const struct mailbox_metadata *metadata)
c398eca6b0fc6583687bd6fe2ee2dbcca2ae9387Timo Sirainen{
c398eca6b0fc6583687bd6fe2ee2dbcca2ae9387Timo Sirainen struct mailbox_status *dest = &ctx->total_status;
c398eca6b0fc6583687bd6fe2ee2dbcca2ae9387Timo Sirainen
c398eca6b0fc6583687bd6fe2ee2dbcca2ae9387Timo Sirainen dest->messages += status->messages;
c398eca6b0fc6583687bd6fe2ee2dbcca2ae9387Timo Sirainen dest->recent += status->recent;
c398eca6b0fc6583687bd6fe2ee2dbcca2ae9387Timo Sirainen dest->unseen += status->unseen;
c398eca6b0fc6583687bd6fe2ee2dbcca2ae9387Timo Sirainen ctx->total_metadata.virtual_size += metadata->virtual_size;
c398eca6b0fc6583687bd6fe2ee2dbcca2ae9387Timo Sirainen}
c398eca6b0fc6583687bd6fe2ee2dbcca2ae9387Timo Sirainen
c398eca6b0fc6583687bd6fe2ee2dbcca2ae9387Timo Sirainenstatic int
8bec19723b39071a1794e76dec35d151473cae5fPhil Carmodystatus_mailbox(struct status_cmd_context *ctx, const struct mailbox_info *info)
8bec19723b39071a1794e76dec35d151473cae5fPhil Carmody{
957d34edbe3599fbb4e7c0bcf3785bd7fd4862c4Timo Sirainen struct mailbox *box;
8bec19723b39071a1794e76dec35d151473cae5fPhil Carmody struct mailbox_status status;
8bec19723b39071a1794e76dec35d151473cae5fPhil Carmody struct mailbox_metadata metadata;
8bec19723b39071a1794e76dec35d151473cae5fPhil Carmody
8bec19723b39071a1794e76dec35d151473cae5fPhil Carmody box = doveadm_mailbox_find(ctx->ctx.cur_mail_user, info->vname);
8bec19723b39071a1794e76dec35d151473cae5fPhil Carmody if (mailbox_get_status(box, ctx->status_items, &status) < 0 ||
8bec19723b39071a1794e76dec35d151473cae5fPhil Carmody mailbox_get_metadata(box, ctx->metadata_items, &metadata) < 0) {
8bec19723b39071a1794e76dec35d151473cae5fPhil Carmody doveadm_mail_failed_mailbox(&ctx->ctx, box);
8bec19723b39071a1794e76dec35d151473cae5fPhil Carmody mailbox_free(&box);
8bec19723b39071a1794e76dec35d151473cae5fPhil Carmody return -1;
8bec19723b39071a1794e76dec35d151473cae5fPhil Carmody }
1d940afbc02516d8c3d016780e1223a779844a1ePhil Carmody if (!ctx->total_sum)
status_output(ctx, box, &status, &metadata);
else
status_sum(ctx, &status, &metadata);
mailbox_free(&box);
return 0;
}
static int
cmd_mailbox_status_run(struct doveadm_mail_cmd_context *_ctx,
struct mail_user *user)
{
struct status_cmd_context *ctx = (struct status_cmd_context *)_ctx;
enum mailbox_list_iter_flags iter_flags =
MAILBOX_LIST_ITER_NO_AUTO_BOXES |
MAILBOX_LIST_ITER_RETURN_NO_FLAGS;
struct doveadm_mailbox_list_iter *iter;
const struct mailbox_info *info;
int ret = 0;
memset(&ctx->total_status, 0, sizeof(ctx->total_status));
memset(&ctx->total_metadata, 0, sizeof(ctx->total_metadata));
iter = doveadm_mailbox_list_iter_init(_ctx, user, ctx->search_args,
iter_flags);
while ((info = doveadm_mailbox_list_iter_next(iter)) != NULL) {
T_BEGIN {
if (status_mailbox(ctx, info) < 0)
ret = -1;
} T_END;
}
if (doveadm_mailbox_list_iter_deinit(&iter) < 0)
ret = -1;
if (ctx->total_sum) {
status_output(ctx, NULL, &ctx->total_status,
&ctx->total_metadata);
}
return ret;
}
static void cmd_mailbox_status_init(struct doveadm_mail_cmd_context *_ctx,
const char *const args[])
{
struct status_cmd_context *ctx = (struct status_cmd_context *)_ctx;
const char *fields = args[0];
if (fields == NULL || args[1] == NULL)
doveadm_mail_help_name("mailbox status");
status_parse_fields(ctx, t_strsplit_spaces(fields, " "));
ctx->search_args = doveadm_mail_mailbox_search_args_build(args+1);
if (!ctx->total_sum) {
doveadm_print_header("mailbox", "mailbox",
DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE);
}
if ((ctx->status_items & STATUS_MESSAGES) != 0)
doveadm_print_header_simple("messages");
if ((ctx->status_items & STATUS_RECENT) != 0)
doveadm_print_header_simple("recent");
if ((ctx->status_items & STATUS_UIDNEXT) != 0)
doveadm_print_header_simple("uidnext");
if ((ctx->status_items & STATUS_UIDVALIDITY) != 0)
doveadm_print_header_simple("uidvalidity");
if ((ctx->status_items & STATUS_UNSEEN) != 0)
doveadm_print_header_simple("unseen");
if ((ctx->status_items & STATUS_HIGHESTMODSEQ) != 0)
doveadm_print_header_simple("highestmodseq");
if ((ctx->metadata_items & MAILBOX_METADATA_VIRTUAL_SIZE) != 0)
doveadm_print_header_simple("vsize");
if ((ctx->metadata_items & MAILBOX_METADATA_GUID) != 0)
doveadm_print_header_simple("guid");
}
static void cmd_mailbox_status_deinit(struct doveadm_mail_cmd_context *_ctx)
{
struct status_cmd_context *ctx = (struct status_cmd_context *)_ctx;
mail_search_args_unref(&ctx->search_args);
}
static bool
cmd_mailbox_status_parse_arg(struct doveadm_mail_cmd_context *_ctx, int c)
{
struct status_cmd_context *ctx = (struct status_cmd_context *)_ctx;
switch (c) {
case 't':
ctx->total_sum = TRUE;
break;
default:
return FALSE;
}
return TRUE;
}
static struct doveadm_mail_cmd_context *cmd_mailbox_status_alloc(void)
{
struct status_cmd_context *ctx;
ctx = doveadm_mail_cmd_alloc(struct status_cmd_context);
ctx->ctx.getopt_args = "t";
ctx->ctx.v.parse_arg = cmd_mailbox_status_parse_arg;
ctx->ctx.v.init = cmd_mailbox_status_init;
ctx->ctx.v.deinit = cmd_mailbox_status_deinit;
ctx->ctx.v.run = cmd_mailbox_status_run;
doveadm_print_init(DOVEADM_PRINT_TYPE_FLOW);
return &ctx->ctx;
}
struct doveadm_mail_cmd cmd_mailbox_status = {
cmd_mailbox_status_alloc, "mailbox status",
"[-t] <fields> <mailbox mask> [...]"
};