From: Timo Sirainen Date: Wed, 9 Jun 2010 18:42:09 +0000 (+0100) Subject: doveadm: Added mailbox status command. X-Git-Tag: 2.0.beta6~16 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b8b085f7bc6f1c0367802a9f00062bbbd981690d;p=thirdparty%2Fdovecot%2Fcore.git doveadm: Added mailbox status command. --HG-- branch : HEAD --- diff --git a/src/doveadm/Makefile.am b/src/doveadm/Makefile.am index 68cd2e8b99..a8f0f29e7c 100644 --- a/src/doveadm/Makefile.am +++ b/src/doveadm/Makefile.am @@ -60,6 +60,7 @@ doveadm_SOURCES = \ doveadm-mail-fetch.c \ doveadm-mail-iter.c \ doveadm-mail-mailbox.c \ + doveadm-mail-mailbox-status.c \ doveadm-mail-list-iter.c \ doveadm-mail-search.c \ doveadm-penalty.c \ diff --git a/src/doveadm/doveadm-mail-mailbox-status.c b/src/doveadm/doveadm-mail-mailbox-status.c new file mode 100644 index 0000000000..1ea3381885 --- /dev/null +++ b/src/doveadm/doveadm-mail-mailbox-status.c @@ -0,0 +1,195 @@ +/* Copyright (c) 2010 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "str.h" +#include "mail-namespace.h" +#include "mail-storage.h" +#include "doveadm-mail.h" +#include "doveadm-mail-list-iter.h" + +#define TOTAL_STATUS_ITEMS \ + (STATUS_MESSAGES | STATUS_RECENT | STATUS_UNSEEN | STATUS_VIRTUAL_SIZE) + +struct status_cmd_context { + struct doveadm_mail_cmd_context ctx; + struct mail_search_args *search_args; + enum mailbox_status_items items; + struct mailbox_status total_status; + + unsigned int guid:1; + unsigned int total_sum:1; +}; + +static void status_parse_fields(struct status_cmd_context *ctx, + const char *const *fields) +{ + if (*fields == NULL) + i_fatal("No status fields"); + + for (; *fields != NULL; fields++) { + const char *field = *fields; + + if (strcmp(field, "messages") == 0) + ctx->items |= STATUS_MESSAGES; + else if (strcmp(field, "recent") == 0) + ctx->items |= STATUS_RECENT; + else if (strcmp(field, "uidnext") == 0) + ctx->items |= STATUS_UIDNEXT; + else if (strcmp(field, "uidvalidity") == 0) + ctx->items |= STATUS_UIDVALIDITY; + else if (strcmp(field, "unseen") == 0) + ctx->items |= STATUS_UNSEEN; + else if (strcmp(field, "highestmodseq") == 0) + ctx->items |= STATUS_HIGHESTMODSEQ; + else if (strcmp(field, "vsize") == 0) + ctx->items |= STATUS_VIRTUAL_SIZE; + else if (strcmp(field, "guid") == 0) + ctx->guid = TRUE; + else + i_fatal("Unknown status field: %s", field); + + if (ctx->total_sum && + ((ctx->items & ~TOTAL_STATUS_ITEMS) != 0 || ctx->guid)) + i_fatal("Status field %s can't be used with -t", field); + } +} + +static void status_output(struct status_cmd_context *ctx, struct mailbox *box, + const struct mailbox_status *status, + uint8_t mailbox_guid[MAIL_GUID_128_SIZE]) +{ + string_t *str = t_str_new(128); + + if (box != NULL) + str_printfa(str, "%s: ", mailbox_get_vname(box)); + + if ((ctx->items & STATUS_MESSAGES) != 0) + str_printfa(str, "messages=%u ", status->messages); + if ((ctx->items & STATUS_RECENT) != 0) + str_printfa(str, "recent=%u ", status->recent); + if ((ctx->items & STATUS_UIDNEXT) != 0) + str_printfa(str, "uidnext=%u ", status->uidnext); + if ((ctx->items & STATUS_UIDVALIDITY) != 0) + str_printfa(str, "uidvalidity=%u ", status->uidvalidity); + if ((ctx->items & STATUS_UNSEEN) != 0) + str_printfa(str, "unseen=%u ", status->unseen); + if ((ctx->items & STATUS_HIGHESTMODSEQ) != 0) { + str_printfa(str, "highestmodseq=%llu ", + (unsigned long long)status->highest_modseq); + } + if ((ctx->items & STATUS_VIRTUAL_SIZE) != 0) { + str_printfa(str, "vsize=%llu ", + (unsigned long long)status->virtual_size); + } + if (ctx->guid) { + str_printfa(str, "guid=%s ", + mail_guid_128_to_string(mailbox_guid)); + } + + str_truncate(str, str_len(str)-1); + dm_printf(&ctx->ctx, "%s\n", str_c(str)); +} + +static void +status_sum(struct status_cmd_context *ctx, + const struct mailbox_status *status) +{ + struct mailbox_status *dest = &ctx->total_status; + + dest->messages += status->messages; + dest->recent += status->recent; + dest->unseen += status->unseen; + dest->virtual_size += status->virtual_size; +} + +static void +status_mailbox(struct status_cmd_context *ctx, const struct mailbox_info *info) +{ + struct mailbox *box; + struct mailbox_status status; + uint8_t mailbox_guid[MAIL_GUID_128_SIZE]; + + box = doveadm_mailbox_find_and_sync(ctx->ctx.cur_mail_user, info->name); + mailbox_get_status(box, ctx->items, &status); + if (ctx->guid) { + if (mailbox_get_guid(box, mailbox_guid) < 0) + memset(mailbox_guid, 0, sizeof(mailbox_guid)); + } + if (!ctx->total_sum) + status_output(ctx, box, &status, mailbox_guid); + else + status_sum(ctx, &status); + mailbox_free(&box); +} + +static void +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_VIRTUAL_NAMES | + MAILBOX_LIST_ITER_RAW_LIST | + MAILBOX_LIST_ITER_NO_AUTO_INBOX | + MAILBOX_LIST_ITER_RETURN_NO_FLAGS; + struct doveadm_mail_list_iter *iter; + const struct mailbox_info *info; + + memset(&ctx->total_status, 0, sizeof(ctx->total_status)); + + iter = doveadm_mail_list_iter_init(user, ctx->search_args, iter_flags); + while ((info = doveadm_mail_list_iter_next(iter)) != NULL) { + T_BEGIN { + status_mailbox(ctx, info); + } T_END; + } + doveadm_mail_list_iter_deinit(&iter); + + if (ctx->total_sum) + status_output(ctx, NULL, &ctx->total_status, NULL); +} + +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); +} + +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.run = cmd_mailbox_status_run; + return &ctx->ctx; +} + +struct doveadm_mail_cmd cmd_mailbox_status = { + cmd_mailbox_status_alloc, "mailbox status", + "[-t] [...]" +}; diff --git a/src/doveadm/doveadm-mail-mailbox.c b/src/doveadm/doveadm-mail-mailbox.c index 6ea01d670c..3d21921376 100644 --- a/src/doveadm/doveadm-mail-mailbox.c +++ b/src/doveadm/doveadm-mail-mailbox.c @@ -33,8 +33,7 @@ struct list_cmd_context { bool mutf7; }; -static const char *const * -doveadm_mailbox_args_to_mutf7(const char *const args[]) +const char *const *doveadm_mailbox_args_to_mutf7(const char *const args[]) { ARRAY_TYPE(const_string) dest; string_t *str; @@ -131,27 +130,35 @@ cmd_mailbox_list_run(struct doveadm_mail_cmd_context *_ctx, doveadm_mail_list_iter_deinit(&iter); } -static void cmd_mailbox_list_init(struct doveadm_mail_cmd_context *_ctx, - const char *const args[]) +struct mail_search_args * +doveadm_mail_mailbox_search_args_build(const char *const args[]) { - struct list_cmd_context *ctx = (struct list_cmd_context *)_ctx; + struct mail_search_args *search_args; struct mail_search_arg *arg; unsigned int i; args = doveadm_mailbox_args_to_mutf7(args); - ctx->search_args = mail_search_build_init(); + search_args = mail_search_build_init(); for (i = 0; args[i] != NULL; i++) { - arg = mail_search_build_add(ctx->search_args, - SEARCH_MAILBOX_GLOB); - arg->value.str = p_strdup(ctx->search_args->pool, args[i]); + arg = mail_search_build_add(search_args, SEARCH_MAILBOX_GLOB); + arg->value.str = p_strdup(search_args->pool, args[i]); } if (i > 1) { - struct mail_search_arg *subargs = ctx->search_args->args; + struct mail_search_arg *subargs = search_args->args; - ctx->search_args->args = NULL; - arg = mail_search_build_add(ctx->search_args, SEARCH_OR); + search_args->args = NULL; + arg = mail_search_build_add(search_args, SEARCH_OR); arg->value.subargs = subargs; } + return search_args; +} + +static void cmd_mailbox_list_init(struct doveadm_mail_cmd_context *_ctx, + const char *const args[]) +{ + struct list_cmd_context *ctx = (struct list_cmd_context *)_ctx; + + ctx->search_args = doveadm_mail_mailbox_search_args_build(args); } static struct doveadm_mail_cmd_context *cmd_mailbox_list_alloc(void) @@ -479,7 +486,7 @@ static void cmd_mailbox_mutf7(int argc, char *argv[]) struct doveadm_mail_cmd cmd_mailbox_list = { cmd_mailbox_list_alloc, "mailbox list", - "[-7|-8] [-s] [ [...]]" + "[-7|-8] [-s] [ [...]]" }; struct doveadm_mail_cmd cmd_mailbox_create = { cmd_mailbox_create_alloc, "mailbox create", diff --git a/src/doveadm/doveadm-mail.c b/src/doveadm/doveadm-mail.c index c251393194..1adea3dfaf 100644 --- a/src/doveadm/doveadm-mail.c +++ b/src/doveadm/doveadm-mail.c @@ -536,7 +536,8 @@ static struct doveadm_mail_cmd *mail_commands[] = { &cmd_mailbox_delete, &cmd_mailbox_rename, &cmd_mailbox_subscribe, - &cmd_mailbox_unsubscribe + &cmd_mailbox_unsubscribe, + &cmd_mailbox_status }; void doveadm_mail_init(void) diff --git a/src/doveadm/doveadm-mail.h b/src/doveadm/doveadm-mail.h index dd70b44ce9..4c7b2c8da9 100644 --- a/src/doveadm/doveadm-mail.h +++ b/src/doveadm/doveadm-mail.h @@ -74,6 +74,9 @@ struct mailbox * 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[]); +const char *const *doveadm_mailbox_args_to_mutf7(const char *const args[]); +struct mail_search_args * +doveadm_mail_mailbox_search_args_build(const char *const args[]); struct doveadm_mail_cmd_context * doveadm_mail_cmd_alloc_size(size_t size); @@ -95,5 +98,6 @@ struct doveadm_mail_cmd cmd_mailbox_delete; struct doveadm_mail_cmd cmd_mailbox_rename; struct doveadm_mail_cmd cmd_mailbox_subscribe; struct doveadm_mail_cmd cmd_mailbox_unsubscribe; +struct doveadm_mail_cmd cmd_mailbox_status; #endif