mail-index.c revision e2ea49bd487d76b425e270321e9cf1e546642de0
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainenstatic int mail_index_try_open_only(struct mail_index *index);
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainenstruct mail_index *mail_index_alloc(const char *dir, const char *prefix)
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen pool_alloconly_create("extra_record_pool", 256);
4ba3717a04823875c2a1d60ff9dc8177ae033d12Timo Sirainen buffer_create_dynamic(index->extra_records_pool,
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen index->max_record_size = sizeof(struct mail_index_record);
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainenuint32_t mail_index_register_record_extra(struct mail_index *index,
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen unsigned int i;
4c61d6b6ad6173f06563c2cee9bd813c59277dd2Timo Sirainen /* see if it's there already */
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen for (i = 0; i < index->extra_records_count; i++) {
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen if (strcmp(index->extra_records[i].name, name) == 0) {
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen i_assert(index->extra_records[i].size == size);
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen i_assert(index->max_record_size + size <= 65535);
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen if (index->extra_records_count >= MAIL_INDEX_MAX_EXTRA_RECORDS) {
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen i_panic("Maximum extra record count reached, "
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen "you'll need to recompile with larger limit. "
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen "MAIL_INDEX_MAX_EXTRA_RECORDS = %d",
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen info.name = p_strdup(index->extra_records_pool, name);
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen buffer_append(index->extra_records_buf, &info, sizeof(info));
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen buffer_get_data(index->extra_records_buf, &buf_size);
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen index->extra_records_count = buf_size / sizeof(info);
4c61d6b6ad6173f06563c2cee9bd813c59277dd2Timo Sirainenstatic int mail_index_check_header(struct mail_index *index,
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen const struct mail_index_header *hdr = map->hdr;
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen unsigned char compat_data[sizeof(hdr->compat_data)];
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen compat_data[0] = MAIL_INDEX_COMPAT_LITTLE_ENDIAN;
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen if (hdr->major_version != MAIL_INDEX_MAJOR_VERSION) {
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen /* major version change - handle silently(?) */
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen if (memcmp(hdr->compat_data, compat_data, sizeof(compat_data)) != 0) {
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen /* architecture change - handle silently(?) */
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen if ((map->hdr->flags & MAIL_INDEX_HDR_FLAG_CORRUPTED) != 0) {
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen /* we've already complained about it */
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen /* following some extra checks that only take a bit of CPU */
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen if (hdr->uid_validity == 0 && hdr->next_uid != 1) {
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen "uid_validity = 0, next_uid = %u",
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen if (hdr->keywords_mask_size != sizeof(keywords_mask_t)) {
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen "keywords_mask_size mismatch: %d != %d",
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen if (hdr->record_size < sizeof(struct mail_index_record)) {
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen sizeof(struct mail_index_record));
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen if (hdr->recent_messages_count > hdr->messages_count ||
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen hdr->seen_messages_count > hdr->messages_count ||
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen hdr->deleted_messages_count > hdr->messages_count)
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen if (hdr->first_recent_uid_lowwater > hdr->next_uid ||
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen hdr->first_unseen_uid_lowwater > hdr->next_uid ||
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen hdr->first_deleted_uid_lowwater > hdr->next_uid)
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainenstatic void mail_index_map_clear(struct mail_index *index,
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen if (munmap(map->mmap_base, map->mmap_size) < 0)
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen mail_index_set_syscall_error(index, "munmap()");
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainenvoid mail_index_unmap(struct mail_index *index, struct mail_index_map *map)
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainenstatic void mail_index_unmap_forced(struct mail_index *index,
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainenstatic int mail_index_mmap(struct mail_index *index, struct mail_index_map *map)
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen /* we had temporarily used a buffer, eg. for updating index */
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen map->mmap_base = index->lock_type != F_WRLCK ?
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen mail_index_set_syscall_error(index, "mmap()");
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen if (map->mmap_size < MAIL_INDEX_HEADER_MIN_SIZE) {
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
if (ret > 0)
if (ret < 0) {
if (ret == 0) {
int i, ret;
for (i = 0; i < MAIL_INDEX_ESTALE_RETRY_COUNT; i++) {
if (ret != 0)
return ret;
if (ret <= 0) {
if (ret == 0) {
int ret;
if (ret != 0)
return ret;
return ret;
if (ret < 0) {
if (ret == 0)
struct mail_index_map *
return map;
return mem_map;
unsigned int lock_id;
int ret;
*lock_id_r = 0;
if (ret <= 0)
return ret;
if (ret == 0) {
*lock_id_r = 0;
return ret;
const char *path;
int fd;
return fd;
const char *path;
int ret;
if (ret != 0) {
/* create it fully in index.tmp first */
if (ret == 0) {
if (ret < 0) {
return ret;
#ifndef WORDS_BIGENDIAN
unsigned int lock_id = 0;
int ret;
if (ret > 0)
else if (ret == 0) {
} else if (ret < 0)
if (lock_id != 0) {
lock_id = 0;
if (lock_id == 0) {
int i = 0, ret;
if (ret <= 0)
if (ret == 0) {
if (ret <= 0)
return ret;
ret = 0;
if (ret > 0)
else if (ret == 0) {
if (ret == 0) {
if (lock_id != 0)
if (ret == 0) {
return ret;
const char *function)
const char *filepath,
const char *function)
return MAIL_INDEX_ERROR_DISKSPACE;
return MAIL_INDEX_ERROR_INTERNAL;
return MAIL_INDEX_ERROR_NONE;