mail-transaction-log-view.c revision 8830fab191cab8440281eb641dfdd93974b2933b
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (C) 2003-2004 Timo Sirainen */
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen#include "lib.h"
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen#include "buffer.h"
70ead6466f9baa8294e71fc2fba0a4f54f488b5eTimo Sirainen#include "mail-index-private.h"
a020eb653b2620a989e4795adceb6136037327b2Timo Sirainen#include "mail-transaction-log-private.h"
bdd36cfdba3ff66d25570a9ff568d69e1eb543cfTimo Sirainen#include "mail-transaction-util.h"
dd7cbb32412c2f4d2d223af66672535bc1237246Timo Sirainen
57f5683fd9dc9bc79816c418bb30fdbc33b68a8cTimo Sirainenstruct mail_transaction_log_view {
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen struct mail_transaction_log *log;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen struct mail_transaction_log_view *next;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen uint32_t min_file_seq, max_file_seq;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen uoff_t min_file_offset, max_file_offset;
1701b354e81ff1dfd0b6c7bb4412b8d9c2b9f986Timo Sirainen
1701b354e81ff1dfd0b6c7bb4412b8d9c2b9f986Timo Sirainen enum mail_transaction_type type_mask;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen struct mail_transaction_header tmp_hdr;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen struct mail_transaction_log_file *cur, *head, *tail;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen uoff_t cur_offset;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen uint32_t prev_file_seq;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen uoff_t prev_file_offset;
70ead6466f9baa8294e71fc2fba0a4f54f488b5eTimo Sirainen
1ae5d61ec366fdb2f3c5b150ca378d6141b0f4bdTimo Sirainen unsigned int broken:1;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen};
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainenstruct mail_transaction_log_view *
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainenmail_transaction_log_view_open(struct mail_transaction_log *log)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen{
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen struct mail_transaction_log_view *view;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen view = i_new(struct mail_transaction_log_view, 1);
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen view->log = log;
c4478af52de63804efef2055580adf1dfc8679c6Timo Sirainen view->broken = TRUE;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen view->head = view->tail = view->log->head;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen view->head->refcount++;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen view->next = log->views;
379175cfba8150d481d9898b78330b719d128d84Timo Sirainen log->views = view;
379175cfba8150d481d9898b78330b719d128d84Timo Sirainen return view;
379175cfba8150d481d9898b78330b719d128d84Timo Sirainen}
379175cfba8150d481d9898b78330b719d128d84Timo Sirainen
379175cfba8150d481d9898b78330b719d128d84Timo Sirainenvoid mail_transaction_log_view_close(struct mail_transaction_log_view *view)
34512eaad8b1b2f929e6d6e3a2f7252c29fba97bTimo Sirainen{
34512eaad8b1b2f929e6d6e3a2f7252c29fba97bTimo Sirainen struct mail_transaction_log_view **p;
34512eaad8b1b2f929e6d6e3a2f7252c29fba97bTimo Sirainen struct mail_transaction_log_file *file;
34512eaad8b1b2f929e6d6e3a2f7252c29fba97bTimo Sirainen
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen for (p = &view->log->views; *p != NULL; p = &(*p)->next) {
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen if (*p == view) {
a8d47e2427558d5011dfc75694b704760c1ef8baTimo Sirainen *p = view->next;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen break;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen }
4c892b0d94c5b1d6853dbe8e0b38059ea5b08ecaTimo Sirainen }
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen for (file = view->tail; file != view->head; file = file->next)
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen file->refcount--;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen view->head->refcount--;
4c892b0d94c5b1d6853dbe8e0b38059ea5b08ecaTimo Sirainen
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen mail_transaction_logs_clean(view->log);
34512eaad8b1b2f929e6d6e3a2f7252c29fba97bTimo Sirainen i_free(view);
3c2e763ab035567b2081a805648537b27e7cbbcfTimo Sirainen}
013a8a91c83c6ea24bc75322b81235f19e26fa8fTimo Sirainen
d9076f5939edf5d20a261494b1a861dcbb0d32e2Timo Sirainenvoid mail_transaction_log_views_close(struct mail_transaction_log *log)
a020eb653b2620a989e4795adceb6136037327b2Timo Sirainen{
a8d47e2427558d5011dfc75694b704760c1ef8baTimo Sirainen struct mail_transaction_log_view *view;
a8d47e2427558d5011dfc75694b704760c1ef8baTimo Sirainen
a8d47e2427558d5011dfc75694b704760c1ef8baTimo Sirainen for (view = log->views; view != NULL; view = view->next)
a8d47e2427558d5011dfc75694b704760c1ef8baTimo Sirainen view->log = NULL;
a8d47e2427558d5011dfc75694b704760c1ef8baTimo Sirainen}
a8d47e2427558d5011dfc75694b704760c1ef8baTimo Sirainen
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainenint
379175cfba8150d481d9898b78330b719d128d84Timo Sirainenmail_transaction_log_view_set(struct mail_transaction_log_view *view,
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen uint32_t min_file_seq, uoff_t min_file_offset,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen uint32_t max_file_seq, uoff_t max_file_offset,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen enum mail_transaction_type type_mask)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen{
34512eaad8b1b2f929e6d6e3a2f7252c29fba97bTimo Sirainen /* FIXME: error handling for "not found" case is bad.. should the
34512eaad8b1b2f929e6d6e3a2f7252c29fba97bTimo Sirainen caller after all check it and handle as it sees best..? */
34512eaad8b1b2f929e6d6e3a2f7252c29fba97bTimo Sirainen struct mail_transaction_log_file *file, *first;
34512eaad8b1b2f929e6d6e3a2f7252c29fba97bTimo Sirainen uint32_t seq;
34512eaad8b1b2f929e6d6e3a2f7252c29fba97bTimo Sirainen uoff_t end_offset;
34512eaad8b1b2f929e6d6e3a2f7252c29fba97bTimo Sirainen int ret;
34512eaad8b1b2f929e6d6e3a2f7252c29fba97bTimo Sirainen
34512eaad8b1b2f929e6d6e3a2f7252c29fba97bTimo Sirainen i_assert(min_file_seq <= max_file_seq);
34512eaad8b1b2f929e6d6e3a2f7252c29fba97bTimo Sirainen
34512eaad8b1b2f929e6d6e3a2f7252c29fba97bTimo Sirainen if (view->log == NULL)
34512eaad8b1b2f929e6d6e3a2f7252c29fba97bTimo Sirainen return -1;
34512eaad8b1b2f929e6d6e3a2f7252c29fba97bTimo Sirainen
34512eaad8b1b2f929e6d6e3a2f7252c29fba97bTimo Sirainen if (min_file_seq == view->log->tail->hdr.prev_file_seq &&
34512eaad8b1b2f929e6d6e3a2f7252c29fba97bTimo Sirainen min_file_offset == view->log->tail->hdr.prev_file_offset) {
34512eaad8b1b2f929e6d6e3a2f7252c29fba97bTimo Sirainen /* we can skip this */
34512eaad8b1b2f929e6d6e3a2f7252c29fba97bTimo Sirainen min_file_seq = view->log->tail->hdr.file_seq;
34512eaad8b1b2f929e6d6e3a2f7252c29fba97bTimo Sirainen min_file_offset = sizeof(struct mail_transaction_log_header);
34512eaad8b1b2f929e6d6e3a2f7252c29fba97bTimo Sirainen
34512eaad8b1b2f929e6d6e3a2f7252c29fba97bTimo Sirainen if (min_file_seq > max_file_seq) {
34512eaad8b1b2f929e6d6e3a2f7252c29fba97bTimo Sirainen /* empty view */
34512eaad8b1b2f929e6d6e3a2f7252c29fba97bTimo Sirainen max_file_seq = min_file_seq;
34512eaad8b1b2f929e6d6e3a2f7252c29fba97bTimo Sirainen max_file_offset = min_file_offset;
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen }
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen }
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen ret = mail_transaction_log_file_find(view->log, min_file_seq, &file);
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen if (ret <= 0) {
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen if (ret == 0) {
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen mail_index_set_error(view->log->index,
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen "Lost transaction log file %s seq %u",
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen view->log->tail->filepath, min_file_seq);
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen }
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen return -1;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen }
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen /* check these later than others as index file may have corrupted
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen log_file_offset. we should have recreated the log file and
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen skipped min_file_seq file above.. max_file_offset can be broken
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen only if min_file_seq = max_file_seq. */
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen i_assert(min_file_offset >= sizeof(struct mail_transaction_log_header));
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen i_assert(max_file_offset >= sizeof(struct mail_transaction_log_header));
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen i_assert(min_file_seq != max_file_seq ||
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen min_file_offset <= max_file_offset);
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen end_offset = min_file_seq == max_file_seq ?
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen max_file_offset : (uoff_t)-1;
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen ret = mail_transaction_log_file_map(file, min_file_offset, end_offset);
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen if (ret <= 0) {
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen if (ret == 0) {
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen mail_index_set_error(view->log->index,
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen "Lost transaction log file %s seq %u",
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen file->filepath, file->hdr.file_seq);
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen }
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen return -1;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen }
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen first = file;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen for (seq = min_file_seq+1; seq <= max_file_seq; seq++) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen file = file->next;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (file == NULL || file->hdr.file_seq != seq) {
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen mail_index_set_error(view->log->index,
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen "Lost transaction log file %s seq %u",
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen view->log->tail->filepath, seq);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return -1;
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen }
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen end_offset = file->hdr.file_seq == max_file_seq ?
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen max_file_offset : (uoff_t)-1;
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen ret = mail_transaction_log_file_map(file,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen sizeof(struct mail_transaction_log_header),
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen end_offset);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (ret == 0) {
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen mail_index_set_error(view->log->index,
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen "Lost transaction log file %s seq %u",
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen file->filepath, file->hdr.file_seq);
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen }
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen if (ret <= 0)
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen return -1;
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen }
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen i_assert(max_file_offset <= file->hdr.used_size);
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen /* we have all of them. update refcounts. */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (view->tail->hdr.file_seq < first->hdr.file_seq) {
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen /* unref old files */
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen for (file = view->tail; file != first; file = file->next)
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen file->refcount--;
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen view->tail = first;
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen } else {
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen /* going backwards, reference them */
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen for (file = first; file != view->tail; file = file->next)
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen file->refcount++;
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen }
a26b7e87b4157cfa800f9bcd8c4c044462d21268Timo Sirainen
a26b7e87b4157cfa800f9bcd8c4c044462d21268Timo Sirainen /* reference all new files */
a26b7e87b4157cfa800f9bcd8c4c044462d21268Timo Sirainen for (file = view->head->next; file != NULL; file = file->next)
a26b7e87b4157cfa800f9bcd8c4c044462d21268Timo Sirainen file->refcount++;
a26b7e87b4157cfa800f9bcd8c4c044462d21268Timo Sirainen view->head = view->log->head;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen view->prev_file_seq = 0;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen view->prev_file_offset = 0;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen view->cur = first;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen view->cur_offset = min_file_offset;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen view->min_file_seq = min_file_seq;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen view->min_file_offset = min_file_offset;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen view->max_file_seq = max_file_seq;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen view->max_file_offset = max_file_offset;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen view->type_mask = type_mask;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen view->broken = FALSE;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen return 0;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen}
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainenvoid
e51cfb5506de764499cb5b81a098b23cf46f90f1Timo Sirainenmail_transaction_log_view_get_prev_pos(struct mail_transaction_log_view *view,
e51cfb5506de764499cb5b81a098b23cf46f90f1Timo Sirainen uint32_t *file_seq_r,
e51cfb5506de764499cb5b81a098b23cf46f90f1Timo Sirainen uoff_t *file_offset_r)
e51cfb5506de764499cb5b81a098b23cf46f90f1Timo Sirainen{
e51cfb5506de764499cb5b81a098b23cf46f90f1Timo Sirainen *file_seq_r = view->prev_file_seq;
fd4130e3e6aec1dc6b16edc813eabdecbbd8d859Timo Sirainen *file_offset_r = view->prev_file_offset;
8cca3b43b28365cfee4dc733c00caaeab8ecd2adTimo Sirainen}
1ae5d61ec366fdb2f3c5b150ca378d6141b0f4bdTimo Sirainen
4f2fa2e5f5a27e1d59dd38fbbf38e420e006596dTimo Sirainenvoid
4f2fa2e5f5a27e1d59dd38fbbf38e420e006596dTimo Sirainenmail_transaction_log_view_set_corrupted(struct mail_transaction_log_view *view,
e51cfb5506de764499cb5b81a098b23cf46f90f1Timo Sirainen const char *fmt, ...)
e51cfb5506de764499cb5b81a098b23cf46f90f1Timo Sirainen{
e51cfb5506de764499cb5b81a098b23cf46f90f1Timo Sirainen va_list va;
e51cfb5506de764499cb5b81a098b23cf46f90f1Timo Sirainen
e51cfb5506de764499cb5b81a098b23cf46f90f1Timo Sirainen view->broken = TRUE;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen va_start(va, fmt);
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen t_push();
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen mail_transaction_log_file_set_corrupted(view->log->head, "%s",
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen t_strdup_vprintf(fmt, va));
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen t_pop();
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen va_end(va);
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen}
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainenint
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainenmail_transaction_log_view_is_corrupted(struct mail_transaction_log_view *view)
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen{
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen return view->broken;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen}
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenstatic int log_view_get_next(struct mail_transaction_log_view *view,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen const struct mail_transaction_header **hdr_r,
013a8a91c83c6ea24bc75322b81235f19e26fa8fTimo Sirainen const void **data_r)
013a8a91c83c6ea24bc75322b81235f19e26fa8fTimo Sirainen{
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen const struct mail_transaction_header *hdr;
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen struct mail_transaction_log_file *file;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen const struct mail_transaction_type_map *type_rec;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen const void *data;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen unsigned int record_size;
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen size_t file_size;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen for (;;) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen file = view->cur;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen view->prev_file_seq = file->hdr.file_seq;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen view->prev_file_offset = view->cur_offset;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (view->cur_offset != file->hdr.used_size)
f9142439f2b5e86065af7420e80fe52835227dc8Timo Sirainen break;
f9142439f2b5e86065af7420e80fe52835227dc8Timo Sirainen
f9142439f2b5e86065af7420e80fe52835227dc8Timo Sirainen view->cur = file->next;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen view->cur_offset = sizeof(struct mail_transaction_log_header);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen if (view->cur == NULL)
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen return 0;
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen }
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen data = buffer_get_data(file->buffer, &file_size);
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen file_size += file->buffer_offset;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen if (view->cur_offset + sizeof(*hdr) > file_size) {
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen mail_transaction_log_file_set_corrupted(file,
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen "offset points outside file "
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen "(%"PRIuUOFF_T" + %"PRIuSIZE_T" > %"PRIuSIZE_T")",
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen view->cur_offset, sizeof(*hdr), file_size);
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen return -1;
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen }
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen hdr = CONST_PTR_OFFSET(data, view->cur_offset - file->buffer_offset);
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen view->cur_offset += sizeof(*hdr);
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen if (file_size - view->cur_offset < hdr->size) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen mail_transaction_log_file_set_corrupted(file,
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen "record size too large (type=0x%x, offset=%"PRIuUOFF_T
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen ", size=%u, end=%"PRIuSIZE_T")",
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen hdr->type & MAIL_TRANSACTION_TYPE_MASK,
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen view->cur_offset, hdr->size, file_size);
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen view->cur_offset = file_size;
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen return -1;
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen }
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen type_rec = mail_transaction_type_lookup(hdr->type);
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen if (type_rec != NULL)
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen record_size = type_rec->record_size;
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen else {
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen mail_transaction_log_file_set_corrupted(file,
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen "unknown record type 0x%x",
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen hdr->type & MAIL_TRANSACTION_TYPE_MASK);
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen view->cur_offset = file->hdr.used_size;
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen return -1;
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen }
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0) {
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen if ((hdr->type & MAIL_TRANSACTION_TYPE_MASK) !=
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen (MAIL_TRANSACTION_EXPUNGE|MAIL_TRANSACTION_EXPUNGE_PROT)) {
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen mail_transaction_log_file_set_corrupted(file,
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen "found expunge without protection mask");
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return -1;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen } else if ((hdr->type & MAIL_TRANSACTION_TYPE_MASK) != type_rec->type) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen mail_transaction_log_file_set_corrupted(file,
bcf1cf2afb9692b0db555e6ecf662a2fbd19793dTimo Sirainen "extra bits in header type: 0x%x",
bcf1cf2afb9692b0db555e6ecf662a2fbd19793dTimo Sirainen hdr->type & MAIL_TRANSACTION_TYPE_MASK);
bcf1cf2afb9692b0db555e6ecf662a2fbd19793dTimo Sirainen return -1;
bcf1cf2afb9692b0db555e6ecf662a2fbd19793dTimo Sirainen }
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen if (hdr->size % record_size != 0) {
d23dfc385f22d7a2c466d29501c9e0ce5a243deeTimo Sirainen mail_transaction_log_file_set_corrupted(file,
bcf1cf2afb9692b0db555e6ecf662a2fbd19793dTimo Sirainen "record size wrong (type 0x%x, %u %% %u != 0)",
bcf1cf2afb9692b0db555e6ecf662a2fbd19793dTimo Sirainen hdr->type & MAIL_TRANSACTION_TYPE_MASK,
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen hdr->size, record_size);
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen view->cur_offset = file->hdr.used_size;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen return -1;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen }
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen *hdr_r = hdr;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen *data_r = CONST_PTR_OFFSET(data, view->cur_offset -
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen file->buffer_offset);
94ce7e7700cda14a8342cb08e7285507b4b531daTimo Sirainen view->cur_offset += hdr->size;
94ce7e7700cda14a8342cb08e7285507b4b531daTimo Sirainen return 1;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen}
94ce7e7700cda14a8342cb08e7285507b4b531daTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainenint mail_transaction_log_view_next(struct mail_transaction_log_view *view,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen const struct mail_transaction_header **hdr_r,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen const void **data_r, int *skipped_r)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen{
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen const struct mail_transaction_header *hdr;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen const void *data;
fc4e528886f47bf4d2dd0276fb8705c085c3b9aeTimo Sirainen int ret = 0;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (skipped_r != NULL)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen *skipped_r = FALSE;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (view->broken)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return -1;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
94ce7e7700cda14a8342cb08e7285507b4b531daTimo Sirainen while ((ret = log_view_get_next(view, &hdr, &data)) > 0) {
311d3dd2078c1b711a0cef013ba43a94078c115cTimo Sirainen if ((view->type_mask & hdr->type) != 0)
311d3dd2078c1b711a0cef013ba43a94078c115cTimo Sirainen break;
311d3dd2078c1b711a0cef013ba43a94078c115cTimo Sirainen
311d3dd2078c1b711a0cef013ba43a94078c115cTimo Sirainen /* we don't want this record */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (skipped_r != NULL)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen *skipped_r = TRUE;
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen /* FIXME: hide flag/cache updates for appends if
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen append isn't in mask */
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen }
b06633c63fde22b6c8837ae70b2f95fe60075b0aTimo Sirainen
b06633c63fde22b6c8837ae70b2f95fe60075b0aTimo Sirainen if (ret <= 0)
b06633c63fde22b6c8837ae70b2f95fe60075b0aTimo Sirainen return ret;
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen *hdr_r = hdr;
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen *data_r = data;
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen
b06633c63fde22b6c8837ae70b2f95fe60075b0aTimo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0) {
b06633c63fde22b6c8837ae70b2f95fe60075b0aTimo Sirainen /* hide expunge protection */
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen if (*hdr_r != &view->tmp_hdr) {
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen view->tmp_hdr = *hdr;
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen *hdr_r = &view->tmp_hdr;
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen }
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen view->tmp_hdr.type &= ~MAIL_TRANSACTION_EXPUNGE_PROT;
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen }
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen return 1;
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen}
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen