mail-transaction-log-view.c revision e376e08040b5f21ff79a15ae728d2532a34207f6
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2003-2010 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen#include "array.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
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
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainenvoid mail_transaction_log_views_close(struct mail_transaction_log *log)
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen{
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen struct mail_transaction_log_view *view;
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen for (view = log->views; view != NULL; view = view->next)
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen view->log = NULL;
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen}
93b29720c5141f787bd1861796867e4595c9d084Timo 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,
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen bool *reset_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
993e6c2caaae971dd3c34913a42d854e3b623261Timo Sirainen struct mail_transaction_log_file *file, *const *files, *tail;
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen uoff_t start_offset, end_offset;
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen unsigned int i;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uint32_t seq;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(min_file_seq <= max_file_seq);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen *reset_r = FALSE;
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. */
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen return -1;
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen }
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen
993e6c2caaae971dd3c34913a42d854e3b623261Timo Sirainen tail = view->log->files;
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 */
993e6c2caaae971dd3c34913a42d854e3b623261Timo Sirainen if (tail->hdr.prev_file_seq != 0) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* but it doesn't */
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return 0;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
993e6c2caaae971dd3c34913a42d854e3b623261Timo Sirainen min_file_seq = tail->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 }
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen }
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainen
993e6c2caaae971dd3c34913a42d854e3b623261Timo Sirainen if (min_file_seq == tail->hdr.prev_file_seq &&
993e6c2caaae971dd3c34913a42d854e3b623261Timo Sirainen min_file_offset == tail->hdr.prev_file_offset) {
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen /* we can skip this */
993e6c2caaae971dd3c34913a42d854e3b623261Timo Sirainen min_file_seq = tail->hdr.file_seq;
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen min_file_offset = 0;
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen if (min_file_seq > max_file_seq) {
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen /* empty view */
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen max_file_seq = min_file_seq;
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen max_file_offset = min_file_offset;
40ef82c46f6652412b068ebcdac7c3e74840a284Timo Sirainen }
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. */
95a284736b8b11319a3f575ba249ba2eb7dbac1bTimo Sirainen mail_transaction_log_view_set_corrupted(view,
95a284736b8b11319a3f575ba249ba2eb7dbac1bTimo Sirainen "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);
95a284736b8b11319a3f575ba249ba2eb7dbac1bTimo Sirainen return -1;
95a284736b8b11319a3f575ba249ba2eb7dbac1bTimo Sirainen }
8eeafcb306872435f3171e6acf5a9937aec3a175Timo Sirainen
993e6c2caaae971dd3c34913a42d854e3b623261Timo Sirainen if (min_file_offset > 0 && min_file_offset < tail->hdr.hdr_size) {
a4d209d480d453566d331e870b8d0c99af7716c8Timo Sirainen /* log file offset is probably corrupted in the index file. */
a4d209d480d453566d331e870b8d0c99af7716c8Timo Sirainen mail_transaction_log_view_set_corrupted(view,
a4d209d480d453566d331e870b8d0c99af7716c8Timo Sirainen "file_seq=%u, min_file_offset (%"PRIuUOFF_T
a4d209d480d453566d331e870b8d0c99af7716c8Timo Sirainen ") < hdr_size (%u)",
993e6c2caaae971dd3c34913a42d854e3b623261Timo Sirainen min_file_seq, min_file_offset, tail->hdr.hdr_size);
a4d209d480d453566d331e870b8d0c99af7716c8Timo Sirainen return -1;
a4d209d480d453566d331e870b8d0c99af7716c8Timo Sirainen }
a4d209d480d453566d331e870b8d0c99af7716c8Timo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen view->tail = view->head = file = NULL;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen for (seq = min_file_seq; seq <= max_file_seq; seq++) {
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen if (file == NULL || file->hdr.file_seq != seq) {
f537e7efaec891d6b3320ca94331d09ca8c4a4dbTimo Sirainen /* see if we could find the missing file. if we know
f537e7efaec891d6b3320ca94331d09ca8c4a4dbTimo Sirainen the max. file sequence, make sure NFS attribute
f537e7efaec891d6b3320ca94331d09ca8c4a4dbTimo Sirainen cache gets flushed if necessary. */
f537e7efaec891d6b3320ca94331d09ca8c4a4dbTimo Sirainen bool nfs_flush = max_file_seq != (uint32_t)-1;
f537e7efaec891d6b3320ca94331d09ca8c4a4dbTimo Sirainen
f537e7efaec891d6b3320ca94331d09ca8c4a4dbTimo Sirainen ret = mail_transaction_log_find_file(view->log, seq,
f537e7efaec891d6b3320ca94331d09ca8c4a4dbTimo Sirainen nfs_flush, &file);
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen if (ret <= 0) {
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen if (ret < 0)
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen return -1;
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) {
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 */
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 }
c21c33a8c98972c45349066fc76ac9e2c05013c1Timo Sirainen i_assert(min_file_offset >= view->tail->hdr.hdr_size);
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,
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen end_offset);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ret <= 0)
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen return ret;
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
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,
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen view->cur_offset, &view->prev_modseq) < 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
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;
c680a6b35b459045e92814778908da5a93922107Timo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen mail_transaction_log_view_unref_all(view);
f537e7efaec891d6b3320ca94331d09ca8c4a4dbTimo Sirainen if (mail_transaction_log_find_file(view->log, oldest_file_seq, FALSE,
c680a6b35b459045e92814778908da5a93922107Timo Sirainen &file) > 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:
8e361d2906b0e44f7175a20981f8d2280645b58bTimo Sirainen buffer_create_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;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen case MAIL_TRANSACTION_EXPUNGE_GUID:
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if ((rec_size % sizeof(struct mail_transaction_expunge_guid)) != 0) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen mail_transaction_log_file_set_corrupted(file,
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen "Invalid expunge guid record size");
7f7533a29d0e65876acc0ab9dd56b3d7840c3ee7Timo Sirainen return FALSE;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen }
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen break;
b5ac20e30146562322ceb7939f044d52d1e51184Timo Sirainen case MAIL_TRANSACTION_FLAG_UPDATE:
8e361d2906b0e44f7175a20981f8d2280645b58bTimo Sirainen buffer_create_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
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
8e361d2906b0e44f7175a20981f8d2280645b58bTimo Sirainen buffer_create_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:
8e361d2906b0e44f7175a20981f8d2280645b58bTimo Sirainen buffer_create_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;
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
f1e1d821d93e4a1dc6ed8f23febde868b5d64cd5Timo Sirainen data = buffer_get_data(file->buffer, &file_size);
f1e1d821d93e4a1dc6ed8f23febde868b5d64cd5Timo Sirainen file_size += 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) {
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen mail_transaction_update_modseq(hdr, data, &view->prev_modseq);
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}