mbox-sync.c revision 99be58a447b69d62cbd9e764000a06226b9c9c89
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (C) 2004 Timo Sirainen */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/*
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen Modifying mbox can be slow, so we try to do it all at once minimizing the
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen required disk I/O. We may need to:
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - Update message flags in Status, X-Status and X-Keywords headers
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - Write missing X-UID and X-IMAPbase headers
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - Write missing or broken Content-Length header if there's space
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - Expunge specified messages
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen Here's how we do it:
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - Start reading the mails mail headers from the beginning
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - X-Keywords and X-UID headers may contain extra spaces at the end of them,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen remember how much extra each message has and offset to beginning of the
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen spaces
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - If message flags are dirty and there's enough space to write them, do it
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - If we didn't have enough space, remember how much was missing and keep
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen the total amount of them
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - When we encounter expunged message, check if the amount of empty space in
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen previous messages plus size of expunged message is enough to cover the
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen missing space. If yes,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - execute the rewrite plan
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - forget all the messages before the expunged message. only remember
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen how much data we still have to move to cover the expunged message
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - If we encounter end of file, grow the file and execute the rewrite plan
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen Rewrite plan goes:
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - Start from the first message that needs more space
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - If there's expunged messages before us, we have to write over them.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - Move all messages after it backwards to fill it
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - Each moved message's X-Keywords header should have n bytes extra
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen space, unless there's not enough space to do it.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - If there's no expunged messages, we can move data either forward or
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen backward to get it. Calculate which requires less moving. Forward
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen counting may encounter more messages which require extra space, count
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen that too.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - If we decide to move forwards and we had to go through dirty
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen messages, do the moving from last to first dirty message
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - If we encounter end of file, grow the file enough to get the required
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen amount of space plus enough space to fill X-Keywords headers full of
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen spaces.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen*/
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "ioloop.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "buffer.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "istream.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "file-set-size.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "str.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "write-full.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "istream-raw-mbox.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "mbox-storage.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "mbox-file.h"
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen#include "mbox-lock.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mbox-sync-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen#include <stddef.h>
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include <sys/stat.h>
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen#define MBOX_SYNC_SECS 1
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen/* returns -1 = error, 0 = mbox changed since previous lock, 1 = didn't */
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainenstatic int mbox_sync_lock(struct mbox_sync_context *sync_ctx, int lock_type)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen{
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen struct index_mailbox *ibox = sync_ctx->ibox;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen struct stat old_st, st;
d17a90f5ae38edc8c0e6bf42c2162c9c18edb891Timo Sirainen uoff_t old_from_offset = 0, old_offset = 0;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
3f190f4cbb9233a3a6830956cb5c7ae56a577b79Timo Sirainen i_assert(lock_type != F_WRLCK || !ibox->mbox_readonly);
3f190f4cbb9233a3a6830956cb5c7ae56a577b79Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (sync_ctx->lock_id != 0) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (fstat(sync_ctx->fd, &old_st) < 0) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen mbox_set_syscall_error(ibox, "stat()");
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return -1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen }
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen old_from_offset =
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen istream_raw_mbox_get_start_offset(sync_ctx->input);
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen old_offset = sync_ctx->input->v_offset;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen (void)mbox_unlock(ibox, sync_ctx->lock_id);
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen sync_ctx->lock_id = 0;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen } else {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen memset(&old_st, 0, sizeof(old_st));
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen }
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (mbox_lock(ibox, lock_type, &sync_ctx->lock_id) <= 0)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return -1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (mbox_file_open_stream(ibox) < 0)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return -1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen sync_ctx->file_input = sync_ctx->ibox->mbox_file_stream;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen sync_ctx->input = sync_ctx->ibox->mbox_stream;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen sync_ctx->fd = sync_ctx->ibox->mbox_fd;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (old_st.st_mtime == 0) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen /* we didn't have the file open before -> it changed */
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return 0;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen }
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (fstat(sync_ctx->fd, &st) < 0) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen mbox_set_syscall_error(ibox, "fstat()");
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return -1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen }
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (st.st_mtime != old_st.st_mtime || st.st_size != old_st.st_size ||
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen st.st_ino != old_st.st_ino ||
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen !CMP_DEV_T(st.st_dev, old_st.st_dev) ||
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen time(NULL) - st.st_mtime <= MBOX_SYNC_SECS)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return 0;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen /* same as before. we'll have to fix mbox stream to contain
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen correct from_offset, hdr_offset and body_offset. so, seek
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen to from_offset and read through the header. */
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen if (istream_raw_mbox_seek(sync_ctx->input, old_from_offset) < 0) {
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen mail_storage_set_critical(ibox->box.storage,
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen "Message offset %s changed unexpectedly for mbox file "
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen "%s", dec2str(old_from_offset), sync_ctx->ibox->path);
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen return 0;
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen }
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen (void)istream_raw_mbox_get_body_offset(sync_ctx->input);
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen i_stream_seek(sync_ctx->input, old_offset);
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return 1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen}
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainenint mbox_sync_seek(struct mbox_sync_context *sync_ctx, uoff_t from_offset)
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen{
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen if (istream_raw_mbox_seek(sync_ctx->input, from_offset) < 0) {
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen mail_storage_set_critical(sync_ctx->ibox->box.storage,
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen "Unexpectedly lost From-line at offset %"PRIuUOFF_T
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen " from mbox file %s", from_offset,
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen sync_ctx->ibox->path);
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen return -1;
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen }
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen return 0;
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen}
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int mbox_sync_grow_file(struct mbox_sync_context *sync_ctx,
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen struct mbox_sync_mail_context *mail_ctx,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uoff_t grow_size)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen uoff_t src_offset, file_size;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(grow_size > 0);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen /* put the extra space between last message's header and body */
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen file_size = i_stream_get_size(sync_ctx->file_input) + grow_size;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (file_set_size(sync_ctx->fd, file_size) < 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mbox_set_syscall_error(sync_ctx->ibox, "file_set_size()");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen src_offset = mail_ctx->body_offset;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen mail_ctx->body_offset += grow_size;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (mbox_move(sync_ctx, mail_ctx->body_offset, src_offset,
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen file_size - mail_ctx->body_offset) < 0)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen istream_raw_mbox_flush(sync_ctx->input);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
659fe5d24825b160cae512538088020d97a60239Timo Sirainenstatic void mbox_sync_buffer_delete_old(buffer_t *syncs_buf, uint32_t uid)
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen{
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen struct mail_index_sync_rec *sync;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen size_t size, src, dest;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen sync = buffer_get_modifyable_data(syncs_buf, &size);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen size /= sizeof(*sync);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen for (src = dest = 0; src < size; src++) {
659fe5d24825b160cae512538088020d97a60239Timo Sirainen if (sync[src].uid2 >= uid) {
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen if (src != dest)
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen sync[dest] = sync[src];
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen dest++;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen buffer_set_used_size(syncs_buf, dest * sizeof(*sync));
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen}
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic int
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenmbox_sync_read_next_mail(struct mbox_sync_context *sync_ctx,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen struct mbox_sync_mail_context *mail_ctx)
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen{
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainen /* get EOF */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen (void)istream_raw_mbox_get_header_offset(sync_ctx->input);
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainen if (istream_raw_mbox_is_eof(sync_ctx->input))
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen memset(mail_ctx, 0, sizeof(*mail_ctx));
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mail_ctx->sync_ctx = sync_ctx;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_ctx->seq = ++sync_ctx->seq;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mail_ctx->header = sync_ctx->header;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen mail_ctx->from_offset =
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen istream_raw_mbox_get_start_offset(sync_ctx->input);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mail_ctx->mail.offset =
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen istream_raw_mbox_get_header_offset(sync_ctx->input);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainen if (mail_ctx->seq == 1)
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainen sync_ctx->seen_first_mail = TRUE;
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen if (mail_ctx->seq > 1 && sync_ctx->dest_first_mail) {
96c253a039f102fa78a313ee05200ab3970112dcTimo Sirainen /* First message was expunged and this is the next one.
96c253a039f102fa78a313ee05200ab3970112dcTimo Sirainen Skip \n header */
96c253a039f102fa78a313ee05200ab3970112dcTimo Sirainen mail_ctx->from_offset++;
96c253a039f102fa78a313ee05200ab3970112dcTimo Sirainen }
96c253a039f102fa78a313ee05200ab3970112dcTimo Sirainen
3cfff0ca01961d885bdbd6ef08d761880116af07Timo Sirainen mbox_sync_parse_next_mail(sync_ctx->input, mail_ctx, FALSE);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen i_assert(sync_ctx->input->v_offset != mail_ctx->from_offset);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mail_ctx->mail.body_size =
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen istream_raw_mbox_get_body_size(sync_ctx->input,
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mail_ctx->content_length);
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen i_assert(mail_ctx->mail.body_size < OFF_T_MAX);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen /* save the offset permanently with recent flag state */
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen mail_ctx->mail.from_offset = mail_ctx->from_offset;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if ((mail_ctx->mail.flags & MBOX_NONRECENT) == 0) {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen /* need to add 'O' flag to Status-header */
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen mail_ctx->need_rewrite = TRUE;
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen // FIXME: save it somewhere
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainenstatic int mbox_sync_buf_have_expunges(buffer_t *syncs_buf)
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen{
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen const struct mail_index_sync_rec *sync;
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen size_t size, i;
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen sync = buffer_get_data(syncs_buf, &size);
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen size /= sizeof(*sync);
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen for (i = 0; i < size; i++) {
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen if (sync[i].type == MAIL_INDEX_SYNC_TYPE_EXPUNGE)
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen return TRUE;
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen }
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen return FALSE;
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen}
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic int mbox_sync_read_index_syncs(struct mbox_sync_context *sync_ctx,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen uint32_t uid, int *sync_expunge_r)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen{
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen struct mail_index_sync_rec *sync_rec = &sync_ctx->sync_rec;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen int ret;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen *sync_expunge_r = FALSE;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
3f190f4cbb9233a3a6830956cb5c7ae56a577b79Timo Sirainen if (sync_ctx->ibox->mbox_readonly || sync_ctx->index_sync_ctx == NULL)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mbox_sync_buffer_delete_old(sync_ctx->syncs, uid);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen while (uid >= sync_rec->uid1) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (sync_rec->uid1 != 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen i_assert(uid <= sync_rec->uid2);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen buffer_append(sync_ctx->syncs, sync_rec,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sizeof(*sync_rec));
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (sync_rec->type == MAIL_INDEX_SYNC_TYPE_EXPUNGE)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen *sync_expunge_r = TRUE;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ret = mail_index_sync_next(sync_ctx->index_sync_ctx, sync_rec);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (ret < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (ret == 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen memset(sync_rec, 0, sizeof(*sync_rec));
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen break;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen if (!*sync_expunge_r)
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen *sync_expunge_r = mbox_sync_buf_have_expunges(sync_ctx->syncs);
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen}
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainenstatic void mbox_sync_apply_index_syncs(buffer_t *syncs_buf, uint8_t *flags,
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen keywords_mask_t keywords)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen{
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen const struct mail_index_sync_rec *sync;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen size_t size, i;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen sync = buffer_get_data(syncs_buf, &size);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen size /= sizeof(*sync);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen for (i = 0; i < size; i++) {
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen if (sync[i].type != MAIL_INDEX_SYNC_TYPE_FLAGS)
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen continue;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen mail_index_sync_flags_apply(&sync[i], flags, keywords);
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen }
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen}
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic int
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenmbox_sync_read_index_rec(struct mbox_sync_context *sync_ctx,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen uint32_t uid, const struct mail_index_record **rec_r)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen{
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen const struct mail_index_record *rec = NULL;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen uint32_t messages_count;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen messages_count = mail_index_view_get_message_count(sync_ctx->sync_view);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen while (sync_ctx->idx_seq < messages_count) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mail_index_lookup(sync_ctx->sync_view,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ++sync_ctx->idx_seq, &rec) < 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_storage_set_index_error(sync_ctx->ibox);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (uid <= rec->uid)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen break;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* externally expunged message, remove from index */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_index_expunge(sync_ctx->t, sync_ctx->idx_seq);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen rec = NULL;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (rec != NULL && rec->uid != uid) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* new UID in the middle of the mailbox - shouldn't happen */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_storage_set_critical(sync_ctx->ibox->box.storage,
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen "mbox sync: UID inserted in the middle of mailbox %s "
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen "(%u > %u)", sync_ctx->ibox->path, rec->uid, uid);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_index_mark_corrupted(sync_ctx->ibox->index);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen *rec_r = rec;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainenstatic int mbox_sync_get_from_offset(struct mbox_sync_context *sync_ctx,
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen uint32_t seq, uint64_t *offset_r)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen{
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen const void *data;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen /* see if from_offset needs updating */
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (mail_index_lookup_extra(sync_ctx->sync_view, seq,
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen sync_ctx->ibox->mbox_extra_idx,
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen &data) < 0) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen mail_storage_set_index_error(sync_ctx->ibox);
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return -1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen }
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen *offset_r = *((const uint64_t *)data);
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return 0;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen}
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic int
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenmbox_sync_update_from_offset(struct mbox_sync_context *sync_ctx,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen struct mbox_sync_mail *mail,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen int nocheck)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen{
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen uint64_t offset;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (!nocheck) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (mbox_sync_get_from_offset(sync_ctx, sync_ctx->idx_seq,
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen &offset) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (offset == mail->from_offset)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen } else {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen offset = mail->from_offset;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_index_update_extra_rec(sync_ctx->t, sync_ctx->idx_seq,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->ibox->mbox_extra_idx, &offset);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic int mbox_sync_update_index(struct mbox_sync_context *sync_ctx,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen struct mbox_sync_mail *mail,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen const struct mail_index_record *rec)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen{
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen keywords_mask_t idx_keywords;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen uint8_t idx_flags, mbox_flags;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (rec == NULL) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* new message */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_index_append(sync_ctx->t, mail->uid, &sync_ctx->idx_seq);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mbox_flags = mail->flags & (MAIL_FLAGS_MASK^MAIL_RECENT);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_index_update_flags(sync_ctx->t, sync_ctx->idx_seq,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen MODIFY_REPLACE, mbox_flags,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail->keywords);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen } else {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* see if flags changed */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen idx_flags = rec->flags;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen memcpy(idx_keywords, rec->keywords, INDEX_KEYWORDS_BYTE_COUNT);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mbox_sync_apply_index_syncs(sync_ctx->syncs,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen &idx_flags, idx_keywords);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mbox_flags = (rec->flags & ~MAIL_FLAGS_MASK) |
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen (mail->flags & (MAIL_FLAGS_MASK^MAIL_RECENT));
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (idx_flags != mbox_flags ||
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen memcmp(idx_keywords, mail->keywords,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen INDEX_KEYWORDS_BYTE_COUNT) != 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_index_update_flags(sync_ctx->t, sync_ctx->idx_seq,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen MODIFY_REPLACE, mbox_flags,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail->keywords);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* update from_offsets, but not if we're going to rewrite this message.
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen rewriting would just move it anyway. */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (sync_ctx->need_space_seq == 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen int nocheck = rec == NULL || sync_ctx->expunged_space > 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mbox_sync_update_from_offset(sync_ctx, mail, nocheck) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainenstatic int mbox_read_from_line(struct mbox_sync_mail_context *ctx)
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen{
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen struct istream *input = ctx->sync_ctx->file_input;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen const unsigned char *data;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen size_t size, from_line_size;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen buffer_set_used_size(ctx->sync_ctx->from_line, 0);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen from_line_size = ctx->hdr_offset - ctx->from_offset;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen i_stream_seek(input, ctx->from_offset);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen for (;;) {
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen data = i_stream_get_data(input, &size);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (size >= from_line_size)
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen size = from_line_size;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen buffer_append(ctx->sync_ctx->from_line, data, size);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen i_stream_skip(input, size);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen from_line_size -= size;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (from_line_size == 0)
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen break;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (i_stream_read(input) < 0)
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen return -1;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen }
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen return 0;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen}
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainenstatic int
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainenmbox_write_from_line(struct mbox_sync_mail_context *ctx, off_t move_diff)
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen{
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen string_t *str = ctx->sync_ctx->from_line;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (pwrite_full(ctx->sync_ctx->fd, str_data(str), str_len(str),
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen ctx->from_offset + move_diff) < 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mbox_set_syscall_error(ctx->sync_ctx->ibox, "pwrite_full()");
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen return -1;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen }
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen istream_raw_mbox_flush(ctx->sync_ctx->input);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen return 0;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen}
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainenstatic void
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainenupdate_from_offsets(struct index_mailbox *ibox,
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen struct mail_index_transaction *t, buffer_t *mails_buf,
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen uint32_t seq1, uint32_t seq2)
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen{
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen const struct mbox_sync_mail *mails;
ab3c1eab9ca13916358a9e8b12df8212fefb7dbfTimo Sirainen uint32_t extra_idx = ibox->mbox_extra_idx;
ab3c1eab9ca13916358a9e8b12df8212fefb7dbfTimo Sirainen uint64_t offset;
99be58a447b69d62cbd9e764000a06226b9c9c89Timo Sirainen size_t size;
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen
99be58a447b69d62cbd9e764000a06226b9c9c89Timo Sirainen mails = buffer_get_modifyable_data(mails_buf, &size);
99be58a447b69d62cbd9e764000a06226b9c9c89Timo Sirainen i_assert((seq2-seq1+1) * sizeof(*mails) == size);
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen for (; seq1 <= seq2; seq1++, mails++) {
ab3c1eab9ca13916358a9e8b12df8212fefb7dbfTimo Sirainen if (mails->uid != 0) {
ab3c1eab9ca13916358a9e8b12df8212fefb7dbfTimo Sirainen offset = mails->from_offset;
ab3c1eab9ca13916358a9e8b12df8212fefb7dbfTimo Sirainen mail_index_update_extra_rec(t, seq1, extra_idx,
ab3c1eab9ca13916358a9e8b12df8212fefb7dbfTimo Sirainen &offset);
ab3c1eab9ca13916358a9e8b12df8212fefb7dbfTimo Sirainen }
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen }
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen}
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainenstatic int mbox_sync_check_excl_lock(struct mbox_sync_context *sync_ctx)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen{
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen int ret;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (sync_ctx->ibox->mbox_lock_type == F_RDLCK) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if ((ret = mbox_sync_lock(sync_ctx, F_WRLCK)) < 0)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return -1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (ret == 0)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return -2;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen }
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return 0;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen}
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic int mbox_sync_handle_expunge(struct mbox_sync_mail_context *mail_ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen int ret;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if ((ret = mbox_sync_check_excl_lock(mail_ctx->sync_ctx)) < 0)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return ret;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_ctx->mail.offset = mail_ctx->from_offset;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_ctx->mail.space =
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_ctx->body_offset - mail_ctx->from_offset +
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_ctx->mail.body_size;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_ctx->mail.body_size = 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen if (mail_ctx->sync_ctx->dest_first_mail) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* expunging first message, fix space to contain next
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen message's \n header too since it will be removed. */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_ctx->mail.space++;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_ctx->sync_ctx->expunged_space += mail_ctx->mail.space;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic int mbox_sync_handle_header(struct mbox_sync_mail_context *mail_ctx)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen{
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen struct mbox_sync_context *sync_ctx = mail_ctx->sync_ctx;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen off_t move_diff;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen int ret;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
3f190f4cbb9233a3a6830956cb5c7ae56a577b79Timo Sirainen if (sync_ctx->ibox->mbox_readonly)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (sync_ctx->expunged_space > 0 && sync_ctx->need_space_seq == 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* move the header backwards to fill expunged space */
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if ((ret = mbox_sync_check_excl_lock(sync_ctx)) < 0)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return ret;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen move_diff = -sync_ctx->expunged_space;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* read the From-line before rewriting overwrites it */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mbox_read_from_line(mail_ctx) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mbox_sync_update_header(mail_ctx, sync_ctx->syncs);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if ((ret = mbox_sync_try_rewrite(mail_ctx, move_diff)) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (ret > 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* rewrite successful, write From-line to
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen new location */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_ctx->mail.from_offset += move_diff;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_ctx->mail.offset += move_diff;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mbox_write_from_line(mail_ctx, move_diff) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen } else if (mail_ctx->need_rewrite ||
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen buffer_get_used_size(sync_ctx->syncs) != 0) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if ((ret = mbox_sync_check_excl_lock(sync_ctx)) < 0)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return ret;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mbox_sync_update_header(mail_ctx, sync_ctx->syncs);
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if ((ret = mbox_sync_try_rewrite(mail_ctx, 0)) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen } else {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* nothing to do */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (ret == 0 && sync_ctx->need_space_seq == 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* first mail with no space to write it */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->need_space_seq = sync_ctx->seq;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->space_diff = 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (sync_ctx->expunged_space > 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* create dummy message to describe the expunged data */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen struct mbox_sync_mail mail;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen memset(&mail, 0, sizeof(mail));
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail.offset = mail_ctx->from_offset -
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->expunged_space;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail.space = sync_ctx->expunged_space;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->need_space_seq--;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen buffer_append(sync_ctx->mails, &mail, sizeof(mail));
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic int
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenmbox_sync_handle_missing_space(struct mbox_sync_mail_context *mail_ctx)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen{
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen struct mbox_sync_context *sync_ctx = mail_ctx->sync_ctx;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen uoff_t extra_space;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen buffer_append(sync_ctx->mails, &mail_ctx->mail, sizeof(mail_ctx->mail));
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->space_diff += mail_ctx->mail.space;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (sync_ctx->space_diff < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* we have enough space now */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen extra_space = MBOX_HEADER_EXTRA_SPACE *
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen (sync_ctx->seq - sync_ctx->need_space_seq + 1);
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mail_ctx->mail.uid == 0 &&
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen (uoff_t)sync_ctx->space_diff > extra_space) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* don't waste too much on extra spacing */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->expunged_space = sync_ctx->space_diff - extra_space;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->space_diff = extra_space;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen } else {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->expunged_space = 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
a205d315b0978985ba77d871f44e4a98273612e6Timo Sirainen if (mbox_sync_rewrite(sync_ctx, sync_ctx->space_diff,
a205d315b0978985ba77d871f44e4a98273612e6Timo Sirainen sync_ctx->need_space_seq, sync_ctx->seq) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen update_from_offsets(sync_ctx->ibox, sync_ctx->t, sync_ctx->mails,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->need_space_seq, sync_ctx->seq);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* mail_ctx may contain wrong data after rewrite, so make sure we
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen don't try to access it */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen memset(mail_ctx, 0, sizeof(*mail_ctx));
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->need_space_seq = 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen buffer_set_used_size(sync_ctx->mails, 0);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainenstatic int
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainenmbox_sync_seek_to_uid(struct mbox_sync_context *sync_ctx, uint32_t uid)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen{
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen uint32_t seq;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen uint64_t offset;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (mail_index_lookup_uid_range(sync_ctx->sync_view, uid, uid,
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen &seq, &seq) < 0)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return -1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (seq == 0)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return 0;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (mbox_sync_get_from_offset(sync_ctx, seq, &offset) < 0)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return -1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen /* set to -1, since they're always increased later */
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen sync_ctx->seq = sync_ctx->idx_seq = seq-1;
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen sync_ctx->dest_first_mail = sync_ctx->seq == 0;
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen if (istream_raw_mbox_seek(sync_ctx->input, offset) < 0) {
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen mail_storage_set_critical(sync_ctx->ibox->box.storage,
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen "Cached message offset %s is invalid for mbox file %s",
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen dec2str(offset), sync_ctx->ibox->path);
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen mail_index_mark_corrupted(sync_ctx->ibox->index);
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen return -1;
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen }
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen (void)istream_raw_mbox_get_body_offset(sync_ctx->input);
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return 0;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen}
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainenstatic int mbox_sync_loop(struct mbox_sync_context *sync_ctx,
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen struct mbox_sync_mail_context *mail_ctx,
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen uint32_t min_message_count)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen{
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen const struct mail_index_record *rec;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen uint32_t uid, messages_count;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen uoff_t offset;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen int ret, expunged;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen if (min_message_count != 0) {
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen if (istream_raw_mbox_seek(sync_ctx->input, 0) < 0) {
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen /* doesn't begin with a From-line */
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen mail_storage_set_error(sync_ctx->ibox->box.storage,
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen "Mailbox isn't a valid mbox file");
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen return -1;
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen }
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen sync_ctx->dest_first_mail = TRUE;
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen } else {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen /* we sync only what we need to. jump to first record that
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen needs updating */
f1b7a02a05fbca580934c7312aae63ea9542aa79Timo Sirainen const struct mail_index_sync_rec *sync_rec;
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen size_t size;
f1b7a02a05fbca580934c7312aae63ea9542aa79Timo Sirainen
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen if (buffer_get_used_size(sync_ctx->syncs) == 0 &&
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen sync_ctx->sync_rec.uid1 == 0) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (mbox_sync_read_index_syncs(sync_ctx, 1,
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen &expunged) < 0)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return -1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen if (buffer_get_used_size(sync_ctx->syncs) == 0 &&
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen sync_ctx->sync_rec.uid1 == 0) {
f1b7a02a05fbca580934c7312aae63ea9542aa79Timo Sirainen /* nothing to do */
f1b7a02a05fbca580934c7312aae63ea9542aa79Timo Sirainen return 0;
f1b7a02a05fbca580934c7312aae63ea9542aa79Timo Sirainen }
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen }
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen sync_rec = buffer_get_data(sync_ctx->syncs, &size);
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen if (size == 0)
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen sync_rec = &sync_ctx->sync_rec;
f1b7a02a05fbca580934c7312aae63ea9542aa79Timo Sirainen if (mbox_sync_seek_to_uid(sync_ctx, sync_rec->uid1) < 0)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return -1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen while ((ret = mbox_sync_read_next_mail(sync_ctx, mail_ctx)) > 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen uid = mail_ctx->mail.uid;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* get all sync records related to this message */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mbox_sync_read_index_syncs(sync_ctx, uid, &expunged) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen if (!expunged) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ret = mbox_sync_handle_header(mail_ctx);
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen sync_ctx->dest_first_mail = FALSE;
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen } else {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_ctx->mail.uid = 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ret = mbox_sync_handle_expunge(mail_ctx);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (ret < 0) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen /* -1 = error, -2 = need to restart */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return ret;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen }
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mbox_sync_read_index_rec(sync_ctx, uid, &rec) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (!expunged) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mbox_sync_update_index(sync_ctx, &mail_ctx->mail,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen rec) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen }
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen istream_raw_mbox_next(sync_ctx->input,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_ctx->mail.body_size);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen offset = istream_raw_mbox_get_start_offset(sync_ctx->input);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (sync_ctx->need_space_seq != 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mbox_sync_handle_missing_space(mail_ctx) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen if (mbox_sync_seek(sync_ctx, offset) < 0)
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen return -1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen } else if (sync_ctx->expunged_space > 0) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (!expunged) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen /* move the body */
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (mbox_move(sync_ctx,
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen mail_ctx->body_offset -
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen sync_ctx->expunged_space,
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen mail_ctx->body_offset,
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen mail_ctx->mail.body_size) < 0)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return -1;
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen if (mbox_sync_seek(sync_ctx, offset) < 0)
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen return -1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen }
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen } else if (sync_ctx->seq >= min_message_count) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen mbox_sync_buffer_delete_old(sync_ctx->syncs, uid+1);
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (buffer_get_used_size(sync_ctx->syncs) == 0) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen /* if there's no sync records left,
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen we can stop */
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (sync_ctx->sync_rec.uid1 == 0)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen break;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen /* we can skip forward to next record which
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen needs updating. */
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen uid = sync_ctx->sync_rec.uid1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (mbox_sync_seek_to_uid(sync_ctx, uid) < 0)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return -1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainen if (istream_raw_mbox_is_eof(sync_ctx->input)) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen /* rest of the messages in index don't exist -> expunge them */
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen messages_count =
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen mail_index_view_get_message_count(sync_ctx->sync_view);
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen while (sync_ctx->idx_seq < messages_count)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen mail_index_expunge(sync_ctx->t, ++sync_ctx->idx_seq);
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen }
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
3cfff0ca01961d885bdbd6ef08d761880116af07Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic int mbox_sync_handle_eof_updates(struct mbox_sync_context *sync_ctx,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen struct mbox_sync_mail_context *mail_ctx)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen{
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen uoff_t offset, extra_space, trailer_size;
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainen if (!istream_raw_mbox_is_eof(sync_ctx->input)) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen i_assert(sync_ctx->need_space_seq == 0);
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen i_assert(sync_ctx->expunged_space == 0);
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return 0;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen }
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen trailer_size = i_stream_get_size(sync_ctx->file_input) -
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->file_input->v_offset;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (sync_ctx->need_space_seq != 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen i_assert(sync_ctx->space_diff < 0);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen extra_space = MBOX_HEADER_EXTRA_SPACE *
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen (sync_ctx->seq - sync_ctx->need_space_seq + 1);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->space_diff -= extra_space;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->space_diff += sync_ctx->expunged_space;
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen if (sync_ctx->expunged_space <= -sync_ctx->space_diff)
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen sync_ctx->expunged_space = 0;
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen else
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen sync_ctx->expunged_space -= -sync_ctx->space_diff;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mail_ctx->have_eoh && !mail_ctx->updated)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen str_append_c(mail_ctx->header, '\n');
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (sync_ctx->space_diff < 0 &&
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mbox_sync_grow_file(sync_ctx, mail_ctx,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen -sync_ctx->space_diff) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mbox_sync_try_rewrite(mail_ctx, 0) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (sync_ctx->seq != sync_ctx->need_space_seq) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen buffer_set_used_size(sync_ctx->mails,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen (sync_ctx->seq -
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->need_space_seq) *
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sizeof(mail_ctx->mail));
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen buffer_append(sync_ctx->mails, &mail_ctx->mail,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sizeof(mail_ctx->mail));
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
a205d315b0978985ba77d871f44e4a98273612e6Timo Sirainen if (mbox_sync_rewrite(sync_ctx, extra_space,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->need_space_seq,
a205d315b0978985ba77d871f44e4a98273612e6Timo Sirainen sync_ctx->seq) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
99be58a447b69d62cbd9e764000a06226b9c9c89Timo Sirainen update_from_offsets(sync_ctx->ibox, sync_ctx->t,
99be58a447b69d62cbd9e764000a06226b9c9c89Timo Sirainen sync_ctx->mails,
99be58a447b69d62cbd9e764000a06226b9c9c89Timo Sirainen sync_ctx->need_space_seq, sync_ctx->seq);
99be58a447b69d62cbd9e764000a06226b9c9c89Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen sync_ctx->need_space_seq = 0;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen buffer_set_used_size(sync_ctx->mails, 0);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (sync_ctx->expunged_space > 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* copy trailer, then truncate the file */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen offset = i_stream_get_size(sync_ctx->file_input) -
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->expunged_space - trailer_size;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mbox_move(sync_ctx, offset,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen offset + sync_ctx->expunged_space,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen trailer_size) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (ftruncate(sync_ctx->fd, offset + trailer_size) < 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mbox_set_syscall_error(sync_ctx->ibox, "ftruncate()");
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen sync_ctx->expunged_space = 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen istream_raw_mbox_flush(sync_ctx->input);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic int mbox_sync_update_index_header(struct mbox_sync_context *sync_ctx)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen{
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen struct stat st;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (fstat(sync_ctx->fd, &st) < 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mbox_set_syscall_error(sync_ctx->ibox, "fstat()");
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
292a66475ffe1037c2535063614f8beb71d266bfTimo Sirainen if ((sync_ctx->base_uid_validity != 0 &&
292a66475ffe1037c2535063614f8beb71d266bfTimo Sirainen sync_ctx->base_uid_validity != sync_ctx->hdr->uid_validity) ||
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainen (sync_ctx->hdr->uid_validity == 0 && sync_ctx->seen_first_mail)) {
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainen if (sync_ctx->base_uid_validity == 0) {
292a66475ffe1037c2535063614f8beb71d266bfTimo Sirainen /* we couldn't rewrite X-IMAPbase because it's
292a66475ffe1037c2535063614f8beb71d266bfTimo Sirainen a read-only mbox */
292a66475ffe1037c2535063614f8beb71d266bfTimo Sirainen i_assert(sync_ctx->ibox->mbox_readonly);
292a66475ffe1037c2535063614f8beb71d266bfTimo Sirainen sync_ctx->base_uid_validity = time(NULL);
292a66475ffe1037c2535063614f8beb71d266bfTimo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_index_update_header(sync_ctx->t,
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen offsetof(struct mail_index_header, uid_validity),
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen &sync_ctx->base_uid_validity,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sizeof(sync_ctx->base_uid_validity));
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen }
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainen
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainen if (istream_raw_mbox_is_eof(sync_ctx->input) &&
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen sync_ctx->next_uid != sync_ctx->hdr->next_uid) {
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen i_assert(sync_ctx->next_uid != 0);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_index_update_header(sync_ctx->t,
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen offsetof(struct mail_index_header, next_uid),
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen &sync_ctx->next_uid, sizeof(sync_ctx->next_uid));
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen }
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if ((uint32_t)st.st_mtime != sync_ctx->hdr->sync_stamp) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen uint32_t sync_stamp = st.st_mtime;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_index_update_header(sync_ctx->t,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen offsetof(struct mail_index_header, sync_stamp),
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen &sync_stamp, sizeof(sync_stamp));
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if ((uint64_t)st.st_size != sync_ctx->hdr->sync_size) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen uint64_t sync_size = st.st_size;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_index_update_header(sync_ctx->t,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen offsetof(struct mail_index_header, sync_size),
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen &sync_size, sizeof(sync_size));
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic void mbox_sync_restart(struct mbox_sync_context *sync_ctx)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen{
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->base_uid_validity = 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->base_uid_last = 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->next_uid = 1;
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen sync_ctx->prev_msg_uid = 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->seq = sync_ctx->idx_seq = 0;
325f4573edfa5b751832ac01023f3e81be992bf0Timo Sirainen
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainen sync_ctx->dest_first_mail = TRUE;
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainen sync_ctx->seen_first_mail = FALSE;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainenstatic int mbox_sync_do(struct mbox_sync_context *sync_ctx)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen{
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen struct mbox_sync_mail_context mail_ctx;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen struct stat st;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen uint32_t min_msg_count;
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen int ret;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (fstat(sync_ctx->fd, &st) < 0) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen mbox_set_syscall_error(sync_ctx->ibox, "stat()");
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen min_msg_count =
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen (uint32_t)st.st_mtime == sync_ctx->hdr->sync_stamp &&
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen (uint64_t)st.st_size == sync_ctx->hdr->sync_size ?
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen 0 : (uint32_t)-1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen mbox_sync_restart(sync_ctx);
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if ((ret = mbox_sync_loop(sync_ctx, &mail_ctx, min_msg_count)) == -1)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (ret == -2) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen /* initially we had mbox read-locked, but later we needed a
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen write-lock. doing it required dropping the read lock.
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen we're here because mbox was modified before we got the
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen write-lock. so, restart the whole syncing. */
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen i_assert(sync_ctx->ibox->mbox_lock_type == F_WRLCK);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen mail_index_transaction_rollback(sync_ctx->t);
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen sync_ctx->t = mail_index_transaction_begin(sync_ctx->sync_view,
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen FALSE);
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mbox_sync_restart(sync_ctx);
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (mbox_sync_loop(sync_ctx, &mail_ctx, (uint32_t)-1) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mbox_sync_handle_eof_updates(sync_ctx, &mail_ctx) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen /* only syncs left should be just appends (and their updates)
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen which weren't synced yet for some reason (crash). we'll just
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen ignore them, as we've overwritten them above. */
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen buffer_set_used_size(sync_ctx->syncs, 0);
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen memset(&sync_ctx->sync_rec, 0, sizeof(sync_ctx->sync_rec));
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mbox_sync_update_index_header(sync_ctx) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen}
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainenstatic int mbox_sync_has_changed(struct index_mailbox *ibox)
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen{
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen const struct mail_index_header *hdr;
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen struct stat st;
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen if (mail_index_get_header(ibox->view, &hdr) < 0) {
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen mail_storage_set_index_error(ibox);
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen return -1;
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen }
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen if (stat(ibox->path, &st) < 0) {
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen mbox_set_syscall_error(ibox, "stat()");
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen return -1;
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen }
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen return (uint32_t)st.st_mtime != hdr->sync_stamp ||
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen (uint64_t)st.st_size != hdr->sync_size;
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen}
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainenstatic int mbox_sync_update_imap_base(struct mbox_sync_context *sync_ctx)
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen{
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen struct mbox_sync_mail_context mail_ctx;
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen if (mbox_sync_seek(sync_ctx, 0) < 0)
1750a5daf336f2bf921b3ec2cc2a93c5cd19f7b8Timo Sirainen return -1;
1750a5daf336f2bf921b3ec2cc2a93c5cd19f7b8Timo Sirainen
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen sync_ctx->t = mail_index_transaction_begin(sync_ctx->sync_view, FALSE);
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen sync_ctx->update_base_uid_last = sync_ctx->next_uid-1;
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
d17a90f5ae38edc8c0e6bf42c2162c9c18edb891Timo Sirainen if (mbox_sync_check_excl_lock(sync_ctx) == -1)
d17a90f5ae38edc8c0e6bf42c2162c9c18edb891Timo Sirainen return -1;
d17a90f5ae38edc8c0e6bf42c2162c9c18edb891Timo Sirainen
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen mbox_sync_restart(sync_ctx);
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen if (mbox_sync_loop(sync_ctx, &mail_ctx, 1) < 0)
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen return -1;
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen if (mbox_sync_handle_eof_updates(sync_ctx, &mail_ctx) < 0)
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen return -1;
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen if (mbox_sync_update_index_header(sync_ctx) < 0)
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen return -1;
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen return 0;
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen}
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainenint mbox_sync(struct index_mailbox *ibox, int last_commit, int lock)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen{
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen struct mail_index_sync_ctx *index_sync_ctx;
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen struct mail_index_view *sync_view;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen struct mbox_sync_context sync_ctx;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen uint32_t seq;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen uoff_t offset;
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen unsigned int lock_id = 0;
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen int ret, lock_type;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen if (lock) {
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen if (mbox_lock(ibox, F_RDLCK, &lock_id) <= 0)
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen return -1;
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen }
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen if ((ret = mbox_sync_has_changed(ibox)) < 0) {
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen if (lock)
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen (void)mbox_unlock(ibox, lock_id);
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen return -1;
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen }
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen if (ret == 0 && !last_commit)
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen return 0;
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (last_commit) {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen seq = ibox->commit_log_file_seq;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen offset = ibox->commit_log_file_offset;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen } else {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen seq = (uint32_t)-1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen offset = (uoff_t)-1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen ret = mail_index_sync_begin(ibox->index, &index_sync_ctx, &sync_view,
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen seq, offset);
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen if (ret <= 0) {
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen if (ret < 0)
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen mail_storage_set_index_error(ibox);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen return ret;
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen }
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen memset(&sync_ctx, 0, sizeof(sync_ctx));
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx.ibox = ibox;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx.from_line = str_new(default_pool, 256);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx.header = str_new(default_pool, 4096);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx.index_sync_ctx = index_sync_ctx;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx.sync_view = sync_view;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx.t = mail_index_transaction_begin(sync_view, FALSE);
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx.mails = buffer_create_dynamic(default_pool, 4096, (size_t)-1);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx.syncs = buffer_create_dynamic(default_pool, 256, (size_t)-1);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ret = mail_index_get_header(sync_view, &sync_ctx.hdr);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen i_assert(ret == 0);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
ce87b6ad8740cc66c5ab232081a2b4a535ff91aeTimo Sirainen lock_type = mail_index_sync_have_more(index_sync_ctx) &&
ce87b6ad8740cc66c5ab232081a2b4a535ff91aeTimo Sirainen !ibox->mbox_readonly ? F_WRLCK : F_RDLCK;
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen if (lock_type == F_WRLCK && lock) {
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen (void)mbox_unlock(ibox, lock_id);
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen lock_id = 0;
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen }
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen if (mbox_sync_lock(&sync_ctx, lock_type) < 0)
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen return -1;
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (mbox_sync_do(&sync_ctx) < 0)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen ret = -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (ret < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_index_transaction_rollback(sync_ctx.t);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen else if (mail_index_transaction_commit(sync_ctx.t, &seq, &offset) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ret = -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen else {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ibox->commit_log_file_seq = 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ibox->commit_log_file_offset = 0;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen sync_ctx.t = NULL;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mail_index_sync_end(index_sync_ctx) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ret = -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
3f190f4cbb9233a3a6830956cb5c7ae56a577b79Timo Sirainen if (sync_ctx.base_uid_last != sync_ctx.next_uid-1 && ret == 0 &&
3f190f4cbb9233a3a6830956cb5c7ae56a577b79Timo Sirainen !ibox->mbox_readonly) {
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen /* rewrite X-IMAPbase header. do it after mail_index_sync_end()
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen so previous transactions have been committed. */
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen /* FIXME: ugly .. */
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen ret = mail_index_sync_begin(ibox->index,
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen &sync_ctx.index_sync_ctx,
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen &sync_ctx.sync_view,
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen (uint32_t)-1, (uoff_t)-1);
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen if (ret < 0)
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen mail_storage_set_index_error(ibox);
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen else {
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen ret = mail_index_get_header(sync_ctx.sync_view,
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen &sync_ctx.hdr);
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen if ((ret = mbox_sync_update_imap_base(&sync_ctx)) < 0)
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen mail_index_transaction_rollback(sync_ctx.t);
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen else if (mail_index_transaction_commit(sync_ctx.t,
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen &seq,
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen &offset) < 0)
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen ret = -1;
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen if (mail_index_sync_end(sync_ctx.index_sync_ctx) < 0)
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen ret = -1;
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen }
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen }
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen if (sync_ctx.lock_id != 0 && (ret < 0 || !lock)) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen /* FIXME: drop to read locking and keep it MBOX_SYNC_SECS+1
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen to make sure we notice changes made by others */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mbox_unlock(ibox, sync_ctx.lock_id) < 0)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen ret = -1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen str_free(sync_ctx.header);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen str_free(sync_ctx.from_line);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen buffer_free(sync_ctx.mails);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen buffer_free(sync_ctx.syncs);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen return ret;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenint mbox_storage_sync(struct mailbox *box, enum mailbox_sync_flags flags)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen struct index_mailbox *ibox = (struct index_mailbox *)box;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if ((flags & MAILBOX_SYNC_FLAG_FAST) == 0 ||
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen ibox->sync_last_check + MAILBOX_FULL_SYNC_INTERVAL <= ioloop_time) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen ibox->sync_last_check = ioloop_time;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen if (mbox_sync(ibox, FALSE, FALSE) < 0)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return index_storage_sync(box, flags);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}