# --- SDE-COPYRIGHT-NOTE-BEGIN --- # This copyright note is auto-generated by ./scripts/Create-CopyPatch. # # Filename: package/.../dovecot/dovecot-2.2.3-0000-upstream-fixes.patch # Copyright (C) 2013 The OpenSDE Project # # More information can be found in the files COPYING and README. # # This patch file is dual-licensed. It is available under the license the # patched project is licensed under, as long as it is an OpenSource license # as defined at http://www.opensource.org/ (e.g. BSD, X11) or under the terms # of the GNU General Public License as published by the Free Software # Foundation; either version 2 of the License, or (at your option) any later # version. # --- SDE-COPYRIGHT-NOTE-END --- From 14f13e05bf6599e138f86f465554e063e6a5a560 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Mon, 17 Jun 2013 00:03:16 +0300 Subject: [PATCH] Make static analyzer happier. diff --git a/src/doveadm/dsync/doveadm-dsync.c b/src/doveadm/dsync/doveadm-dsync.c index b8196e0..605438b 100644 --- a/src/doveadm/dsync/doveadm-dsync.c +++ b/src/doveadm/dsync/doveadm-dsync.c @@ -299,6 +299,9 @@ static bool paths_are_equal(struct mail_user *user1, struct mail_user *user2, { const char *path1, *path2; + i_assert(user1->namespaces != NULL); + i_assert(user2->namespaces != NULL); + return mailbox_list_get_root_path(user1->namespaces->list, type, &path1) && mailbox_list_get_root_path(user2->namespaces->list, type, &path2) && strcmp(path1, path2) == 0; diff --git a/src/doveadm/dsync/test-dsync-mailbox-tree-sync.c b/src/doveadm/dsync/test-dsync-mailbox-tree-sync.c index 3d8b909..e0fc7bf 100644 --- a/src/doveadm/dsync/test-dsync-mailbox-tree-sync.c +++ b/src/doveadm/dsync/test-dsync-mailbox-tree-sync.c @@ -624,7 +624,8 @@ static void test_dsync_mailbox_tree_sync_renames20(void) node_create(tree2, 3, "1/0/2", 0); test_trees_nofree(tree1, &tree2); - test_assert(tree1->root.first_child->next == NULL); + test_assert(tree1->root.first_child != NULL && + tree1->root.first_child->next == NULL); dsync_mailbox_tree_deinit(&tree1); test_end(); } diff --git a/src/imap-login/imap-proxy.c b/src/imap-login/imap-proxy.c index e283d48..e7faebc 100644 --- a/src/imap-login/imap-proxy.c +++ b/src/imap-login/imap-proxy.c @@ -234,6 +234,7 @@ int imap_proxy_parse_line(struct client *client, const char *line) client_proxy_failed(client, TRUE); return -1; } + i_assert(ret == 0); str_truncate(str, 0); base64_encode(data, data_len, str); diff --git a/src/pop3-login/pop3-proxy.c b/src/pop3-login/pop3-proxy.c index dd5c7dc..b2daa47 100644 --- a/src/pop3-login/pop3-proxy.c +++ b/src/pop3-login/pop3-proxy.c @@ -110,6 +110,7 @@ pop3_proxy_continue_sasl_auth(struct client *client, struct ostream *output, error)); return -1; } + i_assert(ret == 0); str_truncate(str, 0); base64_encode(data, data_len, str); -- 1.7.10.2 From c5f34506908996ec4bdbbdd090c440270553e8a1 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Mon, 17 Jun 2013 14:39:59 +0300 Subject: [PATCH] dsync: Minor fixes to checking if namespace is wanted to be synced. diff --git a/src/doveadm/dsync/dsync-brain-mailbox-tree.c b/src/doveadm/dsync/dsync-brain-mailbox-tree.c index fc9b79e..a3fb159 100644 --- a/src/doveadm/dsync/dsync-brain-mailbox-tree.c +++ b/src/doveadm/dsync/dsync-brain-mailbox-tree.c @@ -14,8 +14,8 @@ static bool dsync_brain_want_namespace(struct dsync_brain *brain, struct mail_namespace *ns) { - if (brain->sync_ns == ns) - return TRUE; + if (brain->sync_ns != NULL) + return brain->sync_ns == ns; if (ns->alias_for != NULL) { /* always skip aliases */ return FALSE; @@ -26,11 +26,11 @@ static bool dsync_brain_want_namespace(struct dsync_brain *brain, if ((ns->flags & (NAMESPACE_FLAG_LIST_PREFIX | NAMESPACE_FLAG_LIST_CHILDREN)) != 0) return TRUE; + return FALSE; + } else { + return strcmp(ns->unexpanded_set->location, + SETTING_STRVAR_UNEXPANDED) == 0; } - - return brain->sync_ns == NULL && - strcmp(ns->unexpanded_set->location, - SETTING_STRVAR_UNEXPANDED) == 0; } static void dsync_brain_check_namespaces(struct dsync_brain *brain) -- 1.7.10.2 From ca2ce521c15888f678bafd48adafb895f594f9e8 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Mon, 17 Jun 2013 16:37:46 +0300 Subject: [PATCH] pop3: Fixed crash at deinit diff --git a/src/pop3/pop3-client.c b/src/pop3/pop3-client.c index 6de571c..688ccab 100644 --- a/src/pop3/pop3-client.c +++ b/src/pop3/pop3-client.c @@ -593,7 +593,8 @@ static void client_default_destroy(struct client *client, const char *reason) message sizes. */ (void)mailbox_transaction_commit(&client->trans); } - array_free(&client->all_seqs); + if (array_is_created(&client->all_seqs)) + array_free(&client->all_seqs); if (client->deleted_kw != NULL) mailbox_keywords_unref(&client->deleted_kw); if (client->mailbox != NULL) -- 1.7.10.2 From c1e0a95f98da1099d38caeca9a77413a0b7704a2 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Tue, 18 Jun 2013 11:59:21 +0300 Subject: [PATCH] imap/pop3 proxy: Master user logins were broken by lib-sasl change. diff --git a/src/imap-login/imap-proxy.c b/src/imap-login/imap-proxy.c index e7faebc..ba254de 100644 --- a/src/imap-login/imap-proxy.c +++ b/src/imap-login/imap-proxy.c @@ -79,8 +79,9 @@ static int proxy_write_login(struct imap_client *client, string_t *str) i_assert(client->common.proxy_sasl_client == NULL); memset(&sasl_set, 0, sizeof(sasl_set)); - sasl_set.authid = client->common.proxy_user; - sasl_set.authzid = client->common.proxy_master_user; + sasl_set.authid = client->common.proxy_master_user != NULL ? + client->common.proxy_master_user : client->common.proxy_user; + sasl_set.authzid = client->common.proxy_user; sasl_set.password = client->common.proxy_password; client->common.proxy_sasl_client = sasl_client_new(client->common.proxy_mech, &sasl_set); diff --git a/src/pop3-login/pop3-proxy.c b/src/pop3-login/pop3-proxy.c index b2daa47..beb8f2e 100644 --- a/src/pop3-login/pop3-proxy.c +++ b/src/pop3-login/pop3-proxy.c @@ -55,8 +55,9 @@ static int proxy_send_login(struct pop3_client *client, struct ostream *output) i_assert(client->common.proxy_sasl_client == NULL); memset(&sasl_set, 0, sizeof(sasl_set)); - sasl_set.authid = client->common.proxy_user; - sasl_set.authzid = client->common.proxy_master_user; + sasl_set.authid = client->common.proxy_master_user != NULL ? + client->common.proxy_master_user : client->common.proxy_user; + sasl_set.authzid = client->common.proxy_user; sasl_set.password = client->common.proxy_password; client->common.proxy_sasl_client = sasl_client_new(client->common.proxy_mech, &sasl_set); -- 1.7.10.2 From ea9231b00f7f0ae0bdbca0b7f7d9443ee5387539 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Tue, 18 Jun 2013 12:15:50 +0300 Subject: [PATCH] lib-sasl: API usage comment update diff --git a/src/lib-sasl/sasl-client.h b/src/lib-sasl/sasl-client.h index dc969ef..53f04e4 100644 --- a/src/lib-sasl/sasl-client.h +++ b/src/lib-sasl/sasl-client.h @@ -4,7 +4,8 @@ struct sasl_client_settings { /* authentication ID - must be set with most mechanisms */ const char *authid; - /* authorization ID ("master user") */ + /* authorization ID (who to log in as, if authentication ID is a + master user) */ const char *authzid; /* password - must be set with most mechanisms */ const char *password; -- 1.7.10.2 From 9683a96c657a9f3b4b42e475eec42ab60aa81f15 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Tue, 18 Jun 2013 12:56:27 +0300 Subject: [PATCH] lib-index: If error is found from transaction log, update dovecot.index so it won't be read again. diff --git a/src/lib-index/mail-index-sync.c b/src/lib-index/mail-index-sync.c index 65ef817..bc17e77 100644 --- a/src/lib-index/mail-index-sync.c +++ b/src/lib-index/mail-index-sync.c @@ -895,6 +895,9 @@ void mail_index_sync_set_corrupted(struct mail_index_sync_map_ctx *ctx, uoff_t offset; ctx->errors = TRUE; + /* make sure we don't get to this same error again by updating the + dovecot.index */ + ctx->view->index->need_recreate = TRUE; mail_transaction_log_view_get_prev_pos(ctx->view->log_view, &seq, &offset); -- 1.7.10.2 From f464fa4fe9f876e76aad1bc5efdf23068746cfe4 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Tue, 18 Jun 2013 12:59:17 +0300 Subject: [PATCH] lib-index: Don't bother tracking if header/records were changed. They aren't really needed. When mail_index_write() is called, we already know we want to update the index. diff --git a/src/lib-index/mail-index-fsck.c b/src/lib-index/mail-index-fsck.c index 91c62cf..923a098 100644 --- a/src/lib-index/mail-index-fsck.c +++ b/src/lib-index/mail-index-fsck.c @@ -454,7 +454,6 @@ int mail_index_fsck(struct mail_index *index) mail_index_fsck_map(index, map); } T_END; - map->header_changed = TRUE; mail_index_write(index, FALSE); if (!orig_locked) diff --git a/src/lib-index/mail-index-map.c b/src/lib-index/mail-index-map.c index a735c3c..c489e51 100644 --- a/src/lib-index/mail-index-map.c +++ b/src/lib-index/mail-index-map.c @@ -332,8 +332,6 @@ static void mail_index_map_copy_records(struct mail_index_record_map *dest, dest->records = buffer_get_modifiable_data(dest->buffer, NULL); dest->records_count = src->records_count; - - dest->records_changed = src->records_changed; } static void mail_index_map_copy_header(struct mail_index_map *dest, @@ -396,8 +394,6 @@ struct mail_index_map *mail_index_map_clone(const struct mail_index_map *map) mail_index_map_copy_header(mem_map, map); - mem_map->header_changed = map->header_changed; - /* copy extensions */ if (array_is_created(&map->ext_id_map)) { count = array_count(&map->ext_id_map); diff --git a/src/lib-index/mail-index-modseq.c b/src/lib-index/mail-index-modseq.c index 75aecf3..8fe42a8 100644 --- a/src/lib-index/mail-index-modseq.c +++ b/src/lib-index/mail-index-modseq.c @@ -470,7 +470,6 @@ static void mail_index_modseq_sync_init(struct mail_index_modseq_sync *ctx) } T_END; } } - map->rec_map->records_changed = TRUE; mail_transaction_log_view_close(&ctx->log_view); } @@ -521,7 +520,6 @@ static void mail_index_modseq_update_header(struct mail_index_view *view, buffer_write(map->hdr_copy_buf, ext->hdr_offset, &new_modseq_hdr, sizeof(new_modseq_hdr)); map->hdr_base = map->hdr_copy_buf->data; - map->header_changed = TRUE; } } diff --git a/src/lib-index/mail-index-private.h b/src/lib-index/mail-index-private.h index 1473b28..0e3122c 100644 --- a/src/lib-index/mail-index-private.h +++ b/src/lib-index/mail-index-private.h @@ -127,9 +127,6 @@ struct mail_index_record_map { struct mail_index_map_modseq *modseq; uint32_t last_appended_uid; - - /* The records have changed since it was read */ - bool records_changed; }; struct mail_index_map { @@ -147,8 +144,6 @@ struct mail_index_map { ARRAY(unsigned int) keyword_idx_map; /* file -> index */ struct mail_index_record_map *rec_map; - - unsigned int header_changed:1; }; struct mail_index_module_register { diff --git a/src/lib-index/mail-index-sync-ext.c b/src/lib-index/mail-index-sync-ext.c index 68c2a2d..c9423a7 100644 --- a/src/lib-index/mail-index-sync-ext.c +++ b/src/lib-index/mail-index-sync-ext.c @@ -317,7 +317,6 @@ sync_ext_resize(const struct mail_transaction_ext_intro *u, i_assert((map->hdr_copy_buf->used % sizeof(uint64_t)) == 0); map->hdr_base = map->hdr_copy_buf->data; map->hdr.header_size = map->hdr_copy_buf->used; - map->header_changed = TRUE; ext_hdr = get_ext_header(map, ext); ext_hdr->reset_id = ext->reset_id; @@ -577,7 +576,6 @@ static void mail_index_sync_ext_clear(struct mail_index_view *view, memset(PTR_OFFSET(rec, ext->record_offset), 0, ext->record_size); } - map->rec_map->records_changed = TRUE; } int mail_index_sync_ext_reset(struct mail_index_sync_map_ctx *ctx, @@ -630,9 +628,14 @@ int mail_index_sync_ext_hdr_update(struct mail_index_sync_map_ctx *ctx, ext = array_idx(&map->extensions, ctx->cur_ext_map_idx); if (offset + size > ext->hdr_size) { +#if 1 mail_index_sync_set_corrupted(ctx, "Extension header update points outside header size"); return -1; +#else + size = offset > ext->hdr_size ? 0 : + ext->hdr_size - offset; +#endif } buffer_write(map->hdr_copy_buf, ext->hdr_offset + offset, data, size); @@ -640,8 +643,6 @@ int mail_index_sync_ext_hdr_update(struct mail_index_sync_map_ctx *ctx, if (ext->index_idx == ctx->view->index->modseq_ext_id) mail_index_modseq_hdr_update(ctx->modseq_ctx); - - map->header_changed = TRUE; return 1; } @@ -690,8 +691,6 @@ mail_index_sync_ext_rec_update(struct mail_index_sync_map_ctx *ctx, return ret; } - view->map->rec_map->records_changed = TRUE; - /* @UNSAFE */ memcpy(old_data, u + 1, ext->record_size); return 1; @@ -791,7 +790,5 @@ mail_index_sync_ext_atomic_inc(struct mail_index_sync_map_ctx *ctx, u->uid, u->diff, (unsigned long long)orig_num); return -1; } - - view->map->rec_map->records_changed = TRUE; return 1; } diff --git a/src/lib-index/mail-index-sync-keywords.c b/src/lib-index/mail-index-sync-keywords.c index 36ab1d0..eff6385 100644 --- a/src/lib-index/mail-index-sync-keywords.c +++ b/src/lib-index/mail-index-sync-keywords.c @@ -215,7 +215,6 @@ keywords_update_records(struct mail_index_sync_map_ctx *ctx, if (!mail_index_lookup_seq_range(view, uid1, uid2, &seq1, &seq2)) return 1; - view->map->rec_map->records_changed = TRUE; mail_index_modseq_update_keyword(ctx->modseq_ctx, keyword_idx, seq1, seq2); @@ -337,7 +336,6 @@ mail_index_sync_keywords_reset(struct mail_index_sync_map_ctx *ctx, &seq1, &seq2)) continue; - map->rec_map->records_changed = TRUE; mail_index_modseq_reset_keywords(ctx->modseq_ctx, seq1, seq2); for (seq1--; seq1 < seq2; seq1++) { rec = MAIL_INDEX_MAP_IDX(map, seq1); diff --git a/src/lib-index/mail-index-sync-update.c b/src/lib-index/mail-index-sync-update.c index 986d3a1..508209c 100644 --- a/src/lib-index/mail-index-sync-update.c +++ b/src/lib-index/mail-index-sync-update.c @@ -380,7 +380,6 @@ static int sync_append(const struct mail_index_record *rec, map->rec_map->last_appended_uid = rec->uid; new_flags = rec->flags; - map->rec_map->records_changed = TRUE; mail_index_modseq_append(ctx->modseq_ctx, map->rec_map->records_count); } @@ -408,7 +407,6 @@ static int sync_flag_update(const struct mail_transaction_flag_update *u, if (!mail_index_lookup_seq_range(view, u->uid1, u->uid2, &seq1, &seq2)) return 1; - view->map->rec_map->records_changed = TRUE; if (!MAIL_TRANSACTION_FLAG_UPDATE_IS_INTERNAL(u)) { mail_index_modseq_update_flags(ctx->modseq_ctx, u->add_flags | u->remove_flags, @@ -464,7 +462,6 @@ static int sync_header_update(const struct mail_transaction_header_update *u, buffer_write(map->hdr_copy_buf, u->offset, u + 1, u->size); map->hdr_base = map->hdr_copy_buf->data; - map->header_changed = TRUE; /* @UNSAFE */ if ((uint32_t)(u->offset + u->size) <= sizeof(map->hdr)) { @@ -945,10 +942,8 @@ int mail_index_sync_map(struct mail_index_map **_map, map->refcount--; had_dirty = (map->hdr.flags & MAIL_INDEX_HDR_FLAG_HAVE_DIRTY) != 0; - if (had_dirty) { + if (had_dirty) map->hdr.flags &= ~MAIL_INDEX_HDR_FLAG_HAVE_DIRTY; - map->header_changed = TRUE; - } if (map->hdr_base != map->hdr_copy_buf->data) { /* if syncing updates the header, it updates hdr_copy_buf diff --git a/src/lib-index/mail-index-write.c b/src/lib-index/mail-index-write.c index 3c05f58..958a98b 100644 --- a/src/lib-index/mail-index-write.c +++ b/src/lib-index/mail-index-write.c @@ -119,9 +119,6 @@ static int mail_index_recreate(struct mail_index *index) return ret; } -#define mail_index_map_has_changed(map) \ - ((map)->header_changed || (map)->rec_map->records_changed) - void mail_index_write(struct mail_index *index, bool want_rotate) { struct mail_index_map *map = index->map; @@ -129,7 +126,7 @@ void mail_index_write(struct mail_index *index, bool want_rotate) i_assert(index->log_sync_locked); - if (!mail_index_map_has_changed(map) || index->readonly) + if (index->readonly) return; if (!MAIL_INDEX_IS_IN_MEMORY(index)) { @@ -143,9 +140,6 @@ void mail_index_write(struct mail_index *index, bool want_rotate) index->last_read_log_file_head_offset = hdr->log_file_head_offset; index->last_read_log_file_tail_offset = hdr->log_file_tail_offset; - map->rec_map->records_changed = FALSE; - map->header_changed = FALSE; - if (want_rotate && hdr->log_file_seq == index->log->head->hdr.file_seq && hdr->log_file_tail_offset == hdr->log_file_head_offset) -- 1.7.10.2 From ec67583d343124457f383a72a1ea16359d9e21af Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Tue, 18 Jun 2013 13:00:23 +0300 Subject: [PATCH] mdbox: If mdbox header is corrupted, resize it to make sure its size is correct. diff --git a/src/lib-storage/index/dbox-multi/mdbox-storage.c b/src/lib-storage/index/dbox-multi/mdbox-storage.c index 0c353cc..c938bf6 100644 --- a/src/lib-storage/index/dbox-multi/mdbox-storage.c +++ b/src/lib-storage/index/dbox-multi/mdbox-storage.c @@ -229,7 +229,7 @@ void mdbox_update_header(struct mdbox_mailbox *mbox, if (mdbox_read_header(mbox, &hdr, &need_resize) < 0) { memset(&hdr, 0, sizeof(hdr)); - need_resize = FALSE; + need_resize = TRUE; } new_hdr = hdr; -- 1.7.10.2 From 25f9eabd31f34ccc021a719c07299c6a9dd2bd8c Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Tue, 18 Jun 2013 15:14:42 +0300 Subject: [PATCH] doveadm: Added "flags" command to modify messages' flags. diff --git a/src/doveadm/Makefile.am b/src/doveadm/Makefile.am index bf8824a..30f48d4 100644 --- a/src/doveadm/Makefile.am +++ b/src/doveadm/Makefile.am @@ -64,6 +64,7 @@ common = \ doveadm-mail-batch.c \ doveadm-mail-expunge.c \ doveadm-mail-fetch.c \ + doveadm-mail-flags.c \ doveadm-mail-import.c \ doveadm-mail-index.c \ doveadm-mail-iter.c \ diff --git a/src/doveadm/doveadm-mail-flags.c b/src/doveadm/doveadm-mail-flags.c new file mode 100644 index 0000000..e37d049 --- /dev/null +++ b/src/doveadm/doveadm-mail-flags.c @@ -0,0 +1,143 @@ +/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "imap-util.h" +#include "mail-storage.h" +#include "doveadm-mailbox-list-iter.h" +#include "doveadm-mail-iter.h" +#include "doveadm-mail.h" + +#include + +struct flags_cmd_context { + struct doveadm_mail_cmd_context ctx; + enum modify_type modify_type; + enum mail_flags flags; + const char *const *keywords; +}; + +static int +cmd_flags_run_box(struct flags_cmd_context *ctx, + const struct mailbox_info *info) +{ + struct doveadm_mail_iter *iter; + struct mailbox *box; + struct mail *mail; + struct mail_keywords *kw = NULL; + + if (doveadm_mail_iter_init(&ctx->ctx, info, ctx->ctx.search_args, + 0, NULL, &iter) < 0) + return -1; + box = doveadm_mail_iter_get_mailbox(iter); + + if (ctx->keywords != NULL) { + if (mailbox_keywords_create(box, ctx->keywords, &kw) < 0) { + i_error("Invalid keywords: %s", + mailbox_get_last_error(box, NULL)); + (void)doveadm_mail_iter_deinit(&iter); + ctx->ctx.exit_code = DOVEADM_EX_NOTPOSSIBLE; + return -1; + } + } + + while (doveadm_mail_iter_next(iter, &mail)) { + mail_update_flags(mail, ctx->modify_type, ctx->flags); + if (kw != NULL) + mail_update_keywords(mail, ctx->modify_type, kw); + } + if (kw != NULL) + mailbox_keywords_unref(&kw); + return doveadm_mail_iter_deinit(&iter); +} + +static int +cmd_flags_run(struct doveadm_mail_cmd_context *_ctx, struct mail_user *user) +{ + struct flags_cmd_context *ctx = (struct flags_cmd_context *)_ctx; + const 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; + + 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 (cmd_flags_run_box(ctx, info) < 0) + ret = -1; + } T_END; + if (doveadm_mailbox_list_iter_deinit(&iter) < 0) + ret = -1; + return ret; +} + +static void cmd_flags_init(struct doveadm_mail_cmd_context *_ctx, + const char *const args[]) +{ + struct flags_cmd_context *ctx = (struct flags_cmd_context *)_ctx; + const char *const *tmp; + enum mail_flags flag; + ARRAY_TYPE(const_string) keywords; + + if (args[0] == NULL || args[1] == NULL) + doveadm_mail_help_name("flags"); + + p_array_init(&keywords, _ctx->pool, 8); + for (tmp = t_strsplit(args[0], " "); *tmp != NULL; tmp++) { + const char *str = *tmp; + + if (str[0] == '\\') { + flag = imap_parse_system_flag(str); + if (flag == 0) + i_fatal("Invalid system flag: %s", str); + ctx->flags |= flag; + } else { + str = p_strdup(_ctx->pool, str); + array_append(&keywords, &str, 1); + } + } + if (array_count(&keywords) > 0 || ctx->modify_type == MODIFY_REPLACE) { + array_append_zero(&keywords); + ctx->keywords = array_idx(&keywords, 0); + } + + _ctx->search_args = doveadm_mail_build_search_args(args+1); +} + +static struct doveadm_mail_cmd_context * +cmd_flag_alloc(enum modify_type modify_type) +{ + struct flags_cmd_context *ctx; + + ctx = doveadm_mail_cmd_alloc(struct flags_cmd_context); + ctx->modify_type = modify_type; + ctx->ctx.v.init = cmd_flags_init; + ctx->ctx.v.run = cmd_flags_run; + return &ctx->ctx; +} + +static struct doveadm_mail_cmd_context *cmd_flags_add_alloc(void) +{ + return cmd_flag_alloc(MODIFY_ADD); +} + +static struct doveadm_mail_cmd_context *cmd_flags_remove_alloc(void) +{ + return cmd_flag_alloc(MODIFY_REMOVE); +} + +static struct doveadm_mail_cmd_context *cmd_flags_replace_alloc(void) +{ + return cmd_flag_alloc(MODIFY_REPLACE); +} + +struct doveadm_mail_cmd cmd_flags_add = { + cmd_flags_add_alloc, "flags add", " " +}; +struct doveadm_mail_cmd cmd_flags_remove = { + cmd_flags_remove_alloc, "flags remove", " " +}; +struct doveadm_mail_cmd cmd_flags_replace = { + cmd_flags_replace_alloc, "flags replace", " " +}; diff --git a/src/doveadm/doveadm-mail.c b/src/doveadm/doveadm-mail.c index d035893..5f5fc2e 100644 --- a/src/doveadm/doveadm-mail.c +++ b/src/doveadm/doveadm-mail.c @@ -692,6 +692,9 @@ static struct doveadm_mail_cmd *mail_commands[] = { &cmd_expunge, &cmd_search, &cmd_fetch, + &cmd_flags_add, + &cmd_flags_remove, + &cmd_flags_replace, &cmd_import, &cmd_index, &cmd_altmove, diff --git a/src/doveadm/doveadm-mail.h b/src/doveadm/doveadm-mail.h index 5d0364d..415a614 100644 --- a/src/doveadm/doveadm-mail.h +++ b/src/doveadm/doveadm-mail.h @@ -138,6 +138,9 @@ void doveadm_mail_failed_mailbox(struct doveadm_mail_cmd_context *ctx, extern struct doveadm_mail_cmd cmd_expunge; extern struct doveadm_mail_cmd cmd_search; extern struct doveadm_mail_cmd cmd_fetch; +extern struct doveadm_mail_cmd cmd_flags_add; +extern struct doveadm_mail_cmd cmd_flags_remove; +extern struct doveadm_mail_cmd cmd_flags_replace; extern struct doveadm_mail_cmd cmd_import; extern struct doveadm_mail_cmd cmd_index; extern struct doveadm_mail_cmd cmd_altmove; -- 1.7.10.2 From 67945386cc61f3e4755ec2c46f301f4448877825 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Tue, 18 Jun 2013 17:05:20 +0300 Subject: [PATCH] doveadm: Added deduplicate command. By default it deduplicates only by GUIDs. With -m parameter it deduplicates by Message-Id: header. diff --git a/src/doveadm/Makefile.am b/src/doveadm/Makefile.am index 30f48d4..99e297b 100644 --- a/src/doveadm/Makefile.am +++ b/src/doveadm/Makefile.am @@ -62,6 +62,7 @@ common = \ doveadm-mail.c \ doveadm-mail-altmove.c \ doveadm-mail-batch.c \ + doveadm-mail-deduplicate.c \ doveadm-mail-expunge.c \ doveadm-mail-fetch.c \ doveadm-mail-flags.c \ diff --git a/src/doveadm/doveadm-mail-deduplicate.c b/src/doveadm/doveadm-mail-deduplicate.c new file mode 100644 index 0000000..daa76d1 --- /dev/null +++ b/src/doveadm/doveadm-mail-deduplicate.c @@ -0,0 +1,203 @@ +/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "hash.h" +#include "mail-storage.h" +#include "mail-search-build.h" +#include "doveadm-mailbox-list-iter.h" +#include "doveadm-mail-iter.h" +#include "doveadm-mail.h" + +struct uidlist { + struct uidlist *next; + uint32_t uid; +}; + +struct deduplicate_cmd_context { + struct doveadm_mail_cmd_context ctx; + bool by_msgid; +}; + +static int cmd_deduplicate_uidlist(struct mailbox *box, struct uidlist *uidlist) +{ + struct mailbox_transaction_context *trans; + struct mail_search_context *search_ctx; + struct mail_search_args *search_args; + struct mail_search_arg *arg; + struct mail *mail; + ARRAY_TYPE(seq_range) uids; + int ret = 0; + + /* the uidlist is reversed with oldest mails at the end. + we'll delete everything but the oldest mail. */ + if (uidlist->next == NULL) + return 0; + + t_array_init(&uids, 8); + for (; uidlist->next != NULL; uidlist = uidlist->next) + seq_range_array_add(&uids, uidlist->uid); + + search_args = mail_search_build_init(); + arg = mail_search_build_add(search_args, SEARCH_UIDSET); + arg->value.seqset = uids; + + trans = mailbox_transaction_begin(box, 0); + search_ctx = mailbox_search_init(trans, search_args, NULL, 0, NULL); + mail_search_args_unref(&search_args); + + while (mailbox_search_next(search_ctx, &mail)) + mail_expunge(mail); + if (mailbox_search_deinit(&search_ctx) < 0) + ret = -1; + if (mailbox_transaction_commit(&trans) < 0) + ret = -1; + return ret; +} + +static int +cmd_deduplicate_box(struct doveadm_mail_cmd_context *_ctx, + const struct mailbox_info *info, + struct mail_search_args *search_args) +{ + struct deduplicate_cmd_context *ctx = + (struct deduplicate_cmd_context *)_ctx; + struct doveadm_mail_iter *iter; + struct mailbox *box; + struct mail *mail; + enum mail_error error; + pool_t pool; + HASH_TABLE(const char *, struct uidlist *) hash; + const char *key, *errstr; + struct uidlist *value; + int ret = 0; + + if (doveadm_mail_iter_init(_ctx, info, search_args, 0, NULL, + &iter) < 0) + return -1; + + pool = pool_alloconly_create("deduplicate", 10240); + hash_table_create(&hash, pool, 0, str_hash, strcmp); + while (doveadm_mail_iter_next(iter, &mail)) { + if (ctx->by_msgid) { + if (mail_get_first_header(mail, "Message-ID", &key) < 0) { + errstr = mailbox_get_last_error(box, &error); + if (error == MAIL_ERROR_NOTFOUND) + continue; + i_error("Couldn't lookup Message-ID: for UID=%u: %s", + mail->uid, errstr); + ret = -1; + break; + } + } else { + if (mail_get_special(mail, MAIL_FETCH_GUID, &key) < 0) { + errstr = mailbox_get_last_error(box, &error); + if (error == MAIL_ERROR_NOTFOUND) + continue; + i_error("Couldn't lookup GUID: for UID=%u: %s", + mail->uid, errstr); + ret = -1; + break; + } + } + if (key != NULL && *key != '\0') { + value = p_new(pool, struct uidlist, 1); + value->uid = mail->uid; + value->next = hash_table_lookup(hash, key); + + if (value->next == NULL) { + key = p_strdup(pool, key); + hash_table_insert(hash, key, value); + } else { + hash_table_update(hash, key, value); + } + } + } + + if (doveadm_mail_iter_deinit_keep_box(&iter, &box) < 0) + ret = -1; + + if (ret == 0) { + struct hash_iterate_context *iter; + + iter = hash_table_iterate_init(hash); + while (hash_table_iterate(iter, hash, &key, &value)) { + T_BEGIN { + if (cmd_deduplicate_uidlist(box, value) < 0) + ret = -1; + } T_END; + } + hash_table_iterate_deinit(&iter); + } + + hash_table_destroy(&hash); + pool_unref(&pool); + + if (mailbox_sync(box, 0) < 0) { + doveadm_mail_failed_mailbox(_ctx, box); + ret = -1; + } + mailbox_free(&box); + return ret; +} + +static int +cmd_deduplicate_run(struct doveadm_mail_cmd_context *ctx, struct mail_user *user) +{ + const 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; + + 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 (cmd_deduplicate_box(ctx, info, ctx->search_args) < 0) + ret = -1; + } T_END; + if (doveadm_mailbox_list_iter_deinit(&iter) < 0) + ret = -1; + return ret; +} + +static void cmd_deduplicate_init(struct doveadm_mail_cmd_context *ctx, + const char *const args[]) +{ + if (args[0] == NULL) + doveadm_mail_help_name("deduplicate"); + + ctx->search_args = doveadm_mail_build_search_args(args); +} + +static bool +cmd_deduplicate_parse_arg(struct doveadm_mail_cmd_context *_ctx, int c) +{ + struct deduplicate_cmd_context *ctx = + (struct deduplicate_cmd_context *)_ctx; + + switch (c) { + case 'm': + ctx->by_msgid = TRUE; + break; + default: + return FALSE; + } + return TRUE; +} + +static struct doveadm_mail_cmd_context *cmd_deduplicate_alloc(void) +{ + struct deduplicate_cmd_context *ctx; + + ctx = doveadm_mail_cmd_alloc(struct deduplicate_cmd_context); + ctx->ctx.getopt_args = "m"; + ctx->ctx.v.parse_arg = cmd_deduplicate_parse_arg; + ctx->ctx.v.init = cmd_deduplicate_init; + ctx->ctx.v.run = cmd_deduplicate_run; + return &ctx->ctx; +} + +struct doveadm_mail_cmd cmd_deduplicate = { + cmd_deduplicate_alloc, "deduplicate", "[-m] " +}; diff --git a/src/doveadm/doveadm-mail.c b/src/doveadm/doveadm-mail.c index 5f5fc2e..c955eaa 100644 --- a/src/doveadm/doveadm-mail.c +++ b/src/doveadm/doveadm-mail.c @@ -699,6 +699,7 @@ static struct doveadm_mail_cmd *mail_commands[] = { &cmd_index, &cmd_altmove, &cmd_copy, + &cmd_deduplicate, &cmd_move, &cmd_mailbox_list, &cmd_mailbox_create, diff --git a/src/doveadm/doveadm-mail.h b/src/doveadm/doveadm-mail.h index 415a614..ce07bdf 100644 --- a/src/doveadm/doveadm-mail.h +++ b/src/doveadm/doveadm-mail.h @@ -145,6 +145,7 @@ extern struct doveadm_mail_cmd cmd_import; extern struct doveadm_mail_cmd cmd_index; extern struct doveadm_mail_cmd cmd_altmove; extern struct doveadm_mail_cmd cmd_copy; +extern struct doveadm_mail_cmd cmd_deduplicate; extern struct doveadm_mail_cmd cmd_move; extern struct doveadm_mail_cmd cmd_mailbox_list; extern struct doveadm_mail_cmd cmd_mailbox_create; -- 1.7.10.2 From 703b95b5136b4f0b2600b039f2fc4488dfe3968e Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Tue, 18 Jun 2013 18:54:20 +0300 Subject: [PATCH] sdbox: If sdbox header is corrupted, resize it to make sure its size is correct. diff --git a/src/lib-storage/index/dbox-single/sdbox-storage.c b/src/lib-storage/index/dbox-single/sdbox-storage.c index 9ee0daa..63376c6 100644 --- a/src/lib-storage/index/dbox-single/sdbox-storage.c +++ b/src/lib-storage/index/dbox-single/sdbox-storage.c @@ -185,8 +185,10 @@ static void sdbox_update_header(struct sdbox_mailbox *mbox, struct sdbox_index_header hdr, new_hdr; bool need_resize; - if (sdbox_read_header(mbox, &hdr, TRUE, &need_resize) < 0) + if (sdbox_read_header(mbox, &hdr, TRUE, &need_resize) < 0) { memset(&hdr, 0, sizeof(hdr)); + need_resize = TRUE; + } new_hdr = hdr; -- 1.7.10.2 From ae04e6813463fdd62572c94840623149ba2bae10 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Tue, 18 Jun 2013 18:56:15 +0300 Subject: [PATCH] lib-storage: Fixed crash with some autocreated (e.g. shared) namespaces. diff --git a/src/lib-storage/mailbox-list.c b/src/lib-storage/mailbox-list.c index 03e5fec..70f4d00 100644 --- a/src/lib-storage/mailbox-list.c +++ b/src/lib-storage/mailbox-list.c @@ -808,7 +808,7 @@ int mailbox_list_get_storage(struct mailbox_list **list, const char *vname, return (*list)->v.get_storage(list, vname, storage_r); set = mailbox_settings_find((*list)->ns->user, vname); - if (set != NULL && set->driver[0] != '\0') { + if (set != NULL && set->driver != NULL && set->driver[0] != '\0') { return mailbox_list_get_storage_driver(*list, set->driver, storage_r); } -- 1.7.10.2