dovecot-2.2: doveadm: Added metadata set/unset/get/list commands.
dovecot at dovecot.org
dovecot at dovecot.org
Thu Oct 23 03:39:36 UTC 2014
details: http://hg.dovecot.org/dovecot-2.2/rev/4fe5b4e121a4
changeset: 17990:4fe5b4e121a4
user: Timo Sirainen <tss at iki.fi>
date: Thu Oct 23 06:38:20 2014 +0300
description:
doveadm: Added metadata set/unset/get/list commands.
diffstat:
src/doveadm/Makefile.am | 1 +
src/doveadm/doveadm-mail-mailbox-metadata.c | 289 ++++++++++++++++++++++++++++
src/doveadm/doveadm-mail.c | 4 +
src/doveadm/doveadm-mail.h | 4 +
4 files changed, 298 insertions(+), 0 deletions(-)
diffs (truncated from 332 to 300 lines):
diff -r 89cbc0e91a77 -r 4fe5b4e121a4 src/doveadm/Makefile.am
--- a/src/doveadm/Makefile.am Thu Oct 23 06:37:48 2014 +0300
+++ b/src/doveadm/Makefile.am Thu Oct 23 06:38:20 2014 +0300
@@ -71,6 +71,7 @@
doveadm-mail-index.c \
doveadm-mail-iter.c \
doveadm-mail-mailbox.c \
+ doveadm-mail-mailbox-metadata.c \
doveadm-mail-mailbox-status.c \
doveadm-mail-copymove.c \
doveadm-mailbox-list-iter.c \
diff -r 89cbc0e91a77 -r 4fe5b4e121a4 src/doveadm/doveadm-mail-mailbox-metadata.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/doveadm/doveadm-mail-mailbox-metadata.c Thu Oct 23 06:38:20 2014 +0300
@@ -0,0 +1,289 @@
+/* Copyright (c) 2014 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "str.h"
+#include "mail-namespace.h"
+#include "mail-storage.h"
+#include "doveadm-print.h"
+#include "doveadm-mail.h"
+#include "doveadm-mailbox-list-iter.h"
+
+struct metadata_cmd_context {
+ struct doveadm_mail_cmd_context ctx;
+ const char *mailbox;
+ enum mail_attribute_type key_type;
+ const char *key;
+ struct mail_attribute_value value;
+};
+
+static int
+cmd_mailbox_metadata_set_run(struct doveadm_mail_cmd_context *_ctx,
+ struct mail_user *user)
+{
+ struct metadata_cmd_context *ctx = (struct metadata_cmd_context *)_ctx;
+ struct mail_namespace *ns;
+ struct mailbox *box;
+ struct mailbox_transaction_context *trans;
+ int ret;
+
+ ns = mail_namespace_find(user->namespaces, ctx->mailbox);
+ box = mailbox_alloc(ns->list, ctx->mailbox, 0);
+
+ if (mailbox_open(box) < 0) {
+ i_error("Failed to open mailbox: %s",
+ mailbox_get_last_error(box, NULL));
+ mailbox_free(&box);
+ return -1;
+ }
+ trans = mailbox_transaction_begin(box, 0);
+
+ ret = ctx->value.value == NULL ?
+ mailbox_attribute_unset(trans, ctx->key_type, ctx->key) :
+ mailbox_attribute_set(trans, ctx->key_type, ctx->key, &ctx->value);
+ if (ret < 0) {
+ i_error("Failed to set attribute: %s",
+ mailbox_get_last_error(box, NULL));
+ mailbox_transaction_rollback(&trans);
+ } else if (mailbox_transaction_commit(&trans) < 0) {
+ i_error("Failed to commit transaction: %s",
+ mailbox_get_last_error(box, NULL));
+ ret = -1;
+ }
+
+ mailbox_free(&box);
+ return ret;
+}
+
+static void
+cmd_mailbox_metadata_parse_key(const char *arg,
+ enum mail_attribute_type *type_r,
+ const char **key_r)
+{
+ if (strncmp(arg, "/private/", 9) == 0) {
+ *type_r = MAIL_ATTRIBUTE_TYPE_PRIVATE;
+ *key_r = arg + 9;
+ } else if (strncmp(arg, "/shared/", 8) == 0) {
+ *type_r = MAIL_ATTRIBUTE_TYPE_SHARED;
+ *key_r = arg + 8;
+ } else if (strcmp(arg, "/private") == 0) {
+ *type_r = MAIL_ATTRIBUTE_TYPE_PRIVATE;
+ *key_r = "";
+ } else if (strcmp(arg, "/shared") == 0) {
+ *type_r = MAIL_ATTRIBUTE_TYPE_SHARED;
+ *key_r = "";
+ } else {
+ i_fatal_status(EX_USAGE, "Invalid metadata key '%s': "
+ "Must begin with /private or /shared", arg);
+ }
+}
+
+static void
+cmd_mailbox_metadata_set_init(struct doveadm_mail_cmd_context *_ctx,
+ const char *const args[])
+{
+ struct metadata_cmd_context *ctx = (struct metadata_cmd_context *)_ctx;
+ const char *key;
+
+ if (str_array_length(args) != 3)
+ doveadm_mail_help_name("mailbox metadata set");
+ cmd_mailbox_metadata_parse_key(args[1], &ctx->key_type, &key);
+
+ ctx->mailbox = p_strdup(_ctx->pool, args[0]);
+ ctx->key = p_strdup(_ctx->pool, key);
+ ctx->value.value = p_strdup(_ctx->pool, args[2]);
+}
+
+static struct doveadm_mail_cmd_context *cmd_mailbox_metadata_set_alloc(void)
+{
+ struct metadata_cmd_context *ctx;
+
+ ctx = doveadm_mail_cmd_alloc(struct metadata_cmd_context);
+ ctx->ctx.v.init = cmd_mailbox_metadata_set_init;
+ ctx->ctx.v.run = cmd_mailbox_metadata_set_run;
+ return &ctx->ctx;
+}
+
+static void
+cmd_mailbox_metadata_unset_init(struct doveadm_mail_cmd_context *_ctx,
+ const char *const args[])
+{
+ struct metadata_cmd_context *ctx = (struct metadata_cmd_context *)_ctx;
+ const char *key;
+
+ if (str_array_length(args) != 2)
+ doveadm_mail_help_name("mailbox metadata unset");
+ cmd_mailbox_metadata_parse_key(args[1], &ctx->key_type, &key);
+
+ ctx->mailbox = p_strdup(_ctx->pool, args[0]);
+ ctx->key = p_strdup(_ctx->pool, key);
+}
+
+static struct doveadm_mail_cmd_context *cmd_mailbox_metadata_unset_alloc(void)
+{
+ struct metadata_cmd_context *ctx;
+
+ ctx = doveadm_mail_cmd_alloc(struct metadata_cmd_context);
+ ctx->ctx.v.init = cmd_mailbox_metadata_unset_init;
+ ctx->ctx.v.run = cmd_mailbox_metadata_set_run;
+ return &ctx->ctx;
+}
+
+static int
+cmd_mailbox_metadata_get_run(struct doveadm_mail_cmd_context *_ctx,
+ struct mail_user *user)
+{
+ struct metadata_cmd_context *ctx = (struct metadata_cmd_context *)_ctx;
+ struct mail_namespace *ns;
+ struct mailbox *box;
+ struct mailbox_transaction_context *trans;
+ struct mail_attribute_value value;
+ int ret;
+
+ ns = mail_namespace_find(user->namespaces, ctx->mailbox);
+ box = mailbox_alloc(ns->list, ctx->mailbox, 0);
+
+ if (mailbox_open(box) < 0) {
+ i_error("Failed to open mailbox: %s",
+ mailbox_get_last_error(box, NULL));
+ mailbox_free(&box);
+ return -1;
+ }
+ trans = mailbox_transaction_begin(box, 0);
+
+ ret = mailbox_attribute_get_stream(trans, ctx->key_type, ctx->key, &value);
+ if (ret < 0) {
+ i_error("Failed to get attribute: %s",
+ mailbox_get_last_error(box, NULL));
+ } else if (ret == 0) {
+ /* not found, print as empty */
+ doveadm_print("");
+ } else if (value.value_stream != NULL) {
+ doveadm_print_istream(value.value_stream);
+ } else {
+ doveadm_print(value.value);
+ }
+
+ (void)mailbox_transaction_commit(&trans);
+ mailbox_free(&box);
+ return ret;
+}
+
+static void
+cmd_mailbox_metadata_get_init(struct doveadm_mail_cmd_context *_ctx,
+ const char *const args[])
+{
+ struct metadata_cmd_context *ctx = (struct metadata_cmd_context *)_ctx;
+ const char *key;
+
+ if (str_array_length(args) != 2)
+ doveadm_mail_help_name("mailbox metadata get");
+ cmd_mailbox_metadata_parse_key(args[1], &ctx->key_type, &key);
+
+ ctx->mailbox = p_strdup(_ctx->pool, args[0]);
+ ctx->key = p_strdup(_ctx->pool, key);
+ doveadm_print_header("value", "value",
+ DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE);
+}
+
+static struct doveadm_mail_cmd_context *cmd_mailbox_metadata_get_alloc(void)
+{
+ struct metadata_cmd_context *ctx;
+
+ ctx = doveadm_mail_cmd_alloc(struct metadata_cmd_context);
+ ctx->ctx.v.init = cmd_mailbox_metadata_get_init;
+ ctx->ctx.v.run = cmd_mailbox_metadata_get_run;
+ doveadm_print_init(DOVEADM_PRINT_TYPE_FLOW);
+ return &ctx->ctx;
+}
+
+static int
+cmd_mailbox_metadata_list_run_iter(struct metadata_cmd_context *ctx,
+ struct mailbox *box,
+ enum mail_attribute_type type)
+{
+ struct mailbox_attribute_iter *iter;
+ const char *key;
+
+ iter = mailbox_attribute_iter_init(box, type, ctx->key);
+ while ((key = mailbox_attribute_iter_next(iter)) != NULL)
+ doveadm_print(key);
+ return mailbox_attribute_iter_deinit(&iter);
+}
+
+static int
+cmd_mailbox_metadata_list_run(struct doveadm_mail_cmd_context *_ctx,
+ struct mail_user *user)
+{
+ struct metadata_cmd_context *ctx = (struct metadata_cmd_context *)_ctx;
+ struct mail_namespace *ns;
+ struct mailbox *box;
+ int ret = 0;
+
+ ns = mail_namespace_find(user->namespaces, ctx->mailbox);
+ box = mailbox_alloc(ns->list, ctx->mailbox, 0);
+
+ if (mailbox_open(box) < 0) {
+ i_error("Failed to open mailbox: %s",
+ mailbox_get_last_error(box, NULL));
+ mailbox_free(&box);
+ return -1;
+ }
+
+ if (ctx->key == NULL || ctx->key_type == MAIL_ATTRIBUTE_TYPE_PRIVATE) {
+ if (cmd_mailbox_metadata_list_run_iter(ctx, box, MAIL_ATTRIBUTE_TYPE_PRIVATE) < 0)
+ ret = -1;
+ }
+ if (ctx->key == NULL || ctx->key_type == MAIL_ATTRIBUTE_TYPE_SHARED) {
+ if (cmd_mailbox_metadata_list_run_iter(ctx, box, MAIL_ATTRIBUTE_TYPE_SHARED) < 0)
+ ret = -1;
+ }
+ mailbox_free(&box);
+ return ret;
+}
+
+static void
+cmd_mailbox_metadata_list_init(struct doveadm_mail_cmd_context *_ctx,
+ const char *const args[])
+{
+ struct metadata_cmd_context *ctx = (struct metadata_cmd_context *)_ctx;
+ const char *key;
+
+ if (args[0] == NULL)
+ doveadm_mail_help_name("mailbox metadata list");
+ if (args[1] != NULL)
+ cmd_mailbox_metadata_parse_key(args[1], &ctx->key_type, &key);
+ ctx->mailbox = p_strdup(_ctx->pool, args[0]);
+ doveadm_print_header("key", "key",
+ DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE);
+}
+
+static struct doveadm_mail_cmd_context *cmd_mailbox_metadata_list_alloc(void)
+{
+ struct metadata_cmd_context *ctx;
+
+ ctx = doveadm_mail_cmd_alloc(struct metadata_cmd_context);
+ ctx->ctx.v.init = cmd_mailbox_metadata_list_init;
+ ctx->ctx.v.run = cmd_mailbox_metadata_list_run;
+ doveadm_print_init(DOVEADM_PRINT_TYPE_FLOW);
+ return &ctx->ctx;
+}
+
+struct doveadm_mail_cmd cmd_mailbox_metadata_set = {
+ cmd_mailbox_metadata_set_alloc, "mailbox metadata set",
+ "<mailbox> <key> <value>"
+};
+
+struct doveadm_mail_cmd cmd_mailbox_metadata_unset = {
+ cmd_mailbox_metadata_unset_alloc, "mailbox metadata unset",
+ "<mailbox> <key>"
+};
+
+struct doveadm_mail_cmd cmd_mailbox_metadata_get = {
+ cmd_mailbox_metadata_get_alloc, "mailbox metadata get",
+ "<mailbox> <key>"
+};
+
More information about the dovecot-cvs
mailing list