mail-transaction-log-view.c revision 7888a9d2008eab9985096c46e1da9ee985c22a2a
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "lib.h"
bdd36cfdba3ff66d25570a9ff568d69e1eb543cfTimo Sirainen#include "buffer.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "mail-index-private.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "mail-transaction-log-private.h"
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainen#include "mail-transaction-util.h"
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainen
05b7b8f14426b5fe5d016940eb5916033f0bc841Timo Sirainenstruct mail_transaction_log_view {
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen struct mail_transaction_log *log;
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen struct mail_transaction_log_view *next;
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen uint32_t min_file_seq, max_file_seq;
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen uoff_t min_file_offset, max_file_offset;
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen
dff32d11a411a24f3b76003c1ae22c5a960f180eTimo Sirainen enum mail_transaction_type type_mask;
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen buffer_t *expunges_buf, *data_buf;
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen struct mail_transaction_expunge_traverse_ctx *exp_ctx;
eb209d12e3b1cfed564c35cf19fdb1bf7fcc6811Timo Sirainen struct mail_transaction_header tmp_hdr;
eb209d12e3b1cfed564c35cf19fdb1bf7fcc6811Timo Sirainen
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen struct mail_transaction_log_file *file;
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen uoff_t file_offset;
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen uint32_t prev_file_seq;
ae32667c54480d329eed994b3defab89cd76c077Timo Sirainen uoff_t prev_file_offset;
ae32667c54480d329eed994b3defab89cd76c077Timo Sirainen
bfef6891565ff9018ac92add6eae401e9352c657Timo Sirainen unsigned int broken:1;
bfef6891565ff9018ac92add6eae401e9352c657Timo Sirainen};
05b7b8f14426b5fe5d016940eb5916033f0bc841Timo Sirainen
05b7b8f14426b5fe5d016940eb5916033f0bc841Timo Sirainenstruct mail_transaction_log_view *
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainenmail_transaction_log_view_open(struct mail_transaction_log *log)
8c2b4a45f17a5cb13bb01058ca37798cf48d91baTimo Sirainen{
8c2b4a45f17a5cb13bb01058ca37798cf48d91baTimo Sirainen struct mail_transaction_log_view *view;
8c2b4a45f17a5cb13bb01058ca37798cf48d91baTimo Sirainen
8c2b4a45f17a5cb13bb01058ca37798cf48d91baTimo Sirainen view = i_new(struct mail_transaction_log_view, 1);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen view->log = log;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen view->broken = TRUE;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen view->expunges_buf =
b44033e45e9f48f8a6e1ac5905234fec5de6d6ccAki Tuomi buffer_create_dynamic(default_pool, 512, (size_t)-1);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen view->next = log->views;
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen log->views = view;
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen return view;
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen}
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainenvoid mail_transaction_log_view_close(struct mail_transaction_log_view *view)
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen{
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen mail_transaction_log_view_unset(view);
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen if (view->data_buf != NULL)
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen buffer_free(view->data_buf);
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen buffer_free(view->expunges_buf);
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen i_free(view);
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen}
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainenint
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainenmail_transaction_log_view_set(struct mail_transaction_log_view *view,
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen uint32_t min_file_seq, uoff_t min_file_offset,
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen uint32_t max_file_seq, uoff_t max_file_offset,
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen enum mail_transaction_type type_mask)
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen{
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen /* FIXME: error handling for "not found" case is bad.. should the
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen caller after all check it and handle as it sees best..? */
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen struct mail_transaction_log_file *file, *first;
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen uint32_t seq;
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen uoff_t end_offset;
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen int ret;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
3e0c0a269390de8495e8f6ecaed59a823221480eAki Tuomi i_assert(view->broken);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen i_assert(min_file_seq <= max_file_seq);
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen i_assert(min_file_offset >= sizeof(struct mail_transaction_log_header));
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen i_assert(max_file_offset >= sizeof(struct mail_transaction_log_header));
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen ret = mail_transaction_log_file_find(view->log, min_file_seq, &file);
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen if (ret <= 0) {
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen if (ret == 0 &&
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen min_file_seq == view->log->tail->hdr.prev_file_seq &&
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen min_file_offset == view->log->tail->hdr.prev_file_offset) {
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen /* we can skip this */
b44033e45e9f48f8a6e1ac5905234fec5de6d6ccAki Tuomi min_file_seq = view->log->tail->hdr.file_seq;
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen min_file_offset =
b93ec4e5b569e1216d0c7a6f28cbdccfe4fb32caTimo Sirainen sizeof(struct mail_transaction_log_header);
cdc7ca129c3433d3e4b9d5e90f4c209e4546dfe9Timo Sirainen ret = mail_transaction_log_file_find(view->log,
cdc7ca129c3433d3e4b9d5e90f4c209e4546dfe9Timo Sirainen min_file_seq,
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen &file);
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen }
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen if (ret == 0) {
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen mail_index_set_error(view->log->index,
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen "Lost transaction log file %s seq %u",
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen view->log->tail->filepath, min_file_seq);
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen }
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen if (ret <= 0)
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen return -1;
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen if (min_file_seq > max_file_seq) {
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen /* empty view */
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen max_file_seq = min_file_seq;
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen max_file_offset = min_file_offset;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen end_offset = min_file_seq == max_file_seq ?
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen max_file_offset : (uoff_t)-1;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen ret = mail_transaction_log_file_map(file, min_file_offset, end_offset);
009217abb57a24a4076092e8e4e165545747839eStephan Bosch if (ret <= 0)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return -1;
009217abb57a24a4076092e8e4e165545747839eStephan Bosch first = file;
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen for (seq = min_file_seq+1; seq <= max_file_seq; seq++) {
5f5713d6468dca1acf3d350dd8a33057331f78c5Timo Sirainen file = file->next;
5f5713d6468dca1acf3d350dd8a33057331f78c5Timo Sirainen if (file == NULL || file->hdr.file_seq != seq)
5f5713d6468dca1acf3d350dd8a33057331f78c5Timo Sirainen return -1;
5f5713d6468dca1acf3d350dd8a33057331f78c5Timo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen end_offset = file->hdr.file_seq == max_file_seq ?
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen max_file_offset : (uoff_t)-1;
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen ret = mail_transaction_log_file_map(file,
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen sizeof(struct mail_transaction_log_header),
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen end_offset);
3ee8a7ee6912c7caa4e83d3ce5a5db1590a7ffcdTimo Sirainen if (ret <= 0)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return -1;
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen }
cf9d67e4a9bfee31cf3be05244555d51a3d1b9feTimo Sirainen
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen i_assert(max_file_offset <= file->hdr.used_size);
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen /* we have it all, refcount the files */
d3bae1f9d2448e5c398145ea250849ec12583845Timo Sirainen for (file = first, seq = min_file_seq; seq <= max_file_seq; seq++) {
d3bae1f9d2448e5c398145ea250849ec12583845Timo Sirainen file->refcount++;
5754fa860405e9af20c38981942f6aa97ce3158dTimo Sirainen file = file->next;
5754fa860405e9af20c38981942f6aa97ce3158dTimo Sirainen }
4dc8d682c855ca78db8874e04302e885465c1d65Timo Sirainen
4dc8d682c855ca78db8874e04302e885465c1d65Timo Sirainen buffer_set_used_size(view->expunges_buf, 0);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen view->prev_file_seq = 0;
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen view->prev_file_offset = 0;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen view->file = first;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen view->file_offset = min_file_offset;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
3e0c0a269390de8495e8f6ecaed59a823221480eAki Tuomi view->min_file_seq = min_file_seq;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen view->min_file_offset = min_file_offset;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen view->max_file_seq = max_file_seq;
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen view->max_file_offset = max_file_offset;
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen view->type_mask = type_mask;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen view->broken = FALSE;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen return 0;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
58b8a301b7b36047f10a592751094fbed86d6f0cTimo Sirainen
58b8a301b7b36047f10a592751094fbed86d6f0cTimo Sirainenvoid mail_transaction_log_view_unset(struct mail_transaction_log_view *view)
3dc72a40e457658caa3c033fb6b3418d16e9fd21Timo Sirainen{
3dc72a40e457658caa3c033fb6b3418d16e9fd21Timo Sirainen struct mail_transaction_log_file *file;
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainen
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen if (view->broken)
3dc72a40e457658caa3c033fb6b3418d16e9fd21Timo Sirainen return;
152db3f90f298b7fb2dbbd4276f0fc30a9bc30f6Timo Sirainen
3dc72a40e457658caa3c033fb6b3418d16e9fd21Timo Sirainen view->broken = TRUE;
3dc72a40e457658caa3c033fb6b3418d16e9fd21Timo Sirainen for (file = view->log->tail; file != NULL; file = file->next) {
3dc72a40e457658caa3c033fb6b3418d16e9fd21Timo Sirainen if (file->hdr.file_seq > view->max_file_seq)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen break;
89d6cd658eabf46e07e40037b0e641ed9be1a2a3Timo Sirainen if (file->hdr.file_seq >= view->min_file_seq)
89d6cd658eabf46e07e40037b0e641ed9be1a2a3Timo Sirainen file->refcount--;
ece0a20249ce26208db3415ba2e79423678856f8Timo Sirainen }
ece0a20249ce26208db3415ba2e79423678856f8Timo Sirainen
ece0a20249ce26208db3415ba2e79423678856f8Timo Sirainen mail_transaction_logs_clean(view->log);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainenvoid
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainenmail_transaction_log_view_get_prev_pos(struct mail_transaction_log_view *view,
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen uint32_t *file_seq_r,
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen uoff_t *file_offset_r)
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen *file_seq_r = view->prev_file_seq;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen *file_offset_r = view->prev_file_offset;
1df39b899804fd1dbc560f75382364822935c857Timo Sirainen}
1df39b899804fd1dbc560f75382364822935c857Timo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenvoid
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenmail_transaction_log_view_set_corrupted(struct mail_transaction_log_view *view,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen const char *fmt, ...)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen va_list va;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
009217abb57a24a4076092e8e4e165545747839eStephan Bosch if (!view->broken)
3e0c0a269390de8495e8f6ecaed59a823221480eAki Tuomi mail_transaction_log_view_unset(view);
3e0c0a269390de8495e8f6ecaed59a823221480eAki Tuomi
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen view->broken = TRUE;
c4900d31385344bfadaee53a897daeafdb3063d8Timo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen va_start(va, fmt);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen t_push();
e2fdcdb4ee53ab769123e27997713aaea34910e1Timo Sirainen mail_transaction_log_file_set_corrupted(view->log->head, "%s",
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen t_strdup_vprintf(fmt, va));
4aab01f4eade3d278b61471516c062ce30a84b5fTimo Sirainen t_pop();
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen va_end(va);
152db3f90f298b7fb2dbbd4276f0fc30a9bc30f6Timo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainenint
468c28dfb03613ab8d487b5aebc985a969193aceTimo Sirainenmail_transaction_log_view_is_corrupted(struct mail_transaction_log_view *view)
abe29107f5dce932d28a00912d2d75a01021bef1Timo Sirainen{
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen return view->broken;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen
027f58ea63a1822bbf13d99ee5572e5f8b9e8d8bTimo Sirainenstatic int log_view_get_next(struct mail_transaction_log_view *view,
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen const struct mail_transaction_header **hdr_r,
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen const void **data_r)
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen const struct mail_transaction_header *hdr;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen struct mail_transaction_log_file *file;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen const struct mail_transaction_type_map *type_rec;
abe29107f5dce932d28a00912d2d75a01021bef1Timo Sirainen const void *data;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen unsigned int record_size;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen size_t file_size;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen for (;;) {
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen file = view->file;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen view->prev_file_seq = file->hdr.file_seq;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen view->prev_file_offset = view->file_offset;
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen
ab779efe68458cf6fdcaa4f99527685d5563df0aTimo Sirainen if (view->file_offset != file->hdr.used_size)
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen break;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen
f5d82a4b87a9b17894e1869cfe8b1a90afbced59Timo Sirainen view->file = file->next;
f5d82a4b87a9b17894e1869cfe8b1a90afbced59Timo Sirainen view->file_offset = sizeof(struct mail_transaction_log_header);
ce8d63810932f48176304ed08cd8b7652c4a8addTimo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen if (view->file == NULL)
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen return 0;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen }
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen data = buffer_get_data(file->buffer, &file_size);
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen file_size += file->buffer_offset;
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen
bfef6891565ff9018ac92add6eae401e9352c657Timo Sirainen if (view->file_offset + sizeof(*hdr) > file_size) {
bfef6891565ff9018ac92add6eae401e9352c657Timo Sirainen mail_transaction_log_file_set_corrupted(file,
bfef6891565ff9018ac92add6eae401e9352c657Timo Sirainen "offset points outside file "
bfef6891565ff9018ac92add6eae401e9352c657Timo Sirainen "(%"PRIuUOFF_T" + %"PRIuSIZE_T" > %"PRIuSIZE_T")",
36e091dc733c6cd690c5aae6e411e41adb1eca73Timo Sirainen view->file_offset, sizeof(*hdr), file_size);
36e091dc733c6cd690c5aae6e411e41adb1eca73Timo Sirainen return -1;
36e091dc733c6cd690c5aae6e411e41adb1eca73Timo Sirainen }
36e091dc733c6cd690c5aae6e411e41adb1eca73Timo Sirainen
36e091dc733c6cd690c5aae6e411e41adb1eca73Timo Sirainen hdr = CONST_PTR_OFFSET(data, view->file_offset - file->buffer_offset);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen view->file_offset += sizeof(*hdr);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen if (file_size - view->file_offset < hdr->size) {
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen mail_transaction_log_file_set_corrupted(file,
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen "record size too large (type=0x%x, offset=%"PRIuUOFF_T
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen ", size=%u, end=%"PRIuSIZE_T")",
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen hdr->type & MAIL_TRANSACTION_TYPE_MASK,
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen view->file_offset, hdr->size, file_size);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen view->file_offset = file_size;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen return -1;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen type_rec = mail_transaction_type_lookup(hdr->type);
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen if (type_rec != NULL)
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen record_size = type_rec->record_size;
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen else {
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen mail_transaction_log_file_set_corrupted(file,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen "unknown record type 0x%x",
e2fdcdb4ee53ab769123e27997713aaea34910e1Timo Sirainen hdr->type & MAIL_TRANSACTION_TYPE_MASK);
e2fdcdb4ee53ab769123e27997713aaea34910e1Timo Sirainen view->file_offset = file->hdr.used_size;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return -1;
de92873c366becfaea1554642f89b9169d7955e2Timo Sirainen }
de92873c366becfaea1554642f89b9169d7955e2Timo Sirainen
de92873c366becfaea1554642f89b9169d7955e2Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0) {
de92873c366becfaea1554642f89b9169d7955e2Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_TYPE_MASK) !=
c3a2a487e23a282e59254b82deb9344ed0306bb2Timo Sirainen (MAIL_TRANSACTION_EXPUNGE|MAIL_TRANSACTION_EXPUNGE_PROT)) {
c3a2a487e23a282e59254b82deb9344ed0306bb2Timo Sirainen mail_transaction_log_file_set_corrupted(file,
c3a2a487e23a282e59254b82deb9344ed0306bb2Timo Sirainen "found expunge without protection mask");
1df39b899804fd1dbc560f75382364822935c857Timo Sirainen return -1;
1df39b899804fd1dbc560f75382364822935c857Timo Sirainen }
1f7f4294207557edf83171642ef62ce4922ffc9dTimo Sirainen } else if ((hdr->type & MAIL_TRANSACTION_TYPE_MASK) != type_rec->type) {
1f7f4294207557edf83171642ef62ce4922ffc9dTimo Sirainen mail_transaction_log_file_set_corrupted(file,
1f7f4294207557edf83171642ef62ce4922ffc9dTimo Sirainen "extra bits in header type: 0x%x",
1f7f4294207557edf83171642ef62ce4922ffc9dTimo Sirainen hdr->type & MAIL_TRANSACTION_TYPE_MASK);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return -1;
}
if (hdr->size % record_size != 0) {
mail_transaction_log_file_set_corrupted(file,
"record size wrong (type 0x%x, %u %% %u != 0)",
hdr->type & MAIL_TRANSACTION_TYPE_MASK,
hdr->size, record_size);
view->file_offset = file->hdr.used_size;
return -1;
}
*hdr_r = hdr;
*data_r = CONST_PTR_OFFSET(data, view->file_offset -
file->buffer_offset);
view->file_offset += hdr->size;
return 1;
}
static int seqfix_expunge(const struct mail_transaction_expunge *e,
void *context)
{
struct mail_transaction_log_view *view = context;
struct mail_transaction_expunge new_e;
uint32_t expunges_before;
expunges_before = mail_transaction_expunge_traverse_to(view->exp_ctx,
e->seq2);
if (expunges_before == 0) {
buffer_append(view->data_buf, e, sizeof(*e));
return 1;
}
/* FIXME: if there's expunges in the middle of the
range, we'd have to split this to multiple records */
new_e = *e;
new_e.seq2 += expunges_before;
new_e.seq1 += mail_transaction_expunge_traverse_to(view->exp_ctx,
new_e.seq1);
buffer_append(view->data_buf, &new_e, sizeof(new_e));
return 1;
}
static int seqfix_flag_update(const struct mail_transaction_flag_update *u,
void *context)
{
struct mail_transaction_log_view *view = context;
struct mail_transaction_flag_update new_u;
uint32_t expunges_before;
expunges_before = mail_transaction_expunge_traverse_to(view->exp_ctx,
u->seq2);
if (expunges_before == 0) {
buffer_append(view->data_buf, u, sizeof(*u));
return 1;
}
/* FIXME: if there's expunges in the middle of the
range, we'd have to split this to multiple records */
new_u = *u;
new_u.seq2 += expunges_before;
new_u.seq1 += mail_transaction_expunge_traverse_to(view->exp_ctx,
new_u.seq1);
buffer_append(view->data_buf, &new_u, sizeof(new_u));
return 1;
}
static int seqfix_cache_update(const struct mail_transaction_cache_update *u,
void *context)
{
struct mail_transaction_log_view *view = context;
struct mail_transaction_cache_update new_u;
uint32_t expunges_before;
expunges_before = mail_transaction_expunge_traverse_to(view->exp_ctx,
u->seq);
if (expunges_before != 0) {
new_u = *u;
new_u.seq += expunges_before;
u = &new_u;
}
buffer_append(view->data_buf, u, sizeof(*u));
return 1;
}
int mail_transaction_log_view_next(struct mail_transaction_log_view *view,
const struct mail_transaction_header **hdr_r,
const void **data_r, int *skipped_r)
{
struct mail_transaction_map_functions seqfix_funcs = {
seqfix_expunge, NULL, seqfix_flag_update, seqfix_cache_update
};
const struct mail_transaction_header *hdr;
const void *data;
int ret = 0;
if (skipped_r != NULL)
*skipped_r = FALSE;
if (view->broken)
return -1;
while ((ret = log_view_get_next(view, &hdr, &data)) > 0) {
if ((view->type_mask & hdr->type) != 0)
break;
/* we don't want this record */
if (skipped_r != NULL)
*skipped_r = TRUE;
if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0) {
mail_transaction_log_sort_expunges(view->expunges_buf,
data, hdr->size);
}
/* FIXME: hide flag/cache updates for appends if
append isn't in mask */
}
if (ret <= 0)
return ret;
*hdr_r = hdr;
*data_r = data;
if (buffer_get_used_size(view->expunges_buf) > 0) {
/* we have to fix sequences in the data */
if (view->data_buf == NULL) {
view->data_buf =
buffer_create_dynamic(default_pool,
hdr->size, (size_t)-1);
} else {
buffer_set_used_size(view->data_buf, 0);
}
view->exp_ctx = mail_transaction_expunge_traverse_init(
view->expunges_buf);
ret = mail_transaction_map(hdr, data, &seqfix_funcs, view);
mail_transaction_expunge_traverse_deinit(view->exp_ctx);
if (ret > 0) {
/* modified */
i_assert(buffer_get_used_size(view->data_buf) ==
hdr->size);
*data_r = buffer_get_data(view->data_buf, NULL);
} else {
i_assert(buffer_get_used_size(view->data_buf) == 0);
}
}
if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0) {
mail_transaction_log_sort_expunges(view->expunges_buf,
data, hdr->size);
/* hide expunge protection */
view->tmp_hdr = *hdr;
view->tmp_hdr.type &= ~MAIL_TRANSACTION_EXPUNGE_PROT;
*hdr_r = &view->tmp_hdr;
}
return 1;
}
buffer_t *
mail_transaction_log_view_get_expunges(struct mail_transaction_log_view *view)
{
return view->expunges_buf;
}