mail-transaction-log-view.c revision d6f50f100ce17fa4b3a89e9567a5ff993b38b872
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "lib.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "buffer.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "mail-index-private.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "mail-transaction-log-private.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "mail-transaction-util.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstruct mail_transaction_log_view {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct mail_transaction_log *log;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct mail_transaction_log_view *next;
7a7d2aa11e46195e2d92d6c337d7e78052a5ce67Timo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen uint32_t min_file_seq, max_file_seq;
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen uoff_t min_file_offset, max_file_offset;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen enum mail_transaction_type type_mask;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct mail_transaction_header tmp_hdr;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct mail_transaction_log_file *cur, *head, *tail;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen uoff_t cur_offset;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen uint32_t prev_file_seq;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen uoff_t prev_file_offset;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
499fec3443374cc89fb8c83b8027c1614097d7a3Timo Sirainen unsigned int broken:1;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen};
f5a7396b31762a1f876517e13ce9065820139f7cTimo Sirainen
f5a7396b31762a1f876517e13ce9065820139f7cTimo Sirainenstruct mail_transaction_log_view *
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenmail_transaction_log_view_open(struct mail_transaction_log *log)
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen{
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen struct mail_transaction_log_view *view;
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen view = i_new(struct mail_transaction_log_view, 1);
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen view->log = log;
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen view->broken = TRUE;
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen view->head = view->tail = view->log->head;
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen view->head->refcount++;
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen view->next = log->views;
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen log->views = view;
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen return view;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen}
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainenvoid mail_transaction_log_view_close(struct mail_transaction_log_view *view)
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen{
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen struct mail_transaction_log_view **p;
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen struct mail_transaction_log_file *file;
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen for (p = &view->log->views; *p != NULL; p = &(*p)->next) {
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen if (*p == view) {
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen *p = view->next;
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen break;
11352dc3e4b29f3d2763c82f8ea4f99e8daf4fa3Timo Sirainen }
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen }
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen for (file = view->tail; file != view->head; file = file->next)
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen file->refcount--;
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen view->head->refcount--;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen mail_transaction_logs_clean(view->log);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_free(view);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
cd8507179823de33d6e8242e10dbc15d136245b5Timo Sirainenvoid mail_transaction_log_views_close(struct mail_transaction_log *log)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct mail_transaction_log_view *view;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen for (view = log->views; view != NULL; view = view->next)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen view->log = NULL;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenint
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenmail_transaction_log_view_set(struct mail_transaction_log_view *view,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen uint32_t min_file_seq, uoff_t min_file_offset,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen uint32_t max_file_seq, uoff_t max_file_offset,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen enum mail_transaction_type type_mask)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* FIXME: error handling for "not found" case is bad.. should the
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen caller after all check it and handle as it sees best..? */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct mail_transaction_log_file *file, *first;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen uint32_t seq;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen uoff_t end_offset;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen int ret;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_assert(min_file_seq <= max_file_seq);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (view->log == NULL)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return -1;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (min_file_seq == view->log->tail->hdr.prev_file_seq &&
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen min_file_offset == view->log->tail->hdr.prev_file_offset) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* we can skip this */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen min_file_seq = view->log->tail->hdr.file_seq;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen min_file_offset = sizeof(struct mail_transaction_log_header);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (min_file_seq > max_file_seq) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* empty view */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen max_file_seq = min_file_seq;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen max_file_offset = min_file_offset;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen ret = mail_transaction_log_file_find(view->log, min_file_seq, &file);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (ret <= 0) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (ret == 0) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen mail_index_set_error(view->log->index,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen "Lost transaction log file %s seq %u",
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen view->log->tail->filepath, min_file_seq);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return -1;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen /* check these later than others as index file may have corrupted
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen log_file_offset. we should have recreated the log file and
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen skipped min_file_seq file above.. max_file_offset can be broken
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen only if min_file_seq = max_file_seq. */
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen i_assert(min_file_offset >= sizeof(struct mail_transaction_log_header));
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen i_assert(max_file_offset >= sizeof(struct mail_transaction_log_header));
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen i_assert(min_file_seq != max_file_seq ||
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen min_file_offset <= max_file_offset);
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen end_offset = min_file_seq == max_file_seq ?
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen max_file_offset : (uoff_t)-1;
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen ret = mail_transaction_log_file_map(file, min_file_offset, end_offset);
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen if (ret <= 0) {
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen if (ret == 0) {
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen mail_index_set_error(view->log->index,
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen "Lost transaction log file %s seq %u",
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen file->filepath, file->hdr.file_seq);
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen }
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen return -1;
11352dc3e4b29f3d2763c82f8ea4f99e8daf4fa3Timo Sirainen }
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen first = file;
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen
755aea84bbe2b15ed7fe991f6462a93333ff571fTimo Sirainen for (seq = min_file_seq+1; seq <= max_file_seq; seq++) {
755aea84bbe2b15ed7fe991f6462a93333ff571fTimo Sirainen file = file->next;
755aea84bbe2b15ed7fe991f6462a93333ff571fTimo Sirainen if (file == NULL || file->hdr.file_seq != seq) {
755aea84bbe2b15ed7fe991f6462a93333ff571fTimo Sirainen mail_index_set_error(view->log->index,
755aea84bbe2b15ed7fe991f6462a93333ff571fTimo Sirainen "Lost transaction log file %s seq %u",
755aea84bbe2b15ed7fe991f6462a93333ff571fTimo Sirainen view->log->tail->filepath, seq);
755aea84bbe2b15ed7fe991f6462a93333ff571fTimo Sirainen return -1;
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen }
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen end_offset = file->hdr.file_seq == max_file_seq ?
755aea84bbe2b15ed7fe991f6462a93333ff571fTimo Sirainen max_file_offset : (uoff_t)-1;
755aea84bbe2b15ed7fe991f6462a93333ff571fTimo Sirainen ret = mail_transaction_log_file_map(file,
755aea84bbe2b15ed7fe991f6462a93333ff571fTimo Sirainen sizeof(struct mail_transaction_log_header),
8305127d1074cf9a1e25dec9be2735276462079dTimo Sirainen end_offset);
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen if (ret == 0) {
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen mail_index_set_error(view->log->index,
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen "Lost transaction log file %s seq %u",
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen file->filepath, file->hdr.file_seq);
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen }
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen if (ret <= 0)
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen return -1;
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen }
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen i_assert(max_file_offset <= file->hdr.used_size);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* we have all of them. update refcounts. */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (view->tail->hdr.file_seq < first->hdr.file_seq) {
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen /* unref old files */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen for (file = view->tail; file != first; file = file->next)
596433ccbca59ce2328dc1d029586154cd937155Timo Sirainen file->refcount--;
596433ccbca59ce2328dc1d029586154cd937155Timo Sirainen view->tail = first;
4145cbac82bfc0c8bfeceeca0ef841700117930cTimo Sirainen } else {
4145cbac82bfc0c8bfeceeca0ef841700117930cTimo Sirainen /* going backwards, reference them */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen for (file = first; file != view->tail; file = file->next)
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen file->refcount++;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen }
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainen
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen /* reference all new files */
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen for (file = view->head->next; file != NULL; file = file->next)
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen file->refcount++;
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen view->head = view->log->head;
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen view->prev_file_seq = 0;
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen view->prev_file_offset = 0;
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen view->cur = first;
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen view->cur_offset = min_file_offset;
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen view->min_file_seq = min_file_seq;
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen view->min_file_offset = min_file_offset;
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen view->max_file_seq = max_file_seq;
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen view->max_file_offset = max_file_offset;
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen view->type_mask = type_mask;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen view->broken = FALSE;
7f3b826a89bcb7a72759912e99f574b28309fe1bTimo Sirainen return 0;
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen}
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainenvoid
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainenmail_transaction_log_view_get_prev_pos(struct mail_transaction_log_view *view,
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen uint32_t *file_seq_r,
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen uoff_t *file_offset_r)
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen{
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen *file_seq_r = view->prev_file_seq;
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen *file_offset_r = view->prev_file_offset;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenvoid
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenmail_transaction_log_view_set_corrupted(struct mail_transaction_log_view *view,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *fmt, ...)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen va_list va;
e10d8b1291090c26b9ef499637e6e632485ca5beTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen view->broken = TRUE;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen va_start(va, fmt);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen t_push();
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen mail_transaction_log_file_set_corrupted(view->log->head, "%s",
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen t_strdup_vprintf(fmt, va));
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen t_pop();
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen va_end(va);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
18ccd19c244f49665fe03cda785efa066d2c38dfTimo Sirainenint
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenmail_transaction_log_view_is_corrupted(struct mail_transaction_log_view *view)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return view->broken;
c529313e1cbc22244d4528e80aa3e485f8806cd3Timo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainenstatic int log_view_get_next(struct mail_transaction_log_view *view,
d22301419109ed4a38351715e6760011421dadecTimo Sirainen const struct mail_transaction_header **hdr_r,
d22301419109ed4a38351715e6760011421dadecTimo Sirainen const void **data_r)
d22301419109ed4a38351715e6760011421dadecTimo Sirainen{
d22301419109ed4a38351715e6760011421dadecTimo Sirainen const struct mail_transaction_header *hdr;
499fec3443374cc89fb8c83b8027c1614097d7a3Timo Sirainen struct mail_transaction_log_file *file;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen const struct mail_transaction_type_map *type_rec;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen const void *data;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen unsigned int record_size;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen size_t file_size;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen for (;;) {
d22301419109ed4a38351715e6760011421dadecTimo Sirainen file = view->cur;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (file == NULL)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return 0;
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen view->prev_file_seq = file->hdr.file_seq;
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen view->prev_file_offset = view->cur_offset;
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen if (view->cur_offset != file->hdr.used_size)
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen break;
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen view->cur = file->next;
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen view->cur_offset = sizeof(struct mail_transaction_log_header);
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen }
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen data = buffer_get_data(file->buffer, &file_size);
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen file_size += file->buffer_offset;
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen if (view->cur_offset + sizeof(*hdr) > file_size) {
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen mail_transaction_log_file_set_corrupted(file,
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen "offset points outside file "
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen "(%"PRIuUOFF_T" + %"PRIuSIZE_T" > %"PRIuSIZE_T")",
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen view->cur_offset, sizeof(*hdr), file_size);
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen return -1;
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen }
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen
c4bb0320ab43ea35fa6df88fc745fdad906cee44Timo Sirainen hdr = CONST_PTR_OFFSET(data, view->cur_offset - file->buffer_offset);
c4bb0320ab43ea35fa6df88fc745fdad906cee44Timo Sirainen view->cur_offset += sizeof(*hdr);
c4bb0320ab43ea35fa6df88fc745fdad906cee44Timo Sirainen data = CONST_PTR_OFFSET(hdr, sizeof(*hdr));
047e3bbb00e68a0d43355e11a67b2e912e06de19Timo Sirainen
c4bb0320ab43ea35fa6df88fc745fdad906cee44Timo Sirainen if (file_size - view->cur_offset < hdr->size) {
047e3bbb00e68a0d43355e11a67b2e912e06de19Timo Sirainen mail_transaction_log_file_set_corrupted(file,
047e3bbb00e68a0d43355e11a67b2e912e06de19Timo Sirainen "record size too large (type=0x%x, offset=%"PRIuUOFF_T
047e3bbb00e68a0d43355e11a67b2e912e06de19Timo Sirainen ", size=%u, end=%"PRIuSIZE_T")",
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen hdr->type & MAIL_TRANSACTION_TYPE_MASK,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen view->cur_offset, hdr->size, file_size);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen view->cur_offset = file_size;
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen return -1;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen type_rec = mail_transaction_type_lookup(hdr->type);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen if (type_rec != NULL)
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen record_size = type_rec->record_size;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen else {
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen mail_transaction_log_file_set_corrupted(file,
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen "unknown record type 0x%x",
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen hdr->type & MAIL_TRANSACTION_TYPE_MASK);
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen view->cur_offset = file->hdr.used_size;
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen return -1;
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen }
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0) {
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_TYPE_MASK) !=
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen (MAIL_TRANSACTION_EXPUNGE|MAIL_TRANSACTION_EXPUNGE_PROT)) {
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen mail_transaction_log_file_set_corrupted(file,
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen "found expunge without protection mask");
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen return -1;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen } else if ((hdr->type & MAIL_TRANSACTION_TYPE_MASK) != type_rec->type) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mail_transaction_log_file_set_corrupted(file,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen "extra bits in header type: 0x%x",
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen hdr->type & MAIL_TRANSACTION_TYPE_MASK);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return -1;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen } else if (hdr->type == MAIL_TRANSACTION_EXTRA_REC_UPDATE) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const struct mail_transaction_extra_rec_header *ehdr = data;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (ehdr->idx >= view->log->index->extra_records_count) {
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen mail_transaction_log_file_set_corrupted(file,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen "extra record update out of range (%u > %u)",
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen ehdr->idx,
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen view->log->index->extra_records_count);
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen return -1;
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen }
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen }
18ccd19c244f49665fe03cda785efa066d2c38dfTimo Sirainen
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen if (hdr->size % record_size != 0) {
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen mail_transaction_log_file_set_corrupted(file,
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen "record size wrong (type 0x%x, %u %% %u != 0)",
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainen hdr->type & MAIL_TRANSACTION_TYPE_MASK,
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen hdr->size, record_size);
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen view->cur_offset = file->hdr.used_size;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return -1;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen *hdr_r = hdr;
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen *data_r = data;
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen view->cur_offset += hdr->size;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return 1;
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenint mail_transaction_log_view_next(struct mail_transaction_log_view *view,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const struct mail_transaction_header **hdr_r,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const void **data_r, int *skipped_r)
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen{
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen const struct mail_transaction_header *hdr;
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen const void *data;
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen int ret = 0;
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen if (skipped_r != NULL)
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen *skipped_r = FALSE;
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen if (view->broken)
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen return -1;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen while ((ret = log_view_get_next(view, &hdr, &data)) > 0) {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if ((view->type_mask & hdr->type) != 0)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen break;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen /* we don't want this record */
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (skipped_r != NULL)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen *skipped_r = TRUE;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen /* FIXME: hide flag/cache updates for appends if
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen append isn't in mask */
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen }
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (ret <= 0)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen return ret;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen *hdr_r = hdr;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen *data_r = data;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0) {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen /* hide expunge protection */
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (*hdr_r != &view->tmp_hdr) {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen view->tmp_hdr = *hdr;
d859478e8b106de6cea54f26861bd4232c92f62cTimo Sirainen *hdr_r = &view->tmp_hdr;
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen }
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen view->tmp_hdr.type &= ~MAIL_TRANSACTION_EXPUNGE_PROT;
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen }
d859478e8b106de6cea54f26861bd4232c92f62cTimo Sirainen
206ed2f6fa3a6fb291498627b2da626581c07a18Timo Sirainen return 1;
206ed2f6fa3a6fb291498627b2da626581c07a18Timo Sirainen}
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen