mail-index.c revision af1e2b2ab5d1c5ca5afe482ef8c8161c17acc190
/* Copyright (C) 2003-2004 Timo Sirainen */
#include "lib.h"
#include "ioloop.h"
#include "array.h"
#include "buffer.h"
#include "hash.h"
#include "mmap-util.h"
#include "nfs-workarounds.h"
#include "read-full.h"
#include "write-full.h"
#include "mail-index-private.h"
#include "mail-index-view-private.h"
#include "mail-index-sync-private.h"
#include "mail-transaction-log.h"
#include "mail-cache.h"
#include <stdio.h>
#include <stddef.h>
#include <time.h>
struct mail_index_module_register mail_index_module_register = { 0 };
{
struct mail_index *index;
return index;
}
{
}
{
}
{
const struct mail_index_registered_ext *extensions;
struct mail_index_registered_ext rext;
unsigned int i, ext_count;
/* see if it's already there */
for (i = 0; i < ext_count; i++) {
return i;
}
return ext_count;
}
void *context)
{
struct mail_index_registered_ext *rext;
}
{
struct mail_index_registered_ext *rext;
}
{
struct mail_index_registered_ext *rext;
}
{
struct mail_index_registered_ext *rext;
}
{
}
{
mail_index_sync_lost_handler_t *const *handlers;
unsigned int i, count;
for (i = 0; i < count; i++) {
break;
}
}
}
{
void *value;
/* keywords_hash keeps a name => index mapping of keywords.
Keywords are never removed from it, so the index values are valid
for the lifetime of the mail_index. */
return TRUE;
}
*idx_r = (unsigned int)-1;
return FALSE;
}
const char *keyword,
unsigned int *idx_r)
{
char *keyword_dup;
return;
}
{
const struct mail_index_ext *ext;
const struct mail_index_keyword_header *kw_hdr;
const struct mail_index_keyword_header_rec *kw_rec;
const char *name;
unsigned int i, name_area_end_offset, old_count;
return 0;
}
/* Extension header contains:
- struct mail_index_keyword_header
- struct mail_index_keyword_header_rec * keywords_count
- const char names[] * keywords_count
*/
/* Keywords can only be added into same mapping. Removing requires a
new mapping (recreating the index file) */
/* nothing changed */
return 0;
}
/* make sure the header is valid */
"Keywords removed unexpectedly",
return -1;
}
"keywords_count larger than header size",
return -1;
}
for (i = 0; i < kw_hdr->keywords_count; i++) {
"name_offset points outside allocated header",
return -1;
}
}
"Keyword header doesn't end with NUL",
return -1;
}
/* create file -> index mapping */
#ifdef DEBUG
/* Check that existing headers are still the same. It's behind DEBUG
since it's pretty useless waste of CPU normally. */
const unsigned int *old_idx;
unsigned int idx;
"Keywords changed unexpectedly",
return -1;
}
}
#endif
/* Register the newly seen keywords */
for (; i < kw_hdr->keywords_count; i++) {
unsigned int idx;
if (*keyword == '\0') {
"Empty keyword name in header",
return -1;
}
}
return 0;
}
{
}
{
/* Note that our caller must close index->fd by itself. */
}
/* have to create it */
return 0;
}
return 1;
}
static int
{
int ret;
if (MAIL_INDEX_IS_IN_MEMORY(index))
return 0;
if (ret == 0) {
/* it's corrupted - recreate it */
}
}
return ret;
}
{
const char *path;
int fd;
if (fd == -1)
return -1;
}
return fd;
}
enum mail_index_open_flags flags)
{
int ret;
if (ret == 0) {
if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) == 0)
return FALSE;
/* if dovecot.index exists, read it first so that we can get
the correct indexid and log sequence */
(void)mail_index_try_open(index);
/* Create a new indexid for us. If we're opening index
into memory, index->map doesn't exist yet. */
}
}
if (ret >= 0) {
if (ret == 0) {
/* doesn't exist / corrupted */
if (ret == 0) {
}
}
}
if (ret < 0) {
if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) == 0)
return FALSE;
if (mail_index_move_to_memory(index) < 0)
return FALSE;
}
return TRUE;
}
enum file_lock_method lock_method)
{
int i = 0, ret = 1;
MAIL_INDEX_HDR_FLAG_CORRUPTED) != 0) {
/* corrupted, reopen files */
} else {
return 1;
}
}
i_strdup("(in-memory index)") :
for (;;) {
index->shared_lock_count = 0;
index->excl_lock_count = 0;
(flags & MAIL_INDEX_OPEN_FLAG_MMAP_DISABLE) != 0;
(flags & MAIL_INDEX_OPEN_FLAG_DOTLOCK_USE_EXCL) != 0;
(flags & MAIL_INDEX_OPEN_FLAG_FSYNC_DISABLE) != 0;
(flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0;
i_fatal("nfs flush requires fsync_disable=no");
i_fatal("nfs flush requires mmap_disable=yes");
/* doesn't exist and create flag not used */
ret = 0;
break;
}
if (ret == 0) {
/* completely broken, reopen */
if (i++ < 3) {
continue;
}
/* too many tries */
ret = -1;
}
}
break;
}
if (ret <= 0)
return ret;
}
{
}
index->shared_lock_count = 0;
}
{
}
{
if (MAIL_INDEX_IS_IN_MEMORY(index))
return 0;
return mail_index_try_open_only(index);
return mail_index_try_open_only(index);
}
return 0;
}
/* the same file */
return 1;
}
/* new file, new locks. the old fd can keep its locks, they don't
matter anymore as no-one's going to modify the file. */
return mail_index_try_open_only(index);
}
{
int ret;
if (MAIL_INDEX_IS_IN_MEMORY(index))
return 0;
if (index->excl_lock_count > 0) {
/* we have index exclusively locked, nothing could
have changed. */
return 0;
}
return ret <= 0 ? -1 : 0;
}
{
}
{
else {
}
return -1;
}
{
struct mail_index_map *map;
if (MAIL_INDEX_IS_IN_MEMORY(index))
/* set the index as being into memory */
/* index was never even opened. just mark it as being in
memory and let the caller re-open the index. */
return -1;
}
/* move index map to memory */
}
/* move transaction log to memory */
}
}
return 0;
}
{
}
const char *function)
{
return -1;
}
}
const char *filepath,
const char *function)
{
return -1;
}
}
{
}
{
}
}
#ifdef WORDS_BIGENDIAN
/* FIXME: Unfortunately these functions were originally written to use
endian-specific code and we can't avoid that without breaking backwards
compatibility. When we do break it, just select one of these. */
{
offset >>= 2;
}
{
return 0;
return (((offset & 0x0000007f)) |
}
#else
{
offset >>= 2;
}
{
return 0;
}
#endif