mbox-sync-full.c revision 749c1abc1804e227afa6bae2d5ddf8bcc96e7cc4
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (C) 2002 Timo Sirainen */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
08d6658a4e2ec8104cd1307f6baa75fdb07a24f8Mark Washenberger#include "lib.h"
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen#include "istream.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "hex-binary.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "message-parser.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "message-part-serialize.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "mbox-index.h"
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen#include "mbox-lock.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "mail-index-util.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include <unistd.h>
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include <fcntl.h>
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic void skip_line(struct istream *input)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen const unsigned char *msg;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen size_t i, size;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen while (i_stream_read_data(input, &msg, &size, 0) > 0) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen for (i = 0; i < size; i++) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (msg[i] == '\n') {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen i_stream_skip(input, i+1);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen i_stream_skip(input, i);
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstatic int verify_header_md5sum(struct mail_index *index,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen struct mail_index_record *rec,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen unsigned char current_digest[16])
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen{
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen const unsigned char *old_digest;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen size_t size;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen /* MD5 sums must match */
788a0754cfd38dcfec1902844b085e4e84cfe7e6Timo Sirainen old_digest = index->lookup_field_raw(index, rec, DATA_FIELD_MD5, &size);
788a0754cfd38dcfec1902844b085e4e84cfe7e6Timo Sirainen return old_digest != NULL && size >= 16 &&
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen memcmp(old_digest, current_digest, 16) == 0;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen}
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic int mail_update_header_size(struct mail_index *index,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct mail_index_record *rec,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct mail_index_update *update,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct message_size *hdr_size)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen const void *part_data;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen const char *error;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen void *part_data_copy;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen uoff_t virtual_size;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen size_t size;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* update FIELD_HDR_HEADER_SIZE */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen index->update_field_raw(update, DATA_HDR_HEADER_SIZE,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen &hdr_size->physical_size,
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen sizeof(hdr_size->physical_size));
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* reset FIELD_HDR_VIRTUAL_SIZE - we don't know it anymore */
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen virtual_size = (uoff_t)-1;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen index->update_field_raw(update, DATA_HDR_VIRTUAL_SIZE,
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen &virtual_size, sizeof(virtual_size));
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* update DATA_FIELD_MESSAGEPART */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if ((rec->data_fields & DATA_FIELD_MESSAGEPART) == 0)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return TRUE;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen part_data = index->lookup_field_raw(index, rec, DATA_FIELD_MESSAGEPART,
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen &size);
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen if (part_data == NULL) {
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen /* well, this wasn't expected but don't bother failing */
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen return TRUE;
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen t_push();
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* copy & update the part data */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen part_data_copy = t_malloc(size);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen memcpy(part_data_copy, part_data, size);
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen if (!message_part_serialize_update_header(part_data_copy, size,
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen hdr_size, &error)) {
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen index_set_corrupted(index,
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen "Corrupted cached message_part data (%s)",
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen error);
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen t_pop();
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen return FALSE;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen index->update_field_raw(update, DATA_FIELD_MESSAGEPART,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen part_data_copy, size);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen t_pop();
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return TRUE;
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen}
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainenstatic int match_next_record(struct mail_index *index,
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen struct mail_index_record *rec,
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen unsigned int seq, struct istream *input,
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen struct mail_index_record **next_rec, int *dirty)
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct mail_index_update *update;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen struct message_size hdr_parsed_size;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen struct mbox_header_context ctx;
fc8d5f0ac909cca77840538e8beef98a8d40c21cTimo Sirainen uoff_t header_offset, body_offset, offset;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen uoff_t hdr_size, body_size;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen unsigned char current_digest[16];
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen int hdr_size_fixed;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen *next_rec = NULL;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen /* skip the From-line */
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen skip_line(input);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen header_offset = input->v_offset;
fc8d5f0ac909cca77840538e8beef98a8d40c21cTimo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen hdr_size = 0; body_offset = 0; hdr_size_fixed = FALSE;
fc8d5f0ac909cca77840538e8beef98a8d40c21cTimo Sirainen do {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (!mbox_mail_get_location(index, rec, NULL, NULL, &body_size))
fc8d5f0ac909cca77840538e8beef98a8d40c21cTimo Sirainen return FALSE;
33dd58ab84a020c4f061d2f6031eb6d4c168df1bTimo Sirainen
33dd58ab84a020c4f061d2f6031eb6d4c168df1bTimo Sirainen i_stream_seek(input, header_offset);
33dd58ab84a020c4f061d2f6031eb6d4c168df1bTimo Sirainen
33dd58ab84a020c4f061d2f6031eb6d4c168df1bTimo Sirainen if (body_size == 0 && !hdr_size_fixed) {
33dd58ab84a020c4f061d2f6031eb6d4c168df1bTimo Sirainen /* possibly broken message, find the next From-line
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen and make sure header parser won't pass it. */
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen mbox_skip_header(input);
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen i_stream_set_read_limit(input, input->v_offset);
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen i_stream_seek(input, header_offset);
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen hdr_size_fixed = TRUE;
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen hdr_size = 0;
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen }
5d4855d7b4dcffb6975ed8e3c9c376dac74e5c8aTimo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (hdr_size == 0) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* get the MD5 sum of fixed headers and the current
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen message flags in Status and X-Status fields */
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen mbox_header_init_context(&ctx, index, input);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen message_parse_header(NULL, input, &hdr_parsed_size,
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen mbox_header_cb, &ctx);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen md5_final(&ctx.md5, current_digest);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen mbox_header_free_context(&ctx);
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen i_stream_set_read_limit(input, 0);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen body_offset = input->v_offset;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (verify_header_md5sum(index, rec, current_digest) &&
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen mbox_verify_end_of_body(input, body_offset + body_size)) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* valid message */
8eb94c5190ba09bb6f6f068eec7bf96750f08d1dTimo Sirainen update = index->update_begin(index, rec);
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen /* update flags, unless we've changed them */
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen if ((rec->index_flags & INDEX_MAIL_FLAG_DIRTY) == 0) {
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen if (!index->update_flags(index, rec, seq,
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen ctx.flags, TRUE))
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen return FALSE;
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen /* update_flags() sets dirty flag, remove it */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen rec->index_flags &= ~INDEX_MAIL_FLAG_DIRTY;
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen } else {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (rec->msg_flags != ctx.flags)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen *dirty = TRUE;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen /* update location */
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (!mbox_mail_get_location(index, rec, &offset,
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen NULL, NULL))
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen return FALSE;
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen if (offset != header_offset) {
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen index->update_field_raw(update,
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen DATA_FIELD_LOCATION,
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen &header_offset,
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen sizeof(uoff_t));
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen }
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen /* update size */
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen if (hdr_size != hdr_parsed_size.physical_size ) {
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen if (!mail_update_header_size(index, rec, update,
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen &hdr_parsed_size))
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen return FALSE;
8eb94c5190ba09bb6f6f068eec7bf96750f08d1dTimo Sirainen }
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen if (!index->update_end(update))
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen return FALSE;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen *next_rec = rec;
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen break;
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen }
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen /* try next message */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen (void)index->expunge(index, rec, seq, TRUE);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen rec = index->next(index, rec);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen } while (rec != NULL);
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen return TRUE;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic int mbox_sync_from_stream(struct mail_index *index,
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen struct istream *input)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen struct mail_index_record *rec;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen uoff_t from_offset;
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen const unsigned char *data;
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen size_t size;
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen unsigned int seq;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen int dirty;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen mbox_skip_empty_lines(input);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen /* first make sure we start with a "From " line. If file is too
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen small, we'll just treat it as empty mbox file. */
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (i_stream_read_data(input, &data, &size, 5) > 0 &&
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen strncmp((const char *) data, "From ", 5) != 0) {
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen index_set_error(index, "File isn't in mbox format: %s",
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen index->mailbox_path);
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen return FALSE;
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen }
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen /* we'll go through the mailbox and index in order matching the
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen messages by their size and Message-ID. old mails aren't remembered,
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen so we handle well only the cases when mail has been deleted. if
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen mails have been reordered (eg. sorted by someone) most of the mails
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen will show up as being new. if we really wanted to support that well,
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen we could save the message-ids into hash but I don't know if it's
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen worth the trouble. */
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen seq = 1;
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen rec = index->lookup(index, 1);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen dirty = FALSE;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen while (rec != NULL) {
4376643cd2c7110e752c09f838f2c4eee6ed8ac6Timo Sirainen from_offset = input->v_offset;
938835576b218f6bb9498d829cef9514f8609c6fTimo Sirainen if (input->v_offset != 0) {
938835576b218f6bb9498d829cef9514f8609c6fTimo Sirainen /* we're at the [\r]\n before the From-line,
938835576b218f6bb9498d829cef9514f8609c6fTimo Sirainen skip it */
938835576b218f6bb9498d829cef9514f8609c6fTimo Sirainen if (!mbox_skip_crlf(input)) {
938835576b218f6bb9498d829cef9514f8609c6fTimo Sirainen /* they just went and broke it, even while
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen we had it locked. */
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen index_set_error(index,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen "Error syncing mbox file %s: "
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen "LF not found where expected",
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen index->mailbox_path);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen return FALSE;
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen }
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (input->v_offset == input->v_size)
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen break;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen if (!match_next_record(index, rec, seq, input, &rec, &dirty))
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return FALSE;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (rec == NULL) {
a8e132559a7ebe54c8269d79ce29fa3338c76199Timo Sirainen /* Get back to line before From */
e2a700d0628e395d64cbcef4b5b4510816bf51c4Timo Sirainen i_stream_seek(input, from_offset);
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen break;
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen }
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen seq++;
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen rec = index->next(index, rec);
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen }
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen /* delete the rest of the records */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen while (rec != NULL) {
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen (void)index->expunge(index, rec, seq, TRUE);
a8e132559a7ebe54c8269d79ce29fa3338c76199Timo Sirainen
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen rec = index->next(index, rec);
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen }
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (!dirty && (index->header->flags & MAIL_INDEX_FLAG_DIRTY_MESSAGES)) {
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen /* no flags were dirty anymore, no need to rewrite */
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen index->header->flags &= ~MAIL_INDEX_FLAG_DIRTY_MESSAGES;
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen }
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen if (input->v_offset == input->v_size)
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen return TRUE;
e2a700d0628e395d64cbcef4b5b4510816bf51c4Timo Sirainen else
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen return mbox_index_append(index, input);
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen}
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainenint mbox_sync_full(struct mail_index *index)
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen{
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen struct istream *input;
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen int failed;
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen i_assert(index->lock_type == MAIL_LOCK_EXCLUSIVE);
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen input = mbox_get_stream(index, 0, MAIL_LOCK_SHARED);
430c0b0c370bebeeceba2e206be76bc134742f41Timo Sirainen if (input == NULL)
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen return FALSE;
a3dd97fb6d92a89c3de0597fed2d4b044c7aeb84Timo Sirainen
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen failed = !mbox_sync_from_stream(index, input);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen i_stream_unref(input);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen return !failed;
484e12acec34f16e5a8adc001e23ae48f1dda8c7Timo Sirainen}
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen