]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
doveadm: Added mailbox status command.
authorTimo Sirainen <tss@iki.fi>
Wed, 9 Jun 2010 18:42:09 +0000 (19:42 +0100)
committerTimo Sirainen <tss@iki.fi>
Wed, 9 Jun 2010 18:42:09 +0000 (19:42 +0100)
--HG--
branch : HEAD

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

index 68cd2e8b99dac643d41ab2ea9299fe10798ab298..a8f0f29e7cb7f9bae35fc3b0f5ab327c80c49408 100644 (file)
@@ -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 (file)
index 0000000..1ea3381
--- /dev/null
@@ -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] <fields> <mailbox mask> [...]"
+};
index 6ea01d670c6723cd76ef9798ad2d7602f3b8220a..3d21921376db9fa991fec578980cee74a31cf274 100644 (file)
@@ -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] [<mailbox> [...]]"
+       "[-7|-8] [-s] [<mailbox mask> [...]]"
 };
 struct doveadm_mail_cmd cmd_mailbox_create = {
        cmd_mailbox_create_alloc, "mailbox create",
index c25139319412ac8638e609145be12e6cf25f0bc1..1adea3dfaff8fc0db3707a33d16ed17bf288412f 100644 (file)
@@ -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)
index dd70b44ce94fa3c2cdb3ec0f798761090882d765..4c7b2c8da999f3ccd223e3ad895661faf0de95b2 100644 (file)
@@ -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