mail-transaction-log-view.c revision 847b3aa7e14ce05d382a44937a8ef5277bce5acb
/* Copyright (C) 2003-2004 Timo Sirainen */
#include "lib.h"
#include "array.h"
#include "mail-index-private.h"
#include "mail-transaction-log-private.h"
#include "mail-transaction-util.h"
struct mail_transaction_log_view {
struct mail_transaction_log *log;
struct mail_transaction_log_view *next;
struct mail_transaction_header tmp_hdr;
/* a list of log files we've referenced. we have to keep this list
explicitly because more files may be added into the linked list
at any time. */
unsigned int broken:1;
};
struct mail_transaction_log_view *
{
struct mail_transaction_log_view *view;
return view;
}
static void
{
struct mail_transaction_log_file *const *files;
unsigned int i, count;
for (i = 0; i < count; i++)
}
{
struct mail_transaction_log_view **p;
if (*p == view) {
break;
}
}
}
{
struct mail_transaction_log_view *view;
}
int
{
int ret;
/* transaction log is closed already. this log view shouldn't
be used anymore. */
return -1;
}
if (min_file_seq == 0) {
/* index file doesn't exist yet. this transaction log should
start from the beginning */
/* but it doesn't */
return 0;
}
min_file_offset = 0;
if (max_file_seq == 0) {
}
}
/* we can skip this */
min_file_offset = 0;
if (min_file_seq > max_file_seq) {
/* empty view */
}
}
/* find the oldest log file first. */
if (ret <= 0)
return ret;
if (min_file_offset == 0) {
/* this could happen if internal transactions haven't yet been
committed but external are. just assume we're at the
beginning. */
}
/* log file offset is probably corrupted in the index file. */
"file_seq=%u, min_file_offset (%"PRIuUOFF_T
return -1;
}
if (ret <= 0)
return ret;
/* see if we could find the missing file */
if (ret <= 0) {
if (ret < 0)
return -1;
/* not found / corrupted */
}
}
/* we just wanted to sync everything */
break;
}
/* missing files in the middle */
return 0;
}
if (ret <= 0)
return ret;
}
/* we have all of them. update refcounts. */
/* reference all used files */
}
view->prev_file_seq = 0;
view->prev_file_offset = 0;
return 1;
}
void
{
}
static bool
struct mail_transaction_log_file **last_r,
{
return TRUE;
}
for (;;) {
/* last file */
/* we're all finished */
}
/* end of file, go to next one */
} else {
continue;
}
}
/* not EOF */
break;
}
return last;
}
{
struct mail_transaction_log_file *cur;
}
void
const char *fmt, ...)
{
t_push();
t_pop();
}
bool
{
}
static bool
const struct mail_transaction_header *hdr,
const void *data)
{
/* we want to be extra careful with expunges */
if (rec_type != (MAIL_TRANSACTION_EXPUNGE |
"expunge record missing protection mask");
return FALSE;
}
}
if (rec_size == 0) {
"Empty record contents (type=0x%x)", rec_type);
return FALSE;
}
/* records that are exported by syncing and view syncing will be
checked here so that we don't have to implement the same validation
multiple times. other records are checked internally by
mail_index_sync_record(). */
t_push();
switch (rec_type) {
case MAIL_TRANSACTION_APPEND:
if ((rec_size % sizeof(struct mail_index_record)) != 0) {
"Invalid append record size");
}
break;
case MAIL_TRANSACTION_EXPUNGE:
sizeof(struct mail_transaction_expunge));
break;
sizeof(struct mail_transaction_flag_update));
break;
case MAIL_TRANSACTION_KEYWORD_UPDATE: {
unsigned int seqset_offset;
if ((seqset_offset % 4) != 0)
if (seqset_offset > rec_size) {
"Invalid keyword update record size");
break;
}
break;
}
sizeof(struct mail_transaction_keyword_reset));
break;
default:
break;
}
if (array_is_created(&uids)) {
"Invalid record size (type=0x%x)", rec_type);
count = 0;
} else if (count == 0) {
"No UID ranges (type=0x%x)", rec_type);
}
"Invalid UID range "
"(%u .. %u, type=0x%x)",
break;
}
"Non-sorted UID ranges (type=0x%x)",
rec_type);
break;
}
}
}
t_pop();
return ret;
}
static int
const struct mail_transaction_header **hdr_r,
const void **data_r)
{
const struct mail_transaction_header *hdr;
struct mail_transaction_log_file *file;
const void *data;
return 0;
/* prev_file_offset should point to beginning of previous log record.
when we reach EOF, it should be left there, not to beginning of the
next file that's not included inside the view. */
&view->cur_offset)) {
/* if the last file was the beginning of a file, we want to
move prev pointers there */
return 0;
}
"offset points outside file "
return -1;
}
"record size too small (type=0x%x, "
return -1;
}
"record size too large (type=0x%x, "
return -1;
}
return -1;
return 1;
}
const struct mail_transaction_header **hdr_r,
{
const struct mail_transaction_header *hdr;
const void *data;
int ret = 0;
return -1;
/* drop expunge protection */
else
/* the record is within our wanted mask */
break;
}
/* we don't want this record */
append isn't in mask */
}
if (ret < 0) {
return -1;
}
if (ret == 0)
return 0;
/* return type without expunge protection */
/* return record's size */
return 1;
}
{
struct mail_transaction_log_file *file;
break;
}
}
}