mail-transaction-log-view.c revision f75188af11dce30be322cc2eefa3e3884871abf7
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "lib.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "buffer.h"
65cca8364f483126b396aeb2036dc879ad45ab8dTimo Sirainen#include "mail-index-private.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "mail-transaction-log-private.h"
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen#include "mail-transaction-util.h"
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainenstruct mail_transaction_log_view {
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen struct mail_transaction_log *log;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen struct mail_transaction_log_view *next;
b1f37113a5760bee842c5a7678bb5fa6f5bd8b60Timo Sirainen
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen uint32_t min_file_seq, max_file_seq;
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen uoff_t min_file_offset, max_file_offset;
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen enum mail_transaction_type type_mask;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen struct mail_transaction_header tmp_hdr;
13d98ffa534f2e7d04a832c9d0153fc9c568b878Timo Sirainen
13d98ffa534f2e7d04a832c9d0153fc9c568b878Timo Sirainen struct mail_transaction_log_file *cur, *head, *tail;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen uoff_t cur_offset;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen uint32_t prev_file_seq;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen uoff_t prev_file_offset;
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen unsigned int broken:1;
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainen};
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstruct mail_transaction_log_view *
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenmail_transaction_log_view_open(struct mail_transaction_log *log)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct mail_transaction_log_view *view;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen view = i_new(struct mail_transaction_log_view, 1);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen view->log = log;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen view->broken = TRUE;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
220e21750948941dc6e33b8f11b552fa21d7f81eTimo Sirainen view->head = view->tail = view->log->head;
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen view->head->refcount++;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen view->next = log->views;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen log->views = view;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen return view;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen}
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainenvoid mail_transaction_log_view_close(struct mail_transaction_log_view *view)
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen{
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen struct mail_transaction_log_view **p;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen struct mail_transaction_log_file *file;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen for (p = &view->log->views; *p != NULL; p = &(*p)->next) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (*p == view) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen *p = view->next;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen break;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen for (file = view->tail; file != view->head; file = file->next)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen file->refcount--;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen view->head->refcount--;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mail_transaction_logs_clean(view->log);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_free(view);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenvoid mail_transaction_log_views_close(struct mail_transaction_log *log)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen struct mail_transaction_log_view *view;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen for (view = log->views; view != NULL; view = view->next)
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen view->log = NULL;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenint
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenmail_transaction_log_view_set(struct mail_transaction_log_view *view,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen uint32_t min_file_seq, uoff_t min_file_offset,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen uint32_t max_file_seq, uoff_t max_file_offset,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen enum mail_transaction_type type_mask)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* FIXME: error handling for "not found" case is bad.. should the
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen caller after all check it and handle as it sees best..? */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct mail_transaction_log_file *file, *first;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen uint32_t seq;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen uoff_t end_offset;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen int ret;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_assert(min_file_seq <= max_file_seq);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen if (view->log == NULL)
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen return -1;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen if (min_file_seq == 0) {
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen /* new index, transaction file not synced yet */
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen min_file_seq = 1;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen min_file_offset = 0;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen if (max_file_seq == 0) {
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen max_file_seq = min_file_seq;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen max_file_offset = min_file_offset;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen }
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (min_file_seq == view->log->tail->hdr.prev_file_seq &&
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen min_file_offset == view->log->tail->hdr.prev_file_offset) {
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen /* we can skip this */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen min_file_seq = view->log->tail->hdr.file_seq;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen min_file_offset = 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (min_file_seq > max_file_seq) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* empty view */
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen max_file_seq = min_file_seq;
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen max_file_offset = min_file_offset;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen ret = mail_transaction_log_file_find(view->log, min_file_seq, &file);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (ret <= 0) {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen if (ret == 0) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mail_index_set_error(view->log->index,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen "Lost transaction log file %s seq %u",
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen view->log->tail->filepath, min_file_seq);
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen mail_index_set_inconsistent(view->log->index);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen }
63e207529879438e9f4412d97cdc34bdc82a3702Timo Sirainen return -1;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen }
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen if (min_file_offset == 0) {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen /* this could happen if internal transactions haven't yet been
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen committed but external are. just assume we're at the
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen beginning. */
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen min_file_offset = file->hdr.hdr_size;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen if (max_file_offset == 0 && min_file_seq == max_file_seq)
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen max_file_offset = min_file_offset;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen }
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen /* check these later than others as index file may have corrupted
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen log_file_offset. we should have recreated the log file and
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen skipped min_file_seq file above.. max_file_offset can be broken
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen only if min_file_seq = max_file_seq. */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen i_assert(min_file_offset >= file->hdr.hdr_size);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen i_assert(min_file_seq != max_file_seq ||
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen min_file_offset <= max_file_offset);
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen end_offset = min_file_seq == max_file_seq ?
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen max_file_offset : (uoff_t)-1;
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen ret = mail_transaction_log_file_map(file, min_file_offset, end_offset);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (ret <= 0) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (ret == 0) {
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen mail_index_set_error(view->log->index,
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen "Lost transaction log file %s seq %u",
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen file->filepath, file->hdr.file_seq);
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen mail_index_set_inconsistent(view->log->index);
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen }
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen return -1;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen }
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen first = file;
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen for (seq = min_file_seq+1; seq <= max_file_seq; seq++) {
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen file = file->next;
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen if (file == NULL || file->hdr.file_seq != seq) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (file == NULL && max_file_seq == (uint32_t)-1) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* we just wanted to sync everything */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen max_file_seq = seq-1;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen break;
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mail_index_set_error(view->log->index,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen "Lost transaction log file %s seq %u",
27586e4785d56aeb76e1fd96af8db799688dc64aTimo Sirainen view->log->tail->filepath, seq);
360123b1b41b7aa8af6c4a91c39046be646cd349Timo Sirainen mail_index_set_inconsistent(view->log->index);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return -1;
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen end_offset = file->hdr.file_seq == max_file_seq ?
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen max_file_offset : (uoff_t)-1;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen ret = mail_transaction_log_file_map(file, file->hdr.hdr_size,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen end_offset);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (ret == 0) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mail_index_set_error(view->log->index,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen "Lost transaction log file %s seq %u",
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen file->filepath, file->hdr.file_seq);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mail_index_set_inconsistent(view->log->index);
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen }
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen if (ret <= 0)
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen return -1;
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen }
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen i_assert(max_file_offset == (uoff_t)-1 ||
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen max_file_offset <= file->sync_offset);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen /* we have all of them. update refcounts. */
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk if (view->tail->hdr.file_seq < first->hdr.file_seq) {
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk /* unref old files */
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk for (file = view->tail; file != first; file = file->next)
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen file->refcount--;
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk view->tail = first;
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk } else {
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk /* going backwards, reference them */
7920a47321690c932ffd4d286cd16b4048d22d41Timo Sirainen for (file = first; file != view->tail; file = file->next)
7920a47321690c932ffd4d286cd16b4048d22d41Timo Sirainen file->refcount++;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen /* reference all new files */
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen for (file = view->head->next; file != NULL; file = file->next)
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen file->refcount++;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen view->head = view->log->head;
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen view->prev_file_seq = 0;
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen view->prev_file_offset = 0;
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen view->cur = first;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen view->cur_offset = min_file_offset;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen view->min_file_seq = min_file_seq;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen view->min_file_offset = min_file_offset;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen view->max_file_seq = max_file_seq;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen view->max_file_offset = max_file_offset;
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen view->type_mask = type_mask;
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen view->broken = FALSE;
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen i_assert(view->cur_offset <= view->cur->sync_offset);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen i_assert(view->cur->hdr.file_seq == min_file_seq);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen return 0;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen}
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainenvoid
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainenmail_transaction_log_view_get_prev_pos(struct mail_transaction_log_view *view,
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen uint32_t *file_seq_r,
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen uoff_t *file_offset_r)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen{
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen *file_seq_r = view->prev_file_seq;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen *file_offset_r = view->prev_file_offset;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen}
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainenvoid
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainenmail_transaction_log_view_set_corrupted(struct mail_transaction_log_view *view,
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen const char *fmt, ...)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen{
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen va_list va;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen view->broken = TRUE;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen va_start(va, fmt);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen t_push();
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen mail_transaction_log_file_set_corrupted(view->log->head, "%s",
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen t_strdup_vprintf(fmt, va));
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen t_pop();
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen va_end(va);
5c597df6aa8d81de4053c6986fab7739f3b44b20Timo Sirainen}
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainenint
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainenmail_transaction_log_view_is_corrupted(struct mail_transaction_log_view *view)
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen{
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen return view->broken;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen}
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainenstatic int
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainenlog_view_get_next(struct mail_transaction_log_view *view,
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen const struct mail_transaction_header **hdr_r,
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen const void **data_r)
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen{
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen const struct mail_transaction_header *hdr;
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen struct mail_transaction_log_file *file;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen const struct mail_transaction_type_map *type_rec;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen const void *data;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen unsigned int record_size;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen uint32_t hdr_size;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen size_t file_size;
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen if (view->cur == NULL)
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen return 0;
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* prev_file_offset should point to beginning of previous log record.
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen when we reach EOF, it should be left there, not to beginning of the
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen next file. */
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen view->prev_file_seq = view->cur->hdr.file_seq;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen view->prev_file_offset = view->cur_offset;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen if (view->cur->hdr.file_seq == view->max_file_seq) {
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen /* last file */
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen if (view->cur_offset == view->max_file_offset ||
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen view->cur_offset == view->cur->sync_offset) {
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen /* we're all finished */
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen view->cur = NULL;
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen return 0;
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen }
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen } else if (view->cur_offset == view->cur->sync_offset) {
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen /* end of file, go to next one */
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen view->cur = view->cur->next;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen if (view->cur == NULL)
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen return 0;
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen view->cur_offset = view->cur->hdr.hdr_size;
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen return log_view_get_next(view, hdr_r, data_r);
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen }
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen file = view->cur;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen data = buffer_get_data(file->buffer, &file_size);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen file_size += file->buffer_offset;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (view->cur_offset + sizeof(*hdr) > file_size) {
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen mail_transaction_log_file_set_corrupted(file,
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen "offset points outside file "
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen "(%"PRIuUOFF_T" + %"PRIuSIZE_T" > %"PRIuSIZE_T")",
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen view->cur_offset, sizeof(*hdr), file_size);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen return -1;
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen }
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen hdr = CONST_PTR_OFFSET(data, view->cur_offset - file->buffer_offset);
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen data = CONST_PTR_OFFSET(hdr, sizeof(*hdr));
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen hdr_size = mail_index_offset_to_uint32(hdr->size);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen if (file_size - view->cur_offset < hdr_size) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mail_transaction_log_file_set_corrupted(file,
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen "record size too large (type=0x%x, offset=%"PRIuUOFF_T
360123b1b41b7aa8af6c4a91c39046be646cd349Timo Sirainen ", size=%u, end=%"PRIuSIZE_T")",
360123b1b41b7aa8af6c4a91c39046be646cd349Timo Sirainen hdr->type & MAIL_TRANSACTION_TYPE_MASK,
360123b1b41b7aa8af6c4a91c39046be646cd349Timo Sirainen view->cur_offset, hdr_size, file_size);
360123b1b41b7aa8af6c4a91c39046be646cd349Timo Sirainen return -1;
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen }
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (hdr_size < sizeof(*hdr)) {
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen type_rec = NULL;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen record_size = 0;
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen } else {
5494a6bc149da8f02fd25c0434a9d612ac33f659Timo Sirainen type_rec = mail_transaction_type_lookup(hdr->type);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen if (type_rec != NULL)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen record_size = type_rec->record_size;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen else {
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen mail_transaction_log_file_set_corrupted(file,
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen "unknown record type 0x%x",
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen hdr->type & MAIL_TRANSACTION_TYPE_MASK);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen return -1;
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen }
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen }
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (hdr_size < sizeof(*hdr) + record_size) {
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen mail_transaction_log_file_set_corrupted(file,
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen "record size too small (type=0x%x, size=%u)",
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen hdr->type & MAIL_TRANSACTION_TYPE_MASK, hdr_size);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen return -1;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen }
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen if ((hdr_size - sizeof(*hdr)) % record_size != 0) {
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen mail_transaction_log_file_set_corrupted(file,
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen "record size wrong (type 0x%x, %u %% %u != 0)",
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen hdr->type & MAIL_TRANSACTION_TYPE_MASK,
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen (hdr_size - sizeof(*hdr)), record_size);
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen return -1;
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if ((hdr->type & MAIL_TRANSACTION_TYPE_MASK) !=
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen (MAIL_TRANSACTION_EXPUNGE|MAIL_TRANSACTION_EXPUNGE_PROT)) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen mail_transaction_log_file_set_corrupted(file,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen "found expunge without protection mask");
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return -1;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen } else if ((hdr->type & MAIL_TRANSACTION_TYPE_MASK) != type_rec->type) {
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen mail_transaction_log_file_set_corrupted(file,
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen "extra bits in header type: 0x%x",
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen hdr->type & MAIL_TRANSACTION_TYPE_MASK);
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen return -1;
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen } else if (hdr->type == MAIL_TRANSACTION_EXT_INTRO) {
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen const struct mail_transaction_ext_intro *intro;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen uint32_t i;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen for (i = 0; i < hdr_size; ) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (i + sizeof(*intro) > hdr_size) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen /* should be just extra padding */
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen break;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen
4a514fb20e04df397842cde11cc9ea92abfe9728Timo Sirainen intro = CONST_PTR_OFFSET(data, i);
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen if (intro->name_size >
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen hdr_size - sizeof(*hdr) - sizeof(*intro)) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen mail_transaction_log_file_set_corrupted(file,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen "extension intro: name_size too large");
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return -1;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen i += sizeof(*intro) + intro->name_size;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen }
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen *hdr_r = hdr;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen *data_r = data;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen view->cur_offset += hdr_size;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return 1;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen}
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainenint mail_transaction_log_view_next(struct mail_transaction_log_view *view,
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen const struct mail_transaction_header **hdr_r,
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen const void **data_r, int *skipped_r)
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen{
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen const struct mail_transaction_header *hdr;
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen const void *data;
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen int ret = 0;
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen if (skipped_r != NULL)
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen *skipped_r = FALSE;
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen if (view->broken)
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen return -1;
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen while ((ret = log_view_get_next(view, &hdr, &data)) > 0) {
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen if ((view->type_mask & hdr->type) != 0) {
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen /* looks like this is within our mask, but expunge
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen protection may mess up the check. */
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) == 0 ||
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen (view->type_mask & MAIL_TRANSACTION_EXPUNGE) != 0)
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen break;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen }
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen /* we don't want this record */
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (skipped_r != NULL)
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen *skipped_r = TRUE;
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen /* FIXME: hide flag/cache updates for appends if
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen append isn't in mask */
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen }
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (ret < 0) {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen view->cur_offset = view->cur->sync_offset;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen return -1;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen }
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (ret == 0)
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen return 0;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen view->tmp_hdr = *hdr;
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen view->tmp_hdr.size =
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen mail_index_offset_to_uint32(view->tmp_hdr.size) - sizeof(*hdr);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen i_assert(view->tmp_hdr.size != 0);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0) {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen /* hide expunge protection */
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen view->tmp_hdr.type &= ~MAIL_TRANSACTION_EXPUNGE_PROT;
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen }
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen *hdr_r = &view->tmp_hdr;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen *data_r = data;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen return 1;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen}
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen