dbox-sync-expunge.c revision e063aca6bc2f08bec516d4b631052ea9191f011d
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher/* Copyright (C) 2005 Timo Sirainen */
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher#include "lib.h"
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher#include "array.h"
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher#include "istream.h"
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher#include "ostream.h"
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher#include "write-full.h"
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher#include "hex-dec.h"
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher#include "seq-range-array.h"
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher#include "dbox-storage.h"
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher#include "dbox-uidlist.h"
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher#include "dbox-file.h"
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher#include "dbox-sync.h"
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher#include <stddef.h>
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagherstatic int
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagherdbox_sync_rec_get_uids(struct dbox_sync_context *ctx,
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher const struct dbox_sync_rec *sync_rec,
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher uint32_t *uid1_r, uint32_t *uid2_r)
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher{
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher if (mail_index_lookup_uid(ctx->sync_view, sync_rec->seq1, uid1_r) < 0) {
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher mail_storage_set_index_error(&ctx->mbox->ibox);
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher return -1;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher }
74e95cfd9d3939dfe9417d79d2f6fc79b361405fJakub Hrozek if (mail_index_lookup_uid(ctx->sync_view, sync_rec->seq2, uid2_r) < 0) {
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher mail_storage_set_index_error(&ctx->mbox->ibox);
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek return -1;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek }
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek return 0;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek}
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagherstatic int
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagherdbox_next_expunge(struct dbox_sync_context *ctx,
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher const struct dbox_sync_file_entry *sync_entry,
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher unsigned int *sync_idx, uint32_t *uid1_r, uint32_t *uid2_r)
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher{
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher struct mailbox *box = &ctx->mbox->ibox.box;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher const struct dbox_sync_rec *sync_recs, *sync_rec;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher unsigned int count;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher uint32_t uid, seq;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher sync_recs = array_get(&sync_entry->sync_recs, &count);
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher while (*sync_idx < count) {
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher *sync_idx += 1;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher sync_rec = &sync_recs[*sync_idx];
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher if (sync_rec->type != MAIL_INDEX_SYNC_TYPE_EXPUNGE)
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher continue;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher if (dbox_sync_rec_get_uids(ctx, sync_rec, uid1_r, uid2_r) < 0)
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher return -1;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher if (box->v.sync_notify != NULL) {
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher /* all of the UIDs uid1..uid2 should exist */
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher for (uid = *uid1_r; uid <= *uid2_r; uid++) {
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher box->v.sync_notify(box, uid,
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher MAILBOX_SYNC_TYPE_EXPUNGE);
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher }
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher }
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher for (seq = sync_rec->seq1; seq != sync_rec->seq2; seq++)
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher mail_index_expunge(ctx->trans, seq);
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher return 1;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher }
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher *uid1_r = *uid2_r = 0;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher return 0;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher}
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagherstatic int dbox_sync_expunge_copy(struct dbox_sync_context *ctx,
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher const struct dbox_sync_file_entry *sync_entry,
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher unsigned int sync_idx,
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher uint32_t first_nonexpunged_uid,
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher const struct dbox_uidlist_entry *orig_entry,
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher uoff_t orig_offset)
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher{
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher struct dbox_mailbox *mbox = ctx->mbox;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher struct mail_storage *storage = &mbox->storage->storage;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher struct dotlock *dotlock;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher struct istream *input;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher struct ostream *output;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher struct dbox_file *file;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher struct dbox_uidlist_entry dest_entry;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher const struct dbox_sync_rec *sync_recs;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher const char *path, *lock_path;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher uint32_t file_seq, seq, uid1, uid2;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher unsigned int sync_count;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher int ret, fd;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher uoff_t full_size;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher off_t bytes;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher ret = dbox_file_seek(mbox, orig_entry->file_seq, orig_offset, FALSE);
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher if (ret >= 0 && mbox->file->hdr.have_expunged_mails != '0') {
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher /* there are some expunged mails in the file, go through all
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher of the mails. */
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher ret = dbox_file_seek(mbox, orig_entry->file_seq,
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher mbox->file->header_size, FALSE);
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher }
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher /* skip mails until we find the first we don't want expunged */
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher while (ret > 0) {
e4c29d1f8e3b2c2b268105f169e5156a0a36aebfOndrej Kos ret = dbox_file_seek_next_nonexpunged(mbox);
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher if (mbox->file->seeked_uid >= first_nonexpunged_uid)
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher break;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher }
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher if (ret <= 0) {
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher if (ret == 0) {
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher mail_storage_set_critical(storage,
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher "%s: Expunging lost UID %u from file %u",
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher mbox->path, first_nonexpunged_uid,
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher orig_entry->file_seq);
346f41f1ede975cb2db0af570f5b454b9b306704Stephen Gallagher }
346f41f1ede975cb2db0af570f5b454b9b306704Stephen Gallagher return ret;
346f41f1ede975cb2db0af570f5b454b9b306704Stephen Gallagher }
346f41f1ede975cb2db0af570f5b454b9b306704Stephen Gallagher
346f41f1ede975cb2db0af570f5b454b9b306704Stephen Gallagher sync_recs = array_get(&sync_entry->sync_recs, &sync_count);
346f41f1ede975cb2db0af570f5b454b9b306704Stephen Gallagher if (sync_idx == sync_count)
346f41f1ede975cb2db0af570f5b454b9b306704Stephen Gallagher uid1 = uid2 = 0;
346f41f1ede975cb2db0af570f5b454b9b306704Stephen Gallagher else {
346f41f1ede975cb2db0af570f5b454b9b306704Stephen Gallagher if (dbox_sync_rec_get_uids(ctx, &sync_recs[sync_idx],
346f41f1ede975cb2db0af570f5b454b9b306704Stephen Gallagher &uid1, &uid2) < 0)
346f41f1ede975cb2db0af570f5b454b9b306704Stephen Gallagher return -1;
346f41f1ede975cb2db0af570f5b454b9b306704Stephen Gallagher }
346f41f1ede975cb2db0af570f5b454b9b306704Stephen Gallagher
346f41f1ede975cb2db0af570f5b454b9b306704Stephen Gallagher file_seq = dbox_uidlist_get_new_file_seq(mbox->uidlist);
346f41f1ede975cb2db0af570f5b454b9b306704Stephen Gallagher
346f41f1ede975cb2db0af570f5b454b9b306704Stephen Gallagher for (;; file_seq++) {
346f41f1ede975cb2db0af570f5b454b9b306704Stephen Gallagher path = t_strdup_printf("%s/"DBOX_MAIL_FILE_FORMAT,
346f41f1ede975cb2db0af570f5b454b9b306704Stephen Gallagher mbox->path, file_seq);
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher fd = file_dotlock_open(&mbox->storage->new_file_dotlock_set,
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher path, DOTLOCK_CREATE_FLAG_NONBLOCK,
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher &dotlock);
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher if (fd >= 0)
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher break;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher if (errno != EAGAIN) {
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher mail_storage_set_critical(storage,
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher "file_dotlock_open(%s) failed: %m", path);
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher return -1;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher }
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher /* try again with another file name */
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny }
7119f0c483049a8850d3075c0b1062f35200a538Jakub Hrozek output = o_stream_create_file(fd, default_pool, 0, FALSE);
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek lock_path = file_dotlock_get_lock_path(dotlock);
7119f0c483049a8850d3075c0b1062f35200a538Jakub Hrozek
7119f0c483049a8850d3075c0b1062f35200a538Jakub Hrozek memset(&dest_entry, 0, sizeof(dest_entry));
7119f0c483049a8850d3075c0b1062f35200a538Jakub Hrozek t_array_init(&dest_entry.uid_list, array_count(&orig_entry->uid_list));
7119f0c483049a8850d3075c0b1062f35200a538Jakub Hrozek dest_entry.file_seq = file_seq;
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny /* write file header */
4a1e58d85409fbb7a12ac244c3dbef8c0c1b15dfMichal Zidek file = i_new(struct dbox_file, 1);
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny file->fd = -1;
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny file->output = output;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek if (dbox_file_write_header(mbox, file) < 0)
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny ret = -1;
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny dbox_file_close(file);
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny while (ret > 0) {
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny /* update mail's location in index */
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny uint32_t uid = mbox->file->seeked_uid;
04759b59e71c78ab23b84d13dd29d9c6dd680adbMichal Zidek uint64_t hdr_offset = output->offset;
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny if (mail_index_lookup_uid_range(ctx->sync_view, uid, uid,
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny &seq, &seq) < 0) {
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny mail_storage_set_index_error(&ctx->mbox->ibox);
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny ret = -1;
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny break;
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny }
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny if (seq == 0) {
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny mail_storage_set_critical(storage,
4a1e58d85409fbb7a12ac244c3dbef8c0c1b15dfMichal Zidek "Expunged UID %u reappeared in file %s",
4a1e58d85409fbb7a12ac244c3dbef8c0c1b15dfMichal Zidek uid, path);
4a1e58d85409fbb7a12ac244c3dbef8c0c1b15dfMichal Zidek mail_index_mark_corrupted(mbox->ibox.index);
4a1e58d85409fbb7a12ac244c3dbef8c0c1b15dfMichal Zidek ret = -1;
4a1e58d85409fbb7a12ac244c3dbef8c0c1b15dfMichal Zidek break;
4a1e58d85409fbb7a12ac244c3dbef8c0c1b15dfMichal Zidek }
4a1e58d85409fbb7a12ac244c3dbef8c0c1b15dfMichal Zidek
4a1e58d85409fbb7a12ac244c3dbef8c0c1b15dfMichal Zidek mail_index_update_ext(ctx->trans, seq, mbox->dbox_file_ext_idx,
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek &file_seq, NULL);
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek mail_index_update_ext(ctx->trans, seq,
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek mbox->dbox_offset_ext_idx,
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek &hdr_offset, NULL);
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek /* copy the mail */
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek full_size = mbox->file->mail_header_size +
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek mbox->file->seeked_mail_size;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek input = i_stream_create_limit(default_pool, mbox->file->input,
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek mbox->file->seeked_offset,
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek full_size);
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek bytes = o_stream_send_istream(output, input);
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek i_stream_destroy(&input);
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek if (bytes < 0) {
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek mail_storage_set_critical(storage,
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek "o_stream_send_istream(%s) failed: %m",
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek lock_path);
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek ret = -1;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek break;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek }
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek if ((uoff_t)bytes != full_size) {
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek mail_storage_set_critical(storage,
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek "o_stream_send_istream(%s) wrote only %"
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny PRIuUOFF_T" of %"PRIuUOFF_T" bytes", lock_path,
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny (uoff_t)bytes, full_size);
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek ret = -1;
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny break;
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny }
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny seq_range_array_add(&dest_entry.uid_list, 0,
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny mbox->file->seeked_uid);
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny /* seek to next non-expunged mail */
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny for (;;) {
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny ret = dbox_file_seek_next_nonexpunged(mbox);
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny if (ret <= 0)
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny break;
b096321a5a02dda0b6b71ba0f9c4d8feacd979e4Michal Zidek
b096321a5a02dda0b6b71ba0f9c4d8feacd979e4Michal Zidek while (mbox->file->seeked_uid > uid2 && uid2 != 0) {
b096321a5a02dda0b6b71ba0f9c4d8feacd979e4Michal Zidek ret = dbox_next_expunge(ctx, sync_entry,
b096321a5a02dda0b6b71ba0f9c4d8feacd979e4Michal Zidek &sync_idx,
b096321a5a02dda0b6b71ba0f9c4d8feacd979e4Michal Zidek &uid1, &uid2);
b096321a5a02dda0b6b71ba0f9c4d8feacd979e4Michal Zidek if (ret <= 0)
b096321a5a02dda0b6b71ba0f9c4d8feacd979e4Michal Zidek break;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek }
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek if (ret <= 0) {
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek if (ret == 0) {
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek /* we want to keep copying */
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek ret = 1;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek }
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek break;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek }
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek if (mbox->file->seeked_uid < uid1 || uid1 == 0)
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek break;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek }
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek }
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek if (ret == 0) {
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek struct dbox_file_header hdr;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek /* update append_offset in header */
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek DEC2HEX(hdr.append_offset_hex, output->offset);
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek o_stream_flush(output);
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny if (pwrite_full(fd, hdr.append_offset_hex,
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny sizeof(hdr.append_offset_hex),
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny offsetof(struct dbox_file_header,
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny append_offset_hex)) < 0) {
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny mail_storage_set_critical(storage,
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny "pwrite_full(%s) failed: %m", lock_path);
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny ret = -1;
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny }
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny }
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny o_stream_destroy(&output);
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny if (ret < 0) {
7119f0c483049a8850d3075c0b1062f35200a538Jakub Hrozek file_dotlock_delete(&dotlock);
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek return -1;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek } else {
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek if (file_dotlock_replace(&dotlock, 0) < 0)
7119f0c483049a8850d3075c0b1062f35200a538Jakub Hrozek return -1;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek
7119f0c483049a8850d3075c0b1062f35200a538Jakub Hrozek /* new file created successfully. append it to uidlist. */
7119f0c483049a8850d3075c0b1062f35200a538Jakub Hrozek dbox_uidlist_sync_append(ctx->uidlist_sync_ctx, &dest_entry);
7119f0c483049a8850d3075c0b1062f35200a538Jakub Hrozek return 0;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek }
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek}
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek
7119f0c483049a8850d3075c0b1062f35200a538Jakub Hrozekstatic int dbox_sync_expunge_file(struct dbox_sync_context *ctx,
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek const struct dbox_sync_file_entry *sync_entry,
7119f0c483049a8850d3075c0b1062f35200a538Jakub Hrozek unsigned int sync_idx)
7119f0c483049a8850d3075c0b1062f35200a538Jakub Hrozek{
9ab243b369ba317cc964080786dbcdebaf23d6beMichal Zidek struct dbox_mailbox *mbox = ctx->mbox;
9ab243b369ba317cc964080786dbcdebaf23d6beMichal Zidek const struct dbox_sync_rec *sync_recs;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek struct dbox_uidlist_entry *entry;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek struct seq_range *range;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek const char *path;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek unsigned int i, count, sync_count;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek uint32_t file_seq, uid, exp_uid1, exp_uid2, first_expunged_uid;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek uoff_t offset;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek int ret;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek bool seen_expunges, skipped_expunges;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek sync_recs = array_get(&sync_entry->sync_recs, &sync_count);
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek if (dbox_sync_get_file_offset(ctx, sync_recs[sync_idx].seq1,
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek &file_seq, &offset) < 0)
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek return -1;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek i_assert(file_seq == sync_entry->file_seq);
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek entry = dbox_uidlist_entry_lookup(mbox->uidlist, sync_entry->file_seq);
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek if (entry == NULL) {
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek /* file is already unlinked. just remove from index. */
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek return 0;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek }
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek if (dbox_sync_rec_get_uids(ctx, &sync_recs[sync_idx],
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek &exp_uid1, &exp_uid2) < 0)
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek return -1;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek /* find the first non-expunged mail */
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek first_expunged_uid = exp_uid1;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek seen_expunges = FALSE; skipped_expunges = FALSE; uid = 0;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek range = array_get_modifiable(&entry->uid_list, &count);
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek for (i = 0; i < count; i++) {
9ab243b369ba317cc964080786dbcdebaf23d6beMichal Zidek uid = range[i].seq1;
9ab243b369ba317cc964080786dbcdebaf23d6beMichal Zidek
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher if (!seen_expunges) {
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher if (uid < first_expunged_uid) {
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny /* range begins with non-expunged messages */
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny uid = first_expunged_uid;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher skipped_expunges = TRUE;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher }
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher }
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher while (uid <= range[i].seq2) {
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher if (uid < exp_uid1 || exp_uid1 == 0) {
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher /* non-expunged mails exist in this file */
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher break;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher }
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher seen_expunges = TRUE;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher if (range[i].seq2 < exp_uid2) {
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher /* fully used up this uid range */
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher uid = range[i].seq2 + 1;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher break;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher }
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher /* this sync_rec was fully used. look up the next.
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek range[] doesn't contain non-existing UIDs, so
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek exp_uid2+1 should exist in it. */
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek if (uid <= exp_uid2)
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek uid = exp_uid2 + 1;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek ret = dbox_next_expunge(ctx, sync_entry, &sync_idx,
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek &exp_uid1, &exp_uid2);
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek if (ret <= 0) {
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek if (ret < 0)
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher return -1;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher /* end of sync records */
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher break;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher }
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher }
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher if (uid <= range[i].seq2) {
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher /* non-expunged mails exist in this file */
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher break;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher }
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher }
9ab243b369ba317cc964080786dbcdebaf23d6beMichal Zidek
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher if (i != count) {
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher /* mails expunged from the middle. have to copy everything
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher after the first expunged mail to new file. after copying
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher we'll truncate/unlink the old file. */
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher if (dbox_sync_expunge_copy(ctx, sync_entry, sync_idx,
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek uid, entry, offset) < 0)
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek return -1;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher i++;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher }
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher if (!skipped_expunges) {
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher /* all mails expunged from file, unlink it. */
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek path = t_strdup_printf("%s/"DBOX_MAIL_FILE_FORMAT,
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher mbox->path, entry->file_seq);
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher if (unlink(path) < 0) {
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher mail_storage_set_critical(&mbox->storage->storage,
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher "unlink(%s) failed: %m", path);
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher return -1;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher }
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher dbox_uidlist_sync_unlink(ctx->uidlist_sync_ctx,
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher entry->file_seq);
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher return 0;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher }
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher /* mails expunged from the end of file, ftruncate() it */
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher ret = dbox_file_seek(mbox, entry->file_seq, offset, FALSE);
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny if (ret <= 0) {
b1caacb098ae99ad65144120fdec4d0fd98ad9d5Pavel Březina if (ret < 0)
b1caacb098ae99ad65144120fdec4d0fd98ad9d5Pavel Březina return -1;
b1caacb098ae99ad65144120fdec4d0fd98ad9d5Pavel Březina
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher /* unexpected EOF -> already truncated */
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher } else {
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek /* file can no longer be appended to */
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek if (pwrite_full(mbox->file->fd, "00000000EFFFFFFF", 16,
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher offsetof(struct dbox_file_header,
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher append_offset_hex)) < 0) {
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher mail_storage_set_critical(&mbox->storage->storage,
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher "pwrite_full(%s) failed: %m", mbox->path);
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny return -1;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek }
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek
016e0d7202ff965018e41869c5ab501f86b0d081Jan Zeleny if (ftruncate(mbox->file->fd, offset) < 0) {
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher mail_storage_set_critical(&mbox->storage->storage,
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher "ftruncate(%s) failed: %m", mbox->file->path);
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher return -1;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher }
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek if (mbox->file->hdr.have_expunged_mails != '0') {
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek /* all mails in the file are expunged now */
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek if (pwrite_full(mbox->file->fd, "0", 1,
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek offsetof(struct dbox_file_header,
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek have_expunged_mails)) < 0) {
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher mail_storage_set_critical(
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher &mbox->storage->storage,
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher "pwrite_full(%s) failed: %m",
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher mbox->path);
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher return -1;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher }
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher }
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher }
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher /* remove from uidlist entry */
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher for (; i > 0; i--) {
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher if (range[i-1].seq1 < first_expunged_uid)
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher break;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher }
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher array_delete(&entry->uid_list, i, count-i);
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher if (i > 0 && range[i-1].seq2 >= first_expunged_uid)
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher range[i-1].seq2 = first_expunged_uid-1;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher /* file can no longer be written to */
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher entry->file_size = INT_MAX;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher dbox_uidlist_sync_set_modified(ctx->uidlist_sync_ctx);
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher return 0;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher}
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagherstatic int
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagheruidlist_entry_remove_uids(struct dbox_sync_context *ctx,
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher const struct dbox_sync_file_entry *sync_entry)
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher{
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek struct dbox_uidlist_entry *entry;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher const struct dbox_sync_rec *recs;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher uint32_t uid;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher unsigned int i, count, seq;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher entry = dbox_uidlist_entry_lookup(ctx->mbox->uidlist,
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher sync_entry->file_seq);
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher if (entry == NULL)
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek return 0;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek recs = array_get(&sync_entry->sync_recs, &count);
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek for (i = 0; i < count; i++) {
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek if (recs[i].type != MAIL_INDEX_SYNC_TYPE_EXPUNGE)
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek continue;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher for (seq = recs[i].seq1; seq <= recs[i].seq2; seq++) {
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher if (mail_index_lookup_uid(ctx->sync_view,
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher seq, &uid) < 0) {
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher mail_storage_set_index_error(&ctx->mbox->ibox);
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher return -1;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher }
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher seq_range_array_remove(&entry->uid_list, uid);
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher }
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher }
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher if (array_count(&entry->uid_list) == 0) {
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher dbox_uidlist_sync_unlink(ctx->uidlist_sync_ctx,
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher entry->file_seq);
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher }
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher dbox_uidlist_sync_set_modified(ctx->uidlist_sync_ctx);
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher return 0;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher}
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagherint dbox_sync_expunge(struct dbox_sync_context *ctx,
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher const struct dbox_sync_file_entry *sync_entry,
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher unsigned int sync_idx)
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher{
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher struct dbox_mailbox *mbox = ctx->mbox;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher const struct dbox_sync_rec *sync_rec;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher struct dotlock *dotlock;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher const char *path;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher int ret;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek if (ctx->dotlock_failed_file_seq != sync_entry->file_seq) {
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher /* we need to have the file locked in case another process is
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher appending there already. */
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher path = t_strdup_printf("%s/"DBOX_MAIL_FILE_FORMAT,
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher mbox->path, sync_entry->file_seq);
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher ret = file_dotlock_create(&mbox->storage->new_file_dotlock_set,
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher path, DOTLOCK_CREATE_FLAG_NONBLOCK,
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher &dotlock);
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek if (ret < 0) {
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek mail_storage_set_critical(&mbox->storage->storage,
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek "file_dotlock_create(%s) failed: %m", path);
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek return -1;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek }
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek if (ret > 0) {
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher /* locked - copy the non-expunged mails after the
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher expunged mail to new file */
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher ret = dbox_sync_expunge_file(ctx, sync_entry, sync_idx);
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher file_dotlock_delete(&dotlock);
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek return ret < 0 ? -1 : 1;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek }
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek /* remember that we failed, so we don't waste time trying to
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek lock the file multiple times within same sync. */
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek ctx->dotlock_failed_file_seq = sync_entry->file_seq;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek }
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek /* couldn't lock it, someone's appending. we have no other
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek choice but to just mark the mail expunged. otherwise we'd
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek deadlock (appending process waits for uidlist lock which
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek we have, we wait for file lock which append process has) */
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek sync_rec = array_idx(&sync_entry->sync_recs, sync_idx);
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek if (dbox_sync_update_flags(ctx, sync_rec) < 0)
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek return -1;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek /* mark in the header that the file contains expunged messages */
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek if (pwrite_full(mbox->file->fd, "1", 1,
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek offsetof(struct dbox_file_header,
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek have_expunged_mails)) < 0) {
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek mail_storage_set_critical(&mbox->storage->storage,
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek "pwrite(%s) failed: %m", mbox->file->path);
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek return -1;
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek }
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek /* remove UIDs from the uidlist entry */
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek return uidlist_entry_remove_uids(ctx, sync_entry);
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek}
55d80b1301fe969fb4ba2b9481027887b9462dbbJakub Hrozek