mail-index.c revision ffd9a1898a18fadfc5dce399162c25d50548f905
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen#include "ioloop.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "array.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "buffer.h"
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen#include "hash.h"
ffd9a1898a18fadfc5dce399162c25d50548f905Timo Sirainen#include "str-sanitize.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mmap-util.h"
89b548af722113acb5d63dfffb44423cb60f91e4Timo Sirainen#include "nfs-workarounds.h"
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen#include "read-full.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "write-full.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-index-private.h"
66ae183b6e895216037bd921367670f4b0665911Timo Sirainen#include "mail-index-view-private.h"
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen#include "mail-index-sync-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-transaction-log.h"
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen#include "mail-cache.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <stdio.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <stddef.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <time.h>
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen#include <sys/stat.h>
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen
46c31f64b9f0949f00b7819f45b22f2d64b2ea27Timo Sirainenstruct mail_index_module_register mail_index_module_register = { 0 };
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo 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;
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen
8fa41238067c854435884c459963fde6f8c6436bTimo Sirainen index->extension_pool =
8fa41238067c854435884c459963fde6f8c6436bTimo Sirainen pool_alloconly_create(MEMPOOL_GROWING"index extension", 1024);
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen p_array_init(&index->extensions, index->extension_pool, 5);
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen i_array_init(&index->sync_lost_handlers, 4);
46c31f64b9f0949f00b7819f45b22f2d64b2ea27Timo Sirainen i_array_init(&index->module_contexts,
46c31f64b9f0949f00b7819f45b22f2d64b2ea27Timo Sirainen I_MIN(5, mail_index_module_register.id));
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index->mode = 0600;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index->gid = (gid_t)-1;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen index->keywords_ext_id =
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen mail_index_ext_register(index, "keywords", 128, 2, 1);
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen index->keywords_pool = pool_alloconly_create("keywords", 512);
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen i_array_init(&index->keywords, 16);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen index->keywords_hash =
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen hash_create(default_pool, index->keywords_pool, 0,
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen strcase_hash, (hash_cmp_callback_t *)strcasecmp);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen index->log = mail_transaction_log_alloc(index);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return index;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenvoid mail_index_free(struct mail_index **_index)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen struct mail_index *index = *_index;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen *_index = NULL;
ee246b46953e4b94b2f22e093373674fa9155500Timo Sirainen mail_index_close(index);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen mail_transaction_log_free(&index->log);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen hash_destroy(index->keywords_hash);
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen pool_unref(index->extension_pool);
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen pool_unref(index->keywords_pool);
ee246b46953e4b94b2f22e093373674fa9155500Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_free(&index->sync_lost_handlers);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen array_free(&index->keywords);
46c31f64b9f0949f00b7819f45b22f2d64b2ea27Timo Sirainen array_free(&index->module_contexts);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo 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}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainenvoid mail_index_set_permissions(struct mail_index *index,
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen mode_t mode, gid_t gid)
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen{
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen index->mode = mode & 0666;
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen index->gid = gid;
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen}
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainenuint32_t mail_index_ext_register(struct mail_index *index, const char *name,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen uint32_t default_hdr_size,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen uint16_t default_record_size,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen uint16_t default_record_align)
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen{
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen const struct mail_index_registered_ext *extensions;
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen struct mail_index_registered_ext rext;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen unsigned int i, ext_count;
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen
ffd9a1898a18fadfc5dce399162c25d50548f905Timo Sirainen if (strcmp(name, str_sanitize(name, -1)) != 0)
ffd9a1898a18fadfc5dce399162c25d50548f905Timo Sirainen i_panic("mail_index_ext_register(%s): Invalid name", name);
ffd9a1898a18fadfc5dce399162c25d50548f905Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen extensions = array_get(&index->extensions, &ext_count);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* see if it's already there */
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen for (i = 0; i < ext_count; i++) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (strcmp(extensions[i].name, name) == 0)
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen return i;
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen }
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen memset(&rext, 0, sizeof(rext));
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen rext.name = p_strdup(index->extension_pool, name);
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen rext.index_idx = ext_count;
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen rext.hdr_size = default_hdr_size;
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen rext.record_size = default_record_size;
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen rext.record_align = default_record_align;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen array_append(&index->extensions, &rext, 1);
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen return ext_count;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen}
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenvoid mail_index_register_expunge_handler(struct mail_index *index,
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen uint32_t ext_id, bool call_always,
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen mail_index_expunge_handler_t *cb,
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen void *context)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen{
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen struct mail_index_registered_ext *rext;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen rext = array_idx_modifiable(&index->extensions, ext_id);
7d7b5c98f086ffa8ac9c90f21db17748ca607202Timo Sirainen i_assert(rext->expunge_handler == NULL || rext->expunge_handler == cb);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen rext->expunge_handler = cb;
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen rext->expunge_context = context;
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen rext->expunge_handler_call_always = call_always;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen}
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainenvoid mail_index_unregister_expunge_handler(struct mail_index *index,
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen uint32_t ext_id)
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen{
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen struct mail_index_registered_ext *rext;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen rext = array_idx_modifiable(&index->extensions, ext_id);
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen i_assert(rext->expunge_handler != NULL);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen rext->expunge_handler = NULL;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen}
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenvoid mail_index_register_sync_handler(struct mail_index *index, uint32_t ext_id,
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen mail_index_sync_handler_t *cb,
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen enum mail_index_sync_handler_type type)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen{
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen struct mail_index_registered_ext *rext;
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen rext = array_idx_modifiable(&index->extensions, ext_id);
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen i_assert(rext->sync_handler.callback == NULL);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen rext->sync_handler.callback = cb;
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen rext->sync_handler.type = type;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen}
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainenvoid mail_index_unregister_sync_handler(struct mail_index *index,
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen uint32_t ext_id)
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen{
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen struct mail_index_registered_ext *rext;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen rext = array_idx_modifiable(&index->extensions, ext_id);
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen i_assert(rext->sync_handler.callback != NULL);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen rext->sync_handler.callback = NULL;
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen rext->sync_handler.type = 0;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen}
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainenvoid mail_index_register_sync_lost_handler(struct mail_index *index,
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen mail_index_sync_lost_handler_t *cb)
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen{
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_append(&index->sync_lost_handlers, &cb, 1);
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen}
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainenvoid mail_index_unregister_sync_lost_handler(struct mail_index *index,
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen mail_index_sync_lost_handler_t *cb)
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen{
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen mail_index_sync_lost_handler_t *const *handlers;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen unsigned int i, count;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen handlers = array_get(&index->sync_lost_handlers, &count);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen for (i = 0; i < count; i++) {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen if (handlers[i] == cb) {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen array_delete(&index->sync_lost_handlers, i, 1);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen break;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen }
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen }
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen}
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenbool mail_index_keyword_lookup(struct mail_index *index,
6825360d446542046757b06064282301c4c6b27cTimo Sirainen const char *keyword, unsigned int *idx_r)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen{
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen void *value;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen /* keywords_hash keeps a name => index mapping of keywords.
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen Keywords are never removed from it, so the index values are valid
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen for the lifetime of the mail_index. */
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (hash_lookup_full(index->keywords_hash, keyword, NULL, &value)) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen *idx_r = POINTER_CAST_TO(value, unsigned int);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen return TRUE;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen }
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
6825360d446542046757b06064282301c4c6b27cTimo Sirainen *idx_r = (unsigned int)-1;
6825360d446542046757b06064282301c4c6b27cTimo Sirainen return FALSE;
6825360d446542046757b06064282301c4c6b27cTimo Sirainen}
6825360d446542046757b06064282301c4c6b27cTimo Sirainen
6825360d446542046757b06064282301c4c6b27cTimo Sirainenvoid mail_index_keyword_lookup_or_create(struct mail_index *index,
6825360d446542046757b06064282301c4c6b27cTimo Sirainen const char *keyword,
6825360d446542046757b06064282301c4c6b27cTimo Sirainen unsigned int *idx_r)
6825360d446542046757b06064282301c4c6b27cTimo Sirainen{
6825360d446542046757b06064282301c4c6b27cTimo Sirainen char *keyword_dup;
6825360d446542046757b06064282301c4c6b27cTimo Sirainen
c8d093d149253fe8faec267c5057f45fe626f84cTimo Sirainen i_assert(*keyword != '\0');
c8d093d149253fe8faec267c5057f45fe626f84cTimo Sirainen
6825360d446542046757b06064282301c4c6b27cTimo Sirainen if (mail_index_keyword_lookup(index, keyword, idx_r))
6825360d446542046757b06064282301c4c6b27cTimo Sirainen return;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen keyword = keyword_dup = p_strdup(index->keywords_pool, keyword);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen *idx_r = array_count(&index->keywords);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen hash_insert(index->keywords_hash, keyword_dup, POINTER_CAST(*idx_r));
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen array_append(&index->keywords, &keyword, 1);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen}
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainenconst ARRAY_TYPE(keywords) *mail_index_get_keywords(struct mail_index *index)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen{
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen return &index->keywords;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen}
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainenint mail_index_try_open_only(struct mail_index *index)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen i_assert(index->fd == -1);
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen i_assert(!MAIL_INDEX_IS_IN_MEMORY(index));
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* Note that our caller must close index->fd by itself. */
89b548af722113acb5d63dfffb44423cb60f91e4Timo Sirainen index->fd = nfs_safe_open(index->filepath, O_RDWR);
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen index->readonly = FALSE;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen if (index->fd == -1 && errno == EACCES) {
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen index->fd = open(index->filepath, O_RDONLY);
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen index->readonly = TRUE;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen }
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen if (index->fd == -1) {
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen if (errno != ENOENT)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen return mail_index_set_syscall_error(index, "open()");
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen /* have to create it */
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen return 0;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen }
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen return 1;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen}
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainenstatic int
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenmail_index_try_open(struct mail_index *index)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen{
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen int ret;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen i_assert(index->fd == -1);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen if (MAIL_INDEX_IS_IN_MEMORY(index))
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen return 0;
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen i_assert(index->map == NULL || index->map->rec_map->lock_id == 0);
14c474d9f4591c397ed0b5206af6537c7b52c924Timo Sirainen ret = mail_index_map(index, MAIL_INDEX_SYNC_HANDLER_HEAD);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen if (ret == 0) {
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen /* it's corrupted - recreate it */
e3689d0f073341e844638f34e1e4d0b7bb053cc8Timo Sirainen if (index->fd != -1) {
e3689d0f073341e844638f34e1e4d0b7bb053cc8Timo Sirainen if (close(index->fd) < 0)
e3689d0f073341e844638f34e1e4d0b7bb053cc8Timo Sirainen mail_index_set_syscall_error(index, "close()");
e3689d0f073341e844638f34e1e4d0b7bb053cc8Timo Sirainen index->fd = -1;
e3689d0f073341e844638f34e1e4d0b7bb053cc8Timo Sirainen }
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen }
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen return ret;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen}
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mail_index_create_tmp_file(struct mail_index *index, const char **path_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
d22390f33eedbd2413debabc0662dde5241b1aa6Timo Sirainen mode_t old_mask;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *path;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int fd;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen i_assert(!MAIL_INDEX_IS_IN_MEMORY(index));
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen path = *path_r = t_strconcat(index->filepath, ".tmp", NULL);
d22390f33eedbd2413debabc0662dde5241b1aa6Timo Sirainen old_mask = umask(0);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fd = open(path, O_RDWR|O_CREAT|O_TRUNC, index->mode);
d22390f33eedbd2413debabc0662dde5241b1aa6Timo Sirainen umask(old_mask);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (fd == -1)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return mail_index_file_set_syscall_error(index, path, "open()");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
d22390f33eedbd2413debabc0662dde5241b1aa6Timo Sirainen if (index->gid != (gid_t)-1 && fchown(fd, (uid_t)-1, index->gid) < 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_file_set_syscall_error(index, path, "fchown()");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return fd;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainenstatic int mail_index_open_files(struct mail_index *index,
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen enum mail_index_open_flags flags)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int ret;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen bool created = FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen ret = mail_transaction_log_open(index->log);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ret == 0) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) == 0)
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen return 0;
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen /* if dovecot.index exists, read it first so that we can get
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen the correct indexid and log sequence */
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen (void)mail_index_try_open(index);
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen if (index->indexid == 0) {
af1e2b2ab5d1c5ca5afe482ef8c8161c17acc190Timo Sirainen /* Create a new indexid for us. If we're opening index
af1e2b2ab5d1c5ca5afe482ef8c8161c17acc190Timo Sirainen into memory, index->map doesn't exist yet. */
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen index->indexid = ioloop_time;
af1e2b2ab5d1c5ca5afe482ef8c8161c17acc190Timo Sirainen if (index->map != NULL)
af1e2b2ab5d1c5ca5afe482ef8c8161c17acc190Timo Sirainen index->map->hdr.indexid = index->indexid;
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen }
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen ret = mail_transaction_log_create(index->log);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen created = TRUE;
95a284736b8b11319a3f575ba249ba2eb7dbac1bTimo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (ret >= 0) {
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen ret = index->map != NULL ? 0 : mail_index_try_open(index);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (ret == 0) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* doesn't exist / corrupted */
0b49cfeae91a4020a404714b11c99e8e955fb631Timo Sirainen mail_transaction_log_close(index->log);
0b49cfeae91a4020a404714b11c99e8e955fb631Timo Sirainen ret = mail_transaction_log_create(index->log);
af1e2b2ab5d1c5ca5afe482ef8c8161c17acc190Timo Sirainen if (ret == 0) {
af1e2b2ab5d1c5ca5afe482ef8c8161c17acc190Timo Sirainen if (index->map != NULL)
af1e2b2ab5d1c5ca5afe482ef8c8161c17acc190Timo Sirainen mail_index_unmap(&index->map);
0b49cfeae91a4020a404714b11c99e8e955fb631Timo Sirainen index->map = mail_index_map_alloc(index);
af1e2b2ab5d1c5ca5afe482ef8c8161c17acc190Timo Sirainen }
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen }
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (ret < 0) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* open/create failed, fallback to in-memory indexes */
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) == 0)
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen return -1;
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (mail_index_move_to_memory(index) < 0)
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen return -1;
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen }
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen index->cache = created ? mail_cache_create(index) :
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen mail_cache_open_or_create(index);
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen return 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
a53cb86b4d733d9c48ee4d285bed477c80825804Timo Sirainenint mail_index_open(struct mail_index *index, enum mail_index_open_flags flags,
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen enum file_lock_method lock_method)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen int ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0c27b881989bc2b391281650ee89a8cc4d89f5e7Timo Sirainen if (index->opened) {
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen if (index->map != NULL &&
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen (index->map->hdr.flags &
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen MAIL_INDEX_HDR_FLAG_CORRUPTED) != 0) {
0c27b881989bc2b391281650ee89a8cc4d89f5e7Timo Sirainen /* corrupted, reopen files */
0c27b881989bc2b391281650ee89a8cc4d89f5e7Timo Sirainen mail_index_close(index);
0c27b881989bc2b391281650ee89a8cc4d89f5e7Timo Sirainen } else {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen i_assert(index->map != NULL);
99e8698f598d2b83da7c581584a538c0713fd11dTimo Sirainen return 1;
0c27b881989bc2b391281650ee89a8cc4d89f5e7Timo Sirainen }
0c27b881989bc2b391281650ee89a8cc4d89f5e7Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen index->filepath = MAIL_INDEX_IS_IN_MEMORY(index) ?
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen i_strdup("(in-memory index)") :
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen i_strconcat(index->dir, "/", index->prefix, NULL);
ee246b46953e4b94b2f22e093373674fa9155500Timo Sirainen
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen index->shared_lock_count = 0;
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen index->excl_lock_count = 0;
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen index->lock_type = F_UNLCK;
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen index->lock_id_counter = 2;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen index->readonly = FALSE;
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen index->nodiskspace = FALSE;
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen index->index_lock_timeout = FALSE;
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen index->log_locked = FALSE;
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen index->mmap_disable = (flags & MAIL_INDEX_OPEN_FLAG_MMAP_DISABLE) != 0;
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen index->use_excl_dotlocks =
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen (flags & MAIL_INDEX_OPEN_FLAG_DOTLOCK_USE_EXCL) != 0;
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen index->fsync_disable =
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen (flags & MAIL_INDEX_OPEN_FLAG_FSYNC_DISABLE) != 0;
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen index->nfs_flush = (flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0;
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen index->lock_method = lock_method;
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen if (index->nfs_flush && index->fsync_disable)
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen i_fatal("nfs flush requires fsync_disable=no");
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen if (index->nfs_flush && !index->mmap_disable)
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen i_fatal("nfs flush requires mmap_disable=yes");
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen if ((ret = mail_index_open_files(index, flags)) <= 0) {
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen /* doesn't exist and create flag not used */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_close(index);
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen return ret;
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen i_assert(index->map != NULL);
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen index->opened = TRUE;
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen return 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic void mail_index_close_file(struct mail_index *index)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen if (index->file_lock != NULL)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen file_lock_free(&index->file_lock);
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (index->fd != -1) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (close(index->fd) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_set_syscall_error(index, "close()");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index->fd = -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
14c474d9f4591c397ed0b5206af6537c7b52c924Timo Sirainen index->lock_id_counter += 2;
e670e1783fe4541dc3fc6109a181d45b0a9c2635Timo Sirainen index->lock_type = F_UNLCK;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen index->shared_lock_count = 0;
e670e1783fe4541dc3fc6109a181d45b0a9c2635Timo Sirainen index->excl_lock_count = 0;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenvoid mail_index_close(struct mail_index *index)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
90c5979b3c530707744beab6413f9d1e446335d1Timo Sirainen if (index->map != NULL)
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainen mail_index_unmap(&index->map);
90c5979b3c530707744beab6413f9d1e446335d1Timo Sirainen
90c5979b3c530707744beab6413f9d1e446335d1Timo Sirainen mail_index_close_file(index);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen mail_transaction_log_close(index->log);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (index->cache != NULL)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen mail_cache_free(&index->cache);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen i_free_and_null(index->filepath);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen index->indexid = 0;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen index->opened = FALSE;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen}
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenint mail_index_reopen_if_changed(struct mail_index *index)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen{
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen struct stat st1, st2;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen i_assert(index->excl_lock_count == 0);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen if (MAIL_INDEX_IS_IN_MEMORY(index))
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen return 0;
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (index->fd == -1)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return mail_index_try_open_only(index);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen if (fstat(index->fd, &st1) < 0) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (errno != ESTALE)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return mail_index_set_syscall_error(index, "fstat()");
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* deleted/recreated, reopen */
eb77c0a041648af50abc027811f6b7951c3a80cdTimo Sirainen mail_index_close_file(index);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return mail_index_try_open_only(index);
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen }
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen if (index->nfs_flush)
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen nfs_flush_attr_cache(index->filepath);
6143fece58262865ce89b5012b73ef08f2ad6abcTimo Sirainen if (nfs_safe_stat(index->filepath, &st2) < 0) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (errno == ENOENT)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return 0;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return mail_index_set_syscall_error(index, "stat()");
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen }
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (st1.st_ino == st2.st_ino && CMP_DEV_T(st1.st_dev, st2.st_dev)) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* the same file */
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen return 1;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* new file, new locks. the old fd can keep its locks, they don't
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen matter anymore as no-one's going to modify the file. */
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen mail_index_close_file(index);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return mail_index_try_open_only(index);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen}
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainenint mail_index_refresh(struct mail_index *index)
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen{
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen int ret;
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen if (MAIL_INDEX_IS_IN_MEMORY(index))
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen return 0;
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen if (index->excl_lock_count > 0) {
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen /* we have index exclusively locked, nothing could
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen have changed. */
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen return 0;
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen }
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen
14c474d9f4591c397ed0b5206af6537c7b52c924Timo Sirainen ret = mail_index_map(index, MAIL_INDEX_SYNC_HANDLER_HEAD);
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen return ret <= 0 ? -1 : 0;
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen}
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct mail_cache *mail_index_get_cache(struct mail_index *index)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return index->cache;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mail_index_set_error(struct mail_index *index, const char *fmt, ...)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen va_list va;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_free(index->error);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (fmt == NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index->error = NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen va_start(va, fmt);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index->error = i_strdup_vprintf(fmt, va);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen va_end(va);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_error("%s", index->error);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainenint mail_index_move_to_memory(struct mail_index *index)
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen{
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen struct mail_index_map *map;
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen
c61d52810496376a2ea60b8f4e27bbcaa8754f3fTimo Sirainen if (MAIL_INDEX_IS_IN_MEMORY(index))
2469ed8e17534f6cb5f41493df8c7e6f3b2c9b61Timo Sirainen return index->map == NULL ? -1 : 0;
c61d52810496376a2ea60b8f4e27bbcaa8754f3fTimo Sirainen
f4e0148e539c6dd4e12b8305ab0dd5e63c46ba67Timo Sirainen /* set the index as being into memory */
f4e0148e539c6dd4e12b8305ab0dd5e63c46ba67Timo Sirainen i_free_and_null(index->dir);
f4e0148e539c6dd4e12b8305ab0dd5e63c46ba67Timo Sirainen
2bd96c58be42146cb84076331604cadb2994fce5Timo Sirainen i_free(index->filepath);
2bd96c58be42146cb84076331604cadb2994fce5Timo Sirainen index->filepath = i_strdup("(in-memory index)");
2bd96c58be42146cb84076331604cadb2994fce5Timo Sirainen
5cc772dc8b507be0bc1996b5717943ba13432e08Timo Sirainen if (index->map == NULL) {
27db4ce5fe399c981e09dcf9e885a1546afd34f4Timo Sirainen /* index was never even opened. just mark it as being in
5cc772dc8b507be0bc1996b5717943ba13432e08Timo Sirainen memory and let the caller re-open the index. */
5cc772dc8b507be0bc1996b5717943ba13432e08Timo Sirainen i_assert(index->fd == -1);
5cc772dc8b507be0bc1996b5717943ba13432e08Timo Sirainen return -1;
5cc772dc8b507be0bc1996b5717943ba13432e08Timo Sirainen }
5cc772dc8b507be0bc1996b5717943ba13432e08Timo Sirainen
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen /* move index map to memory */
ccffbed92cb02c24fd717808a84138240bf1885bTimo Sirainen if (!MAIL_INDEX_MAP_IS_IN_MEMORY(index->map)) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen map = mail_index_map_clone(index->map);
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainen mail_index_unmap(&index->map);
ccffbed92cb02c24fd717808a84138240bf1885bTimo Sirainen index->map = map;
ccffbed92cb02c24fd717808a84138240bf1885bTimo Sirainen }
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen
ae14dfd895881f9d1c6899b0c09f1a8b51447d61Timo Sirainen if (index->log != NULL) {
ae14dfd895881f9d1c6899b0c09f1a8b51447d61Timo Sirainen /* move transaction log to memory */
902222fb0928d1701f20a384b73f327b1d9a15ddTimo Sirainen mail_transaction_log_move_to_memory(index->log);
ae14dfd895881f9d1c6899b0c09f1a8b51447d61Timo Sirainen }
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen if (index->file_lock != NULL)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen file_lock_free(&index->file_lock);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
31189eeac1ccaaf1201c60427f8c1087b0f5dfceTimo Sirainen if (index->fd != -1) {
31189eeac1ccaaf1201c60427f8c1087b0f5dfceTimo Sirainen if (close(index->fd) < 0)
31189eeac1ccaaf1201c60427f8c1087b0f5dfceTimo Sirainen mail_index_set_syscall_error(index, "close()");
31189eeac1ccaaf1201c60427f8c1087b0f5dfceTimo Sirainen index->fd = -1;
31189eeac1ccaaf1201c60427f8c1087b0f5dfceTimo Sirainen }
902222fb0928d1701f20a384b73f327b1d9a15ddTimo Sirainen return 0;
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen}
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen
87712707722ef7d73acb065546e61afa4455cd9eTimo Sirainenvoid mail_index_mark_corrupted(struct mail_index *index)
5ec0ca7ff13595daf0d096c17100afb352e6294aTimo Sirainen{
e3689d0f073341e844638f34e1e4d0b7bb053cc8Timo Sirainen index->indexid = 0;
87712707722ef7d73acb065546e61afa4455cd9eTimo Sirainen
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen index->map->hdr.flags |= MAIL_INDEX_HDR_FLAG_CORRUPTED;
bc1d1497d715cc5c820ff518f070f78c39ef6cdcTimo Sirainen if (unlink(index->filepath) < 0 && errno != ENOENT && errno != ESTALE)
bc1d1497d715cc5c820ff518f070f78c39ef6cdcTimo Sirainen mail_index_set_syscall_error(index, "unlink()");
5ec0ca7ff13595daf0d096c17100afb352e6294aTimo Sirainen}
5ec0ca7ff13595daf0d096c17100afb352e6294aTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mail_index_set_syscall_error(struct mail_index *index,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *function)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(function != NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ENOSPACE(errno)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index->nodiskspace = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return mail_index_set_error(index, "%s failed with index file %s: %m",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen function, index->filepath);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mail_index_file_set_syscall_error(struct mail_index *index,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *filepath,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *function)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(filepath != NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(function != NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ENOSPACE(errno)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index->nodiskspace = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return mail_index_set_error(index, "%s failed with file %s: %m",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen function, filepath);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenconst char *mail_index_get_error_message(struct mail_index *index)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return index->error;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_index_reset_error(struct mail_index *index)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (index->error != NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_free(index->error);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index->error = NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index->nodiskspace = FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index->index_lock_timeout = FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainen#ifdef WORDS_BIGENDIAN
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainen/* FIXME: Unfortunately these functions were originally written to use
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainen endian-specific code and we can't avoid that without breaking backwards
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainen compatibility. When we do break it, just select one of these. */
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainenuint32_t mail_index_uint32_to_offset(uint32_t offset)
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen{
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen i_assert(offset < 0x40000000);
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen i_assert((offset & 3) == 0);
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen offset >>= 2;
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainen return 0x00000080 | ((offset & 0x0000007f)) |
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainen 0x00008000 | ((offset & 0x00003f80) >> 7 << 8) |
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainen 0x00800000 | ((offset & 0x001fc000) >> 14 << 16) |
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainen 0x80000000 | ((offset & 0x0fe00000) >> 21 << 24);
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen}
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainenuint32_t mail_index_offset_to_uint32(uint32_t offset)
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen{
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainen if ((offset & 0x80808080) != 0x80808080)
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainen return 0;
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainen return (((offset & 0x0000007f)) |
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainen ((offset & 0x00007f00) >> 8 << 7) |
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainen ((offset & 0x007f0000) >> 16 << 14) |
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainen ((offset & 0x7f000000) >> 24 << 21)) << 2;
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainen}
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainen#else
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainenuint32_t mail_index_uint32_to_offset(uint32_t offset)
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainen{
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainen i_assert(offset < 0x40000000);
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainen i_assert((offset & 3) == 0);
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainen
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainen offset >>= 2;
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainen return 0x80000000 | ((offset & 0x0000007f) << 24) |
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainen 0x00800000 | ((offset & 0x00003f80) >> 7 << 16) |
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainen 0x00008000 | ((offset & 0x001fc000) >> 14 << 8) |
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainen 0x00000080 | ((offset & 0x0fe00000) >> 21);
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainen}
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainen
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainenuint32_t mail_index_offset_to_uint32(uint32_t offset)
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainen{
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen if ((offset & 0x80808080) != 0x80808080)
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen return 0;
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainen return (((offset & 0x0000007f) << 21) |
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainen ((offset & 0x00007f00) >> 8 << 14) |
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainen ((offset & 0x007f0000) >> 16 << 7) |
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainen ((offset & 0x7f000000) >> 24)) << 2;
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen}
2b498cb82aaad8a11adb5a27a29c55b9c334a1ecTimo Sirainen#endif