Mercurial > dovecot > core-2.2
changeset 16398:4883a8e1db13
dsync: Added -x parameter to exclude mailboxes from sync.
Multiple -x parameters can be added. Giving \flag as parameter means that
the mailbox with the given SPECIAL-USE \flag is skipped. For example:
doveadm sync -x '\All' -x '\Flagged' -x '\Important' mdbox:~/mdbox
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 26 May 2013 21:57:36 +0300 |
parents | 0b02dc66e9f1 |
children | 360fd0ccd3dd |
files | src/doveadm/dsync/doveadm-dsync.c src/doveadm/dsync/dsync-brain-mailbox-tree.c src/doveadm/dsync/dsync-brain-private.h src/doveadm/dsync/dsync-brain.c src/doveadm/dsync/dsync-brain.h src/doveadm/dsync/dsync-ibc-pipe.c src/doveadm/dsync/dsync-ibc-stream.c src/doveadm/dsync/dsync-ibc.h src/doveadm/dsync/dsync-mailbox-tree-fill.c src/doveadm/dsync/dsync-mailbox-tree.h |
diffstat | 10 files changed, 95 insertions(+), 23 deletions(-) [+] |
line wrap: on
line diff
--- a/src/doveadm/dsync/doveadm-dsync.c Sun May 26 21:44:50 2013 +0300 +++ b/src/doveadm/dsync/doveadm-dsync.c Sun May 26 21:57:36 2013 +0300 @@ -36,7 +36,7 @@ #include <ctype.h> #include <sys/wait.h> -#define DSYNC_COMMON_GETOPT_ARGS "+dEfg:l:m:n:Nr:Rs:U" +#define DSYNC_COMMON_GETOPT_ARGS "+dEfg:l:m:n:Nr:Rs:Ux:" #define DSYNC_REMOTE_CMD_EXIT_WAIT_SECS 30 enum dsync_run_type { @@ -51,6 +51,7 @@ const char *mailbox, *namespace_prefix; guid_128_t mailbox_guid; const char *state_input, *rawlog_path; + ARRAY_TYPE(const_string) exclude_mailboxes; const char *remote_name; const char *local_location; @@ -496,6 +497,10 @@ memcpy(set.sync_box_guid, ctx->mailbox_guid, sizeof(set.sync_box_guid)); set.lock_timeout_secs = ctx->lock_timeout; set.state = ctx->state_input; + if (array_count(&ctx->exclude_mailboxes) > 0) { + /* array is NULL-terminated in init() */ + set.exclude_mailboxes = array_idx(&ctx->exclude_mailboxes, 0); + } user->dsyncing = TRUE; @@ -803,6 +808,8 @@ if (args[0] == NULL) doveadm_mail_help_name(_ctx->cmd->name); } + if (array_count(&ctx->exclude_mailboxes) > 0) + array_append_zero(&ctx->exclude_mailboxes); lib_signals_ignore(SIGHUP, TRUE); } @@ -817,6 +824,7 @@ cmd_mailbox_dsync_parse_arg(struct doveadm_mail_cmd_context *_ctx, int c) { struct dsync_cmd_context *ctx = (struct dsync_cmd_context *)_ctx; + const char *str; switch (c) { case 'd': @@ -847,6 +855,10 @@ else ctx->mailbox = optarg; break; + case 'x': + str = optarg; + array_append(&ctx->exclude_mailboxes, &str, 1); + break; case 'n': ctx->namespace_prefix = optarg; break; @@ -891,6 +903,7 @@ doveadm_print_init(DOVEADM_PRINT_TYPE_FLOW); doveadm_print_header("state", "state", DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE); + p_array_init(&ctx->exclude_mailboxes, ctx->ctx.pool, 4); return &ctx->ctx; } @@ -995,11 +1008,11 @@ struct doveadm_mail_cmd cmd_dsync_mirror = { cmd_dsync_alloc, "sync", - "[-dfR] [-l <secs>] [-m <mailbox>] [-n <namespace>] [-s <state>] <dest>" + "[-dfR] [-l <secs>] [-m <mailbox>] [-n <namespace>] [-x <exclude>] [-s <state>] <dest>" }; struct doveadm_mail_cmd cmd_dsync_backup = { cmd_dsync_backup_alloc, "backup", - "[-dfR] [-l <secs>] [-m <mailbox>] [-n <namespace>] [-s <state>] <dest>" + "[-dfR] [-l <secs>] [-m <mailbox>] [-n <namespace>] [-x <exclude>] [-s <state>] <dest>" }; struct doveadm_mail_cmd cmd_dsync_server = { cmd_dsync_server_alloc, "dsync-server", &doveadm_mail_cmd_hide
--- a/src/doveadm/dsync/dsync-brain-mailbox-tree.c Sun May 26 21:44:50 2013 +0300 +++ b/src/doveadm/dsync/dsync-brain-mailbox-tree.c Sun May 26 21:57:36 2013 +0300 @@ -83,20 +83,14 @@ doveadm_settings->dsync_alt_char[0]); /* fill the local mailbox tree */ - if (brain->sync_ns != NULL) { - if (dsync_mailbox_tree_fill(brain->local_mailbox_tree, - brain->sync_ns, brain->sync_box, - brain->sync_box_guid) < 0) + for (ns = brain->user->namespaces; ns != NULL; ns = ns->next) { + if (!dsync_brain_want_namespace(brain, ns)) + continue; + if (dsync_mailbox_tree_fill(brain->local_mailbox_tree, ns, + brain->sync_box, + brain->sync_box_guid, + brain->exclude_mailboxes) < 0) brain->failed = TRUE; - } else { - for (ns = brain->user->namespaces; ns != NULL; ns = ns->next) { - if (!dsync_brain_want_namespace(brain, ns)) - continue; - if (dsync_mailbox_tree_fill(brain->local_mailbox_tree, - ns, brain->sync_box, - brain->sync_box_guid) < 0) - brain->failed = TRUE; - } } brain->local_tree_iter =
--- a/src/doveadm/dsync/dsync-brain-private.h Sun May 26 21:44:50 2013 +0300 +++ b/src/doveadm/dsync/dsync-brain-private.h Sun May 26 21:57:36 2013 +0300 @@ -52,6 +52,7 @@ struct mail_namespace *sync_ns; const char *sync_box; guid_128_t sync_box_guid; + const char *const *exclude_mailboxes; enum dsync_brain_sync_type sync_type; unsigned int lock_timeout;
--- a/src/doveadm/dsync/dsync-brain.c Sun May 26 21:44:50 2013 +0300 +++ b/src/doveadm/dsync/dsync-brain.c Sun May 26 21:57:36 2013 +0300 @@ -103,6 +103,8 @@ if (set->sync_ns != NULL) brain->sync_ns = set->sync_ns; brain->sync_box = p_strdup(brain->pool, set->sync_box); + brain->exclude_mailboxes = set->exclude_mailboxes == NULL ? NULL : + p_strarray_dup(brain->pool, set->exclude_mailboxes); memcpy(brain->sync_box_guid, set->sync_box_guid, sizeof(brain->sync_box_guid)); brain->lock_timeout = set->lock_timeout_secs; @@ -124,6 +126,7 @@ ibc_set.sync_ns_prefix = set->sync_ns == NULL ? NULL : set->sync_ns->prefix; ibc_set.sync_box = set->sync_box; + ibc_set.exclude_mailboxes = set->exclude_mailboxes; memcpy(ibc_set.sync_box_guid, set->sync_box_guid, sizeof(ibc_set.sync_box_guid)); ibc_set.sync_type = sync_type; @@ -312,6 +315,8 @@ ibc_set->sync_ns_prefix); } brain->sync_box = p_strdup(brain->pool, ibc_set->sync_box); + brain->exclude_mailboxes = ibc_set->exclude_mailboxes == NULL ? NULL : + p_strarray_dup(brain->pool, ibc_set->exclude_mailboxes); memcpy(brain->sync_box_guid, ibc_set->sync_box_guid, sizeof(brain->sync_box_guid)); i_assert(brain->sync_type == DSYNC_BRAIN_SYNC_TYPE_UNKNOWN);
--- a/src/doveadm/dsync/dsync-brain.h Sun May 26 21:44:50 2013 +0300 +++ b/src/doveadm/dsync/dsync-brain.h Sun May 26 21:57:36 2013 +0300 @@ -37,6 +37,9 @@ const char *sync_box; /* Sync only this mailbox GUID */ guid_128_t sync_box_guid; + /* Exclude these mailboxes from the sync. They can contain '*' + wildcards and be \special-use flags. */ + const char *const *exclude_mailboxes; /* If non-zero, use dsync lock file for this user */ unsigned int lock_timeout_secs;
--- a/src/doveadm/dsync/dsync-ibc-pipe.c Sun May 26 21:44:50 2013 +0300 +++ b/src/doveadm/dsync/dsync-ibc-pipe.c Sun May 26 21:57:36 2013 +0300 @@ -161,6 +161,8 @@ item->u.set = *set; item->u.set.sync_ns_prefix = p_strdup(item->pool, set->sync_ns_prefix); item->u.set.sync_box = p_strdup(item->pool, set->sync_box); + item->u.set.exclude_mailboxes = set->exclude_mailboxes == NULL ? NULL : + p_strarray_dup(item->pool, set->exclude_mailboxes); memcpy(item->u.set.sync_box_guid, set->sync_box_guid, sizeof(item->u.set.sync_box_guid)); }
--- a/src/doveadm/dsync/dsync-ibc-stream.c Sun May 26 21:44:50 2013 +0300 +++ b/src/doveadm/dsync/dsync-ibc-stream.c Sun May 26 21:57:36 2013 +0300 @@ -73,7 +73,7 @@ .chr = 'H', .required_keys = "hostname", .optional_keys = "sync_ns_prefix sync_box sync_box_guid sync_type " - "debug sync_visible_namespaces " + "debug sync_visible_namespaces exclude_mailboxes" "send_mail_requests backup_send backup_recv lock_timeout" }, { .name = "mailbox_state", @@ -594,6 +594,18 @@ } if (set->sync_box != NULL) dsync_serializer_encode_add(encoder, "sync_box", set->sync_box); + if (set->exclude_mailboxes != NULL) { + string_t *substr = t_str_new(64); + unsigned int i; + + for (i = 0; set->exclude_mailboxes[i] != NULL; i++) { + if (i != 0) + str_append_c(substr, '\t'); + str_append_tabescaped(substr, set->exclude_mailboxes[i]); + } + dsync_serializer_encode_add(encoder, "exclude_mailboxes", + str_c(substr)); + } if (!guid_128_is_empty(set->sync_box_guid)) { dsync_serializer_encode_add(encoder, "sync_box_guid", guid_128_to_string(set->sync_box_guid)); @@ -670,6 +682,11 @@ "Invalid sync_box_guid: %s", value); return DSYNC_IBC_RECV_RET_TRYAGAIN; } + if (dsync_deserializer_decode_try(decoder, "exclude_mailboxes", &value) && + *value != '\0') { + char **boxes = p_strsplit_tabescaped(pool, value); + set->exclude_mailboxes = (const void *)boxes; + } if (dsync_deserializer_decode_try(decoder, "sync_type", &value)) { switch (value[0]) { case 'f':
--- a/src/doveadm/dsync/dsync-ibc.h Sun May 26 21:44:50 2013 +0300 +++ b/src/doveadm/dsync/dsync-ibc.h Sun May 26 21:57:36 2013 +0300 @@ -49,6 +49,9 @@ const char *sync_box; /* if non-empty, sync only this mailbox GUID */ guid_128_t sync_box_guid; + /* Exclude these mailboxes from the sync. They can contain '*' + wildcards and be \special-use flags. */ + const char *const *exclude_mailboxes; enum dsync_brain_sync_type sync_type; enum dsync_brain_flags brain_flags;
--- a/src/doveadm/dsync/dsync-mailbox-tree-fill.c Sun May 26 21:44:50 2013 +0300 +++ b/src/doveadm/dsync/dsync-mailbox-tree-fill.c Sun May 26 21:57:36 2013 +0300 @@ -5,6 +5,7 @@ #include "hash.h" #include "guid.h" #include "str.h" +#include "wildcard-match.h" #include "mailbox-log.h" #include "mail-namespace.h" #include "mail-storage.h" @@ -265,9 +266,39 @@ return ret; } +static bool +dsync_mailbox_info_is_excluded(const struct mailbox_info *info, + const char *const *exclude_mailboxes) +{ + const char *const *info_specialuses; + unsigned int i; + + if (exclude_mailboxes == NULL) + return FALSE; + + info_specialuses = info->special_use == NULL ? NULL : + t_strsplit(info->special_use, " "); + for (i = 0; exclude_mailboxes[i] != NULL; i++) { + const char *exclude = exclude_mailboxes[i]; + + if (exclude[0] == '\\') { + /* special-use */ + if (info_specialuses != NULL && + str_array_icase_find(info_specialuses, exclude)) + return TRUE; + } else { + /* mailbox with wildcards */ + if (wildcard_match(info->vname, exclude)) + return TRUE; + } + } + return FALSE; +} + int dsync_mailbox_tree_fill(struct dsync_mailbox_tree *tree, struct mail_namespace *ns, const char *box_name, - const guid_128_t box_guid) + const guid_128_t box_guid, + const char *const *exclude_mailboxes) { const enum mailbox_list_iter_flags list_flags = /* FIXME: we'll skip symlinks, because we can't handle them @@ -298,10 +329,12 @@ /* first add all of the existing mailboxes */ iter = mailbox_list_iter_init(ns->list, list_pattern, list_flags); - while ((info = mailbox_list_iter_next(iter)) != NULL) { - if (dsync_mailbox_tree_add(tree, info, box_guid) < 0) - ret = -1; - } + while ((info = mailbox_list_iter_next(iter)) != NULL) T_BEGIN { + if (!dsync_mailbox_info_is_excluded(info, exclude_mailboxes)) { + if (dsync_mailbox_tree_add(tree, info, box_guid) < 0) + ret = -1; + } + } T_END; if (mailbox_list_iter_deinit(&iter) < 0) { i_error("Mailbox listing for namespace '%s' failed", ns->prefix); ret = -1;
--- a/src/doveadm/dsync/dsync-mailbox-tree.h Sun May 26 21:44:50 2013 +0300 +++ b/src/doveadm/dsync/dsync-mailbox-tree.h Sun May 26 21:57:36 2013 +0300 @@ -132,7 +132,8 @@ non-NULL, add only that mailbox to the tree. */ int dsync_mailbox_tree_fill(struct dsync_mailbox_tree *tree, struct mail_namespace *ns, const char *box_name, - const guid_128_t box_guid); + const guid_128_t box_guid, + const char *const *exclude_mailboxes); /* Return all known deleted mailboxes and directories. */ const struct dsync_mailbox_delete *