diff options
Diffstat (limited to 'src/lib-storage/index/dbox-multi/mdbox-deleted-storage.c')
-rw-r--r-- | src/lib-storage/index/dbox-multi/mdbox-deleted-storage.c | 319 |
1 files changed, 319 insertions, 0 deletions
diff --git a/src/lib-storage/index/dbox-multi/mdbox-deleted-storage.c b/src/lib-storage/index/dbox-multi/mdbox-deleted-storage.c new file mode 100644 index 0000000..4fdf1ab --- /dev/null +++ b/src/lib-storage/index/dbox-multi/mdbox-deleted-storage.c @@ -0,0 +1,319 @@ +/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "array.h" +#include "ioloop.h" +#include "mkdir-parents.h" +#include "master-service.h" +#include "mail-index-modseq.h" +#include "mail-index-alloc-cache.h" +#include "mailbox-log.h" +#include "mailbox-list-private.h" +#include "mail-copy.h" +#include "dbox-mail.h" +#include "dbox-save.h" +#include "mdbox-map.h" +#include "mdbox-file.h" +#include "mdbox-sync.h" +#include "mdbox-storage-rebuild.h" +#include "mdbox-storage.h" + +extern struct mail_storage mdbox_deleted_storage; +extern struct mailbox mdbox_deleted_mailbox; +extern struct dbox_storage_vfuncs mdbox_deleted_dbox_storage_vfuncs; + +static struct mail_storage *mdbox_deleted_storage_alloc(void) +{ + struct mdbox_storage *storage; + pool_t pool; + + pool = pool_alloconly_create("mdbox deleted storage", 2048); + storage = p_new(pool, struct mdbox_storage, 1); + storage->storage.v = mdbox_dbox_storage_vfuncs; + storage->storage.storage = mdbox_deleted_storage; + storage->storage.storage.pool = pool; + return &storage->storage.storage; +} + +static struct mailbox * +mdbox_deleted_mailbox_alloc(struct mail_storage *storage, + struct mailbox_list *list, + const char *vname, enum mailbox_flags flags) +{ + struct mdbox_mailbox *mbox; + pool_t pool; + + flags |= MAILBOX_FLAG_READONLY | MAILBOX_FLAG_NO_INDEX_FILES; + + pool = pool_alloconly_create("mdbox deleted mailbox", 1024*3); + mbox = p_new(pool, struct mdbox_mailbox, 1); + mbox->box = mdbox_deleted_mailbox; + mbox->box.pool = pool; + mbox->box.storage = storage; + mbox->box.list = list; + mbox->box.mail_vfuncs = &mdbox_mail_vfuncs; + + index_storage_mailbox_alloc(&mbox->box, vname, flags, MAIL_INDEX_PREFIX); + + mbox->storage = MDBOX_STORAGE(storage); + return &mbox->box; +} + +static int +mdbox_deleted_mailbox_create_indexes(struct mailbox *box, + const struct mailbox_update *update, + struct mail_index_transaction *trans) +{ + struct mdbox_mailbox *mbox = MDBOX_MAILBOX(box); + struct mail_index_transaction *new_trans = NULL; + uint32_t uid_validity = ioloop_time; + uint32_t uid_next = 1; + + if (update != NULL && update->uid_validity != 0) + uid_validity = update->uid_validity; + + if (trans == NULL) { + new_trans = mail_index_transaction_begin(box->view, 0); + trans = new_trans; + } + + mail_index_update_header(trans, + offsetof(struct mail_index_header, uid_validity), + &uid_validity, sizeof(uid_validity), TRUE); + mail_index_update_header(trans, + offsetof(struct mail_index_header, next_uid), + &uid_next, sizeof(uid_next), TRUE); + mbox->creating = TRUE; + mdbox_update_header(mbox, trans, update); + mbox->creating = FALSE; + + if (new_trans != NULL) { + if (mail_index_transaction_commit(&new_trans) < 0) { + mailbox_set_index_error(box); + return -1; + } + } + return 0; +} + +static const char * +mdbox_get_attachment_path_suffix(struct dbox_file *file ATTR_UNUSED) +{ + return ""; +} + +static int +mdbox_deleted_mailbox_get_metadata(struct mailbox *box, + enum mailbox_metadata_items items, + struct mailbox_metadata *metadata_r) +{ + if (index_mailbox_get_metadata(box, items, metadata_r) < 0) + return -1; + + if ((items & MAILBOX_METADATA_GUID) != 0) + guid_128_generate(metadata_r->guid); + return 0; +} + +static struct mail_save_context * +mdbox_deleted_save_alloc(struct mailbox_transaction_context *t) +{ + struct mail_save_context *ctx; + + ctx = i_new(struct mail_save_context, 1); + ctx->transaction = t; + return ctx; +} + +static int +mdbox_deleted_save_begin(struct mail_save_context *ctx, + struct istream *input ATTR_UNUSED) +{ + mail_storage_set_error(ctx->transaction->box->storage, + MAIL_ERROR_NOTPOSSIBLE, "mdbox_deleted doesn't support saving mails"); + return -1; +} + +static int +mdbox_deleted_save_continue(struct mail_save_context *ctx ATTR_UNUSED) +{ + return -1; +} + +static int mdbox_deleted_save_finish(struct mail_save_context *ctx) +{ + index_save_context_free(ctx); + return -1; +} + +static void +mdbox_deleted_save_cancel(struct mail_save_context *ctx) +{ + index_save_context_free(ctx); +} + +static int mdbox_deleted_sync(struct mdbox_mailbox *mbox, + enum mdbox_sync_flags flags ATTR_UNUSED) +{ + struct mail_index_sync_ctx *index_sync_ctx; + struct mail_index_view *sync_view; + struct mail_index_transaction *trans; + struct mdbox_mail_index_record rec; + struct mdbox_map_mail_index_record map_rec; + enum mail_index_sync_flags sync_flags; + uint16_t refcount; + uint32_t map_seq, map_count, seq, uid = 0; + int ret = 0; + + if (mbox->mdbox_deleted_synced) { + /* don't bother supporting incremental syncs */ + return 0; + } + if (!mbox->box.inbox_user && mbox->box.name[0] != '\0') { + /* since mailbox list currently shows all the existing + mailboxes, we don't want all of them to list the deleted + messages. only show messages in user's INBOX or the + namespace prefix. */ + return 0; + } + + if (mdbox_map_open(mbox->storage->map) < 0) + return -1; + + if (mdbox_deleted_mailbox_create_indexes(&mbox->box, NULL, NULL) < 0) + return -1; + + i_zero(&rec); + rec.save_date = ioloop_time; + + sync_flags = index_storage_get_sync_flags(&mbox->box); + if (mail_index_sync_begin(mbox->box.index, &index_sync_ctx, + &sync_view, &trans, sync_flags) < 0) { + mailbox_set_index_error(&mbox->box); + return -1; + } + + map_count = mdbox_map_get_messages_count(mbox->storage->map); + for (map_seq = 1; map_seq <= map_count; map_seq++) { + if (mdbox_map_lookup_seq_full(mbox->storage->map, map_seq, + &map_rec, &refcount) < 0) { + ret = -1; + break; + } + if (refcount == 0) { + rec.map_uid = mdbox_map_lookup_uid(mbox->storage->map, + map_seq); + mail_index_append(trans, ++uid, &seq); + mail_index_update_ext(trans, seq, + mbox->ext_id, &rec, NULL); + } + } + + if (ret < 0) + mail_index_sync_rollback(&index_sync_ctx); + else { + if (mail_index_sync_commit(&index_sync_ctx) < 0) { + mailbox_set_index_error(&mbox->box); + ret = -1; + } else { + mbox->mdbox_deleted_synced = TRUE; + } + } + return ret; +} + +static struct mailbox_sync_context * +mdbox_deleted_storage_sync_init(struct mailbox *box, + enum mailbox_sync_flags flags) +{ + struct mdbox_mailbox *mbox = MDBOX_MAILBOX(box); + enum mdbox_sync_flags mdbox_sync_flags = 0; + int ret = 0; + + if (index_mailbox_want_full_sync(&mbox->box, flags) || + mbox->storage->corrupted) + ret = mdbox_deleted_sync(mbox, mdbox_sync_flags); + + return index_mailbox_sync_init(box, flags, ret < 0); +} + +struct mail_storage mdbox_deleted_storage = { + .name = MDBOX_DELETED_STORAGE_NAME, + .class_flags = MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT | + MAIL_STORAGE_CLASS_FLAG_HAVE_MAIL_GUIDS | + MAIL_STORAGE_CLASS_FLAG_HAVE_MAIL_SAVE_GUIDS | + MAIL_STORAGE_CLASS_FLAG_BINARY_DATA, + + .v = { + mdbox_get_setting_parser_info, + mdbox_deleted_storage_alloc, + mdbox_storage_create, + mdbox_storage_destroy, + NULL, + dbox_storage_get_list_settings, + NULL, + mdbox_deleted_mailbox_alloc, + NULL, + NULL, + } +}; + +struct mailbox mdbox_deleted_mailbox = { + .v = { + index_storage_is_readonly, + index_storage_mailbox_enable, + index_storage_mailbox_exists, + mdbox_mailbox_open, + index_storage_mailbox_close, + index_storage_mailbox_free, + dbox_mailbox_create, + index_storage_mailbox_update, + index_storage_mailbox_delete, + index_storage_mailbox_rename, + index_storage_get_status, + mdbox_deleted_mailbox_get_metadata, + index_storage_set_subscribed, + index_storage_attribute_set, + index_storage_attribute_get, + index_storage_attribute_iter_init, + index_storage_attribute_iter_next, + index_storage_attribute_iter_deinit, + index_storage_list_index_has_changed, + index_storage_list_index_update_sync, + mdbox_deleted_storage_sync_init, + index_mailbox_sync_next, + index_mailbox_sync_deinit, + NULL, + dbox_notify_changes, + index_transaction_begin, + index_transaction_commit, + index_transaction_rollback, + NULL, + dbox_mail_alloc, + index_storage_search_init, + index_storage_search_deinit, + index_storage_search_next_nonblock, + index_storage_search_next_update_seq, + index_storage_search_next_match_mail, + mdbox_deleted_save_alloc, + mdbox_deleted_save_begin, + mdbox_deleted_save_continue, + mdbox_deleted_save_finish, + mdbox_deleted_save_cancel, + mail_storage_copy, + NULL, + NULL, + NULL, + index_storage_is_inconsistent + } +}; + +struct dbox_storage_vfuncs mdbox_deleted_dbox_storage_vfuncs = { + mdbox_file_unrefed, + mdbox_file_create_fd, + mdbox_mail_open, + mdbox_deleted_mailbox_create_indexes, + mdbox_get_attachment_path_suffix, + mdbox_set_mailbox_corrupted, + mdbox_set_file_corrupted +}; |