1
/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */
6
#include "mkdir-parents.h"
7
#include "master-service.h"
8
#include "mail-index-modseq.h"
9
#include "mail-index-alloc-cache.h"
10
#include "mailbox-log.h"
11
#include "mailbox-list-private.h"
12
#include "mail-copy.h"
13
#include "dbox-mail.h"
14
#include "dbox-save.h"
15
#include "mdbox-map.h"
16
#include "mdbox-file.h"
17
#include "mdbox-sync.h"
18
#include "mdbox-storage-rebuild.h"
19
#include "mdbox-storage.h"
21
extern struct mail_storage mdbox_deleted_storage;
22
extern struct mailbox mdbox_deleted_mailbox;
23
extern struct dbox_storage_vfuncs mdbox_deleted_dbox_storage_vfuncs;
25
static struct mail_storage *mdbox_deleted_storage_alloc(void)
27
struct mdbox_storage *storage;
30
pool = pool_alloconly_create("mdbox deleted storage", 2048);
31
storage = p_new(pool, struct mdbox_storage, 1);
32
storage->storage.v = mdbox_dbox_storage_vfuncs;
33
storage->storage.storage = mdbox_deleted_storage;
34
storage->storage.storage.pool = pool;
35
return &storage->storage.storage;
38
static struct mailbox *
39
mdbox_deleted_mailbox_alloc(struct mail_storage *storage,
40
struct mailbox_list *list,
41
const char *vname, enum mailbox_flags flags)
43
struct mdbox_mailbox *mbox;
46
flags |= MAILBOX_FLAG_READONLY | MAILBOX_FLAG_NO_INDEX_FILES;
48
pool = pool_alloconly_create("mdbox deleted mailbox", 1024*3);
49
mbox = p_new(pool, struct mdbox_mailbox, 1);
50
mbox->box = mdbox_deleted_mailbox;
51
mbox->box.pool = pool;
52
mbox->box.storage = storage;
53
mbox->box.list = list;
54
mbox->box.mail_vfuncs = &mdbox_mail_vfuncs;
56
index_storage_mailbox_alloc(&mbox->box, vname, flags, MAIL_INDEX_PREFIX);
58
mbox->storage = (struct mdbox_storage *)storage;
63
mdbox_deleted_mailbox_create_indexes(struct mailbox *box,
64
const struct mailbox_update *update,
65
struct mail_index_transaction *trans)
67
struct mdbox_mailbox *mbox = (struct mdbox_mailbox *)box;
68
struct mail_index_transaction *new_trans = NULL;
69
uint32_t uid_validity = ioloop_time;
70
uint32_t uid_next = 1;
72
if (update != NULL && update->uid_validity != 0)
73
uid_validity = update->uid_validity;
76
new_trans = mail_index_transaction_begin(box->view, 0);
80
mail_index_update_header(trans,
81
offsetof(struct mail_index_header, uid_validity),
82
&uid_validity, sizeof(uid_validity), TRUE);
83
mail_index_update_header(trans,
84
offsetof(struct mail_index_header, next_uid),
85
&uid_next, sizeof(uid_next), TRUE);
86
mbox->creating = TRUE;
87
mdbox_update_header(mbox, trans, update);
88
mbox->creating = FALSE;
90
if (new_trans != NULL) {
91
if (mail_index_transaction_commit(&new_trans) < 0) {
92
mailbox_set_index_error(box);
100
mdbox_get_attachment_path_suffix(struct dbox_file *file ATTR_UNUSED)
106
mdbox_deleted_mailbox_get_metadata(struct mailbox *box,
107
enum mailbox_metadata_items items,
108
struct mailbox_metadata *metadata_r)
110
if (index_mailbox_get_metadata(box, items, metadata_r) < 0)
113
if ((items & MAILBOX_METADATA_GUID) != 0)
114
guid_128_generate(metadata_r->guid);
118
static struct mail_save_context *
119
mdbox_deleted_save_alloc(struct mailbox_transaction_context *t)
121
struct mail_save_context *ctx;
123
ctx = i_new(struct mail_save_context, 1);
124
ctx->transaction = t;
129
mdbox_deleted_save_begin(struct mail_save_context *ctx,
130
struct istream *input ATTR_UNUSED)
132
mail_storage_set_error(ctx->transaction->box->storage,
133
MAIL_ERROR_NOTPOSSIBLE, "mdbox_deleted doesn't support saving mails");
138
mdbox_deleted_save_continue(struct mail_save_context *ctx ATTR_UNUSED)
143
static int mdbox_deleted_save_finish(struct mail_save_context *ctx)
145
index_save_context_free(ctx);
150
mdbox_deleted_save_cancel(struct mail_save_context *ctx)
152
index_save_context_free(ctx);
155
static int mdbox_deleted_sync(struct mdbox_mailbox *mbox,
156
enum mdbox_sync_flags flags ATTR_UNUSED)
158
struct mail_index_sync_ctx *index_sync_ctx;
159
struct mail_index_view *sync_view;
160
struct mail_index_transaction *trans;
161
struct mdbox_mail_index_record rec;
162
struct mdbox_map_mail_index_record map_rec;
163
enum mail_index_sync_flags sync_flags;
165
uint32_t map_seq, map_count, seq, uid = 0;
168
if (mbox->mdbox_deleted_synced) {
169
/* don't bother supporting incremental syncs */
172
if (!mbox->box.inbox_user && mbox->box.name[0] != '\0') {
173
/* since mailbox list currently shows all the existing
174
mailboxes, we don't want all of them to list the deleted
175
messages. only show messages in user's INBOX or the
180
if (mdbox_map_open(mbox->storage->map) < 0)
183
if (mdbox_deleted_mailbox_create_indexes(&mbox->box, NULL, NULL) < 0)
186
memset(&rec, 0, sizeof(rec));
187
rec.save_date = ioloop_time;
189
sync_flags = index_storage_get_sync_flags(&mbox->box);
190
if (mail_index_sync_begin(mbox->box.index, &index_sync_ctx,
191
&sync_view, &trans, sync_flags) < 0) {
192
mailbox_set_index_error(&mbox->box);
196
map_count = mdbox_map_get_messages_count(mbox->storage->map);
197
for (map_seq = 1; map_seq <= map_count; map_seq++) {
198
if (mdbox_map_lookup_seq_full(mbox->storage->map, map_seq,
199
&map_rec, &refcount) < 0) {
204
rec.map_uid = mdbox_map_lookup_uid(mbox->storage->map,
206
mail_index_append(trans, ++uid, &seq);
207
mail_index_update_ext(trans, seq,
208
mbox->ext_id, &rec, NULL);
213
mail_index_sync_rollback(&index_sync_ctx);
215
if (mail_index_sync_commit(&index_sync_ctx) < 0) {
216
mailbox_set_index_error(&mbox->box);
219
mbox->mdbox_deleted_synced = TRUE;
225
static struct mailbox_sync_context *
226
mdbox_deleted_storage_sync_init(struct mailbox *box,
227
enum mailbox_sync_flags flags)
229
struct mdbox_mailbox *mbox = (struct mdbox_mailbox *)box;
230
enum mdbox_sync_flags mdbox_sync_flags = 0;
234
if (mailbox_open(box) < 0)
238
if (ret == 0 && (index_mailbox_want_full_sync(&mbox->box, flags) ||
239
mbox->storage->corrupted))
240
ret = mdbox_deleted_sync(mbox, mdbox_sync_flags);
242
return index_mailbox_sync_init(box, flags, ret < 0);
245
struct mail_storage mdbox_deleted_storage = {
246
.name = MDBOX_DELETED_STORAGE_NAME,
247
.class_flags = MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT |
248
MAIL_STORAGE_CLASS_FLAG_HAVE_MAIL_GUIDS |
249
MAIL_STORAGE_CLASS_FLAG_HAVE_MAIL_SAVE_GUIDS |
250
MAIL_STORAGE_CLASS_FLAG_BINARY_DATA,
253
mdbox_get_setting_parser_info,
254
mdbox_deleted_storage_alloc,
255
mdbox_storage_create,
256
mdbox_storage_destroy,
258
dbox_storage_get_list_settings,
260
mdbox_deleted_mailbox_alloc,
265
struct mailbox mdbox_deleted_mailbox = {
267
index_storage_is_readonly,
268
index_storage_mailbox_enable,
269
index_storage_mailbox_exists,
271
index_storage_mailbox_close,
272
index_storage_mailbox_free,
274
index_storage_mailbox_update,
275
index_storage_mailbox_delete,
276
index_storage_mailbox_rename,
277
index_storage_get_status,
278
mdbox_deleted_mailbox_get_metadata,
279
index_storage_set_subscribed,
280
index_storage_attribute_set,
281
index_storage_attribute_get,
282
index_storage_attribute_iter_init,
283
index_storage_attribute_iter_next,
284
index_storage_attribute_iter_deinit,
285
index_storage_list_index_has_changed,
286
index_storage_list_index_update_sync,
287
mdbox_deleted_storage_sync_init,
288
index_mailbox_sync_next,
289
index_mailbox_sync_deinit,
292
index_transaction_begin,
293
index_transaction_commit,
294
index_transaction_rollback,
297
index_storage_search_init,
298
index_storage_search_deinit,
299
index_storage_search_next_nonblock,
300
index_storage_search_next_update_seq,
301
mdbox_deleted_save_alloc,
302
mdbox_deleted_save_begin,
303
mdbox_deleted_save_continue,
304
mdbox_deleted_save_finish,
305
mdbox_deleted_save_cancel,
310
index_storage_is_inconsistent
314
struct dbox_storage_vfuncs mdbox_deleted_dbox_storage_vfuncs = {
316
mdbox_file_create_fd,
318
mdbox_deleted_mailbox_create_indexes,
319
mdbox_get_attachment_path_suffix,
320
mdbox_set_mailbox_corrupted,
321
mdbox_set_file_corrupted