mail-transaction-log-view.c revision 1b56f5fdd415270c743a38719d41b4d9497bcacd
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen#include "lib.h"
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen#include "buffer.h"
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen#include "mail-index-private.h"
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen#include "mail-transaction-log-private.h"
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen#include "mail-transaction-util.h"
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenstruct mail_transaction_log_view {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen struct mail_transaction_log *log;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen struct mail_transaction_log_view *next;
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen uint32_t min_file_seq, max_file_seq;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen uoff_t min_file_offset, max_file_offset;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen enum mail_transaction_type type_mask;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen struct mail_transaction_header tmp_hdr;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen struct mail_transaction_log_file *cur, *head, *tail;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen uoff_t cur_offset;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen uint32_t prev_file_seq;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen uoff_t prev_file_offset;
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen unsigned int broken:1;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen};
2e99f3f3bb35715ce5e0a75a2f2a9bac3ab4224bTimo Sirainen
2e99f3f3bb35715ce5e0a75a2f2a9bac3ab4224bTimo Sirainenstruct mail_transaction_log_view *
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenmail_transaction_log_view_open(struct mail_transaction_log *log)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen struct mail_transaction_log_view *view;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen view = i_new(struct mail_transaction_log_view, 1);
2e99f3f3bb35715ce5e0a75a2f2a9bac3ab4224bTimo Sirainen view->log = log;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen view->broken = TRUE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen view->head = view->tail = view->log->head;
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen view->head->refcount++;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
b397665e90fa0fc7c6a9156fdd6cf28b571e8e39Timo Sirainen view->next = log->views;
b397665e90fa0fc7c6a9156fdd6cf28b571e8e39Timo Sirainen log->views = view;
b397665e90fa0fc7c6a9156fdd6cf28b571e8e39Timo Sirainen return view;
b397665e90fa0fc7c6a9156fdd6cf28b571e8e39Timo Sirainen}
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenvoid mail_transaction_log_view_close(struct mail_transaction_log_view *view)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen struct mail_transaction_log_view **p;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen struct mail_transaction_log_file *file;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen for (p = &view->log->views; *p != NULL; p = &(*p)->next) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (*p == view) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen *p = view->next;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen break;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen for (file = view->tail; file != view->head; file = file->next)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen file->refcount--;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen view->head->refcount--;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen mail_transaction_logs_clean(view->log);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen i_free(view);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenvoid mail_transaction_log_views_close(struct mail_transaction_log *log)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct mail_transaction_log_view *view;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen for (view = log->views; view != NULL; view = view->next)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen view->log = NULL;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenint
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenmail_transaction_log_view_set(struct mail_transaction_log_view *view,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen uint32_t min_file_seq, uoff_t min_file_offset,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen uint32_t max_file_seq, uoff_t max_file_offset,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen enum mail_transaction_type type_mask)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen /* FIXME: error handling for "not found" case is bad.. should the
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen caller after all check it and handle as it sees best..? */
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen struct mail_transaction_log_file *file, *first;
0f66f12eb4cdbf47670975044c88d8f388bf92dfTimo Sirainen uint32_t seq;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen uoff_t end_offset;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen int ret;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen i_assert(min_file_seq <= max_file_seq);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (view->log == NULL)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return -1;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (min_file_seq == view->log->tail->hdr.prev_file_seq &&
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen min_file_offset == view->log->tail->hdr.prev_file_offset) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen /* we can skip this */
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen min_file_seq = view->log->tail->hdr.file_seq;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen min_file_offset = sizeof(struct mail_transaction_log_header);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (min_file_seq > max_file_seq) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen /* empty view */
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen max_file_seq = min_file_seq;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen max_file_offset = min_file_offset;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen ret = mail_transaction_log_file_find(view->log, min_file_seq, &file);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (ret <= 0) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (ret == 0) {
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen mail_index_set_error(view->log->index,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen "Lost transaction log file %s seq %u",
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen view->log->tail->filepath, min_file_seq);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen return -1;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen /* check these later than others as index file may have corrupted
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen log_file_offset. we should have recreated the log file and
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen skipped min_file_seq file above.. max_file_offset can be broken
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen only if min_file_seq = max_file_seq. */
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen i_assert(min_file_offset >= sizeof(struct mail_transaction_log_header));
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen i_assert(max_file_offset >= sizeof(struct mail_transaction_log_header));
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen i_assert(min_file_seq != max_file_seq ||
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen min_file_offset <= max_file_offset);
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen end_offset = min_file_seq == max_file_seq ?
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen max_file_offset : (uoff_t)-1;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen ret = mail_transaction_log_file_map(file, min_file_offset, end_offset);
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen if (ret <= 0) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (ret == 0) {
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen mail_index_set_error(view->log->index,
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen "Lost transaction log file %s seq %u",
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen file->filepath, file->hdr.file_seq);
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen }
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen return -1;
0bf3eac1110a902e7ec7e695c64e8e46c114e623Timo Sirainen }
0bf3eac1110a902e7ec7e695c64e8e46c114e623Timo Sirainen first = file;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen for (seq = min_file_seq+1; seq <= max_file_seq; seq++) {
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen file = file->next;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen if (file == NULL || file->hdr.file_seq != seq) {
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen mail_index_set_error(view->log->index,
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen "Lost transaction log file %s seq %u",
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen file->filepath, seq);
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen return -1;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen }
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen end_offset = file->hdr.file_seq == max_file_seq ?
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen max_file_offset : (uoff_t)-1;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen ret = mail_transaction_log_file_map(file,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen sizeof(struct mail_transaction_log_header),
f153a2cec0319f549388d28f8cfd4d50229d1132Timo Sirainen end_offset);
f153a2cec0319f549388d28f8cfd4d50229d1132Timo Sirainen if (ret == 0) {
f153a2cec0319f549388d28f8cfd4d50229d1132Timo Sirainen mail_index_set_error(view->log->index,
f153a2cec0319f549388d28f8cfd4d50229d1132Timo Sirainen "Lost transaction log file %s seq %u",
f153a2cec0319f549388d28f8cfd4d50229d1132Timo Sirainen file->filepath, file->hdr.file_seq);
dffa503fd4ce31334346e539496084c80a2d8d37Timo Sirainen }
dffa503fd4ce31334346e539496084c80a2d8d37Timo Sirainen if (ret <= 0)
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen return -1;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen }
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen i_assert(max_file_offset <= file->hdr.used_size);
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen /* we have all of them. update refcounts. */
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen if (view->tail->hdr.file_seq < first->hdr.file_seq) {
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen /* unref old files */
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen for (file = view->tail; file != first; file = file->next)
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen file->refcount--;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen view->tail = first;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen } else {
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen /* going backwards, reference them */
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen for (file = first; file != view->tail; file = file->next)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen file->refcount++;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen /* reference all new files */
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen for (file = view->head->next; file != NULL; file = file->next)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen file->refcount++;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen view->head = view->log->head;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen view->prev_file_seq = 0;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen view->prev_file_offset = 0;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen view->cur = first;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen view->cur_offset = min_file_offset;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen view->min_file_seq = min_file_seq;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen view->min_file_offset = min_file_offset;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen view->max_file_seq = max_file_seq;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen view->max_file_offset = max_file_offset;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen view->type_mask = type_mask;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen view->broken = FALSE;
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen return 0;
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen}
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenvoid
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenmail_transaction_log_view_get_prev_pos(struct mail_transaction_log_view *view,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen uint32_t *file_seq_r,
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen uoff_t *file_offset_r)
14c474d9f4591c397ed0b5206af6537c7b52c924Timo Sirainen{
14c474d9f4591c397ed0b5206af6537c7b52c924Timo Sirainen *file_seq_r = view->prev_file_seq;
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen *file_offset_r = view->prev_file_offset;
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen}
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainenvoid
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainenmail_transaction_log_view_set_corrupted(struct mail_transaction_log_view *view,
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen const char *fmt, ...)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen va_list va;
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen view->broken = TRUE;
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen
b6612c334604eeb27e1ca2bd804ac66dcbc2eaadTimo Sirainen va_start(va, fmt);
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen t_push();
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen mail_transaction_log_file_set_corrupted(view->log->head, "%s",
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen t_strdup_vprintf(fmt, va));
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen t_pop();
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen va_end(va);
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen}
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainenint
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainenmail_transaction_log_view_is_corrupted(struct mail_transaction_log_view *view)
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen{
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen return view->broken;
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen}
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainenstatic int log_view_get_next(struct mail_transaction_log_view *view,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen const struct mail_transaction_header **hdr_r,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen const void **data_r)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen const struct mail_transaction_header *hdr;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen struct mail_transaction_log_file *file;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen const struct mail_transaction_type_map *type_rec;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen const void *data;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen unsigned int record_size;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen size_t file_size;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen for (;;) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen file = view->cur;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen view->prev_file_seq = file->hdr.file_seq;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen view->prev_file_offset = view->cur_offset;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (view->cur_offset != file->hdr.used_size)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen break;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen view->cur = file->next;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen view->cur_offset = sizeof(struct mail_transaction_log_header);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (view->cur == NULL)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return 0;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen data = buffer_get_data(file->buffer, &file_size);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen file_size += file->buffer_offset;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (view->cur_offset + sizeof(*hdr) > file_size) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen mail_transaction_log_file_set_corrupted(file,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen "offset points outside file "
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen "(%"PRIuUOFF_T" + %"PRIuSIZE_T" > %"PRIuSIZE_T")",
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen view->cur_offset, sizeof(*hdr), file_size);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return -1;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen hdr = CONST_PTR_OFFSET(data, view->cur_offset - file->buffer_offset);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen view->cur_offset += sizeof(*hdr);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (file_size - view->cur_offset < hdr->size) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen mail_transaction_log_file_set_corrupted(file,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen "record size too large (type=0x%x, offset=%"PRIuUOFF_T
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen ", size=%u, end=%"PRIuSIZE_T")",
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen hdr->type & MAIL_TRANSACTION_TYPE_MASK,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen view->cur_offset, hdr->size, file_size);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen view->cur_offset = file_size;
5707510e5d1c8aa79a0acf737ee1429caf3d59c2Timo Sirainen return -1;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen type_rec = mail_transaction_type_lookup(hdr->type);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (type_rec != NULL)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen record_size = type_rec->record_size;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen else {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen mail_transaction_log_file_set_corrupted(file,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen "unknown record type 0x%x",
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen hdr->type & MAIL_TRANSACTION_TYPE_MASK);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen view->cur_offset = file->hdr.used_size;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return -1;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if ((hdr->type & MAIL_TRANSACTION_TYPE_MASK) !=
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen (MAIL_TRANSACTION_EXPUNGE|MAIL_TRANSACTION_EXPUNGE_PROT)) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen mail_transaction_log_file_set_corrupted(file,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen "found expunge without protection mask");
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return -1;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen } else if ((hdr->type & MAIL_TRANSACTION_TYPE_MASK) != type_rec->type) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen mail_transaction_log_file_set_corrupted(file,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen "extra bits in header type: 0x%x",
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen hdr->type & MAIL_TRANSACTION_TYPE_MASK);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return -1;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (hdr->size % record_size != 0) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen mail_transaction_log_file_set_corrupted(file,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen "record size wrong (type 0x%x, %u %% %u != 0)",
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen hdr->type & MAIL_TRANSACTION_TYPE_MASK,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen hdr->size, record_size);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen view->cur_offset = file->hdr.used_size;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return -1;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen *hdr_r = hdr;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen *data_r = CONST_PTR_OFFSET(data, view->cur_offset -
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen file->buffer_offset);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen view->cur_offset += hdr->size;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return 1;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenint mail_transaction_log_view_next(struct mail_transaction_log_view *view,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen const struct mail_transaction_header **hdr_r,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen const void **data_r, int *skipped_r)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
cc833a7a4e2258afdc834ace4bfe6579820a1df3Timo Sirainen const struct mail_transaction_header *hdr;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen const void *data;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen int ret = 0;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (skipped_r != NULL)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen *skipped_r = FALSE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (view->broken)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return -1;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen while ((ret = log_view_get_next(view, &hdr, &data)) > 0) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if ((view->type_mask & hdr->type) != 0)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen break;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen /* we don't want this record */
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (skipped_r != NULL)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen *skipped_r = TRUE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen /* FIXME: hide flag/cache updates for appends if
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen append isn't in mask */
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (ret <= 0)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return ret;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen *hdr_r = hdr;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen *data_r = data;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen /* hide expunge protection */
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (*hdr_r != &view->tmp_hdr) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen view->tmp_hdr = *hdr;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen *hdr_r = &view->tmp_hdr;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen view->tmp_hdr.type &= ~MAIL_TRANSACTION_EXPUNGE_PROT;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return 1;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen