mail-index.c revision 51b979b6414b940f04677a7e2d064be119345954
89a126810703c666309310d0f3189e9834d70b5bTimo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "ioloop.h"
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen#include "array.h"
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen#include "buffer.h"
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen#include "hash.h"
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen#include "mmap-util.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "nfs-workarounds.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "read-full.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "write-full.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-index-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-index-view-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-index-sync-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-transaction-log.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-cache.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <stdio.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <stddef.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <time.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <sys/stat.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct mail_index_module_register mail_index_module_register = { 0 };
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct mail_index *mail_index_alloc(const char *dir, const char *prefix)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_index *index;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index = i_new(struct mail_index, 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index->dir = i_strdup(dir);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index->prefix = i_strdup(prefix);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index->fd = -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen index->extension_pool =
ad850190d946d34966a56838cfdb216e021b5b5fTimo Sirainen pool_alloconly_create(MEMPOOL_GROWING"index extension", 1024);
ad850190d946d34966a56838cfdb216e021b5b5fTimo Sirainen p_array_init(&index->extensions, index->extension_pool, 5);
ad850190d946d34966a56838cfdb216e021b5b5fTimo Sirainen i_array_init(&index->sync_lost_handlers, 4);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_array_init(&index->module_contexts,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen I_MIN(5, mail_index_module_register.id));
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen index->mode = 0600;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen index->gid = (gid_t)-1;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen index->keywords_ext_id =
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen mail_index_ext_register(index, "keywords", 128, 2, 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index->keywords_pool = pool_alloconly_create("keywords", 512);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_array_init(&index->keywords, 16);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index->keywords_hash =
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen hash_create(default_pool, index->keywords_pool, 0,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen strcase_hash, (hash_cmp_callback_t *)strcasecmp);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index->log = mail_transaction_log_alloc(index);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return index;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_index_free(struct mail_index **_index)
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen{
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen struct mail_index *index = *_index;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *_index = NULL;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen mail_index_close(index);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_transaction_log_free(&index->log);
6e235046e1d8e9d89fc948f5c623676c20421a28Timo Sirainen hash_destroy(index->keywords_hash);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen pool_unref(index->extension_pool);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen pool_unref(index->keywords_pool);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen array_free(&index->sync_lost_handlers);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen array_free(&index->keywords);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen array_free(&index->module_contexts);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_free(index->error);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_free(index->dir);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_free(index->prefix);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_free(index);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainenvoid mail_index_set_permissions(struct mail_index *index,
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen mode_t mode, gid_t gid)
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen{
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen index->mode = mode & 0666;
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen index->gid = gid;
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen}
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainenuint32_t mail_index_ext_register(struct mail_index *index, const char *name,
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainen uint32_t default_hdr_size,
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen uint16_t default_record_size,
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainen uint16_t default_record_align)
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainen{
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainen const struct mail_index_registered_ext *extensions;
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainen struct mail_index_registered_ext rext;
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainen unsigned int i, ext_count;
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen extensions = array_get(&index->extensions, &ext_count);
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen /* see if it's already there */
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainen for (i = 0; i < ext_count; i++) {
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen if (strcmp(extensions[i].name, name) == 0)
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen return i;
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen }
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen memset(&rext, 0, sizeof(rext));
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen rext.name = p_strdup(index->extension_pool, name);
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen rext.index_idx = ext_count;
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen rext.hdr_size = default_hdr_size;
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen rext.record_size = default_record_size;
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen rext.record_align = default_record_align;
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen array_append(&index->extensions, &rext, 1);
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen return ext_count;
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen}
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainenvoid mail_index_register_expunge_handler(struct mail_index *index,
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen uint32_t ext_id, bool call_always,
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen mail_index_expunge_handler_t *cb,
04b8a90af181cc4c7959266855e8ed50a22ed413Timo Sirainen void *context)
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen{
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainen struct mail_index_registered_ext *rext;
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen rext = array_idx_modifiable(&index->extensions, ext_id);
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen i_assert(rext->expunge_handler == NULL || rext->expunge_handler == cb);
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen rext->expunge_handler = cb;
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen rext->expunge_context = context;
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen rext->expunge_handler_call_always = call_always;
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen}
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainenvoid mail_index_unregister_expunge_handler(struct mail_index *index,
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainen uint32_t ext_id)
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainen{
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen struct mail_index_registered_ext *rext;
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen rext = array_idx_modifiable(&index->extensions, ext_id);
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen i_assert(rext->expunge_handler != NULL);
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen rext->expunge_handler = NULL;
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen}
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainenvoid mail_index_register_sync_handler(struct mail_index *index, uint32_t ext_id,
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen mail_index_sync_handler_t *cb,
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen enum mail_index_sync_handler_type type)
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen{
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen struct mail_index_registered_ext *rext;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen rext = array_idx_modifiable(&index->extensions, ext_id);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen i_assert(rext->sync_handler.callback == NULL);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen rext->sync_handler.callback = cb;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen rext->sync_handler.type = type;
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen}
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainenvoid mail_index_unregister_sync_handler(struct mail_index *index,
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen uint32_t ext_id)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen struct mail_index_registered_ext *rext;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen rext = array_idx_modifiable(&index->extensions, ext_id);
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen i_assert(rext->sync_handler.callback != NULL);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen rext->sync_handler.callback = NULL;
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen rext->sync_handler.type = 0;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen}
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_index_register_sync_lost_handler(struct mail_index *index,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_sync_lost_handler_t *cb)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen array_append(&index->sync_lost_handlers, &cb, 1);
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen}
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainenvoid mail_index_unregister_sync_lost_handler(struct mail_index *index,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_sync_lost_handler_t *cb)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen mail_index_sync_lost_handler_t *const *handlers;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen unsigned int i, count;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen handlers = array_get(&index->sync_lost_handlers, &count);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen for (i = 0; i < count; i++) {
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (handlers[i] == cb) {
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen array_delete(&index->sync_lost_handlers, i, 1);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen break;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen }
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen }
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen}
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainenbool mail_index_keyword_lookup(struct mail_index *index,
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen const char *keyword, bool autocreate,
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen unsigned int *idx_r)
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen{
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen char *keyword_dup;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen void *value;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen /* keywords_hash keeps a name => index mapping of keywords.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen Keywords are never removed from it, so the index values are valid
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen for the lifetime of the mail_index. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (hash_lookup_full(index->keywords_hash, keyword, NULL, &value)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *idx_r = POINTER_CAST_TO(value, unsigned int);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!autocreate) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *idx_r = (unsigned int)-1;
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen return FALSE;
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen }
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen keyword = keyword_dup = p_strdup(index->keywords_pool, keyword);
e192a3b1ca8ae857e7d87298ea507d32977ba570Timo Sirainen *idx_r = array_count(&index->keywords);
e192a3b1ca8ae857e7d87298ea507d32977ba570Timo Sirainen
e192a3b1ca8ae857e7d87298ea507d32977ba570Timo Sirainen hash_insert(index->keywords_hash, keyword_dup, POINTER_CAST(*idx_r));
811f2e26d9782d9cb99fdf82e18ffa0a77564fe2Timo Sirainen array_append(&index->keywords, &keyword, 1);
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen return TRUE;
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen}
c4877db8b6559846f4b58be8e42422dc734c193fTimo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainenint mail_index_map_parse_keywords(struct mail_index_map *map)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen struct mail_index *index = map->index;
8b9342aa96b2f297e23afb261f9f7dd859800952Timo Sirainen const struct mail_index_ext *ext;
8b9342aa96b2f297e23afb261f9f7dd859800952Timo Sirainen const struct mail_index_keyword_header *kw_hdr;
8b9342aa96b2f297e23afb261f9f7dd859800952Timo Sirainen const struct mail_index_keyword_header_rec *kw_rec;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *name;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int i, name_area_end_offset, old_count;
37e6cf44d61a81c6839e3ab76234b54309d8d292Timo Sirainen uint32_t ext_id;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen map->keywords_read = TRUE;
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ext_id = mail_index_map_lookup_ext(map, "keywords");
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (ext_id == (uint32_t)-1) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (array_is_created(&map->keyword_idx_map))
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen array_clear(&map->keyword_idx_map);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ext = array_idx(&map->extensions, ext_id);
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen /* Extension header contains:
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen - struct mail_index_keyword_header
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen - struct mail_index_keyword_header_rec * keywords_count
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - const char names[] * keywords_count
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(ext->hdr_offset < map->hdr.header_size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen kw_hdr = CONST_PTR_OFFSET(map->hdr_base, ext->hdr_offset);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen kw_rec = (const void *)(kw_hdr + 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen name = (const char *)(kw_rec + kw_hdr->keywords_count);
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen old_count = !array_is_created(&map->keyword_idx_map) ? 0 :
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen array_count(&map->keyword_idx_map);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen /* Keywords can only be added into same mapping. Removing requires a
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen new mapping (recreating the index file) */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (kw_hdr->keywords_count == old_count) {
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen /* nothing changed */
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen return 0;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen }
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen /* make sure the header is valid */
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen if (kw_hdr->keywords_count < old_count) {
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen "Keywords removed unexpectedly",
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen index->filepath);
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen return -1;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen }
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen if ((size_t)(name - (const char *)kw_hdr) > ext->hdr_size) {
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen "keywords_count larger than header size",
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen index->filepath);
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen return -1;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen }
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen name_area_end_offset = (const char *)kw_hdr + ext->hdr_size - name;
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen for (i = 0; i < kw_hdr->keywords_count; i++) {
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen if (kw_rec[i].name_offset > name_area_end_offset) {
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen "name_offset points outside allocated header",
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen index->filepath);
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen return -1;
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen }
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen }
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen if (name[name_area_end_offset-1] != '\0') {
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen "Keyword header doesn't end with NUL",
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen index->filepath);
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen return -1;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen }
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen /* create file -> index mapping */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!array_is_created(&map->keyword_idx_map))
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen i_array_init(&map->keyword_idx_map, kw_hdr->keywords_count);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen#ifdef DEBUG
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* Check that existing headers are still the same. It's behind DEBUG
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen since it's pretty useless waste of CPU normally. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (i = 0; i < array_count(&map->keyword_idx_map); i++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *keyword = name + kw_rec[i].name_offset;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const unsigned int *old_idx;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen unsigned int idx;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen old_idx = array_idx(&map->keyword_idx_map, i);
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen if (!mail_index_keyword_lookup(index, keyword, FALSE, &idx) ||
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen idx != *old_idx) {
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen "Keywords changed unexpectedly",
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen index->filepath);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#endif
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* Register the newly seen keywords */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i = array_count(&map->keyword_idx_map);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen for (; i < kw_hdr->keywords_count; i++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *keyword = name + kw_rec[i].name_offset;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int idx;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (void)mail_index_keyword_lookup(index, keyword, TRUE, &idx);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen array_append(&map->keyword_idx_map, &idx, 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainenconst ARRAY_TYPE(keywords) *mail_index_get_keywords(struct mail_index *index)
f519e4c2ad4ef826f1b08f3e0138b9b287a52c80Timo Sirainen{
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen /* Make sure all the keywords are in index->keywords. It's quick to do
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen if nothing has changed. */
d565eaa943f29a49b97230ced57eec40ee65b4f9Timo Sirainen (void)mail_index_map_parse_keywords(index->map);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return &index->keywords;
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen}
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mail_index_try_open_only(struct mail_index *index)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen i_assert(index->fd == -1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(!MAIL_INDEX_IS_IN_MEMORY(index));
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen /* Note that our caller must close index->fd by itself. */
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen index->fd = nfs_safe_open(index->filepath, O_RDWR);
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen index->readonly = FALSE;
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen if (index->fd == -1 && errno == EACCES) {
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen index->fd = open(index->filepath, O_RDONLY);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index->readonly = TRUE;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen }
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (index->fd == -1) {
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (errno != ENOENT)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return mail_index_set_syscall_error(index, "open()");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* have to create it */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen return 1;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic int
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenmail_index_try_open(struct mail_index *index)
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen{
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen int ret;
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen i_assert(index->fd == -1);
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen if (MAIL_INDEX_IS_IN_MEMORY(index))
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen return 0;
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen i_assert(index->map == NULL || index->map->lock_id == 0);
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen ret = mail_index_map(index, MAIL_INDEX_SYNC_HANDLER_HEAD);
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen if (ret == 0) {
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen /* it's corrupted - recreate it */
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen if (index->fd != -1) {
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen if (close(index->fd) < 0)
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen mail_index_set_syscall_error(index, "close()");
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen index->fd = -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen return ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mail_index_create_tmp_file(struct mail_index *index, const char **path_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mode_t old_mask;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *path;
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen int fd;
a835194f9a9dae88528367a791cbc282589f6c01Timo Sirainen
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen i_assert(!MAIL_INDEX_IS_IN_MEMORY(index));
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen path = *path_r = t_strconcat(index->filepath, ".tmp", NULL);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen old_mask = umask(0);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fd = open(path, O_RDWR|O_CREAT|O_TRUNC, index->mode);
8887bf3757d51d73887dd20b1db3334d867d3817Timo Sirainen umask(old_mask);
8da095519878426b012058e6f331a669f327f47fTimo Sirainen if (fd == -1)
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen return mail_index_file_set_syscall_error(index, path, "open()");
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen if (index->gid != (gid_t)-1 && fchown(fd, (uid_t)-1, index->gid) < 0) {
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen mail_index_file_set_syscall_error(index, path, "fchown()");
ce19e80b5a907d51a7cdf081e09699af8367dbfaTimo Sirainen return -1;
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen }
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return fd;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen}
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenstatic bool mail_index_open_files(struct mail_index *index,
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen enum mail_index_open_flags flags)
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen{
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen int ret;
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen bool created = FALSE;
9315dd69233d554452df0c12bc57002d2042a8f4Timo Sirainen
9315dd69233d554452df0c12bc57002d2042a8f4Timo Sirainen ret = mail_transaction_log_open(index->log);
69bd816e46fdee6182d0cb2e4c6be32399a555c8Timo Sirainen if (ret == 0) {
69bd816e46fdee6182d0cb2e4c6be32399a555c8Timo Sirainen if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) == 0)
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen return FALSE;
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen /* if dovecot.index exists, read it first so that we can get
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen the correct indexid and log sequence */
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen (void)mail_index_try_open(index);
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (index->indexid == 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* create a new indexid for us */
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen index->indexid = ioloop_time;
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen }
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen ret = mail_transaction_log_create(index->log);
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen created = TRUE;
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen }
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen if (ret >= 0) {
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen ret = index->map != NULL ? 0 : mail_index_try_open(index);
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen if (ret == 0) {
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen /* doesn't exist / corrupted */
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen index->map = mail_index_map_alloc(index);
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen }
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen }
5196f9ea42d02000f9c3d22f20aa816140af4422Timo Sirainen if (ret < 0) {
5196f9ea42d02000f9c3d22f20aa816140af4422Timo Sirainen /* open/create failed, fallback to in-memory indexes */
5196f9ea42d02000f9c3d22f20aa816140af4422Timo Sirainen if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) == 0)
5196f9ea42d02000f9c3d22f20aa816140af4422Timo Sirainen return FALSE;
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen if (mail_index_move_to_memory(index) < 0)
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen return FALSE;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen index->cache = created ? mail_cache_create(index) :
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen mail_cache_open_or_create(index);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen return TRUE;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen}
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainenint mail_index_open(struct mail_index *index, enum mail_index_open_flags flags,
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen enum file_lock_method lock_method)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen{
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen int i = 0, ret = 1;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen if (index->opened) {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen if (index->map != NULL &&
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen (index->map->hdr.flags &
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen MAIL_INDEX_HDR_FLAG_CORRUPTED) != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* corrupted, reopen files */
ba00293b85c7fb4e7a2d100991c716e17b9daaaeTimo Sirainen mail_index_close(index);
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen } else {
0cea9b1f4fa0495a48f5f097e40492517d67e1baTimo Sirainen i_assert(index->map != NULL);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return 1;
0cea9b1f4fa0495a48f5f097e40492517d67e1baTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index->filepath = MAIL_INDEX_IS_IN_MEMORY(index) ?
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_strdup("(in-memory index)") :
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen i_strconcat(index->dir, "/", index->prefix, NULL);
2af769daebd83719ac696a440e06f6020471cec0Timo Sirainen
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen for (;;) {
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen index->shared_lock_count = 0;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen index->excl_lock_count = 0;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen index->lock_type = F_UNLCK;
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen index->lock_id_counter = 2;
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen
cc833a7a4e2258afdc834ace4bfe6579820a1df3Timo Sirainen index->readonly = FALSE;
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen index->nodiskspace = FALSE;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen index->index_lock_timeout = FALSE;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen index->log_locked = FALSE;
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen index->mmap_disable =
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen (flags & MAIL_INDEX_OPEN_FLAG_MMAP_DISABLE) != 0;
5bdad39213d28ab35e615a7f4ea1712ab25b6a80Timo Sirainen index->use_excl_dotlocks =
5bdad39213d28ab35e615a7f4ea1712ab25b6a80Timo Sirainen (flags & MAIL_INDEX_OPEN_FLAG_DOTLOCK_USE_EXCL) != 0;
5bdad39213d28ab35e615a7f4ea1712ab25b6a80Timo Sirainen index->fsync_disable =
5bdad39213d28ab35e615a7f4ea1712ab25b6a80Timo Sirainen (flags & MAIL_INDEX_OPEN_FLAG_FSYNC_DISABLE) != 0;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen index->nfs_flush =
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen (flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0;
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen index->lock_method = lock_method;
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen if (index->nfs_flush && index->fsync_disable) {
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen i_warning("nfs_flush_cache=yes requires "
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen "fsync_disable=no, changing it");
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen index->fsync_disable = FALSE;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen }
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen if (index->nfs_flush && !index->mmap_disable) {
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen i_warning("nfs_flush_cache=yes requires "
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen "mmap_disable=yes, changing it");
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen index->mmap_disable = TRUE;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen }
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen i_assert(!index->opened);
2af769daebd83719ac696a440e06f6020471cec0Timo Sirainen if (!mail_index_open_files(index, flags)) {
2af769daebd83719ac696a440e06f6020471cec0Timo Sirainen /* doesn't exist and create flag not used */
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen ret = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen i_assert(index->map != NULL);
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen index->opened = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (index->fsck) {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen index->fsck = FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = mail_index_fsck(index);
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen if (ret == 0) {
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen /* completely broken, reopen */
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen if (i++ < 3) {
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen mail_index_close(index);
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen continue;
ba482d3624ca4f1b3d638e6e8470ba5134f21493Timo Sirainen }
ba482d3624ca4f1b3d638e6e8470ba5134f21493Timo Sirainen /* too many tries */
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen ret = -1;
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen }
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen }
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen break;
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen }
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (ret <= 0)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen mail_index_close(index);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen i_assert(ret <= 0 || index->map != NULL);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen return ret;
cf3bea6d9b57f8608bec22d98ad547a507b05f66Timo Sirainen}
cf3bea6d9b57f8608bec22d98ad547a507b05f66Timo Sirainen
cf3bea6d9b57f8608bec22d98ad547a507b05f66Timo Sirainenstatic void mail_index_close_file(struct mail_index *index)
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen{
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen if (index->file_lock != NULL)
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen file_lock_free(&index->file_lock);
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen if (index->fd != -1) {
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen if (close(index->fd) < 0)
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen mail_index_set_syscall_error(index, "close()");
cf3bea6d9b57f8608bec22d98ad547a507b05f66Timo Sirainen index->fd = -1;
e6e43b396799aa5704c679a3017d6c7195f9347dTimo Sirainen }
cf3bea6d9b57f8608bec22d98ad547a507b05f66Timo Sirainen
cf3bea6d9b57f8608bec22d98ad547a507b05f66Timo Sirainen if (index->lock_type == F_RDLCK)
cf3bea6d9b57f8608bec22d98ad547a507b05f66Timo Sirainen index->lock_type = F_UNLCK;
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen index->lock_id_counter += 2;
2af769daebd83719ac696a440e06f6020471cec0Timo Sirainen index->shared_lock_count = 0;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen}
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainenvoid mail_index_close(struct mail_index *index)
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen{
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen if (index->map != NULL)
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen mail_index_unmap(&index->map);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_close_file(index);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen mail_transaction_log_close(index->log);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (index->cache != NULL)
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen mail_cache_free(&index->cache);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_free_and_null(index->filepath);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen index->indexid = 0;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen index->opened = FALSE;
114a0f74e0f825c6bd8aeadfafb248a030762a1fTimo Sirainen}
114a0f74e0f825c6bd8aeadfafb248a030762a1fTimo Sirainen
114a0f74e0f825c6bd8aeadfafb248a030762a1fTimo Sirainenint mail_index_reopen_if_changed(struct mail_index *index)
114a0f74e0f825c6bd8aeadfafb248a030762a1fTimo Sirainen{
7981779f9aebd25728d3c26555d598ff842cf2e2Timo Sirainen struct stat st1, st2;
7981779f9aebd25728d3c26555d598ff842cf2e2Timo Sirainen
7981779f9aebd25728d3c26555d598ff842cf2e2Timo Sirainen i_assert(index->excl_lock_count == 0);
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen if (MAIL_INDEX_IS_IN_MEMORY(index))
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen return 0;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (index->fd == -1)
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen return mail_index_try_open_only(index);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (fstat(index->fd, &st1) < 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (errno != ESTALE)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return mail_index_set_syscall_error(index, "fstat()");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* deleted/recreated, reopen */
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return mail_index_try_open_only(index);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (index->nfs_flush)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen nfs_flush_attr_cache(index->filepath);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if (nfs_safe_stat(index->filepath, &st2) < 0) {
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if (errno == ENOENT)
1a21e7049796c98d6d998fcf7a438d7a97193dc4Timo Sirainen return 0;
1a21e7049796c98d6d998fcf7a438d7a97193dc4Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return mail_index_set_syscall_error(index, "stat()");
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (st1.st_ino == st2.st_ino && CMP_DEV_T(st1.st_dev, st2.st_dev)) {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen /* the same file */
1a21e7049796c98d6d998fcf7a438d7a97193dc4Timo Sirainen return 1;
1a21e7049796c98d6d998fcf7a438d7a97193dc4Timo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
1a21e7049796c98d6d998fcf7a438d7a97193dc4Timo Sirainen /* new file, new locks. the old fd can keep its locks, they don't
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen matter anymore as no-one's going to modify the file. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_close_file(index);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen return mail_index_try_open_only(index);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainenint mail_index_refresh(struct mail_index *index)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen{
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen int ret;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen if (MAIL_INDEX_IS_IN_MEMORY(index))
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen return 0;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (index->excl_lock_count > 0) {
62cfc346eb7b0a4fd9e1ab6edd63b98711161229Timo Sirainen /* we have index exclusively locked, nothing could
62cfc346eb7b0a4fd9e1ab6edd63b98711161229Timo Sirainen have changed. */
62cfc346eb7b0a4fd9e1ab6edd63b98711161229Timo Sirainen return 0;
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen }
62cfc346eb7b0a4fd9e1ab6edd63b98711161229Timo Sirainen
62cfc346eb7b0a4fd9e1ab6edd63b98711161229Timo Sirainen ret = mail_index_map(index, MAIL_INDEX_SYNC_HANDLER_HEAD);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return ret <= 0 ? -1 : 0;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen}
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainenstruct mail_cache *mail_index_get_cache(struct mail_index *index)
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen{
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen return index->cache;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen}
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenint mail_index_set_error(struct mail_index *index, const char *fmt, ...)
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen{
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen va_list va;
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen i_free(index->error);
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen if (fmt == NULL)
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen index->error = NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen va_start(va, fmt);
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen index->error = i_strdup_vprintf(fmt, va);
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen va_end(va);
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen i_error("%s", index->error);
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen }
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen return -1;
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen}
9566c1b4506d49778659e3dc65997f3c0399cb7eTimo Sirainen
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainenint mail_index_move_to_memory(struct mail_index *index)
9566c1b4506d49778659e3dc65997f3c0399cb7eTimo Sirainen{
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen struct mail_index_map *map;
9566c1b4506d49778659e3dc65997f3c0399cb7eTimo Sirainen
9566c1b4506d49778659e3dc65997f3c0399cb7eTimo Sirainen if (MAIL_INDEX_IS_IN_MEMORY(index))
9566c1b4506d49778659e3dc65997f3c0399cb7eTimo Sirainen return index->map == NULL ? -1 : 0;
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen /* set the index as being into memory */
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen i_free_and_null(index->dir);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_free(index->filepath);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index->filepath = i_strdup("(in-memory index)");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (index->map == NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* index was never even opened. just mark it as being in
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen memory and let the caller re-open the index. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(index->fd == -1);
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen return -1;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen /* move index map to memory */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!MAIL_INDEX_MAP_IS_IN_MEMORY(index->map)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen map = mail_index_map_clone(index->map);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_unmap(&index->map);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index->map = map;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
6f73af3a3a6ee900c7e736874587968d76a20bc0Timo Sirainen
6f73af3a3a6ee900c7e736874587968d76a20bc0Timo Sirainen if (index->log != NULL) {
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen /* move transaction log to memory */
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen mail_transaction_log_move_to_memory(index->log);
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen }
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen
0f66f12eb4cdbf47670975044c88d8f388bf92dfTimo Sirainen if (index->file_lock != NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen file_lock_free(&index->file_lock);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen /* close the index file. */
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen if (close(index->fd) < 0)
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen mail_index_set_syscall_error(index, "close()");
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen index->fd = -1;
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen return 0;
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen}
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainenvoid mail_index_mark_corrupted(struct mail_index *index)
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen{
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen index->indexid = 0;
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen index->map->hdr.flags |= MAIL_INDEX_HDR_FLAG_CORRUPTED;
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen if (unlink(index->filepath) < 0 && errno != ENOENT && errno != ESTALE)
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen mail_index_set_syscall_error(index, "unlink()");
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen}
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainenint mail_index_set_syscall_error(struct mail_index *index,
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen const char *function)
{
i_assert(function != NULL);
if (ENOSPACE(errno)) {
index->nodiskspace = TRUE;
return -1;
}
return mail_index_set_error(index, "%s failed with index file %s: %m",
function, index->filepath);
}
int mail_index_file_set_syscall_error(struct mail_index *index,
const char *filepath,
const char *function)
{
i_assert(filepath != NULL);
i_assert(function != NULL);
if (ENOSPACE(errno)) {
index->nodiskspace = TRUE;
return -1;
}
return mail_index_set_error(index, "%s failed with file %s: %m",
function, filepath);
}
const char *mail_index_get_error_message(struct mail_index *index)
{
return index->error;
}
void mail_index_reset_error(struct mail_index *index)
{
if (index->error != NULL) {
i_free(index->error);
index->error = NULL;
}
index->nodiskspace = FALSE;
index->index_lock_timeout = FALSE;
}
#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. */
uint32_t mail_index_uint32_to_offset(uint32_t offset)
{
i_assert(offset < 0x40000000);
i_assert((offset & 3) == 0);
offset >>= 2;
return 0x00000080 | ((offset & 0x0000007f)) |
0x00008000 | ((offset & 0x00003f80) >> 7 << 8) |
0x00800000 | ((offset & 0x001fc000) >> 14 << 16) |
0x80000000 | ((offset & 0x0fe00000) >> 21 << 24);
}
uint32_t mail_index_offset_to_uint32(uint32_t offset)
{
if ((offset & 0x80808080) != 0x80808080)
return 0;
return (((offset & 0x0000007f)) |
((offset & 0x00007f00) >> 8 << 7) |
((offset & 0x007f0000) >> 16 << 14) |
((offset & 0x7f000000) >> 24 << 21)) << 2;
}
#else
uint32_t mail_index_uint32_to_offset(uint32_t offset)
{
i_assert(offset < 0x40000000);
i_assert((offset & 3) == 0);
offset >>= 2;
return 0x80000000 | ((offset & 0x0000007f) << 24) |
0x00800000 | ((offset & 0x00003f80) >> 7 << 16) |
0x00008000 | ((offset & 0x001fc000) >> 14 << 8) |
0x00000080 | ((offset & 0x0fe00000) >> 21);
}
uint32_t mail_index_offset_to_uint32(uint32_t offset)
{
if ((offset & 0x80808080) != 0x80808080)
return 0;
return (((offset & 0x0000007f) << 21) |
((offset & 0x00007f00) >> 8 << 14) |
((offset & 0x007f0000) >> 16 << 7) |
((offset & 0x7f000000) >> 24)) << 2;
}
#endif