bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2003-2018 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen#include "array.h"
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen#include "str.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-index-private.h"
993e6c2caaae971dd3c34913a42d854e3b623261Timo Sirainen#include "mail-transaction-log-view-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct mail_transaction_log_view *
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmail_transaction_log_view_open(struct mail_transaction_log *log)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_transaction_log_view *view;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen view = i_new(struct mail_transaction_log_view, 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen view->log = log;
7888a9d2008eab9985096c46e1da9ee985c22a2aTimo Sirainen view->broken = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
9e0b187933b52db68c1aefb913970eeba47b986eAki Tuomi i_assert(view->log->head != NULL);
9e0b187933b52db68c1aefb913970eeba47b986eAki Tuomi
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen view->head = view->tail = view->log->head;
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen view->head->refcount++;
213b139965e8bde6c8aff02ffd9fd39a74c887a9Timo Sirainen i_array_init(&view->file_refs, 8);
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen array_append(&view->file_refs, &view->head, 1);
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen view->next = log->views;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen log->views = view;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return view;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainenstatic void
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainenmail_transaction_log_view_unref_all(struct mail_transaction_log_view *view)
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen{
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen struct mail_transaction_log_file *const *files;
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen unsigned int i, count;
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen files = array_get(&view->file_refs, &count);
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen for (i = 0; i < count; i++)
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen files[i]->refcount--;
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen array_clear(&view->file_refs);
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen}
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenvoid mail_transaction_log_view_close(struct mail_transaction_log_view **_view)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen struct mail_transaction_log_view *view = *_view;
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen struct mail_transaction_log_view **p;
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen *_view = NULL;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen for (p = &view->log->views; *p != NULL; p = &(*p)->next) {
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen if (*p == view) {
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen *p = view->next;
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen break;
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen }
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen }
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen mail_transaction_log_view_unref_all(view);
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen mail_transaction_logs_clean(view->log);
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen array_free(&view->file_refs);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_free(view);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainenstatic const char *
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainenmail_transaction_log_get_file_seqs(struct mail_transaction_log *log)
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen{
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen struct mail_transaction_log_file *file;
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen string_t *str = t_str_new(32);
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen if (log->files == NULL)
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen return "";
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen for (file = log->files; file != NULL; file = file->next)
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen str_printfa(str, ",%u", file->hdr.file_seq);
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen return str_c(str) + 1;
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen}
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainenint mail_transaction_log_view_set(struct mail_transaction_log_view *view,
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen uint32_t min_file_seq, uoff_t min_file_offset,
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen uint32_t max_file_seq, uoff_t max_file_offset,
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen bool *reset_r, const char **reason_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
23c502c6ef08d83e8ed68f90ed75138e14a3a246Timo Sirainen struct mail_transaction_log_file *file, *const *files;
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen uoff_t start_offset, end_offset;
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen unsigned int i;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uint32_t seq;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen *reset_r = FALSE;
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen *reason_r = NULL;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen if (view->log == NULL) {
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen /* transaction log is closed already. this log view shouldn't
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen be used anymore. */
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen *reason_r = "Log already closed";
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen return -1;
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen }
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainen if (min_file_seq == 0) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* index file doesn't exist yet. this transaction log should
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen start from the beginning */
23c502c6ef08d83e8ed68f90ed75138e14a3a246Timo Sirainen if (view->log->files->hdr.prev_file_seq != 0) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* but it doesn't */
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen *reason_r = t_strdup_printf(
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen "Wanted log beginning, but found prev_file_seq=%u",
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen view->log->files->hdr.prev_file_seq);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return 0;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
23c502c6ef08d83e8ed68f90ed75138e14a3a246Timo Sirainen min_file_seq = view->log->files->hdr.file_seq;
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen min_file_offset = 0;
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainen
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainen if (max_file_seq == 0) {
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainen max_file_seq = min_file_seq;
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainen max_file_offset = min_file_offset;
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainen }
23c502c6ef08d83e8ed68f90ed75138e14a3a246Timo Sirainen }
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainen
89334d8c6915db0fc8630470b7f3cd5ee9aa29aaTimo Sirainen for (file = view->log->files; file != NULL; file = file->next) {
89334d8c6915db0fc8630470b7f3cd5ee9aa29aaTimo Sirainen if (file->hdr.prev_file_seq == min_file_seq)
89334d8c6915db0fc8630470b7f3cd5ee9aa29aaTimo Sirainen break;
89334d8c6915db0fc8630470b7f3cd5ee9aa29aaTimo Sirainen }
89334d8c6915db0fc8630470b7f3cd5ee9aa29aaTimo Sirainen
89334d8c6915db0fc8630470b7f3cd5ee9aa29aaTimo Sirainen if (file != NULL && min_file_offset == file->hdr.prev_file_offset) {
89334d8c6915db0fc8630470b7f3cd5ee9aa29aaTimo Sirainen /* we can (and sometimes must) skip to the next file */
89334d8c6915db0fc8630470b7f3cd5ee9aa29aaTimo Sirainen min_file_seq = file->hdr.file_seq;
89334d8c6915db0fc8630470b7f3cd5ee9aa29aaTimo Sirainen min_file_offset = file->hdr.hdr_size;
89334d8c6915db0fc8630470b7f3cd5ee9aa29aaTimo Sirainen }
89334d8c6915db0fc8630470b7f3cd5ee9aa29aaTimo Sirainen
23c502c6ef08d83e8ed68f90ed75138e14a3a246Timo Sirainen for (file = view->log->files; file != NULL; file = file->next) {
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen if (file->hdr.prev_file_seq == max_file_seq)
23c502c6ef08d83e8ed68f90ed75138e14a3a246Timo Sirainen break;
23c502c6ef08d83e8ed68f90ed75138e14a3a246Timo Sirainen }
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen if (file != NULL && max_file_offset == file->hdr.prev_file_offset) {
23c502c6ef08d83e8ed68f90ed75138e14a3a246Timo Sirainen /* we can skip to the next file. we've delayed checking for
23c502c6ef08d83e8ed68f90ed75138e14a3a246Timo Sirainen min_file_seq <= max_file_seq until now, because it's not
23c502c6ef08d83e8ed68f90ed75138e14a3a246Timo Sirainen really an error to specify the same position twice (even if
23c502c6ef08d83e8ed68f90ed75138e14a3a246Timo Sirainen in "wrong" order) */
23c502c6ef08d83e8ed68f90ed75138e14a3a246Timo Sirainen i_assert(min_file_seq <= max_file_seq ||
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen min_file_seq <= file->hdr.file_seq);
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen max_file_seq = file->hdr.file_seq;
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen max_file_offset = file->hdr.hdr_size;
23c502c6ef08d83e8ed68f90ed75138e14a3a246Timo Sirainen } else {
23c502c6ef08d83e8ed68f90ed75138e14a3a246Timo Sirainen i_assert(min_file_seq <= max_file_seq);
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen }
40ef82c46f6652412b068ebcdac7c3e74840a284Timo Sirainen
95a284736b8b11319a3f575ba249ba2eb7dbac1bTimo Sirainen if (min_file_seq == max_file_seq && min_file_offset > max_file_offset) {
95a284736b8b11319a3f575ba249ba2eb7dbac1bTimo Sirainen /* log file offset is probably corrupted in the index file. */
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen *reason_r = t_strdup_printf(
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen "Invalid offset: file_seq=%u, min_file_offset (%"PRIuUOFF_T
95a284736b8b11319a3f575ba249ba2eb7dbac1bTimo Sirainen ") > max_file_offset (%"PRIuUOFF_T")",
95a284736b8b11319a3f575ba249ba2eb7dbac1bTimo Sirainen min_file_seq, min_file_offset, max_file_offset);
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen mail_transaction_log_view_set_corrupted(view, "%s", *reason_r);
95a284736b8b11319a3f575ba249ba2eb7dbac1bTimo Sirainen return -1;
95a284736b8b11319a3f575ba249ba2eb7dbac1bTimo Sirainen }
8eeafcb306872435f3171e6acf5a9937aec3a175Timo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen view->tail = view->head = file = NULL;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen for (seq = min_file_seq; seq <= max_file_seq; seq++) {
6321d9d33937c7fc13a8ff04c220a9e377efeeb8Timo Sirainen const char *reason = NULL;
6321d9d33937c7fc13a8ff04c220a9e377efeeb8Timo Sirainen
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen if (file == NULL || file->hdr.file_seq != seq) {
f537e7efaec891d6b3320ca94331d09ca8c4a4dbTimo Sirainen /* see if we could find the missing file. if we know
faee566824fe3567c8beacf097f9dcfc0d3761b7Timo Sirainen the max. file sequence or we don't have the the min.
faee566824fe3567c8beacf097f9dcfc0d3761b7Timo Sirainen file, make sure NFS attribute cache gets flushed if
faee566824fe3567c8beacf097f9dcfc0d3761b7Timo Sirainen necessary. */
faee566824fe3567c8beacf097f9dcfc0d3761b7Timo Sirainen bool nfs_flush = seq == min_file_seq ||
faee566824fe3567c8beacf097f9dcfc0d3761b7Timo Sirainen max_file_seq != (uint32_t)-1;
f537e7efaec891d6b3320ca94331d09ca8c4a4dbTimo Sirainen
f537e7efaec891d6b3320ca94331d09ca8c4a4dbTimo Sirainen ret = mail_transaction_log_find_file(view->log, seq,
6321d9d33937c7fc13a8ff04c220a9e377efeeb8Timo Sirainen nfs_flush, &file, &reason);
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen if (ret <= 0) {
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen if (ret < 0) {
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen *reason_r = t_strdup_printf(
6321d9d33937c7fc13a8ff04c220a9e377efeeb8Timo Sirainen "Failed to find file seq=%u: %s",
6321d9d33937c7fc13a8ff04c220a9e377efeeb8Timo Sirainen seq, reason);
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen return -1;
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen }
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen /* not found / corrupted */
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen file = NULL;
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen }
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen }
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen if (file == NULL || file->hdr.file_seq != seq) {
6321d9d33937c7fc13a8ff04c220a9e377efeeb8Timo Sirainen i_assert(reason != NULL);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen if (file == NULL && max_file_seq == (uint32_t)-1 &&
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen view->head == view->log->head) {
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen /* we just wanted to sync everything */
ccb77e2f63626ec46e5745ef4f38baa8e8e504fcTimo Sirainen i_assert(max_file_offset == (uoff_t)-1);
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen max_file_seq = seq-1;
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen break;
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen }
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen /* if any of the found files reset the index,
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen ignore any missing files up to it */
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen file = view->tail != NULL ? view->tail :
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen view->log->files;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen for (;; file = file->next) {
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen if (file == NULL ||
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen file->hdr.file_seq > max_file_seq) {
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen /* missing files in the middle */
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen *reason_r = t_strdup_printf(
6321d9d33937c7fc13a8ff04c220a9e377efeeb8Timo Sirainen "Missing middle file seq=%u (between %u..%u, we have seqs %s): %s",
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen seq, min_file_seq, max_file_seq,
6321d9d33937c7fc13a8ff04c220a9e377efeeb8Timo Sirainen mail_transaction_log_get_file_seqs(view->log), reason);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen return 0;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen }
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen if (file->hdr.file_seq >= seq &&
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen file->hdr.prev_file_seq == 0) {
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen /* we can ignore the missing file */
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen break;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen }
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen }
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen seq = file->hdr.file_seq;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen view->tail = NULL;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen }
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen if (view->tail == NULL)
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen view->tail = file;
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen view->head = file;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen file = file->next;
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen }
e376e08040b5f21ff79a15ae728d2532a34207f6Timo Sirainen i_assert(view->tail != NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen if (min_file_offset == 0) {
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen /* beginning of the file */
c21c33a8c98972c45349066fc76ac9e2c05013c1Timo Sirainen min_file_offset = view->tail->hdr.hdr_size;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen if (min_file_offset > max_file_offset &&
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen min_file_seq == max_file_seq) {
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen /* we don't actually want to show anything */
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen max_file_offset = min_file_offset;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen }
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen }
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen if (min_file_offset < view->tail->hdr.hdr_size) {
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen /* log file offset is probably corrupted in the index file. */
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen *reason_r = t_strdup_printf(
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen "Invalid min_file_offset: file_seq=%u, min_file_offset (%"PRIuUOFF_T
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen ") < hdr_size (%u)",
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen min_file_seq, min_file_offset, view->tail->hdr.hdr_size);
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen mail_transaction_log_view_set_corrupted(view, "%s", *reason_r);
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen return -1;
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen }
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen if (max_file_offset < view->head->hdr.hdr_size) {
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen /* log file offset is probably corrupted in the index file. */
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen *reason_r = t_strdup_printf(
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen "Invalid max_file_offset: file_seq=%u, min_file_offset (%"PRIuUOFF_T
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen ") < hdr_size (%u)",
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen max_file_seq, max_file_offset, view->head->hdr.hdr_size);
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen mail_transaction_log_view_set_corrupted(view, "%s", *reason_r);
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen return -1;
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen }
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen /* we have all of them. update refcounts. */
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen mail_transaction_log_view_unref_all(view);
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen /* Reference all used files. */
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen for (file = view->tail;; file = file->next) {
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen array_append(&view->file_refs, &file, 1);
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen file->refcount++;
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen if (file == view->head)
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen break;
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen }
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen view->cur = view->tail;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen view->cur_offset = view->cur->hdr.file_seq == min_file_seq ?
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen min_file_offset : view->cur->hdr.hdr_size;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen /* Map the files only after we've found them all. Otherwise if we map
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen one file and then another file just happens to get rotated, we could
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen include both files in the view but skip the last transactions from
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen the first file.
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen We're mapping the files in reverse order so that _log_file_map()
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen can verify that prev_file_offset matches how far it actually managed
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen to sync the file. */
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen files = array_idx(&view->file_refs, 0);
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen for (i = array_count(&view->file_refs); i > 0; i--) {
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen file = files[i-1];
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen start_offset = file->hdr.file_seq == min_file_seq ?
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen min_file_offset : file->hdr.hdr_size;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen end_offset = file->hdr.file_seq == max_file_seq ?
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen max_file_offset : (uoff_t)-1;
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen ret = mail_transaction_log_file_map(file, start_offset,
ce9d23c7c1e621398d2572a1d95171136f7ef6a2Timo Sirainen end_offset, reason_r);
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen if (ret <= 0) {
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen *reason_r = t_strdup_printf(
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen "Failed to map file seq=%u "
ce9d23c7c1e621398d2572a1d95171136f7ef6a2Timo Sirainen "offset=%"PRIuUOFF_T"..%"PRIuUOFF_T" (ret=%d): %s",
ce9d23c7c1e621398d2572a1d95171136f7ef6a2Timo Sirainen file->hdr.file_seq, start_offset, end_offset, ret, *reason_r);
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen return ret;
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen }
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen if (file->hdr.prev_file_seq == 0) {
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen /* this file resets the index.
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen don't bother reading the others. */
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen if (view->cur != file ||
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen view->cur_offset == file->hdr.hdr_size) {
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen view->cur = file;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen view->cur_offset = file->hdr.hdr_size;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen *reset_r = TRUE;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen break;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen }
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen i_assert(i == 1);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
7471f28b16b81f9af413c879b3efb16eeafd2bd9Timo Sirainen if (min_file_seq == view->head->hdr.file_seq &&
7471f28b16b81f9af413c879b3efb16eeafd2bd9Timo Sirainen min_file_offset > view->head->sync_offset) {
7471f28b16b81f9af413c879b3efb16eeafd2bd9Timo Sirainen /* log file offset is probably corrupted in the index file. */
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen *reason_r = t_strdup_printf(
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen "Invalid offset: file_seq=%u, min_file_offset (%"PRIuUOFF_T
7471f28b16b81f9af413c879b3efb16eeafd2bd9Timo Sirainen ") > sync_offset (%"PRIuUOFF_T")", min_file_seq,
7471f28b16b81f9af413c879b3efb16eeafd2bd9Timo Sirainen min_file_offset, view->head->sync_offset);
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen mail_transaction_log_view_set_corrupted(view, "%s", *reason_r);
7471f28b16b81f9af413c879b3efb16eeafd2bd9Timo Sirainen return -1;
7471f28b16b81f9af413c879b3efb16eeafd2bd9Timo Sirainen }
7471f28b16b81f9af413c879b3efb16eeafd2bd9Timo Sirainen
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen i_assert(max_file_seq == (uint32_t)-1 ||
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen max_file_seq == view->head->hdr.file_seq);
527ed64bc924b4a13b570a8450f8be3efdf71879Timo Sirainen i_assert(max_file_offset == (uoff_t)-1 ||
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen max_file_offset <= view->head->sync_offset);
688f0fdfb7ca946e38ae34459b0ca30b71c8457cTimo Sirainen i_assert(min_file_seq != max_file_seq ||
688f0fdfb7ca946e38ae34459b0ca30b71c8457cTimo Sirainen max_file_seq != view->head->hdr.file_seq ||
688f0fdfb7ca946e38ae34459b0ca30b71c8457cTimo Sirainen max_file_offset != (uoff_t)-1 ||
688f0fdfb7ca946e38ae34459b0ca30b71c8457cTimo Sirainen min_file_offset <= view->head->sync_offset);
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen view->prev_file_seq = view->cur->hdr.file_seq;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen view->prev_file_offset = view->cur_offset;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen view->min_file_seq = min_file_seq;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen view->min_file_offset = min_file_offset;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen view->max_file_seq = max_file_seq;
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen view->max_file_offset = I_MIN(max_file_offset, view->head->sync_offset);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen view->broken = FALSE;
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen if (mail_transaction_log_file_get_highest_modseq_at(view->cur,
a0c8af555ec481ab12c2a99518cf7b20debd1627Timo Sirainen view->cur_offset, &view->prev_modseq, reason_r) < 0)
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen return -1;
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen
fadd878cd6098f5b873c21c121209a922679dae4Timo Sirainen i_assert(view->cur_offset <= view->cur->sync_offset);
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen return 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainenint mail_transaction_log_view_set_all(struct mail_transaction_log_view *view)
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen{
1e16e4fb4b1d99e835f19f0f5720d6c75d8c6783Timo Sirainen struct mail_transaction_log_file *file, *first;
ce9d23c7c1e621398d2572a1d95171136f7ef6a2Timo Sirainen const char *reason = NULL;
ac8cb75fb110a9d03363d1219a5672ce3c4ff89aTimo Sirainen int ret;
3ea86ed7cf06ba04e4aa6cd1c4df9be336c06cd3Timo Sirainen
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen /* make sure .log.2 file is opened */
6321d9d33937c7fc13a8ff04c220a9e377efeeb8Timo Sirainen (void)mail_transaction_log_find_file(view->log, 1, FALSE, &file, &reason);
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen
1e16e4fb4b1d99e835f19f0f5720d6c75d8c6783Timo Sirainen first = view->log->files;
1e16e4fb4b1d99e835f19f0f5720d6c75d8c6783Timo Sirainen i_assert(first != NULL);
1e16e4fb4b1d99e835f19f0f5720d6c75d8c6783Timo Sirainen
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen for (file = view->log->files; file != NULL; file = file->next) {
ac8cb75fb110a9d03363d1219a5672ce3c4ff89aTimo Sirainen ret = mail_transaction_log_file_map(file, file->hdr.hdr_size,
ce9d23c7c1e621398d2572a1d95171136f7ef6a2Timo Sirainen (uoff_t)-1, &reason);
ce9d23c7c1e621398d2572a1d95171136f7ef6a2Timo Sirainen if (ret < 0) {
ce9d23c7c1e621398d2572a1d95171136f7ef6a2Timo Sirainen first = NULL;
ce9d23c7c1e621398d2572a1d95171136f7ef6a2Timo Sirainen break;
ce9d23c7c1e621398d2572a1d95171136f7ef6a2Timo Sirainen }
ac8cb75fb110a9d03363d1219a5672ce3c4ff89aTimo Sirainen if (ret == 0) {
ac8cb75fb110a9d03363d1219a5672ce3c4ff89aTimo Sirainen /* corrupted */
ac8cb75fb110a9d03363d1219a5672ce3c4ff89aTimo Sirainen first = NULL;
ac8cb75fb110a9d03363d1219a5672ce3c4ff89aTimo Sirainen } else if (file->hdr.prev_file_seq == 0) {
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen /* this file resets the index. skip the old ones. */
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen first = file;
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen }
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen }
ac8cb75fb110a9d03363d1219a5672ce3c4ff89aTimo Sirainen if (first == NULL) {
ac8cb75fb110a9d03363d1219a5672ce3c4ff89aTimo Sirainen /* index wasn't reset after corruption was found */
ce9d23c7c1e621398d2572a1d95171136f7ef6a2Timo Sirainen i_assert(reason != NULL);
9c42095655057048c18aee9de20a0ddce77df379Timo Sirainen mail_index_set_error(view->log->index,
ce9d23c7c1e621398d2572a1d95171136f7ef6a2Timo Sirainen "Failed to map transaction log %s for all-view: %s",
9c42095655057048c18aee9de20a0ddce77df379Timo Sirainen view->log->filepath, reason);
ac8cb75fb110a9d03363d1219a5672ce3c4ff89aTimo Sirainen return -1;
ac8cb75fb110a9d03363d1219a5672ce3c4ff89aTimo Sirainen }
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen mail_transaction_log_view_unref_all(view);
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen for (file = first; file != NULL; file = file->next) {
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen array_append(&view->file_refs, &file, 1);
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen file->refcount++;
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen }
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen view->tail = first;
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen view->cur = view->tail;
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen view->cur_offset = view->tail->hdr.hdr_size;
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen view->prev_file_seq = view->cur->hdr.file_seq;
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen view->prev_file_offset = view->cur_offset;
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen view->min_file_seq = view->cur->hdr.file_seq;
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen view->min_file_offset = view->cur_offset;
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen view->max_file_seq = view->head->hdr.file_seq;
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen view->max_file_offset = view->head->sync_offset;
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen view->broken = FALSE;
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen if (mail_transaction_log_file_get_highest_modseq_at(view->cur,
a0c8af555ec481ab12c2a99518cf7b20debd1627Timo Sirainen view->cur_offset, &view->prev_modseq, &reason) < 0) {
9c42095655057048c18aee9de20a0ddce77df379Timo Sirainen mail_index_set_error(view->log->index,
a0c8af555ec481ab12c2a99518cf7b20debd1627Timo Sirainen "Failed to get modseq in %s for all-view: %s",
9c42095655057048c18aee9de20a0ddce77df379Timo Sirainen view->log->filepath, reason);
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen return -1;
a0c8af555ec481ab12c2a99518cf7b20debd1627Timo Sirainen }
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen return 0;
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen}
6d3bb841d4ec2c12ac2d4ecf6146ef8d8a7dd731Timo Sirainen
c680a6b35b459045e92814778908da5a93922107Timo Sirainenvoid mail_transaction_log_view_clear(struct mail_transaction_log_view *view,
c680a6b35b459045e92814778908da5a93922107Timo Sirainen uint32_t oldest_file_seq)
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen{
c680a6b35b459045e92814778908da5a93922107Timo Sirainen struct mail_transaction_log_file *file;
6321d9d33937c7fc13a8ff04c220a9e377efeeb8Timo Sirainen const char *reason;
c680a6b35b459045e92814778908da5a93922107Timo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen mail_transaction_log_view_unref_all(view);
0fa842717a8b163252e55c229c37ca0c5d7ff056Timo Sirainen if (oldest_file_seq != 0 &&
0fa842717a8b163252e55c229c37ca0c5d7ff056Timo Sirainen mail_transaction_log_find_file(view->log, oldest_file_seq, FALSE,
6321d9d33937c7fc13a8ff04c220a9e377efeeb8Timo Sirainen &file, &reason) > 0) {
096953143c4032bad154637f687551856f7946cbTimo Sirainen for (; file != NULL; file = file->next) {
096953143c4032bad154637f687551856f7946cbTimo Sirainen array_append(&view->file_refs, &file, 1);
096953143c4032bad154637f687551856f7946cbTimo Sirainen file->refcount++;
096953143c4032bad154637f687551856f7946cbTimo Sirainen }
c680a6b35b459045e92814778908da5a93922107Timo Sirainen }
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen view->cur = view->head = view->tail = NULL;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen view->mark_file = NULL;
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen view->mark_offset = 0;
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen view->mark_modseq = 0;
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen view->min_file_seq = view->max_file_seq = 0;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen view->min_file_offset = view->max_file_offset = 0;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen view->cur_offset = 0;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen view->prev_file_seq = 0;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen view->prev_file_offset = 0;
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen view->prev_modseq = 0;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen}
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmail_transaction_log_view_get_prev_pos(struct mail_transaction_log_view *view,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uint32_t *file_seq_r,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uoff_t *file_offset_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *file_seq_r = view->prev_file_seq;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *file_offset_r = view->prev_file_offset;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainenuint64_t
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainenmail_transaction_log_view_get_prev_modseq(struct mail_transaction_log_view *view)
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen{
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen return view->prev_modseq;
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen}
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainenstatic bool
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainenmail_transaction_log_view_get_last(struct mail_transaction_log_view *view,
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen struct mail_transaction_log_file **last_r,
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen uoff_t *last_offset_r)
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen{
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen struct mail_transaction_log_file *cur = view->cur;
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen uoff_t cur_offset = view->cur_offset;
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen bool last = FALSE;
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen if (cur == NULL) {
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen *last_r = NULL;
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen return TRUE;
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen }
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen for (;;) {
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen if (cur->hdr.file_seq == view->max_file_seq) {
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen /* last file */
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen if (cur_offset == view->max_file_offset ||
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen cur_offset == cur->sync_offset) {
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen /* we're all finished */
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen last = TRUE;
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen }
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen } else if (cur_offset == cur->sync_offset) {
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen /* end of file, go to next one */
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen if (cur->next == NULL) {
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen last = TRUE;
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen } else {
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen cur = cur->next;
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen cur_offset = cur->hdr.hdr_size;
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen continue;
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen }
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen }
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen /* not EOF */
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen break;
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen }
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen *last_r = cur;
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen *last_offset_r = cur_offset;
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen return last;
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen}
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainenbool mail_transaction_log_view_is_last(struct mail_transaction_log_view *view)
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen{
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen struct mail_transaction_log_file *cur;
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen uoff_t cur_offset;
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen return mail_transaction_log_view_get_last(view, &cur, &cur_offset);
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen}
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmail_transaction_log_view_set_corrupted(struct mail_transaction_log_view *view,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *fmt, ...)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen va_list va;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen view->broken = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen va_start(va, fmt);
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen T_BEGIN {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen mail_transaction_log_file_set_corrupted(view->log->head, "%s",
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen t_strdup_vprintf(fmt, va));
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen } T_END;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen va_end(va);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenbool
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmail_transaction_log_view_is_corrupted(struct mail_transaction_log_view *view)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return view->broken;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainenstatic bool
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainenlog_view_is_uid_range_valid(struct mail_transaction_log_file *file,
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen enum mail_transaction_type rec_type,
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen const ARRAY_TYPE(seq_range) *uids)
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen{
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen const struct seq_range *rec, *prev = NULL;
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen unsigned int i, count = array_count(uids);
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen if ((uids->arr.buffer->used % uids->arr.element_size) != 0) {
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen mail_transaction_log_file_set_corrupted(file,
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen "Invalid record size (type=0x%x)", rec_type);
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen return FALSE;
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen } else if (count == 0) {
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen mail_transaction_log_file_set_corrupted(file,
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen "No UID ranges (type=0x%x)", rec_type);
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen return FALSE;
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen }
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen for (i = 0; i < count; i++, prev = rec) {
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen rec = array_idx(uids, i);
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen if (rec->seq1 > rec->seq2 || rec->seq1 == 0) {
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen mail_transaction_log_file_set_corrupted(file,
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen "Invalid UID range (%u .. %u, type=0x%x)",
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen rec->seq1, rec->seq2, rec_type);
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen return FALSE;
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen }
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen if (prev != NULL && rec->seq1 <= prev->seq2) {
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen mail_transaction_log_file_set_corrupted(file,
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen "Non-sorted UID ranges (type=0x%x)", rec_type);
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen return FALSE;
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen }
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen }
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen return TRUE;
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen}
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainenstatic bool
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainenlog_view_is_record_valid(struct mail_transaction_log_file *file,
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen const struct mail_transaction_header *hdr,
8bae533c96e129dca8ee7b494d7de5aeb4a043a2Timo Sirainen const void *data)
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen{
b5ac20e30146562322ceb7939f044d52d1e51184Timo Sirainen enum mail_transaction_type rec_type;
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen ARRAY_TYPE(seq_range) uids = ARRAY_INIT;
8e361d2906b0e44f7175a20981f8d2280645b58bTimo Sirainen buffer_t uid_buf;
075912b4566a79c7bc59bf229c9f629ef7be0ea2Timo Sirainen uint32_t rec_size;
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen
b5ac20e30146562322ceb7939f044d52d1e51184Timo Sirainen rec_type = hdr->type & MAIL_TRANSACTION_TYPE_MASK;
075912b4566a79c7bc59bf229c9f629ef7be0ea2Timo Sirainen rec_size = mail_index_offset_to_uint32(hdr->size) - sizeof(*hdr);
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen /* we want to be extra careful with expunges */
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0) {
b5ac20e30146562322ceb7939f044d52d1e51184Timo Sirainen if (rec_type != (MAIL_TRANSACTION_EXPUNGE |
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen MAIL_TRANSACTION_EXPUNGE_PROT)) {
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen mail_transaction_log_file_set_corrupted(file,
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen "expunge record missing protection mask");
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen return FALSE;
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen }
37b805dfb45902b6b41c45482f67e6f98e08b0a3Timo Sirainen rec_type &= ~MAIL_TRANSACTION_EXPUNGE_PROT;
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen }
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXPUNGE_GUID) != 0) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if (rec_type != (MAIL_TRANSACTION_EXPUNGE_GUID |
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen MAIL_TRANSACTION_EXPUNGE_PROT)) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen mail_transaction_log_file_set_corrupted(file,
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen "expunge guid record missing protection mask");
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen return FALSE;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen }
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen rec_type &= ~MAIL_TRANSACTION_EXPUNGE_PROT;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen }
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen if (rec_size == 0) {
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen mail_transaction_log_file_set_corrupted(file,
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen "Empty record contents (type=0x%x)", rec_type);
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen return FALSE;
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen }
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen /* records that are exported by syncing and view syncing will be
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen checked here so that we don't have to implement the same validation
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen multiple times. other records are checked internally by
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen mail_index_sync_record(). */
b5ac20e30146562322ceb7939f044d52d1e51184Timo Sirainen switch (rec_type) {
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen case MAIL_TRANSACTION_APPEND:
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen if ((rec_size % sizeof(struct mail_index_record)) != 0) {
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen mail_transaction_log_file_set_corrupted(file,
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen "Invalid append record size");
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen return FALSE;
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen }
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen break;
b5ac20e30146562322ceb7939f044d52d1e51184Timo Sirainen case MAIL_TRANSACTION_EXPUNGE:
3281669db44d09a087a203201248abbc81b3cc1aTimo Sirainen buffer_create_from_const_data(&uid_buf, data, rec_size);
8e361d2906b0e44f7175a20981f8d2280645b58bTimo Sirainen array_create_from_buffer(&uids, &uid_buf,
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen sizeof(struct mail_transaction_expunge));
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen break;
6f0bb992c9f55de912295493892651d57e5e9827Timo Sirainen case MAIL_TRANSACTION_EXPUNGE_GUID: {
6f0bb992c9f55de912295493892651d57e5e9827Timo Sirainen const struct mail_transaction_expunge_guid *recs = data;
6f0bb992c9f55de912295493892651d57e5e9827Timo Sirainen unsigned int i, count;
6f0bb992c9f55de912295493892651d57e5e9827Timo Sirainen
6f0bb992c9f55de912295493892651d57e5e9827Timo Sirainen if ((rec_size % sizeof(*recs)) != 0) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen mail_transaction_log_file_set_corrupted(file,
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen "Invalid expunge guid record size");
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen return FALSE;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen }
6f0bb992c9f55de912295493892651d57e5e9827Timo Sirainen count = rec_size / sizeof(*recs);
6f0bb992c9f55de912295493892651d57e5e9827Timo Sirainen for (i = 0; i < count; i++) {
6f0bb992c9f55de912295493892651d57e5e9827Timo Sirainen if (recs[i].uid == 0) {
6f0bb992c9f55de912295493892651d57e5e9827Timo Sirainen mail_transaction_log_file_set_corrupted(file,
6f0bb992c9f55de912295493892651d57e5e9827Timo Sirainen "Expunge guid record with uid=0");
6f0bb992c9f55de912295493892651d57e5e9827Timo Sirainen return FALSE;
6f0bb992c9f55de912295493892651d57e5e9827Timo Sirainen }
6f0bb992c9f55de912295493892651d57e5e9827Timo Sirainen }
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen break;
6f0bb992c9f55de912295493892651d57e5e9827Timo Sirainen }
b5ac20e30146562322ceb7939f044d52d1e51184Timo Sirainen case MAIL_TRANSACTION_FLAG_UPDATE:
3281669db44d09a087a203201248abbc81b3cc1aTimo Sirainen buffer_create_from_const_data(&uid_buf, data, rec_size);
8e361d2906b0e44f7175a20981f8d2280645b58bTimo Sirainen array_create_from_buffer(&uids, &uid_buf,
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen sizeof(struct mail_transaction_flag_update));
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen break;
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen case MAIL_TRANSACTION_KEYWORD_UPDATE: {
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen const struct mail_transaction_keyword_update *rec = data;
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen unsigned int seqset_offset;
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen seqset_offset = sizeof(*rec) + rec->name_size;
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen if ((seqset_offset % 4) != 0)
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen seqset_offset += 4 - (seqset_offset % 4);
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen
d200ae87140a1985fe527e6527bc4bd3035189b1Timo Sirainen if (rec->name_size == 0) {
d200ae87140a1985fe527e6527bc4bd3035189b1Timo Sirainen mail_transaction_log_file_set_corrupted(file,
d200ae87140a1985fe527e6527bc4bd3035189b1Timo Sirainen "Trying to use empty keyword");
d200ae87140a1985fe527e6527bc4bd3035189b1Timo Sirainen return FALSE;
d200ae87140a1985fe527e6527bc4bd3035189b1Timo Sirainen }
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen if (seqset_offset > rec_size) {
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen mail_transaction_log_file_set_corrupted(file,
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen "Invalid keyword update record size");
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen return FALSE;
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen }
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen
3281669db44d09a087a203201248abbc81b3cc1aTimo Sirainen buffer_create_from_const_data(&uid_buf,
8e361d2906b0e44f7175a20981f8d2280645b58bTimo Sirainen CONST_PTR_OFFSET(data, seqset_offset),
8e361d2906b0e44f7175a20981f8d2280645b58bTimo Sirainen rec_size - seqset_offset);
8e361d2906b0e44f7175a20981f8d2280645b58bTimo Sirainen array_create_from_buffer(&uids, &uid_buf,
8e361d2906b0e44f7175a20981f8d2280645b58bTimo Sirainen sizeof(uint32_t)*2);
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen break;
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen }
b5ac20e30146562322ceb7939f044d52d1e51184Timo Sirainen case MAIL_TRANSACTION_KEYWORD_RESET:
3281669db44d09a087a203201248abbc81b3cc1aTimo Sirainen buffer_create_from_const_data(&uid_buf, data, rec_size);
8e361d2906b0e44f7175a20981f8d2280645b58bTimo Sirainen array_create_from_buffer(&uids, &uid_buf,
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen sizeof(struct mail_transaction_keyword_reset));
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen break;
cf05507f63b12bd1ee4efffc2f316ebcd9fd7089Timo Sirainen case MAIL_TRANSACTION_EXT_INTRO: {
cf05507f63b12bd1ee4efffc2f316ebcd9fd7089Timo Sirainen const struct mail_transaction_ext_intro *rec;
cf05507f63b12bd1ee4efffc2f316ebcd9fd7089Timo Sirainen unsigned int i;
cf05507f63b12bd1ee4efffc2f316ebcd9fd7089Timo Sirainen
cf05507f63b12bd1ee4efffc2f316ebcd9fd7089Timo Sirainen for (i = 0; i < rec_size; ) {
cf05507f63b12bd1ee4efffc2f316ebcd9fd7089Timo Sirainen if (i + sizeof(*rec) > rec_size) {
cf05507f63b12bd1ee4efffc2f316ebcd9fd7089Timo Sirainen /* should be just extra padding */
cf05507f63b12bd1ee4efffc2f316ebcd9fd7089Timo Sirainen break;
cf05507f63b12bd1ee4efffc2f316ebcd9fd7089Timo Sirainen }
cf05507f63b12bd1ee4efffc2f316ebcd9fd7089Timo Sirainen
cf05507f63b12bd1ee4efffc2f316ebcd9fd7089Timo Sirainen rec = CONST_PTR_OFFSET(data, i);
cf05507f63b12bd1ee4efffc2f316ebcd9fd7089Timo Sirainen if (i + sizeof(*rec) + rec->name_size > rec_size) {
cf05507f63b12bd1ee4efffc2f316ebcd9fd7089Timo Sirainen mail_transaction_log_file_set_corrupted(file,
cf05507f63b12bd1ee4efffc2f316ebcd9fd7089Timo Sirainen "ext intro: name_size too large");
cf05507f63b12bd1ee4efffc2f316ebcd9fd7089Timo Sirainen return FALSE;
cf05507f63b12bd1ee4efffc2f316ebcd9fd7089Timo Sirainen }
cf05507f63b12bd1ee4efffc2f316ebcd9fd7089Timo Sirainen i += sizeof(*rec) + rec->name_size;
cf05507f63b12bd1ee4efffc2f316ebcd9fd7089Timo Sirainen if ((i % 4) != 0)
cf05507f63b12bd1ee4efffc2f316ebcd9fd7089Timo Sirainen i += 4 - (i % 4);
cf05507f63b12bd1ee4efffc2f316ebcd9fd7089Timo Sirainen }
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen break;
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen }
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen case MAIL_TRANSACTION_ATTRIBUTE_UPDATE: {
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen const char *attr_changes = data;
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen unsigned int i;
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen for (i = 0; i+2 < rec_size && attr_changes[i] != '\0'; ) {
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen if (attr_changes[i] != '+' && attr_changes[i] != '-') {
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen mail_transaction_log_file_set_corrupted(file,
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen "attribute update: Invalid prefix 0x%02x",
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen attr_changes[i]);
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen return FALSE;
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen }
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen i++;
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen if (attr_changes[i] != 'p' && attr_changes[i] != 's') {
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen mail_transaction_log_file_set_corrupted(file,
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen "attribute update: Invalid type 0x%02x",
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen attr_changes[i]);
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen return FALSE;
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen }
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen i++;
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen if (attr_changes[i] == '\0') {
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen mail_transaction_log_file_set_corrupted(file,
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen "attribute update: Empty key");
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen return FALSE;
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen }
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen i += strlen(attr_changes+i) + 1;
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen }
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen if (i == 0 || (i < rec_size && attr_changes[i] != '\0')) {
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen mail_transaction_log_file_set_corrupted(file,
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen "attribute update doesn't end with NUL");
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen return FALSE;
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen }
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen break;
cf05507f63b12bd1ee4efffc2f316ebcd9fd7089Timo Sirainen }
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen default:
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen break;
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen }
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen if (array_is_created(&uids)) {
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen if (!log_view_is_uid_range_valid(file, rec_type, &uids))
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen return FALSE;
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen }
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen return TRUE;
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen}
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen
a8012fea2a7315033bc467acbf46be8e7323318cTimo Sirainenstatic int
a8012fea2a7315033bc467acbf46be8e7323318cTimo Sirainenlog_view_get_next(struct mail_transaction_log_view *view,
a8012fea2a7315033bc467acbf46be8e7323318cTimo Sirainen const struct mail_transaction_header **hdr_r,
834b90e1f426d1e3308670e09c050bcdea546eb8Timo Sirainen const void **data_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mail_transaction_header *hdr;
0add8c99ca65e56dbf613595fc37c41aafff3f7fTimo Sirainen struct mail_transaction_log_file *file;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const void *data;
b5ac20e30146562322ceb7939f044d52d1e51184Timo Sirainen enum mail_transaction_type rec_type;
075912b4566a79c7bc59bf229c9f629ef7be0ea2Timo Sirainen uint32_t full_size;
f1e1d821d93e4a1dc6ed8f23febde868b5d64cd5Timo Sirainen size_t file_size;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen int ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen if (view->cur == NULL)
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen return 0;
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen
fadd878cd6098f5b873c21c121209a922679dae4Timo Sirainen /* prev_file_offset should point to beginning of previous log record.
fadd878cd6098f5b873c21c121209a922679dae4Timo Sirainen when we reach EOF, it should be left there, not to beginning of the
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen next file that's not included inside the view. */
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen if (mail_transaction_log_view_get_last(view, &view->cur,
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen &view->cur_offset)) {
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen /* if the last file was the beginning of a file, we want to
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen move prev pointers there */
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen view->prev_file_seq = view->cur->hdr.file_seq;
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen view->prev_file_offset = view->cur_offset;
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen view->cur = NULL;
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen return 0;
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen }
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen view->prev_file_seq = view->cur->hdr.file_seq;
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen view->prev_file_offset = view->cur_offset;
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen
fadd878cd6098f5b873c21c121209a922679dae4Timo Sirainen file = view->cur;
b7cf555b699d73f2d71de0dabc088af6a7be3627Timo Sirainen
b88c43d09a288e99d439c78de4cc613212ea924cTimo Sirainen data = file->buffer->data;
b88c43d09a288e99d439c78de4cc613212ea924cTimo Sirainen file_size = file->buffer->used + file->buffer_offset;
f1e1d821d93e4a1dc6ed8f23febde868b5d64cd5Timo Sirainen
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen if (view->cur_offset + sizeof(*hdr) > file_size) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_transaction_log_file_set_corrupted(file,
f1e1d821d93e4a1dc6ed8f23febde868b5d64cd5Timo Sirainen "offset points outside file "
f1e1d821d93e4a1dc6ed8f23febde868b5d64cd5Timo Sirainen "(%"PRIuUOFF_T" + %"PRIuSIZE_T" > %"PRIuSIZE_T")",
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen view->cur_offset, sizeof(*hdr), file_size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
6eb30032b4a50c383dea4c9c74342d906de6ad36Timo Sirainen i_assert(view->cur_offset >= file->buffer_offset);
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen hdr = CONST_PTR_OFFSET(data, view->cur_offset - file->buffer_offset);
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen data = CONST_PTR_OFFSET(hdr, sizeof(*hdr));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
b5ac20e30146562322ceb7939f044d52d1e51184Timo Sirainen rec_type = hdr->type & MAIL_TRANSACTION_TYPE_MASK;
075912b4566a79c7bc59bf229c9f629ef7be0ea2Timo Sirainen full_size = mail_index_offset_to_uint32(hdr->size);
075912b4566a79c7bc59bf229c9f629ef7be0ea2Timo Sirainen if (full_size < sizeof(*hdr)) {
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen mail_transaction_log_file_set_corrupted(file,
1225a5a7ce39f1d5545d5ed3b84ecd4f72438d36Timo Sirainen "record size too small (type=0x%x, "
1225a5a7ce39f1d5545d5ed3b84ecd4f72438d36Timo Sirainen "offset=%"PRIuUOFF_T", size=%u)",
b5ac20e30146562322ceb7939f044d52d1e51184Timo Sirainen rec_type, view->cur_offset, full_size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
075912b4566a79c7bc59bf229c9f629ef7be0ea2Timo Sirainen if (file_size - view->cur_offset < full_size) {
6eb30032b4a50c383dea4c9c74342d906de6ad36Timo Sirainen mail_transaction_log_file_set_corrupted(file,
1225a5a7ce39f1d5545d5ed3b84ecd4f72438d36Timo Sirainen "record size too large (type=0x%x, "
1225a5a7ce39f1d5545d5ed3b84ecd4f72438d36Timo Sirainen "offset=%"PRIuUOFF_T", size=%u, end=%"PRIuSIZE_T")",
b5ac20e30146562322ceb7939f044d52d1e51184Timo Sirainen rec_type, view->cur_offset, full_size, file_size);
6eb30032b4a50c383dea4c9c74342d906de6ad36Timo Sirainen return -1;
6eb30032b4a50c383dea4c9c74342d906de6ad36Timo Sirainen }
6eb30032b4a50c383dea4c9c74342d906de6ad36Timo Sirainen
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen T_BEGIN {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen ret = log_view_is_record_valid(file, hdr, data) ? 1 : -1;
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen } T_END;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen if (ret > 0) {
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen mail_transaction_update_modseq(hdr, data, &view->prev_modseq,
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen MAIL_TRANSACTION_LOG_HDR_VERSION(&file->hdr));
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen *hdr_r = hdr;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen *data_r = data;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen view->cur_offset += full_size;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen }
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen return ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mail_transaction_log_view_next(struct mail_transaction_log_view *view,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mail_transaction_header **hdr_r,
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen const void **data_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mail_transaction_header *hdr;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const void *data;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int ret = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (view->broken)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen ret = log_view_get_next(view, &hdr, &data);
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen if (ret <= 0) {
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen if (ret < 0)
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen view->cur_offset = view->cur->sync_offset;
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen return ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen /* drop expunge protection */
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_TYPE_MASK) ==
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen (MAIL_TRANSACTION_EXPUNGE | MAIL_TRANSACTION_EXPUNGE_PROT) ||
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen (hdr->type & MAIL_TRANSACTION_TYPE_MASK) ==
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen (MAIL_TRANSACTION_EXPUNGE_GUID | MAIL_TRANSACTION_EXPUNGE_PROT))
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen view->tmp_hdr.type = hdr->type & ~MAIL_TRANSACTION_EXPUNGE_PROT;
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen else
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen view->tmp_hdr.type = hdr->type;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8bae533c96e129dca8ee7b494d7de5aeb4a043a2Timo Sirainen /* return record's size */
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen view->tmp_hdr.size = mail_index_offset_to_uint32(hdr->size);
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen i_assert(view->tmp_hdr.size > sizeof(*hdr));
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen view->tmp_hdr.size -= sizeof(*hdr);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen *hdr_r = &view->tmp_hdr;
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen *data_r = data;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
ccffbed92cb02c24fd717808a84138240bf1885bTimo Sirainen
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainenvoid mail_transaction_log_view_mark(struct mail_transaction_log_view *view)
ccffbed92cb02c24fd717808a84138240bf1885bTimo Sirainen{
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen i_assert(view->cur->hdr.file_seq == view->prev_file_seq);
ccffbed92cb02c24fd717808a84138240bf1885bTimo Sirainen
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen view->mark_file = view->cur;
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen view->mark_offset = view->prev_file_offset;
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen view->mark_next_offset = view->cur_offset;
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen view->mark_modseq = view->prev_modseq;
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen}
ccffbed92cb02c24fd717808a84138240bf1885bTimo Sirainen
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainenvoid mail_transaction_log_view_rewind(struct mail_transaction_log_view *view)
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen{
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen i_assert(view->mark_file != NULL);
ccffbed92cb02c24fd717808a84138240bf1885bTimo Sirainen
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen view->cur = view->mark_file;
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen view->cur_offset = view->mark_next_offset;
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen view->prev_file_seq = view->cur->hdr.file_seq;
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen view->prev_file_offset = view->mark_offset;
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen view->prev_modseq = view->mark_modseq;
ccffbed92cb02c24fd717808a84138240bf1885bTimo Sirainen}