mail-transaction-log-view.c revision b5b3b4c9159f506cdfdce7399faaeeffdf73faf7
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen/* Copyright (c) 2003-2010 Dovecot authors, see the included COPYING file */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen#include "lib.h"
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen#include "array.h"
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen#include "mail-index-private.h"
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen#include "mail-transaction-log-view-private.h"
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainenstruct mail_transaction_log_view *
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenmail_transaction_log_view_open(struct mail_transaction_log *log)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen{
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen struct mail_transaction_log_view *view;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view = i_new(struct mail_transaction_log_view, 1);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->log = log;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->broken = TRUE;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->head = view->tail = view->log->head;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->head->refcount++;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen i_array_init(&view->file_refs, 8);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen array_append(&view->file_refs, &view->head, 1);
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->next = log->views;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen log->views = view;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return view;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen}
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenstatic void
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenmail_transaction_log_view_unref_all(struct mail_transaction_log_view *view)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen{
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen struct mail_transaction_log_file *const *files;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen unsigned int i, count;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen files = array_get(&view->file_refs, &count);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen for (i = 0; i < count; i++)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen files[i]->refcount--;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen array_clear(&view->file_refs);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen}
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenvoid mail_transaction_log_view_close(struct mail_transaction_log_view **_view)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen{
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen struct mail_transaction_log_view *view = *_view;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen struct mail_transaction_log_view **p;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen *_view = NULL;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen for (p = &view->log->views; *p != NULL; p = &(*p)->next) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (*p == view) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen *p = view->next;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen break;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen mail_transaction_log_view_unref_all(view);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen mail_transaction_logs_clean(view->log);
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen array_free(&view->file_refs);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen i_free(view);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen}
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainenvoid mail_transaction_log_views_close(struct mail_transaction_log *log)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen{
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen struct mail_transaction_log_view *view;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen for (view = log->views; view != NULL; view = view->next)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->log = NULL;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen}
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenint mail_transaction_log_view_set(struct mail_transaction_log_view *view,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen uint32_t min_file_seq, uoff_t min_file_offset,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen uint32_t max_file_seq, uoff_t max_file_offset,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen bool *reset_r)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen{
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen struct mail_transaction_log_file *file, *const *files, *tail;
bd63b5b860658b01b1f46f26d406e1e4a9dc019aTimo Sirainen uoff_t start_offset, end_offset;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen unsigned int i;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen uint32_t seq;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen int ret;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen i_assert(min_file_seq <= max_file_seq);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen *reset_r = FALSE;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (view->log == NULL) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* transaction log is closed already. this log view shouldn't
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen be used anymore. */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return -1;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen tail = view->log->files;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (min_file_seq == 0) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* index file doesn't exist yet. this transaction log should
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen start from the beginning */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (tail->hdr.prev_file_seq != 0) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* but it doesn't */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return 0;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen min_file_seq = tail->hdr.file_seq;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen min_file_offset = 0;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (max_file_seq == 0) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen max_file_seq = min_file_seq;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen max_file_offset = min_file_offset;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (min_file_seq == tail->hdr.prev_file_seq &&
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen min_file_offset == tail->hdr.prev_file_offset) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* we can skip this */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen min_file_seq = tail->hdr.file_seq;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen min_file_offset = 0;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (min_file_seq > max_file_seq) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* empty view */
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen max_file_seq = min_file_seq;
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen max_file_offset = min_file_offset;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (min_file_seq == max_file_seq && min_file_offset > max_file_offset) {
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen /* log file offset is probably corrupted in the index file. */
049da065aa64c1a5ed46eed6cde7382b011612a9Timo Sirainen mail_transaction_log_view_set_corrupted(view,
049da065aa64c1a5ed46eed6cde7382b011612a9Timo Sirainen "file_seq=%u, min_file_offset (%"PRIuUOFF_T
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen ") > max_file_offset (%"PRIuUOFF_T")",
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen min_file_seq, min_file_offset, max_file_offset);
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen return -1;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (min_file_offset > 0 && min_file_offset < tail->hdr.hdr_size) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* log file offset is probably corrupted in the index file. */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen mail_transaction_log_view_set_corrupted(view,
27a44fcfd8d19bffe0f267f20a2b5d3fe7600fddTimo Sirainen "file_seq=%u, min_file_offset (%"PRIuUOFF_T
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen ") < hdr_size (%u)",
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen min_file_seq, min_file_offset, tail->hdr.hdr_size);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return -1;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->tail = view->head = file = NULL;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen for (seq = min_file_seq; seq <= max_file_seq; seq++) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (file == NULL || file->hdr.file_seq != seq) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* see if we could find the missing file. if we know
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen the max. file sequence, make sure NFS attribute
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen cache gets flushed if necessary. */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen bool nfs_flush = max_file_seq != (uint32_t)-1;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen ret = mail_transaction_log_find_file(view->log, seq,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen nfs_flush, &file);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (ret <= 0) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (ret < 0)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return -1;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* not found / corrupted */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen file = NULL;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (file == NULL || file->hdr.file_seq != seq) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (file == NULL && max_file_seq == (uint32_t)-1 &&
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->head == view->log->head) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* we just wanted to sync everything */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen i_assert(max_file_offset == (uoff_t)-1);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen max_file_seq = seq-1;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen break;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* if any of the found files reset the index,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen ignore any missing files up to it */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen file = view->tail != NULL ? view->tail :
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->log->files;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen for (;; file = file->next) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (file == NULL ||
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen file->hdr.file_seq > max_file_seq) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* missing files in the middle */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return 0;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (file->hdr.file_seq >= seq &&
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen file->hdr.prev_file_seq == 0) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* we can ignore the missing file */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen break;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen seq = file->hdr.file_seq;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->tail = NULL;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (view->tail == NULL)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->tail = file;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->head = file;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen file = file->next;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen i_assert(view->tail != NULL);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen if (min_file_offset == 0) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* beginning of the file */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen min_file_offset = view->tail->hdr.hdr_size;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (min_file_offset > max_file_offset &&
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen min_file_seq == max_file_seq) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* we don't actually want to show anything */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen max_file_offset = min_file_offset;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen i_assert(min_file_offset >= view->tail->hdr.hdr_size);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (min_file_seq == view->head->hdr.file_seq &&
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen min_file_offset > view->head->sync_offset) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* log file offset is probably corrupted in the index file. */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen mail_transaction_log_view_set_corrupted(view,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen "file_seq=%u, min_file_offset (%"PRIuUOFF_T
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen ") > sync_offset (%"PRIuUOFF_T")", min_file_seq,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen min_file_offset, view->head->sync_offset);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return -1;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* we have all of them. update refcounts. */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen mail_transaction_log_view_unref_all(view);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* Reference all used files. */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen for (file = view->tail;; file = file->next) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen array_append(&view->file_refs, &file, 1);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen file->refcount++;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (file == view->head)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen break;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->cur = view->tail;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->cur_offset = view->cur->hdr.file_seq == min_file_seq ?
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen min_file_offset : view->cur->hdr.hdr_size;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* Map the files only after we've found them all. Otherwise if we map
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen one file and then another file just happens to get rotated, we could
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen include both files in the view but skip the last transactions from
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen the first file.
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen We're mapping the files in reverse order so that _log_file_map()
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen can verify that prev_file_offset matches how far it actually managed
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen to sync the file. */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen files = array_idx(&view->file_refs, 0);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen for (i = array_count(&view->file_refs); i > 0; i--) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen file = files[i-1];
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen start_offset = file->hdr.file_seq == min_file_seq ?
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen min_file_offset : file->hdr.hdr_size;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen end_offset = file->hdr.file_seq == max_file_seq ?
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen max_file_offset : (uoff_t)-1;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen ret = mail_transaction_log_file_map(file, start_offset,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen end_offset);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (ret <= 0)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return ret;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (file->hdr.prev_file_seq == 0) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* this file resets the index.
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen don't bother reading the others. */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (view->cur != file ||
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->cur_offset == file->hdr.hdr_size) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->cur = file;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->cur_offset = file->hdr.hdr_size;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen *reset_r = TRUE;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen break;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen i_assert(i == 1);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen i_assert(max_file_seq == (uint32_t)-1 ||
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen max_file_seq == view->head->hdr.file_seq);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen i_assert(max_file_offset == (uoff_t)-1 ||
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen max_file_offset <= view->head->sync_offset);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen i_assert(min_file_seq != max_file_seq ||
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen max_file_seq != view->head->hdr.file_seq ||
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen max_file_offset != (uoff_t)-1 ||
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen min_file_offset <= view->head->sync_offset);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->prev_file_seq = view->cur->hdr.file_seq;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->prev_file_offset = view->cur_offset;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->min_file_seq = min_file_seq;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->min_file_offset = min_file_offset;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->max_file_seq = max_file_seq;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->max_file_offset = I_MIN(max_file_offset, view->head->sync_offset);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->broken = FALSE;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (mail_transaction_log_file_get_highest_modseq_at(view->cur,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->cur_offset, &view->prev_modseq) < 0)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return -1;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen i_assert(view->cur_offset <= view->cur->sync_offset);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return 1;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen}
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenvoid mail_transaction_log_view_clear(struct mail_transaction_log_view *view,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen uint32_t oldest_file_seq)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen{
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen struct mail_transaction_log_file *file;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen mail_transaction_log_view_unref_all(view);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (mail_transaction_log_find_file(view->log, oldest_file_seq, FALSE,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen &file) > 0) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen for (; file != NULL; file = file->next) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen array_append(&view->file_refs, &file, 1);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen file->refcount++;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->cur = view->head = view->tail = NULL;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->mark_file = NULL;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->mark_offset = 0;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->mark_modseq = 0;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->min_file_seq = view->max_file_seq = 0;
c8c4bbf6b1415e9d0845bc8f1cd6d19b76ab0392Timo Sirainen view->min_file_offset = view->max_file_offset = 0;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->cur_offset = 0;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->prev_file_seq = 0;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->prev_file_offset = 0;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->prev_modseq = 0;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen}
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenvoid
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenmail_transaction_log_view_get_prev_pos(struct mail_transaction_log_view *view,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen uint32_t *file_seq_r,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen uoff_t *file_offset_r)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen{
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen *file_seq_r = view->prev_file_seq;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen *file_offset_r = view->prev_file_offset;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen}
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenuint64_t
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenmail_transaction_log_view_get_prev_modseq(struct mail_transaction_log_view *view)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen{
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return view->prev_modseq;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen}
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenstatic bool
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenmail_transaction_log_view_get_last(struct mail_transaction_log_view *view,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen struct mail_transaction_log_file **last_r,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen uoff_t *last_offset_r)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen{
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen struct mail_transaction_log_file *cur = view->cur;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen uoff_t cur_offset = view->cur_offset;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen bool last = FALSE;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (cur == NULL) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen *last_r = NULL;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return TRUE;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen for (;;) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (cur->hdr.file_seq == view->max_file_seq) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* last file */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (cur_offset == view->max_file_offset ||
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen cur_offset == cur->sync_offset) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* we're all finished */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen last = TRUE;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen } else if (cur_offset == cur->sync_offset) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* end of file, go to next one */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (cur->next == NULL) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen last = TRUE;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen } else {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen cur = cur->next;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen cur_offset = cur->hdr.hdr_size;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen continue;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* not EOF */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen break;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen *last_r = cur;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen *last_offset_r = cur_offset;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return last;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen}
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenbool mail_transaction_log_view_is_last(struct mail_transaction_log_view *view)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen{
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen struct mail_transaction_log_file *cur;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen uoff_t cur_offset;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return mail_transaction_log_view_get_last(view, &cur, &cur_offset);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen}
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainenvoid
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainenmail_transaction_log_view_set_corrupted(struct mail_transaction_log_view *view,
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen const char *fmt, ...)
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen{
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen va_list va;
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->broken = TRUE;
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen va_start(va, fmt);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen T_BEGIN {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen mail_transaction_log_file_set_corrupted(view->log->head, "%s",
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen t_strdup_vprintf(fmt, va));
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen } T_END;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen va_end(va);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen}
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenbool
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenmail_transaction_log_view_is_corrupted(struct mail_transaction_log_view *view)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen{
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return view->broken;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen}
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenstatic bool
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenlog_view_is_uid_range_valid(struct mail_transaction_log_file *file,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen enum mail_transaction_type rec_type,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen const ARRAY_TYPE(seq_range) *uids)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen{
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen const struct seq_range *rec, *prev = NULL;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen unsigned int i, count = array_count(uids);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if ((uids->arr.buffer->used % uids->arr.element_size) != 0) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen mail_transaction_log_file_set_corrupted(file,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen "Invalid record size (type=0x%x)", rec_type);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return FALSE;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen } else if (count == 0) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen mail_transaction_log_file_set_corrupted(file,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen "No UID ranges (type=0x%x)", rec_type);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return FALSE;
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen for (i = 0; i < count; i++, prev = rec) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen rec = array_idx(uids, i);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (rec->seq1 > rec->seq2 || rec->seq1 == 0) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen mail_transaction_log_file_set_corrupted(file,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen "Invalid UID range (%u .. %u, type=0x%x)",
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen rec->seq1, rec->seq2, rec_type);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return FALSE;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (prev != NULL && rec->seq1 <= prev->seq2) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen mail_transaction_log_file_set_corrupted(file,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen "Non-sorted UID ranges (type=0x%x)", rec_type);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return FALSE;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return TRUE;
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen}
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenstatic bool
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainenlog_view_is_record_valid(struct mail_transaction_log_file *file,
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen const struct mail_transaction_header *hdr,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen const void *data)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen{
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen enum mail_transaction_type rec_type;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen ARRAY_TYPE(seq_range) uids = ARRAY_INIT;
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen buffer_t uid_buf;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen uint32_t rec_size;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen rec_type = hdr->type & MAIL_TRANSACTION_TYPE_MASK;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen rec_size = mail_index_offset_to_uint32(hdr->size) - sizeof(*hdr);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* we want to be extra careful with expunges */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0) {
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen if (rec_type != (MAIL_TRANSACTION_EXPUNGE |
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen MAIL_TRANSACTION_EXPUNGE_PROT)) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen mail_transaction_log_file_set_corrupted(file,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen "expunge record missing protection mask");
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return FALSE;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen rec_type &= ~MAIL_TRANSACTION_EXPUNGE_PROT;
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen }
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXPUNGE_GUID) != 0) {
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen if (rec_type != (MAIL_TRANSACTION_EXPUNGE_GUID |
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen MAIL_TRANSACTION_EXPUNGE_PROT)) {
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen mail_transaction_log_file_set_corrupted(file,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen "expunge guid record missing protection mask");
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return FALSE;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen rec_type &= ~MAIL_TRANSACTION_EXPUNGE_PROT;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
0e7d5ff38f28d8c85e197a031bbb66b322ff89e6Timo Sirainen if (rec_size == 0) {
0e7d5ff38f28d8c85e197a031bbb66b322ff89e6Timo Sirainen mail_transaction_log_file_set_corrupted(file,
0e7d5ff38f28d8c85e197a031bbb66b322ff89e6Timo Sirainen "Empty record contents (type=0x%x)", rec_type);
0e7d5ff38f28d8c85e197a031bbb66b322ff89e6Timo Sirainen return FALSE;
0e7d5ff38f28d8c85e197a031bbb66b322ff89e6Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
0e7d5ff38f28d8c85e197a031bbb66b322ff89e6Timo Sirainen /* records that are exported by syncing and view syncing will be
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen checked here so that we don't have to implement the same validation
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen multiple times. other records are checked internally by
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen mail_index_sync_record(). */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen switch (rec_type) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen case MAIL_TRANSACTION_APPEND:
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if ((rec_size % sizeof(struct mail_index_record)) != 0) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen mail_transaction_log_file_set_corrupted(file,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen "Invalid append record size");
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return FALSE;
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen }
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen break;
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen case MAIL_TRANSACTION_EXPUNGE:
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen buffer_create_const_data(&uid_buf, data, rec_size);
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen array_create_from_buffer(&uids, &uid_buf,
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen sizeof(struct mail_transaction_expunge));
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen break;
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen case MAIL_TRANSACTION_EXPUNGE_GUID:
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen if ((rec_size % sizeof(struct mail_transaction_expunge_guid)) != 0) {
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen mail_transaction_log_file_set_corrupted(file,
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen "Invalid expunge guid record size");
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen return FALSE;
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen }
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen break;
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen case MAIL_TRANSACTION_FLAG_UPDATE:
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen buffer_create_const_data(&uid_buf, data, rec_size);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen array_create_from_buffer(&uids, &uid_buf,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen sizeof(struct mail_transaction_flag_update));
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen break;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen case MAIL_TRANSACTION_KEYWORD_UPDATE: {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen const struct mail_transaction_keyword_update *rec = data;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen unsigned int seqset_offset;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen seqset_offset = sizeof(*rec) + rec->name_size;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if ((seqset_offset % 4) != 0)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen seqset_offset += 4 - (seqset_offset % 4);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (seqset_offset > rec_size) {
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen mail_transaction_log_file_set_corrupted(file,
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen "Invalid keyword update record size");
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return FALSE;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen buffer_create_const_data(&uid_buf,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen CONST_PTR_OFFSET(data, seqset_offset),
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen rec_size - seqset_offset);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen array_create_from_buffer(&uids, &uid_buf,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen sizeof(uint32_t)*2);
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen break;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen case MAIL_TRANSACTION_KEYWORD_RESET:
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen buffer_create_const_data(&uid_buf, data, rec_size);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen array_create_from_buffer(&uids, &uid_buf,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen sizeof(struct mail_transaction_keyword_reset));
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen break;
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen default:
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen break;
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (array_is_created(&uids)) {
b10c3f9ed997748fdbb03b9daadc8c31eed02120Timo Sirainen if (!log_view_is_uid_range_valid(file, rec_type, &uids))
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return FALSE;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return TRUE;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen}
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenstatic int
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenlog_view_get_next(struct mail_transaction_log_view *view,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen const struct mail_transaction_header **hdr_r,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen const void **data_r)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen{
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen const struct mail_transaction_header *hdr;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen struct mail_transaction_log_file *file;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen const void *data;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen enum mail_transaction_type rec_type;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen uint32_t full_size;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen size_t file_size;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen int ret;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (view->cur == NULL)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return 0;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* prev_file_offset should point to beginning of previous log record.
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen when we reach EOF, it should be left there, not to beginning of the
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen next file that's not included inside the view. */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (mail_transaction_log_view_get_last(view, &view->cur,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen &view->cur_offset)) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen /* if the last file was the beginning of a file, we want to
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen move prev pointers there */
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->prev_file_seq = view->cur->hdr.file_seq;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->prev_file_offset = view->cur_offset;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->cur = NULL;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return 0;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->prev_file_seq = view->cur->hdr.file_seq;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->prev_file_offset = view->cur_offset;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen file = view->cur;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen data = buffer_get_data(file->buffer, &file_size);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen file_size += file->buffer_offset;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (view->cur_offset + sizeof(*hdr) > file_size) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen mail_transaction_log_file_set_corrupted(file,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen "offset points outside file "
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen "(%"PRIuUOFF_T" + %"PRIuSIZE_T" > %"PRIuSIZE_T")",
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->cur_offset, sizeof(*hdr), file_size);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return -1;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen i_assert(view->cur_offset >= file->buffer_offset);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen hdr = CONST_PTR_OFFSET(data, view->cur_offset - file->buffer_offset);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen data = CONST_PTR_OFFSET(hdr, sizeof(*hdr));
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen rec_type = hdr->type & MAIL_TRANSACTION_TYPE_MASK;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen full_size = mail_index_offset_to_uint32(hdr->size);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (full_size < sizeof(*hdr)) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen mail_transaction_log_file_set_corrupted(file,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen "record size too small (type=0x%x, "
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen "offset=%"PRIuUOFF_T", size=%u)",
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen rec_type, view->cur_offset, full_size);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return -1;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (file_size - view->cur_offset < full_size) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen mail_transaction_log_file_set_corrupted(file,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen "record size too large (type=0x%x, "
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen "offset=%"PRIuUOFF_T", size=%u, end=%"PRIuSIZE_T")",
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen rec_type, view->cur_offset, full_size, file_size);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return -1;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen T_BEGIN {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen ret = log_view_is_record_valid(file, hdr, data) ? 1 : -1;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen } T_END;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (ret > 0) {
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen mail_transaction_update_modseq(hdr, data, &view->prev_modseq);
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen *hdr_r = hdr;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen *data_r = data;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen view->cur_offset += full_size;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen }
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return ret;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen}
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainenint mail_transaction_log_view_next(struct mail_transaction_log_view *view,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen const struct mail_transaction_header **hdr_r,
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen const void **data_r)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen{
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen const struct mail_transaction_header *hdr;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen const void *data;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen int ret = 0;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen if (view->broken)
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen return -1;
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen
c8593b070319d0ff83f8d6c4b5ed5abf2d578a06Timo Sirainen ret = log_view_get_next(view, &hdr, &data);
if (ret <= 0) {
if (ret < 0)
view->cur_offset = view->cur->sync_offset;
return ret;
}
/* drop expunge protection */
if ((hdr->type & MAIL_TRANSACTION_TYPE_MASK) ==
(MAIL_TRANSACTION_EXPUNGE | MAIL_TRANSACTION_EXPUNGE_PROT) ||
(hdr->type & MAIL_TRANSACTION_TYPE_MASK) ==
(MAIL_TRANSACTION_EXPUNGE_GUID | MAIL_TRANSACTION_EXPUNGE_PROT))
view->tmp_hdr.type = hdr->type & ~MAIL_TRANSACTION_EXPUNGE_PROT;
else
view->tmp_hdr.type = hdr->type;
/* return record's size */
view->tmp_hdr.size = mail_index_offset_to_uint32(hdr->size);
i_assert(view->tmp_hdr.size > sizeof(*hdr));
view->tmp_hdr.size -= sizeof(*hdr);
*hdr_r = &view->tmp_hdr;
*data_r = data;
return 1;
}
void mail_transaction_log_view_mark(struct mail_transaction_log_view *view)
{
i_assert(view->cur->hdr.file_seq == view->prev_file_seq);
view->mark_file = view->cur;
view->mark_offset = view->prev_file_offset;
view->mark_next_offset = view->cur_offset;
view->mark_modseq = view->prev_modseq;
}
void mail_transaction_log_view_rewind(struct mail_transaction_log_view *view)
{
i_assert(view->mark_file != NULL);
view->cur = view->mark_file;
view->cur_offset = view->mark_next_offset;
view->prev_file_seq = view->cur->hdr.file_seq;
view->prev_file_offset = view->mark_offset;
view->prev_modseq = view->mark_modseq;
}