mail-transaction-log-view.c revision 075912b4566a79c7bc59bf229c9f629ef7be0ea2
/* 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,
const struct mail_transaction_type_map *type_rec)
{
/* we want to be extra careful with expunges */
if (hdr_type != (MAIL_TRANSACTION_EXPUNGE |
"expunge record missing protection mask");
return FALSE;
}
"extra bits in header type: 0x%x", hdr_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 (hdr_type) {
case MAIL_TRANSACTION_EXPUNGE: {
sizeof(struct mail_transaction_expunge));
break;
}
case MAIL_TRANSACTION_FLAG_UPDATE: {
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;
}
case MAIL_TRANSACTION_KEYWORD_RESET: {
sizeof(struct mail_transaction_keyword_reset));
break;
}
default:
break;
}
if (array_is_created(&uids)) {
"Invalid UID range "
"(%u .. %u, type=0x%x)",
break;
}
"Non-sorted UID ranges (type=0x%x)",
hdr_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 struct mail_transaction_type_map *type_rec;
const void *data;
unsigned int record_size;
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;
}
/* we'll fail below with "records size too small" */
record_size = 0;
} else {
else {
"unknown record type 0x%x", hdr_type);
return -1;
}
}
"record size too small (type=0x%x, "
return -1;
}
if (record_size != 0 &&
"record size wrong (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;
/* looks like this is within our mask, but expunge
protection may mess up the check. */
break;
}
/* we don't want this record */
append isn't in mask */
}
if (ret < 0) {
return -1;
}
if (ret == 0)
return 0;
/* hide expunge protection */
}
return 1;
}
{
struct mail_transaction_log_file *file;
break;
}
}
}