mail-index.c revision c53e8ee216904ffe6de4f6518d9f9f5107b7610e
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/* Copyright (c) 2003-2007 Dovecot authors, see the included COPYING file */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include "lib.h"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include "ioloop.h"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include "array.h"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include "buffer.h"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include "hash.h"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include "str-sanitize.h"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include "mmap-util.h"
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher#include "nfs-workarounds.h"
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher#include "read-full.h"
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher#include "write-full.h"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include "mail-index-private.h"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include "mail-index-view-private.h"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include "mail-index-sync-private.h"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include "mail-transaction-log.h"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include "mail-cache.h"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include <stdio.h>
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include <stddef.h>
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include <time.h>
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include <sys/stat.h>
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstruct mail_index_module_register mail_index_module_register = { 0 };
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstruct mail_index *mail_index_alloc(const char *dir, const char *prefix)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_index *index;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index = i_new(struct mail_index, 1);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->dir = i_strdup(dir);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->prefix = i_strdup(prefix);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->fd = -1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->extension_pool =
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher pool_alloconly_create(MEMPOOL_GROWING"index extension", 1024);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher p_array_init(&index->extensions, index->extension_pool, 5);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_array_init(&index->sync_lost_handlers, 4);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_array_init(&index->module_contexts,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher I_MIN(5, mail_index_module_register.id));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->mode = 0600;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->gid = (gid_t)-1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->keywords_ext_id =
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_ext_register(index, "keywords", 128, 2, 1);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->keywords_pool = pool_alloconly_create("keywords", 512);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_array_init(&index->keywords, 16);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->keywords_hash =
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher hash_create(default_pool, index->keywords_pool, 0,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher strcase_hash, (hash_cmp_callback_t *)strcasecmp);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->log = mail_transaction_log_alloc(index);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return index;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghervoid mail_index_free(struct mail_index **_index)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_index *index = *_index;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *_index = NULL;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_close(index);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_transaction_log_free(&index->log);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher hash_destroy(&index->keywords_hash);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher pool_unref(&index->extension_pool);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher pool_unref(&index->keywords_pool);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher array_free(&index->sync_lost_handlers);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher array_free(&index->keywords);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher array_free(&index->module_contexts);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_free(index->error);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_free(index->dir);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_free(index->prefix);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_free(index);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghervoid mail_index_set_permissions(struct mail_index *index,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mode_t mode, gid_t gid)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->mode = mode & 0666;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->gid = gid;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagheruint32_t mail_index_ext_register(struct mail_index *index, const char *name,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint32_t default_hdr_size,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint16_t default_record_size,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint16_t default_record_align)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_index_registered_ext rext;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint32_t ext_id;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (strcmp(name, str_sanitize(name, -1)) != 0)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_panic("mail_index_ext_register(%s): Invalid name", name);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (mail_index_ext_lookup(index, name, &ext_id))
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return ext_id;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher memset(&rext, 0, sizeof(rext));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rext.name = p_strdup(index->extension_pool, name);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rext.index_idx = array_count(&index->extensions);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rext.hdr_size = default_hdr_size;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rext.record_size = default_record_size;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rext.record_align = default_record_align;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher array_append(&index->extensions, &rext, 1);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return rext.index_idx;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherbool mail_index_ext_lookup(struct mail_index *index, const char *name,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint32_t *ext_id_r)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const struct mail_index_registered_ext *extensions;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher unsigned int i, count;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher extensions = array_get(&index->extensions, &count);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (i = 0; i < count; i++) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (strcmp(extensions[i].name, name) == 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *ext_id_r = i;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return TRUE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
bdd205037059e56484de3174951b22ff8f0f79f8Stephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
bdd205037059e56484de3174951b22ff8f0f79f8Stephen Gallagher *ext_id_r = (uint32_t)-1;
3a8abe04137d028b8ebd1cb33152aefa55893efbStephen Gallagher return FALSE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghervoid mail_index_register_expunge_handler(struct mail_index *index,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint32_t ext_id, bool call_always,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_expunge_handler_t *cb,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher void *context)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_index_registered_ext *rext;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rext = array_idx_modifiable(&index->extensions, ext_id);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_assert(rext->expunge_handler == NULL || rext->expunge_handler == cb);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rext->expunge_handler = cb;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rext->expunge_context = context;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rext->expunge_handler_call_always = call_always;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghervoid mail_index_unregister_expunge_handler(struct mail_index *index,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint32_t ext_id)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_index_registered_ext *rext;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rext = array_idx_modifiable(&index->extensions, ext_id);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_assert(rext->expunge_handler != NULL);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rext->expunge_handler = NULL;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghervoid mail_index_register_sync_handler(struct mail_index *index, uint32_t ext_id,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_sync_handler_t *cb,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher enum mail_index_sync_handler_type type)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_index_registered_ext *rext;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rext = array_idx_modifiable(&index->extensions, ext_id);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_assert(rext->sync_handler.callback == NULL);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rext->sync_handler.callback = cb;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rext->sync_handler.type = type;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghervoid mail_index_unregister_sync_handler(struct mail_index *index,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint32_t ext_id)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_index_registered_ext *rext;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rext = array_idx_modifiable(&index->extensions, ext_id);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_assert(rext->sync_handler.callback != NULL);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rext->sync_handler.callback = NULL;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rext->sync_handler.type = 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghervoid mail_index_register_sync_lost_handler(struct mail_index *index,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_sync_lost_handler_t *cb)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher array_append(&index->sync_lost_handlers, &cb, 1);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghervoid mail_index_unregister_sync_lost_handler(struct mail_index *index,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_sync_lost_handler_t *cb)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_sync_lost_handler_t *const *handlers;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher unsigned int i, count;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher handlers = array_get(&index->sync_lost_handlers, &count);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (i = 0; i < count; i++) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (handlers[i] == cb) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher array_delete(&index->sync_lost_handlers, i, 1);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher break;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherbool mail_index_keyword_lookup(struct mail_index *index,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const char *keyword, unsigned int *idx_r)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher void *value;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* keywords_hash keeps a name => index mapping of keywords.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher Keywords are never removed from it, so the index values are valid
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for the lifetime of the mail_index. */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (hash_lookup_full(index->keywords_hash, keyword, NULL, &value)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *idx_r = POINTER_CAST_TO(value, unsigned int);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return TRUE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *idx_r = (unsigned int)-1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return FALSE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghervoid mail_index_keyword_lookup_or_create(struct mail_index *index,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const char *keyword,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher unsigned int *idx_r)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher char *keyword_dup;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_assert(*keyword != '\0');
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (mail_index_keyword_lookup(index, keyword, idx_r))
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher keyword = keyword_dup = p_strdup(index->keywords_pool, keyword);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *idx_r = array_count(&index->keywords);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher hash_insert(index->keywords_hash, keyword_dup, POINTER_CAST(*idx_r));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher array_append(&index->keywords, &keyword, 1);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherconst ARRAY_TYPE(keywords) *mail_index_get_keywords(struct mail_index *index)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return &index->keywords;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherint mail_index_try_open_only(struct mail_index *index)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_assert(index->fd == -1);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_assert(!MAIL_INDEX_IS_IN_MEMORY(index));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Note that our caller must close index->fd by itself. */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (index->readonly)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher errno = EACCES;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher else {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->fd = nfs_safe_open(index->filepath, O_RDWR);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->readonly = FALSE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (index->fd == -1 && errno == EACCES) {
bdd205037059e56484de3174951b22ff8f0f79f8Stephen Gallagher index->fd = open(index->filepath, O_RDONLY);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->readonly = TRUE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (index->fd == -1) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (errno != ENOENT)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return mail_index_set_syscall_error(index, "open()");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* have to create it */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return 1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghermail_index_try_open(struct mail_index *index)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher int ret;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_assert(index->fd == -1);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (MAIL_INDEX_IS_IN_MEMORY(index))
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_assert(index->map == NULL || index->map->rec_map->lock_id == 0);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = mail_index_map(index, MAIL_INDEX_SYNC_HANDLER_HEAD);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (ret == 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* it's corrupted - recreate it */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (index->fd != -1) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (close(index->fd) < 0)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_set_syscall_error(index, "close()");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->fd = -1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return ret;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherint mail_index_create_tmp_file(struct mail_index *index, const char **path_r)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mode_t old_mask;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const char *path;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher int fd;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_assert(!MAIL_INDEX_IS_IN_MEMORY(index));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher path = *path_r = t_strconcat(index->filepath, ".tmp", NULL);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher old_mask = umask(0);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher fd = open(path, O_RDWR|O_CREAT|O_TRUNC, index->mode);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher umask(old_mask);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (fd == -1)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return mail_index_file_set_syscall_error(index, path, "open()");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (index->gid != (gid_t)-1 && fchown(fd, (uid_t)-1, index->gid) < 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_file_set_syscall_error(index, path, "fchown()");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return -1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return fd;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int mail_index_open_files(struct mail_index *index,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher enum mail_index_open_flags flags)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher int ret;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher bool created = FALSE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = mail_transaction_log_open(index->log);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (ret == 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) == 0)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* if dovecot.index exists, read it first so that we can get
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher the correct indexid and log sequence */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher (void)mail_index_try_open(index);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (index->indexid == 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Create a new indexid for us. If we're opening index
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher into memory, index->map doesn't exist yet. */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->indexid = ioloop_time;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (index->map != NULL)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->map->hdr.indexid = index->indexid;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = mail_transaction_log_create(index->log);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher created = TRUE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (ret >= 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = index->map != NULL ? 0 : mail_index_try_open(index);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (ret == 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* doesn't exist / corrupted */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_transaction_log_close(index->log);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = mail_transaction_log_create(index->log);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (ret == 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (index->map != NULL)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_unmap(&index->map);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->map = mail_index_map_alloc(index);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (ret < 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* open/create failed, fallback to in-memory indexes */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) == 0)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return -1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (mail_index_move_to_memory(index) < 0)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return -1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->cache = created ? mail_cache_create(index) :
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_cache_open_or_create(index);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return 1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherint mail_index_open(struct mail_index *index, enum mail_index_open_flags flags,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher enum file_lock_method lock_method)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher int ret;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (index->opened) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (index->map != NULL &&
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher (index->map->hdr.flags &
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher MAIL_INDEX_HDR_FLAG_CORRUPTED) != 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* corrupted, reopen files */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_close(index);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher } else {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_assert(index->map != NULL);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return 1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->filepath = MAIL_INDEX_IS_IN_MEMORY(index) ?
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_strdup("(in-memory index)") :
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_strconcat(index->dir, "/", index->prefix, NULL);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->shared_lock_count = 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->excl_lock_count = 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->lock_type = F_UNLCK;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->lock_id_counter = 2;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->readonly = FALSE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->nodiskspace = FALSE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->index_lock_timeout = FALSE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->log_locked = FALSE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->mmap_disable = (flags & MAIL_INDEX_OPEN_FLAG_MMAP_DISABLE) != 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->use_excl_dotlocks =
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher (flags & MAIL_INDEX_OPEN_FLAG_DOTLOCK_USE_EXCL) != 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->fsync_disable =
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher (flags & MAIL_INDEX_OPEN_FLAG_FSYNC_DISABLE) != 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->nfs_flush = (flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->readonly = (flags & MAIL_INDEX_OPEN_FLAG_READONLY) != 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->lock_method = lock_method;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (index->nfs_flush && index->fsync_disable)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_fatal("nfs flush requires fsync_disable=no");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (index->nfs_flush && !index->mmap_disable)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_fatal("nfs flush requires mmap_disable=yes");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if ((ret = mail_index_open_files(index, flags)) <= 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* doesn't exist and create flag not used */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_close(index);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return ret;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_assert(index->map != NULL);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->opened = TRUE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return 1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghervoid mail_index_close_file(struct mail_index *index)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (index->file_lock != NULL)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher file_lock_free(&index->file_lock);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (index->fd != -1) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (close(index->fd) < 0)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_set_syscall_error(index, "close()");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->fd = -1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->lock_id_counter += 2;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->lock_type = F_UNLCK;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher index->shared_lock_count = 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->excl_lock_count = 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghervoid mail_index_close(struct mail_index *index)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (index->map != NULL)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_unmap(&index->map);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_close_file(index);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_transaction_log_close(index->log);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (index->cache != NULL)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_cache_free(&index->cache);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_free_and_null(index->filepath);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->indexid = 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->opened = FALSE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherint mail_index_reopen_if_changed(struct mail_index *index)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct stat st1, st2;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_assert(index->excl_lock_count == 0);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (MAIL_INDEX_IS_IN_MEMORY(index))
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (index->fd == -1)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return mail_index_try_open_only(index);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (fstat(index->fd, &st1) < 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (errno != ESTALE)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return mail_index_set_syscall_error(index, "fstat()");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* deleted/recreated, reopen */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_close_file(index);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return mail_index_try_open_only(index);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (index->nfs_flush)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher nfs_flush_attr_cache(index->filepath);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (nfs_safe_stat(index->filepath, &st2) < 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (errno == ENOENT)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return mail_index_set_syscall_error(index, "stat()");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (st1.st_ino == st2.st_ino && CMP_DEV_T(st1.st_dev, st2.st_dev)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* the same file */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return 1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* new file, new locks. the old fd can keep its locks, they don't
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher matter anymore as no-one's going to modify the file. */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_close_file(index);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return mail_index_try_open_only(index);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherint mail_index_refresh(struct mail_index *index)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher int ret;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (MAIL_INDEX_IS_IN_MEMORY(index))
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (index->excl_lock_count > 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* we have index exclusively locked, nothing could
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher have changed. */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = mail_index_map(index, MAIL_INDEX_SYNC_HANDLER_HEAD);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return ret <= 0 ? -1 : 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstruct mail_cache *mail_index_get_cache(struct mail_index *index)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return index->cache;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherint mail_index_set_error(struct mail_index *index, const char *fmt, ...)
bdd205037059e56484de3174951b22ff8f0f79f8Stephen Gallagher{
bdd205037059e56484de3174951b22ff8f0f79f8Stephen Gallagher va_list va;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_free(index->error);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (fmt == NULL)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->error = NULL;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher else {
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher va_start(va, fmt);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->error = i_strdup_vprintf(fmt, va);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher va_end(va);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_error("%s", index->error);
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return -1;
bdd205037059e56484de3174951b22ff8f0f79f8Stephen Gallagher}
bdd205037059e56484de3174951b22ff8f0f79f8Stephen Gallagher
bdd205037059e56484de3174951b22ff8f0f79f8Stephen Gallagherint mail_index_move_to_memory(struct mail_index *index)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mail_index_map *map;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (MAIL_INDEX_IS_IN_MEMORY(index))
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return index->map == NULL ? -1 : 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* set the index as being into memory */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_free_and_null(index->dir);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_free(index->filepath);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->filepath = i_strdup("(in-memory index)");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (index->map == NULL) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* index was never even opened. just mark it as being in
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher memory and let the caller re-open the index. */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_assert(index->fd == -1);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return -1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* move index map to memory */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (!MAIL_INDEX_MAP_IS_IN_MEMORY(index->map)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher map = mail_index_map_clone(index->map);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_unmap(&index->map);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->map = map;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (index->log != NULL) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* move transaction log to memory */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_transaction_log_move_to_memory(index->log);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (index->file_lock != NULL)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher file_lock_free(&index->file_lock);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (index->fd != -1) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (close(index->fd) < 0)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_set_syscall_error(index, "close()");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->fd = -1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghervoid mail_index_mark_corrupted(struct mail_index *index)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->indexid = 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->map->hdr.flags |= MAIL_INDEX_HDR_FLAG_CORRUPTED;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (unlink(index->filepath) < 0 && errno != ENOENT && errno != ESTALE)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_index_set_syscall_error(index, "unlink()");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherint mail_index_set_syscall_error(struct mail_index *index,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const char *function)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_assert(function != NULL);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (ENOSPACE(errno)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->nodiskspace = TRUE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return -1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return mail_index_set_error(index, "%s failed with index file %s: %m",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher function, index->filepath);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherint mail_index_file_set_syscall_error(struct mail_index *index,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const char *filepath,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const char *function)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_assert(filepath != NULL);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_assert(function != NULL);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (ENOSPACE(errno)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->nodiskspace = TRUE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return -1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return mail_index_set_error(index, "%s failed with file %s: %m",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher function, filepath);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherconst char *mail_index_get_error_message(struct mail_index *index)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return index->error;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghervoid mail_index_reset_error(struct mail_index *index)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (index->error != NULL) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_free(index->error);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->error = NULL;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->nodiskspace = FALSE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher index->index_lock_timeout = FALSE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#ifdef WORDS_BIGENDIAN
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/* FIXME: Unfortunately these functions were originally written to use
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher endian-specific code and we can't avoid that without breaking backwards
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher compatibility. When we do break it, just select one of these. */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagheruint32_t mail_index_uint32_to_offset(uint32_t offset)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher i_assert(offset < 0x40000000);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_assert((offset & 3) == 0);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher offset >>= 2;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return 0x00000080 | ((offset & 0x0000007f)) |
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher 0x00008000 | ((offset & 0x00003f80) >> 7 << 8) |
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher 0x00800000 | ((offset & 0x001fc000) >> 14 << 16) |
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher 0x80000000 | ((offset & 0x0fe00000) >> 21 << 24);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagheruint32_t mail_index_offset_to_uint32(uint32_t offset)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if ((offset & 0x80808080) != 0x80808080)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return (((offset & 0x0000007f)) |
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ((offset & 0x00007f00) >> 8 << 7) |
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ((offset & 0x007f0000) >> 16 << 14) |
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ((offset & 0x7f000000) >> 24 << 21)) << 2;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#else
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagheruint32_t mail_index_uint32_to_offset(uint32_t offset)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_assert(offset < 0x40000000);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_assert((offset & 3) == 0);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher offset >>= 2;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return 0x80000000 | ((offset & 0x0000007f) << 24) |
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher 0x00800000 | ((offset & 0x00003f80) >> 7 << 16) |
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher 0x00008000 | ((offset & 0x001fc000) >> 14 << 8) |
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher 0x00000080 | ((offset & 0x0fe00000) >> 21);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagheruint32_t mail_index_offset_to_uint32(uint32_t offset)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if ((offset & 0x80808080) != 0x80808080)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return (((offset & 0x0000007f) << 21) |
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ((offset & 0x00007f00) >> 8 << 14) |
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ((offset & 0x007f0000) >> 16 << 7) |
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ((offset & 0x7f000000) >> 24)) << 2;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#endif
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher