mail-index.c revision 5a4ab3d6e108a899c8b51bebd0094a37b738d5a1
/* Copyright (C) 2003-2004 Timo Sirainen */
#include "lib.h"
#include "buffer.h"
#include "mmap-util.h"
#include "read-full.h"
#include "write-full.h"
#include "mail-index-private.h"
#include "mail-transaction-log.h"
#include "mail-cache.h"
#include <stdio.h>
#include <stddef.h>
#include <time.h>
{
struct mail_index *index;
return index;
}
{
}
{
}
{
const struct mail_index_ext *extensions;
struct mail_index_ext ext;
unsigned int i;
ext_count /= sizeof(*extensions);
/* see if it's already there */
for (i = 0; i < ext_count; i++) {
return i;
}
return ext_count;
}
unsigned int initial_count)
{
pool_alloconly_create("extensions",
} else {
}
map->ext_id_map =
}
{
const struct mail_index_ext *extensions;
return (uint32_t)-1;
size /= sizeof(*extensions);
for (i = 0; i < size; i++) {
return i;
}
return (uint32_t)-1;
}
{
struct mail_index_ext *ext;
idx = 0;
} else {
}
return idx;
}
{
return FALSE;
return TRUE;
}
{
}
struct mail_index_map *map)
{
const struct mail_index_ext_header *ext_hdr;
unsigned int i, old_count;
const char *name;
/* extension headers always start from 64bit offsets, so if base header
doesn't happen to be 64bit aligned we'll skip some bytes */
/* nothing to do, skip allocatations and all */
return 1;
}
for (i = 0; i < old_count; i++)
"Header extension goes outside header",
return -1;
}
t_push();
t_pop();
}
return 1;
}
struct mail_index_map *map)
{
#ifndef WORDS_BIGENDIAN
#endif
/* major version change - handle silently(?) */
return -1;
}
/* architecture change - handle silently(?) */
return -1;
}
/* we've already complained about it */
return -1;
}
/* following some extra checks that only take a bit of CPU */
"uid_validity = 0, next_uid = %u",
return -1;
}
"keywords_mask_size mismatch: %d != %d",
(int)sizeof(keywords_mask_t));
return -1;
}
"record_size too small: %u < %"PRIuSIZE_T,
sizeof(struct mail_index_record));
return -1;
}
return 0;
return 0;
return 0;
}
struct mail_index_map *map)
{
}
map->mmap_used_size = 0;
map->records_count = 0;
}
}
{
return;
}
struct mail_index_map *map)
{
}
{
const struct mail_index_header *hdr;
struct mail_index_header *mhdr;
unsigned int records_count;
/* we had temporarily used a buffer, eg. for updating index */
}
return -1;
}
return 0;
}
"messages_count too large (%u > %u)",
return 0;
}
/* header smaller than ours, make a copy so our newer headers
won't have garbage in them */
}
return 1;
}
{
ret = 1;
if (ret > 0)
}
"Corrupted header sizes (base %u, full %u)",
return 0;
}
/* @UNSAFE */
sizeof(hdr)),
NULL);
} else {
/* @UNSAFE */
pos),
}
}
if (ret > 0) {
}
/* @UNSAFE */
}
if (ret < 0) {
return 0;
}
return -1;
}
if (ret == 0) {
"Corrupted index file %s: File too small",
return -1;
}
return 1;
}
struct mail_index_map *map)
{
for (i = 0; i < MAIL_INDEX_ESTALE_RETRY_COUNT; i++) {
return ret;
/* ESTALE - reopen index file */
if (ret <= 0) {
if (ret == 0) {
/* the file was lost */
}
return -1;
}
}
/* Too many ESTALE retries */
return -1;
}
{
const struct mail_index_header *hdr;
return 0;
/* always check corrupted-flag to avoid errors later */
return -1;
return 1;
}
return 0;
}
{
struct mail_index_map *map;
int ret;
if (ret != 0)
return ret;
}
/* this map is already used by some views and they may have
pointers into it. leave them and create a new mapping. */
}
map->hdr_copy_buf =
} else if (MAIL_INDEX_MAP_IS_IN_MEMORY(map)) {
if (map->write_to_disk) {
/* we have modified this mapping and it's waiting to
be written to disk once we drop exclusive lock.
mapping couldn't have changed, so do nothing. */
return 1;
}
/* FIXME: we need to re-read header */
}
if (!index->mmap_disable) {
return ret;
}
} else {
return -1;
}
}
if (ret < 0) {
return 0;
}
if (ret == 0)
return 1;
}
struct mail_index_map *
{
struct mail_index_map *mem_map;
struct mail_index_header *hdr;
struct mail_index_ext *extensions;
unsigned int i, count;
if (MAIL_INDEX_MAP_IS_IN_MEMORY(map) &&
return map;
}
else {
for (i = 0; i < map->records_count; i++) {
}
}
/* copy extensions */
0, (size_t)-1);
0, (size_t)-1);
/* fix the name pointers to use our own pool */
NULL);
for (i = 0; i < count; i++) {
extensions[i].name);
}
}
return mem_map;
}
{
return 0;
}
{
int i;
for (i = 0; i < 3; i++) {
}
break;
/* May happen with some OSes with NFS. Try again, although
there's still a race condition with another computer
creating the index file again. However, we can't try forever
as ESTALE happens also if index directory has been deleted
from server.. */
}
/* have to create it */
return 0;
}
return 1;
}
static int
{
unsigned int lock_id;
int ret;
*lock_id_r = 0;
if (ret <= 0)
return ret;
return -1;
}
if (ret == 0) {
/* it's corrupted - recreate it */
*lock_id_r = 0;
} else {
else
}
return ret;
}
const struct mail_index_header *hdr)
{
} else {
return -1;
}
}
return 0;
}
{
const char *path;
int fd;
if (fd == -1)
return -1;
}
return fd;
}
struct mail_index_header *hdr)
{
const char *path;
int ret;
/* log file lock protects index creation */
return -1;
if (ret != 0) {
return ret < 0 ? -1 : 0;
}
/* create it fully in index.tmp first */
ret = -1;
ret = -1;
} else {
}
if (ret == 0) {
/* it's corrupted even while we just created it,
should never happen unless someone pokes the file directly */
"Newly created index file is corrupted: %s", path);
ret = -1;
}
if (ret < 0) {
"unlink()");
}
} else {
/* make it visible to others */
ret = -1;
}
}
return ret;
}
{
#ifndef WORDS_BIGENDIAN
#endif
}
/* returns -1 = error, 0 = won't create, 1 = ok */
enum mail_index_open_flags flags)
{
struct mail_index_header hdr;
unsigned int lock_id = 0;
int ret;
if (ret > 0)
else if (ret == 0) {
/* doesn't exist, or corrupted */
if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) == 0)
return 0;
} else if (ret < 0)
return -1;
return -1;
if (lock_id != 0) {
lock_id = 0;
}
return -1;
}
if (lock_id == 0) {
return -1;
}
return -1;
return 1;
}
{
int i = 0, ret;
return 0;
do {
index->shared_lock_count = 0;
index->excl_lock_count = 0;
(flags & MAIL_INDEX_OPEN_FLAG_MMAP_DISABLE) != 0;
(flags & MAIL_INDEX_OPEN_FLAG_MMAP_NO_WRITE) != 0;
if (ret <= 0)
break;
if (ret == 0) {
/* completely broken, reopen */
if (i++ < 3)
continue;
/* too many tries */
ret = -1;
}
}
break;
} while (1);
if (ret <= 0)
return ret;
}
{
}
}
}
}
}
{
struct mail_index_map *old_map;
/* new file, new locks. the old fd can keep it's locks, they don't
matter anymore as no-one's going to modify the file. */
index->shared_lock_count = 0;
if (fd != -1) {
ret = 0;
} else {
if (ret > 0)
else if (ret == 0) {
/* index file is lost */
ret = -1;
}
}
if (ret == 0) {
ret = -1;
}
if (lock_id != 0)
if (ret == 0) {
} else {
}
}
return ret;
}
{
return -1;
/* lost it? recreate */
(void)mail_index_mark_corrupted(index);
return -1;
}
return -1;
return 1;
} else {
return 0;
}
}
{
}
{
else {
}
return -1;
}
{
}
{
struct mail_index_header hdr;
return;
}
}
const char *function)
{
return -1;
}
}
const char *filepath,
const char *function)
{
return -1;
}
}
{
if (index->nodiskspace)
return MAIL_INDEX_ERROR_DISKSPACE;
return MAIL_INDEX_ERROR_INTERNAL;
return MAIL_INDEX_ERROR_NONE;
}
{
}
{
}
}
{
unsigned char buf[4];
offset >>= 2;
}
{
return 0;
}