summaryrefslogtreecommitdiffstats
path: root/src/lib-storage/index/dbox-multi/mdbox-deleted-storage.c
diff options
context:
space:
mode:
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.c319
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
+};