mbox-sync.c revision 96c253a039f102fa78a313ee05200ab3970112dc
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
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;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (file_set_size(sync_ctx->fd, file_size) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
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
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainenstatic void
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainenmbox_sync_next_mail(struct mbox_sync_context *sync_ctx,
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen struct mbox_sync_mail_context *mail_ctx, uint32_t seq)
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen{
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen uoff_t from_offset;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen memset(mail_ctx, 0, sizeof(*mail_ctx));
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mail_ctx->sync_ctx = sync_ctx;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mail_ctx->seq = 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
96c253a039f102fa78a313ee05200ab3970112dcTimo Sirainen if (seq > 1 && sync_ctx->first_uid == mail_ctx->mail.uid) {
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);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen /* save the offset permanently with recent flag state */
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen from_offset = (mail_ctx->from_offset - sync_ctx->expunged_space) << 1;
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;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen from_offset |= 1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen buffer_append(sync_ctx->ibox->mbox_data_buf, &from_offset,
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen sizeof(from_offset));
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
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen for (i = 0; i < size; i++)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen mail_index_sync_flags_apply(&sync[i], flags, keywords);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen}
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo 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 (move_diff == 0)
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen return 0;
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) {
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen // FIXME: error handling
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
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainenstatic int mbox_sync_do(struct index_mailbox *ibox,
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen struct mail_index_sync_ctx *index_sync_ctx,
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen struct mail_index_view *sync_view,
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen buffer_t *syncs, struct mail_index_sync_rec *sync_rec)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mbox_sync_context sync_ctx;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mbox_sync_mail_context mail_ctx;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen struct mail_index_transaction *t;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen const struct mail_index_header *hdr;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen const struct mail_index_record *rec;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen struct istream *input;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen uint32_t seq, need_space_seq, idx_seq, messages_count;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen uint8_t new_flags;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen off_t space_diff, move_diff;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen uoff_t offset, extra_space, trailer_size;
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen buffer_t *mails;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen size_t size;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen struct stat st;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen int sync_expunge, ret = 0;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen t = mail_index_transaction_begin(sync_view, FALSE);
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (ibox->mbox_data_buf == NULL) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen ibox->mbox_data_buf =
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen buffer_create_dynamic(default_pool, 512, (size_t)-1);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen } else {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen buffer_set_used_size(ibox->mbox_data_buf, 0);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen memset(&sync_ctx, 0, sizeof(sync_ctx));
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen sync_ctx.ibox = ibox;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen sync_ctx.file_input = ibox->mbox_file_stream;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen sync_ctx.input = ibox->mbox_stream;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen sync_ctx.fd = ibox->mbox_fd;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen sync_ctx.from_line = str_new(default_pool, 256);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen sync_ctx.header = str_new(default_pool, 4096);
3cfff0ca01961d885bdbd6ef08d761880116af07Timo Sirainen sync_ctx.next_uid = 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen input = sync_ctx.input;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen istream_raw_mbox_seek(input, 0);
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen mails = buffer_create_dynamic(default_pool, 4096, (size_t)-1);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen messages_count = mail_index_view_get_message_count(sync_view);
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen space_diff = 0; need_space_seq = 0; idx_seq = 0; rec = NULL;
3cfff0ca01961d885bdbd6ef08d761880116af07Timo Sirainen for (seq = 0;;) {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen /* set input->eof */
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen (void)istream_raw_mbox_get_header_offset(input);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (input->eof)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen break;
3cfff0ca01961d885bdbd6ef08d761880116af07Timo Sirainen seq++;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
659fe5d24825b160cae512538088020d97a60239Timo Sirainen mbox_sync_next_mail(&sync_ctx, &mail_ctx, seq);
659fe5d24825b160cae512538088020d97a60239Timo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen /* get all sync records related to this message */
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen ret = 1; sync_expunge = FALSE;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen mbox_sync_buffer_delete_old(syncs, mail_ctx.mail.uid);
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen while (mail_ctx.mail.uid >= sync_rec->uid1 && ret > 0) {
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen if (sync_rec->uid1 != 0) {
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen i_assert(mail_ctx.mail.uid <= sync_rec->uid2);
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen buffer_append(syncs, sync_rec,
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen sizeof(*sync_rec));
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen if (sync_rec->type ==
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen MAIL_INDEX_SYNC_TYPE_EXPUNGE)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen sync_expunge = TRUE;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen ret = mail_index_sync_next(index_sync_ctx, sync_rec);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (ret == 0)
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen memset(sync_rec, 0, sizeof(*sync_rec));
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen if (ret < 0)
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen break;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (seq == 1 && sync_ctx.base_uid_validity == 0) {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (mail_index_get_header(sync_view, &hdr) < 0) {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen ret = -1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen break;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen sync_ctx.base_uid_validity =
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen hdr->uid_validity == 0 ? (uint32_t)ioloop_time :
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen hdr->uid_validity;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen if (!sync_expunge && sync_ctx.first_uid == 0)
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen sync_ctx.first_uid = mail_ctx.mail.uid;
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if ((mail_ctx.need_rewrite || sync_ctx.expunged_space > 0 ||
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen buffer_get_used_size(syncs) != 0) && !ibox->readonly) {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (ibox->mbox_lock_type == F_RDLCK) {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen ret = -2;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen break;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (sync_expunge) {
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen ret = 1;
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen mail_ctx.mail.offset = mail_ctx.from_offset;
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen mail_ctx.mail.space =
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen mail_ctx.body_offset -
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen mail_ctx.from_offset +
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen mail_ctx.mail.body_size;
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen mail_ctx.mail.body_size = 0;
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen
96c253a039f102fa78a313ee05200ab3970112dcTimo Sirainen if (seq == 1)
96c253a039f102fa78a313ee05200ab3970112dcTimo Sirainen mail_ctx.mail.space++;
96c253a039f102fa78a313ee05200ab3970112dcTimo Sirainen
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen sync_ctx.expunged_space += mail_ctx.mail.space;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen } else {
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen move_diff = need_space_seq != 0 ? 0 :
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen -sync_ctx.expunged_space;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen /* read the From-line */
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (move_diff != 0 &&
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen mbox_read_from_line(&mail_ctx) < 0) {
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen ret = -1;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen break;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen }
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen mbox_sync_update_header(&mail_ctx, syncs);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen ret = mbox_sync_try_rewrite(&mail_ctx,
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen move_diff);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (ret > 0) {
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen mail_ctx.mail.offset += move_diff;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen ret = mbox_write_from_line(&mail_ctx,
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen move_diff);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (ret == 0)
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen ret = 1;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen }
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (ret < 0)
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen break;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen if (ret == 0 && need_space_seq == 0) {
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen /* first mail with no space to write it */
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen need_space_seq = seq;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen space_diff = 0;
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen if (sync_ctx.expunged_space > 0) {
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen /* create dummy message to describe
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen the expunged data */
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen struct mbox_sync_mail mail;
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen memset(&mail, 0, sizeof(mail));
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen mail.offset = mail_ctx.from_offset -
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen sync_ctx.expunged_space;
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen mail.space = sync_ctx.expunged_space;
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen need_space_seq--;
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen buffer_append(mails, &mail,
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen sizeof(mail));
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen /* update index */
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen do {
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen if (rec != NULL && rec->uid >= mail_ctx.mail.uid)
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen break;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen if (idx_seq >= messages_count) {
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen rec = NULL;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen break;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen }
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen if (rec != NULL)
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen mail_index_expunge(t, idx_seq);
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen ret = mail_index_lookup(sync_view, ++idx_seq, &rec);
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen } while (ret == 0);
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen if (ret < 0)
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen break;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen if (rec != NULL && rec->uid != mail_ctx.mail.uid) {
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen /* new UID in the middle of the mailbox -
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen shouldn't happen */
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen mail_storage_set_critical(ibox->box.storage,
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen "mbox sync: UID inserted in the middle "
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen "of mailbox (%u > %u)",
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen rec->uid, mail_ctx.mail.uid);
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen mail_index_mark_corrupted(ibox->index);
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen ret = -1;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen break;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen }
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (sync_expunge) {
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (rec != NULL)
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen mail_index_expunge(t, idx_seq);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen } else if (rec != NULL) {
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen /* see if flags changed */
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen keywords_mask_t old_keywords;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen uint8_t old_flags;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen old_flags = rec->flags;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen memcpy(old_keywords, rec->keywords,
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen INDEX_KEYWORDS_BYTE_COUNT);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen mbox_sync_apply_index_syncs(syncs, &old_flags,
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen old_keywords);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen new_flags = (rec->flags & ~MAIL_FLAGS_MASK) |
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen (mail_ctx.mail.flags &
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen (MAIL_FLAGS_MASK^MAIL_RECENT));
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (old_flags != new_flags ||
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen memcmp(old_keywords, mail_ctx.mail.keywords,
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen INDEX_KEYWORDS_BYTE_COUNT) != 0) {
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen mail_index_update_flags(t, idx_seq,
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen MODIFY_REPLACE,
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen new_flags,
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mail_ctx.mail.keywords);
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen }
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen /* we used this record */
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen rec = NULL;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen } else {
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen /* new message */
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mail_index_append(t, mail_ctx.mail.uid, &idx_seq);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen new_flags = mail_ctx.mail.flags &
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen (MAIL_FLAGS_MASK^MAIL_RECENT);
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen mail_index_update_flags(t, idx_seq, MODIFY_REPLACE,
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen new_flags,
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen mail_ctx.mail.keywords);
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen }
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen istream_raw_mbox_next(input, mail_ctx.mail.body_size);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen offset = istream_raw_mbox_get_start_offset(input);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (sync_ctx.expunged_space > 0 && !sync_expunge &&
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen need_space_seq == 0) {
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen /* move the body */
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (mbox_move(&sync_ctx,
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen mail_ctx.body_offset -
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen sync_ctx.expunged_space,
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen mail_ctx.body_offset,
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen mail_ctx.mail.body_size) < 0) {
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen ret = -1;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen break;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen }
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen i_stream_seek(input, offset);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen }
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen if (need_space_seq != 0) {
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen if (sync_expunge)
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen mail_ctx.mail.uid = 0;
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen buffer_append(mails, &mail_ctx.mail,
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen sizeof(mail_ctx.mail));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen space_diff += mail_ctx.mail.space;
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen if (space_diff >= 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* we have enough space now */
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen extra_space = MBOX_HEADER_EXTRA_SPACE *
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen (seq - need_space_seq + 1);
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen if (sync_expunge &&
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen (size_t)space_diff > extra_space) {
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen /* don't waste too much on extra
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen spacing */
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen sync_ctx.expunged_space =
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen space_diff - extra_space;
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen space_diff = extra_space;
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen } else {
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen sync_ctx.expunged_space = 0;
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mbox_sync_rewrite(&sync_ctx, mails,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen need_space_seq, seq,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen space_diff) < 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen /* mail_ctx may contain wrong data after
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen rewrite, so make sure we don't try to access
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen it */
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen memset(&mail_ctx, 0, sizeof(mail_ctx));
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen i_stream_seek(input, offset);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen need_space_seq = 0;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen buffer_set_used_size(mails, 0);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen trailer_size = i_stream_get_size(sync_ctx.file_input) - offset;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (need_space_seq != 0 && ret >= 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(space_diff < 0);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen extra_space = MBOX_HEADER_EXTRA_SPACE *
3cfff0ca01961d885bdbd6ef08d761880116af07Timo Sirainen (seq - need_space_seq + 1);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen space_diff -= extra_space;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen space_diff += sync_ctx.expunged_space;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen sync_ctx.expunged_space -= -space_diff;
3cfff0ca01961d885bdbd6ef08d761880116af07Timo Sirainen
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen if (mail_ctx.have_eoh && !mail_ctx.updated)
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen str_append_c(mail_ctx.header, '\n');
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (space_diff < 0 &&
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen mbox_sync_grow_file(&sync_ctx, &mail_ctx, -space_diff) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = -1;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen else if (mbox_sync_try_rewrite(&mail_ctx, 0) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = -1;
3cfff0ca01961d885bdbd6ef08d761880116af07Timo Sirainen else if (seq != need_space_seq) {
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen buffer_set_used_size(mails, (seq-need_space_seq) *
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen sizeof(mail_ctx.mail));
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen buffer_append(mails, &mail_ctx.mail,
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen sizeof(mail_ctx.mail));
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (mbox_sync_rewrite(&sync_ctx, mails, need_space_seq,
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen seq, extra_space) < 0)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen ret = -1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (sync_ctx.expunged_space > 0) {
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen /* copy trailer, then truncate the file */
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen offset = i_stream_get_size(sync_ctx.file_input) -
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen sync_ctx.expunged_space - trailer_size;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (mbox_move(&sync_ctx, offset,
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen offset + sync_ctx.expunged_space,
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen trailer_size) < 0)
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen ret = -1;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen else if (ftruncate(ibox->mbox_fd, offset + trailer_size) < 0)
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen ret = -1;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen istream_raw_mbox_flush(input);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen }
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (ret >= 0) {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (rec != NULL)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen mail_index_expunge(t, idx_seq);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen while (idx_seq < messages_count)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen mail_index_expunge(t, ++idx_seq);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (sync_ctx.base_uid_last+1 != sync_ctx.next_uid) {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen // FIXME: rewrite X-IMAPbase header
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (ret >= 0) {
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen /* only syncs left should be just appends (and their updates)
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen which weren't synced yet for some reason (crash). we'll just
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen ignore them, as we've overwritten them above. */
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen while (mail_index_sync_next(index_sync_ctx, sync_rec) > 0)
ab6315aa0d5c83f4f1dc98b3715826a686aebffdTimo Sirainen ;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (ret == 0) {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (fstat(ibox->mbox_fd, &st) < 0) {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen mbox_set_syscall_error(ibox, "fstat()");
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen ret = -1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (ret < 0) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen st.st_mtime = 0;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen st.st_size = 0;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if (mail_index_get_header(sync_view, &hdr) < 0)
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen ret = -1;
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen if (sync_ctx.base_uid_validity != hdr->uid_validity) {
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen mail_index_update_header(t,
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen offsetof(struct mail_index_header, uid_validity),
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen &sync_ctx.base_uid_validity,
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen sizeof(sync_ctx.base_uid_validity));
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen }
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen if (sync_ctx.next_uid != hdr->next_uid) {
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen mail_index_update_header(t,
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen offsetof(struct mail_index_header, next_uid),
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen &sync_ctx.next_uid, sizeof(sync_ctx.next_uid));
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen }
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if ((uint32_t)st.st_mtime != hdr->sync_stamp) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen uint32_t sync_stamp = st.st_mtime;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen mail_index_update_header(t,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen offsetof(struct mail_index_header, sync_stamp),
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen &sync_stamp, sizeof(sync_stamp));
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if ((uint64_t)st.st_mtime != hdr->sync_size) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen uint64_t sync_size = st.st_size;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen mail_index_update_header(t,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen offsetof(struct mail_index_header, sync_size),
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen &sync_size, sizeof(sync_size));
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if (ret < 0)
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen mail_index_transaction_rollback(t);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen else {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if (mail_index_transaction_commit(t, &seq, &offset) < 0)
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen ret = -1;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen else if (seq != 0) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen ibox->commit_log_file_seq = seq;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen ibox->commit_log_file_offset = offset;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (ret != -2) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if (mail_index_sync_end(index_sync_ctx) < 0)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen ret = -1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen if (ret == 0) {
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen ibox->commit_log_file_seq = 0;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen ibox->commit_log_file_offset = 0;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen } else {
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen mail_storage_set_index_error(ibox);
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen }
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen ibox->mbox_data = buffer_get_data(ibox->mbox_data_buf, &size);
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen ibox->mbox_data_count = size / sizeof(*ibox->mbox_data);
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen str_free(sync_ctx.header);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen str_free(sync_ctx.from_line);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen buffer_free(mails);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen return ret < 0 ? ret : 0;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen}
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainenint mbox_sync(struct index_mailbox *ibox, int last_commit)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen{
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen struct mail_index_sync_ctx *index_sync_ctx;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen struct mail_index_view *sync_view;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen unsigned int lock_id;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen uint32_t seq;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen uoff_t offset;
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen struct mail_index_sync_rec sync_rec;
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen buffer_t *syncs;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen int ret, lock_type;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo 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);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (ret <= 0)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen return ret;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen memset(&sync_rec, 0, sizeof(sync_rec));
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen syncs = buffer_create_dynamic(default_pool, 256, (size_t)-1);
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen lock_type = mail_index_sync_have_more(index_sync_ctx) ?
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen F_WRLCK : F_RDLCK;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (mbox_lock(ibox, lock_type, &lock_id) > 0 &&
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen mbox_file_open_stream(ibox) == 0) {
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen ret = mbox_sync_do(ibox, index_sync_ctx, sync_view,
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen syncs, &sync_rec);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (ret == -2) {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen /* read lock -> write lock. do it again. */
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen (void)mbox_unlock(ibox, lock_id);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen lock_id = 0;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (mbox_lock(ibox, F_WRLCK, &lock_id) <= 0)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen ret = -1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen else if (mbox_file_open_stream(ibox) < 0)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen ret = -1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen else {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen ret = mbox_sync_do(ibox, index_sync_ctx,
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen sync_view, syncs, &sync_rec);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen } else {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen (void)mail_index_sync_end(index_sync_ctx);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen ret = -1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (lock_id != 0) {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (mbox_unlock(ibox, lock_id) < 0)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen ret = -1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen buffer_free(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
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (mbox_sync(ibox, FALSE) < 0)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return index_storage_sync(box, flags);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}