mail-index.c revision 0cfdf8ba03034ffe98abe73c21fdb69e5c0a4509
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (c) 2003-2014 Dovecot authors, see the included COPYING file */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "lib.h"
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen#include "ioloop.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "array.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "buffer.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "eacces-error.h"
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen#include "hash.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "str-sanitize.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "mmap-util.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "nfs-workarounds.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "read-full.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "write-full.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "mail-index-alloc-cache.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "mail-index-private.h"
22627da0fb77c1d0d9a8e8bc485ef5540b6f2e69Timo Sirainen#include "mail-index-view-private.h"
ab1b9a793d57a60c230a41f65f1a25d52c026233Timo Sirainen#include "mail-index-sync-private.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "mail-index-modseq.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "mail-transaction-log.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "mail-cache.h"
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include <stdio.h>
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include <stddef.h>
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen#include <time.h>
ab1b9a793d57a60c230a41f65f1a25d52c026233Timo Sirainen#include <sys/stat.h>
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenstruct mail_index_module_register mail_index_module_register = { 0 };
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainenstruct mail_index *mail_index_alloc(const char *dir, const char *prefix)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mail_index *index;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen index = i_new(struct mail_index, 1);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen index->dir = i_strdup(dir);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen index->prefix = i_strdup(prefix);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen index->fd = -1;
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen index->extension_pool =
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen pool_alloconly_create(MEMPOOL_GROWING"index extension", 1024);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen p_array_init(&index->extensions, index->extension_pool, 5);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen i_array_init(&index->sync_lost_handlers, 4);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen i_array_init(&index->module_contexts,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen I_MIN(5, mail_index_module_register.id));
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen index->mode = 0600;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen index->gid = (gid_t)-1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen index->lock_method = FILE_LOCK_METHOD_FCNTL;
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen index->max_lock_timeout_secs = UINT_MAX;
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen index->keywords_ext_id =
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen mail_index_ext_register(index, MAIL_INDEX_EXT_KEYWORDS,
68f0dfb4b2815ecbc1bd8d8a68adcfd577ec55aeTimo Sirainen 128, 2, 1);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen index->keywords_pool = pool_alloconly_create("keywords", 512);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen i_array_init(&index->keywords, 16);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen hash_table_create(&index->keywords_hash, index->keywords_pool, 0,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen strcase_hash, strcasecmp);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen index->log = mail_transaction_log_alloc(index);
9c2b0eb659540b9db8dd3a8a6a2515921fbe8eebTimo Sirainen mail_index_modseq_init(index);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen return index;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen}
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenvoid mail_index_free(struct mail_index **_index)
892b3cbf0eba9ba455448adcf71864a409345c6dTimo Sirainen{
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen struct mail_index *index = *_index;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
f4c0b1874b0533bcf2df1d28d584ff02cfdae3faTimo Sirainen *_index = NULL;
f4c0b1874b0533bcf2df1d28d584ff02cfdae3faTimo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen i_assert(index->open_count == 0);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen mail_transaction_log_free(&index->log);
0db5b158a00c08955bdacc99b1e2cd1ec07f4311Timo Sirainen hash_table_destroy(&index->keywords_hash);
0db5b158a00c08955bdacc99b1e2cd1ec07f4311Timo Sirainen pool_unref(&index->extension_pool);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen pool_unref(&index->keywords_pool);
d16b506f5540e3407d256bda35624b38a5ecf88fTimo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen array_free(&index->sync_lost_handlers);
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen array_free(&index->keywords);
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen array_free(&index->module_contexts);
554c1c792dc6fce1e25c74555c2da786bffde75fTimo Sirainen
554c1c792dc6fce1e25c74555c2da786bffde75fTimo Sirainen i_free(index->ext_hdr_init_data);
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen i_free(index->gid_origin);
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen i_free(index->error);
ab1b9a793d57a60c230a41f65f1a25d52c026233Timo Sirainen i_free(index->dir);
ab1b9a793d57a60c230a41f65f1a25d52c026233Timo Sirainen i_free(index->prefix);
6df2db16b3920346ed07cefb86e8bdcb7e1faec5Timo Sirainen i_free(index);
6df2db16b3920346ed07cefb86e8bdcb7e1faec5Timo Sirainen}
ab1b9a793d57a60c230a41f65f1a25d52c026233Timo Sirainen
ab1b9a793d57a60c230a41f65f1a25d52c026233Timo Sirainenvoid mail_index_set_fsync_mode(struct mail_index *index,
ab1b9a793d57a60c230a41f65f1a25d52c026233Timo Sirainen enum fsync_mode mode,
35f3b7e05afecacd0332c210c6e253911c2813d8Timo Sirainen enum mail_index_fsync_mask mask)
ab1b9a793d57a60c230a41f65f1a25d52c026233Timo Sirainen{
ab1b9a793d57a60c230a41f65f1a25d52c026233Timo Sirainen index->fsync_mode = mode;
35f3b7e05afecacd0332c210c6e253911c2813d8Timo Sirainen index->fsync_mask = mask;
ab1b9a793d57a60c230a41f65f1a25d52c026233Timo Sirainen}
ab1b9a793d57a60c230a41f65f1a25d52c026233Timo Sirainen
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainenvoid mail_index_set_permissions(struct mail_index *index,
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainen mode_t mode, gid_t gid, const char *gid_origin)
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainen{
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainen index->mode = mode & 0666;
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainen index->gid = gid;
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainen
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainen i_free(index->gid_origin);
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainen index->gid_origin = i_strdup(gid_origin);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenvoid mail_index_set_lock_method(struct mail_index *index,
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen enum file_lock_method lock_method,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen unsigned int max_timeout_secs)
407caeb5d0c8a6b158e2caef48dd909011d40340Timo Sirainen{
407caeb5d0c8a6b158e2caef48dd909011d40340Timo Sirainen index->lock_method = lock_method;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen index->max_lock_timeout_secs = max_timeout_secs;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainenvoid mail_index_set_ext_init_data(struct mail_index *index, uint32_t ext_id,
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen const void *data, size_t size)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen{
ab1b9a793d57a60c230a41f65f1a25d52c026233Timo Sirainen const struct mail_index_registered_ext *rext;
a54fa00087ba926a3d966a8449d8d7579e89911cTimo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen i_assert(index->ext_hdr_init_data == NULL ||
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen index->ext_hdr_init_id == ext_id);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen rext = array_idx(&index->extensions, ext_id);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen i_assert(rext->hdr_size == size);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen index->ext_hdr_init_id = ext_id;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen i_free(index->ext_hdr_init_data);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen index->ext_hdr_init_data = i_malloc(size);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen memcpy(index->ext_hdr_init_data, data, size);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenuint32_t mail_index_ext_register(struct mail_index *index, const char *name,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen uint32_t default_hdr_size,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen uint16_t default_record_size,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen uint16_t default_record_align)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mail_index_registered_ext rext;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen uint32_t ext_id;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (*name == '\0' || strcmp(name, str_sanitize(name, -1)) != 0)
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen i_panic("mail_index_ext_register(%s): Invalid name", name);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (default_record_size != 0 && default_record_align == 0) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen i_panic("mail_index_ext_register(%s): "
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen "Invalid record alignment", name);
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainen }
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (mail_index_ext_lookup(index, name, &ext_id))
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return ext_id;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen memset(&rext, 0, sizeof(rext));
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen rext.name = p_strdup(index->extension_pool, name);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen rext.index_idx = array_count(&index->extensions);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen rext.hdr_size = default_hdr_size;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen rext.record_size = default_record_size;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen rext.record_align = default_record_align;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen array_append(&index->extensions, &rext, 1);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return rext.index_idx;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainenbool mail_index_ext_lookup(struct mail_index *index, const char *name,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen uint32_t *ext_id_r)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const struct mail_index_registered_ext *extensions;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen unsigned int i, count;
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainen
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainen extensions = array_get(&index->extensions, &count);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen for (i = 0; i < count; i++) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (strcmp(extensions[i].name, name) == 0) {
d16b506f5540e3407d256bda35624b38a5ecf88fTimo Sirainen *ext_id_r = i;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen return TRUE;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen }
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen }
ab1b9a793d57a60c230a41f65f1a25d52c026233Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen *ext_id_r = (uint32_t)-1;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen return FALSE;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen}
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainenvoid mail_index_register_expunge_handler(struct mail_index *index,
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen uint32_t ext_id, bool call_always,
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen mail_index_expunge_handler_t *cb,
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen void *context)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen{
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen struct mail_index_registered_ext *rext;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen rext = array_idx_modifiable(&index->extensions, ext_id);
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen i_assert(rext->expunge_handler == NULL || rext->expunge_handler == cb);
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen rext->expunge_handler = cb;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen rext->expunge_context = context;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen rext->expunge_handler_call_always = call_always;
a0b89f3b1df99b3a32f44623f13ad1893118825bTimo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
a0b89f3b1df99b3a32f44623f13ad1893118825bTimo Sirainenvoid mail_index_unregister_expunge_handler(struct mail_index *index,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen uint32_t ext_id)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mail_index_registered_ext *rext;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen rext = array_idx_modifiable(&index->extensions, ext_id);
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen i_assert(rext->expunge_handler != NULL);
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen rext->expunge_handler = NULL;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainenvoid mail_index_register_sync_handler(struct mail_index *index, uint32_t ext_id,
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen mail_index_sync_handler_t *cb,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen enum mail_index_sync_handler_type type)
a0b89f3b1df99b3a32f44623f13ad1893118825bTimo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mail_index_registered_ext *rext;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen rext = array_idx_modifiable(&index->extensions, ext_id);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen i_assert(rext->sync_handler.callback == NULL);
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen
ab1b9a793d57a60c230a41f65f1a25d52c026233Timo Sirainen rext->sync_handler.callback = cb;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen rext->sync_handler.type = type;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen}
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainenvoid mail_index_unregister_sync_handler(struct mail_index *index,
ab1b9a793d57a60c230a41f65f1a25d52c026233Timo Sirainen uint32_t ext_id)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen{
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen struct mail_index_registered_ext *rext;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen rext = array_idx_modifiable(&index->extensions, ext_id);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen i_assert(rext->sync_handler.callback != NULL);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen rext->sync_handler.callback = NULL;
9349a0afffad990e45d3ad33081e1d2d9e68a753Timo Sirainen rext->sync_handler.type = 0;
9349a0afffad990e45d3ad33081e1d2d9e68a753Timo Sirainen}
9349a0afffad990e45d3ad33081e1d2d9e68a753Timo Sirainen
4c9c55e15f35474f53f11659e796c63b1c34e884Timo Sirainenvoid mail_index_register_sync_lost_handler(struct mail_index *index,
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen mail_index_sync_lost_handler_t *cb)
4c9c55e15f35474f53f11659e796c63b1c34e884Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen array_append(&index->sync_lost_handlers, &cb, 1);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenvoid mail_index_unregister_sync_lost_handler(struct mail_index *index,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen mail_index_sync_lost_handler_t *cb)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen mail_index_sync_lost_handler_t *const *handlers;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen unsigned int i, count;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
ab1b9a793d57a60c230a41f65f1a25d52c026233Timo Sirainen handlers = array_get(&index->sync_lost_handlers, &count);
ab1b9a793d57a60c230a41f65f1a25d52c026233Timo Sirainen for (i = 0; i < count; i++) {
ab1b9a793d57a60c230a41f65f1a25d52c026233Timo Sirainen if (handlers[i] == cb) {
ab1b9a793d57a60c230a41f65f1a25d52c026233Timo Sirainen array_delete(&index->sync_lost_handlers, i, 1);
ab1b9a793d57a60c230a41f65f1a25d52c026233Timo Sirainen break;
ab1b9a793d57a60c230a41f65f1a25d52c026233Timo Sirainen }
ab1b9a793d57a60c230a41f65f1a25d52c026233Timo Sirainen }
ab1b9a793d57a60c230a41f65f1a25d52c026233Timo Sirainen}
ab1b9a793d57a60c230a41f65f1a25d52c026233Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenbool mail_index_keyword_lookup(struct mail_index *index,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const char *keyword, unsigned int *idx_r)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen char *key;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen void *value;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* keywords_hash keeps a name => index mapping of keywords.
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen Keywords are never removed from it, so the index values are valid
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen for the lifetime of the mail_index. */
d16b506f5540e3407d256bda35624b38a5ecf88fTimo Sirainen if (hash_table_lookup_full(index->keywords_hash, keyword,
4c9c55e15f35474f53f11659e796c63b1c34e884Timo Sirainen &key, &value)) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen *idx_r = POINTER_CAST_TO(value, unsigned int);
ab1b9a793d57a60c230a41f65f1a25d52c026233Timo Sirainen return TRUE;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen }
22627da0fb77c1d0d9a8e8bc485ef5540b6f2e69Timo Sirainen
3e28b527dd6048a40684afd29cff0ee008fc0014Timo Sirainen *idx_r = UINT_MAX;
3e28b527dd6048a40684afd29cff0ee008fc0014Timo Sirainen return FALSE;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainenvoid mail_index_keyword_lookup_or_create(struct mail_index *index,
ccffb125d94adff0ad776de5a96e22f864d6fb0aTimo Sirainen const char *keyword,
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen unsigned int *idx_r)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen{
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen char *keyword_dup;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen i_assert(*keyword != '\0');
ab1b9a793d57a60c230a41f65f1a25d52c026233Timo Sirainen
ccffb125d94adff0ad776de5a96e22f864d6fb0aTimo Sirainen if (mail_index_keyword_lookup(index, keyword, idx_r))
ccffb125d94adff0ad776de5a96e22f864d6fb0aTimo Sirainen return;
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen keyword = keyword_dup = p_strdup(index->keywords_pool, keyword);
c44f402f17f9a58ead24ac0083945cae86fb172bTimo Sirainen *idx_r = array_count(&index->keywords);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainen hash_table_insert(index->keywords_hash, keyword_dup,
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainen POINTER_CAST(*idx_r));
c44f402f17f9a58ead24ac0083945cae86fb172bTimo Sirainen array_append(&index->keywords, &keyword, 1);
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainen
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainen /* keep the array NULL-terminated, but the NULL itself invisible */
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainen array_append_zero(&index->keywords);
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainen array_delete(&index->keywords, array_count(&index->keywords)-1, 1);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainen
c44f402f17f9a58ead24ac0083945cae86fb172bTimo Sirainenconst ARRAY_TYPE(keywords) *mail_index_get_keywords(struct mail_index *index)
c44f402f17f9a58ead24ac0083945cae86fb172bTimo Sirainen{
c44f402f17f9a58ead24ac0083945cae86fb172bTimo Sirainen return &index->keywords;
c44f402f17f9a58ead24ac0083945cae86fb172bTimo Sirainen}
c44f402f17f9a58ead24ac0083945cae86fb172bTimo Sirainen
c44f402f17f9a58ead24ac0083945cae86fb172bTimo Sirainenstruct mail_keywords *
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenmail_index_keywords_create(struct mail_index *index,
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainen const char *const keywords[])
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen{
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainen struct mail_keywords *k;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen unsigned int src, dest, i, count;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen count = str_array_length(keywords);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen if (count == 0) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen k = i_new(struct mail_keywords, 1);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen k->index = index;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen k->refcount = 1;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen return k;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen }
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen /* @UNSAFE */
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen k = i_malloc(sizeof(struct mail_keywords) +
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen (sizeof(k->idx) * (count-1)));
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen k->index = index;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen k->refcount = 1;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen /* look up the keywords from index. they're never removed from there
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen so we can permanently store indexes to them. */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen for (src = dest = 0; src < count; src++) {
a1aaf11831cab8346d6d0dc702e37b3f1d95eb43Timo Sirainen mail_index_keyword_lookup_or_create(index, keywords[src],
a1aaf11831cab8346d6d0dc702e37b3f1d95eb43Timo Sirainen &k->idx[dest]);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen /* ignore if this is a duplicate */
a1aaf11831cab8346d6d0dc702e37b3f1d95eb43Timo Sirainen for (i = 0; i < src; i++) {
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (k->idx[i] == k->idx[dest])
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen break;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
c44f402f17f9a58ead24ac0083945cae86fb172bTimo Sirainen if (i == src)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen dest++;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen k->count = dest;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return k;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstruct mail_keywords *
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainenmail_index_keywords_create_from_indexes(struct mail_index *index,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const ARRAY_TYPE(keyword_indexes)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen *keyword_indexes)
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen{
e20e638805c4bd54e039891a3e92760b1dfa189aTimo Sirainen struct mail_keywords *k;
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen const unsigned int *indexes;
e20e638805c4bd54e039891a3e92760b1dfa189aTimo Sirainen unsigned int src, dest, i, count;
e20e638805c4bd54e039891a3e92760b1dfa189aTimo Sirainen
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen indexes = array_get(keyword_indexes, &count);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen if (count == 0) {
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen k = i_new(struct mail_keywords, 1);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen k->index = index;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen k->refcount = 1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return k;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen /* @UNSAFE */
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen k = i_malloc(sizeof(struct mail_keywords) +
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen (sizeof(k->idx) * (count-1)));
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen k->index = index;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen k->refcount = 1;
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen /* copy but skip duplicates */
68f0dfb4b2815ecbc1bd8d8a68adcfd577ec55aeTimo Sirainen for (src = dest = 0; src < count; src++) {
e958a3c4573058f17999f0083a34080ca35e34d8Timo Sirainen for (i = 0; i < src; i++) {
e958a3c4573058f17999f0083a34080ca35e34d8Timo Sirainen if (k->idx[i] == indexes[src])
e958a3c4573058f17999f0083a34080ca35e34d8Timo Sirainen break;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen }
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (i == src)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen k->idx[dest++] = indexes[src];
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen }
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen k->count = dest;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen return k;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen}
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainenvoid mail_index_keywords_ref(struct mail_keywords *keywords)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen{
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen keywords->refcount++;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen}
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainenvoid mail_index_keywords_unref(struct mail_keywords **_keywords)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen{
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen struct mail_keywords *keywords = *_keywords;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen i_assert(keywords->refcount > 0);
68f0dfb4b2815ecbc1bd8d8a68adcfd577ec55aeTimo Sirainen
68f0dfb4b2815ecbc1bd8d8a68adcfd577ec55aeTimo Sirainen *_keywords = NULL;
3656c91dcb8336814bebd4500e81c3dde25233e6Timo Sirainen if (--keywords->refcount == 0)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen i_free(keywords);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen}
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenint mail_index_try_open_only(struct mail_index *index)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen i_assert(index->fd == -1);
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainen i_assert(!MAIL_INDEX_IS_IN_MEMORY(index));
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* Note that our caller must close index->fd by itself. */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (index->readonly)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen errno = EACCES;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen else {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen index->fd = nfs_safe_open(index->filepath, O_RDWR);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen index->readonly = FALSE;
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainen }
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainen
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainen if (index->fd == -1 && errno == EACCES) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen index->fd = open(index->filepath, O_RDONLY);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen index->readonly = TRUE;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (index->fd == -1) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (errno != ENOENT) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen mail_index_set_syscall_error(index, "open()");
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen return -1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* have to create it */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return 0;
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainen }
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainen return 1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainen
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainenstatic int
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainenmail_index_try_open(struct mail_index *index)
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen int ret;
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen i_assert(index->fd == -1);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (MAIL_INDEX_IS_IN_MEMORY(index))
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return 0;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ret = mail_index_map(index, MAIL_INDEX_SYNC_HANDLER_HEAD);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (ret == 0) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* it's corrupted - recreate it */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (index->fd != -1) {
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (close(index->fd) < 0)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen mail_index_set_syscall_error(index, "close()");
f119596e34bc4a7ce374f4aa5f4f1eb12061a372Timo Sirainen index->fd = -1;
f119596e34bc4a7ce374f4aa5f4f1eb12061a372Timo Sirainen }
f119596e34bc4a7ce374f4aa5f4f1eb12061a372Timo Sirainen }
f119596e34bc4a7ce374f4aa5f4f1eb12061a372Timo Sirainen return ret;
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen}
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainenint mail_index_create_tmp_file(struct mail_index *index, const char **path_r)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen{
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen mode_t old_mask;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen const char *path;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen int fd;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen i_assert(!MAIL_INDEX_IS_IN_MEMORY(index));
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen path = *path_r = t_strconcat(index->filepath, ".tmp", NULL);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen old_mask = umask(0);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen fd = open(path, O_RDWR|O_CREAT|O_EXCL, index->mode);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen umask(old_mask);
294c71436de227178c709e4d498e7be9b5d8d7feTimo Sirainen if (fd == -1 && errno == EEXIST) {
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen /* stale temp file. unlink and recreate rather than overwriting,
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen just to make sure locking problems won't cause corruption */
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (unlink(path) < 0) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen i_error("unlink(%s) failed: %m", path);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen return -1;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen }
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen old_mask = umask(0);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen fd = open(path, O_RDWR|O_CREAT|O_EXCL, index->mode);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen umask(old_mask);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (fd == -1) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen mail_index_file_set_syscall_error(index, path, "creat()");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return -1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen mail_index_fchown(index, fd, path);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return fd;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic int mail_index_open_files(struct mail_index *index,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen enum mail_index_open_flags flags)
13a8c553f293349248b161ff851743498916e26eTimo Sirainen{
13a8c553f293349248b161ff851743498916e26eTimo Sirainen int ret;
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen bool created = FALSE;
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen ret = mail_transaction_log_open(index->log);
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen if (ret == 0) {
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) == 0)
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen return 0;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
9fcf7b79236b0045f7709718f7b65ada516565e7Timo Sirainen /* if dovecot.index exists, read it first so that we can get
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen the correct indexid and log sequence */
9fcf7b79236b0045f7709718f7b65ada516565e7Timo Sirainen (void)mail_index_try_open(index);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen if (index->indexid == 0) {
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen /* Create a new indexid for us. If we're opening index
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen into memory, index->map doesn't exist yet. */
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen index->indexid = ioloop_time;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen index->initial_create = TRUE;
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen if (index->map != NULL)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen index->map->hdr.indexid = index->indexid;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen }
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen ret = mail_transaction_log_create(index->log, FALSE);
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen if (index->map != NULL) {
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen /* log creation could have changed it if someone else
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen just created it. */
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen index->map->hdr.indexid = index->indexid;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen }
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen index->initial_create = FALSE;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen created = TRUE;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen }
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (ret >= 0) {
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen ret = index->map != NULL ? 1 : mail_index_try_open(index);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (ret == 0) {
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen /* corrupted */
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen mail_transaction_log_close(index->log);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ret = mail_transaction_log_create(index->log, TRUE);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (ret == 0) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (index->map != NULL)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen mail_index_unmap(&index->map);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen index->map = mail_index_map_alloc(index);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
3656c91dcb8336814bebd4500e81c3dde25233e6Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (ret < 0) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* open/create failed, fallback to in-memory indexes */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) == 0)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen return -1;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (mail_index_move_to_memory(index) < 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return -1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (index->cache == NULL) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen index->cache = created ? mail_cache_create(index) :
3656c91dcb8336814bebd4500e81c3dde25233e6Timo Sirainen mail_cache_open_or_create(index);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return 1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic int
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenmail_index_open_opened(struct mail_index *index,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen enum mail_index_open_flags flags)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen{
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen int ret;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen i_assert(index->map != NULL);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if ((index->map->hdr.flags & MAIL_INDEX_HDR_FLAG_CORRUPTED) != 0) {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen /* index was marked corrupted. we'll probably need to
36c4702131e5a04984ad5d07cf5d8d5c633d43c3Timo Sirainen recreate the files. */
36c4702131e5a04984ad5d07cf5d8d5c633d43c3Timo Sirainen mail_index_unmap(&index->map);
ab1b9a793d57a60c230a41f65f1a25d52c026233Timo Sirainen mail_index_close_file(index);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen mail_transaction_log_close(index->log);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if ((ret = mail_index_open_files(index, flags)) <= 0)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen return ret;
5fe06fea9fee0f5e4e9cb49f6866877223f78b85Timo Sirainen }
5fe06fea9fee0f5e4e9cb49f6866877223f78b85Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen index->open_count++;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen return 1;
ab1b9a793d57a60c230a41f65f1a25d52c026233Timo Sirainen}
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
36c4702131e5a04984ad5d07cf5d8d5c633d43c3Timo Sirainenint mail_index_open(struct mail_index *index, enum mail_index_open_flags flags)
ab1b9a793d57a60c230a41f65f1a25d52c026233Timo Sirainen{
36c4702131e5a04984ad5d07cf5d8d5c633d43c3Timo Sirainen int ret;
36c4702131e5a04984ad5d07cf5d8d5c633d43c3Timo Sirainen
36c4702131e5a04984ad5d07cf5d8d5c633d43c3Timo Sirainen if (index->open_count > 0) {
36c4702131e5a04984ad5d07cf5d8d5c633d43c3Timo Sirainen if ((ret = mail_index_open_opened(index, flags)) <= 0) {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen /* doesn't exist and create flag not used */
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen index->open_count++;
36c4702131e5a04984ad5d07cf5d8d5c633d43c3Timo Sirainen mail_index_close(index);
36c4702131e5a04984ad5d07cf5d8d5c633d43c3Timo Sirainen }
36c4702131e5a04984ad5d07cf5d8d5c633d43c3Timo Sirainen return ret;
36c4702131e5a04984ad5d07cf5d8d5c633d43c3Timo Sirainen }
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen index->filepath = MAIL_INDEX_IS_IN_MEMORY(index) ?
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen i_strdup("(in-memory index)") :
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen i_strconcat(index->dir, "/", index->prefix, NULL);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen index->lock_type = F_UNLCK;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen index->lock_id_counter = 2;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen index->readonly = FALSE;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen index->nodiskspace = FALSE;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen index->index_lock_timeout = FALSE;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen index->log_sync_locked = FALSE;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen index->flags = flags;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen index->readonly = (flags & MAIL_INDEX_OPEN_FLAG_READONLY) != 0;
840a3701b7a0f7fadd17738998c33790a8dfad2dTimo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if ((flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0 &&
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen index->fsync_mode != FSYNC_MODE_ALWAYS)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen i_fatal("nfs flush requires mail_fsync=always");
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if ((flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0 &&
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen (flags & MAIL_INDEX_OPEN_FLAG_MMAP_DISABLE) == 0)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen i_fatal("nfs flush requires mmap_disable=yes");
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen /* NOTE: increase open_count only after mail_index_open_files().
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen it's used elsewhere to check if we're doing an initial opening
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen of the index files */
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if ((ret = mail_index_open_files(index, flags)) <= 0) {
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen /* doesn't exist and create flag not used */
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen index->open_count++;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen mail_index_close(index);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen return ret;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen }
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen index->open_count++;
f6e301cb2060c4367d8145e2bf5d553ba87ceb34Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen i_assert(index->map != NULL);
06f537a8e0b399222cc2a7755015ef3963525fd2Timo Sirainen mail_index_alloc_cache_index_opened(index);
06f537a8e0b399222cc2a7755015ef3963525fd2Timo Sirainen return 1;
06f537a8e0b399222cc2a7755015ef3963525fd2Timo Sirainen}
06f537a8e0b399222cc2a7755015ef3963525fd2Timo Sirainen
06f537a8e0b399222cc2a7755015ef3963525fd2Timo Sirainenint mail_index_open_or_create(struct mail_index *index,
87b8a4b6805d0b13af6a417dc70bdc74027bf1d3Timo Sirainen enum mail_index_open_flags flags)
87b8a4b6805d0b13af6a417dc70bdc74027bf1d3Timo Sirainen{
87b8a4b6805d0b13af6a417dc70bdc74027bf1d3Timo Sirainen int ret;
06f537a8e0b399222cc2a7755015ef3963525fd2Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen flags |= MAIL_INDEX_OPEN_FLAG_CREATE;
06f537a8e0b399222cc2a7755015ef3963525fd2Timo Sirainen ret = mail_index_open(index, flags);
06f537a8e0b399222cc2a7755015ef3963525fd2Timo Sirainen i_assert(ret != 0);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen return ret < 0 ? -1 : 0;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen}
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainenvoid mail_index_close_file(struct mail_index *index)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen{
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (index->file_lock != NULL)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen file_lock_free(&index->file_lock);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (index->fd != -1) {
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (close(index->fd) < 0)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen mail_index_set_syscall_error(index, "close()");
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen index->fd = -1;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen }
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen index->lock_id_counter += 2;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen index->lock_type = F_UNLCK;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenvoid mail_index_close(struct mail_index *index)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen i_assert(index->open_count > 0);
26cdaf7097427fa90343260fa236af12ab93cca3Timo Sirainen
26cdaf7097427fa90343260fa236af12ab93cca3Timo Sirainen mail_index_alloc_cache_index_closing(index);
26cdaf7097427fa90343260fa236af12ab93cca3Timo Sirainen if (--index->open_count > 0)
26cdaf7097427fa90343260fa236af12ab93cca3Timo Sirainen return;
26cdaf7097427fa90343260fa236af12ab93cca3Timo Sirainen
26cdaf7097427fa90343260fa236af12ab93cca3Timo Sirainen i_assert(!index->syncing);
26cdaf7097427fa90343260fa236af12ab93cca3Timo Sirainen i_assert(index->views == NULL);
26cdaf7097427fa90343260fa236af12ab93cca3Timo Sirainen
26cdaf7097427fa90343260fa236af12ab93cca3Timo Sirainen if (index->map != NULL)
26cdaf7097427fa90343260fa236af12ab93cca3Timo Sirainen mail_index_unmap(&index->map);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen mail_index_close_file(index);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen mail_transaction_log_close(index->log);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (index->cache != NULL)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen mail_cache_free(&index->cache);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen i_free_and_null(index->filepath);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen index->indexid = 0;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenint mail_index_unlink(struct mail_index *index)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const char *path;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen int last_errno = 0;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (MAIL_INDEX_IS_IN_MEMORY(index) || index->readonly)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen return 0;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* main index */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (unlink(index->filepath) < 0 && errno != ENOENT)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen last_errno = errno;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* logs */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen path = t_strconcat(index->filepath, MAIL_TRANSACTION_LOG_SUFFIX, NULL);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (unlink(path) < 0 && errno != ENOENT)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen last_errno = errno;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen path = t_strconcat(index->filepath,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen MAIL_TRANSACTION_LOG_SUFFIX".2", NULL);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (unlink(path) < 0 && errno != ENOENT)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen last_errno = errno;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* cache */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen path = t_strconcat(index->filepath, MAIL_CACHE_FILE_SUFFIX, NULL);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (unlink(path) < 0 && errno != ENOENT)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen last_errno = errno;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (last_errno == 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return 0;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen else {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen errno = last_errno;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return -1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenint mail_index_reopen_if_changed(struct mail_index *index)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct stat st1, st2;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (MAIL_INDEX_IS_IN_MEMORY(index))
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return 0;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (index->fd == -1)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return mail_index_try_open_only(index);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if ((index->flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen nfs_flush_file_handle_cache(index->filepath);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (nfs_safe_stat(index->filepath, &st2) < 0) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (errno == ENOENT)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return 0;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen mail_index_set_syscall_error(index, "stat()");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return -1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (fstat(index->fd, &st1) < 0) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (!ESTALE_FSTAT(errno)) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen mail_index_set_syscall_error(index, "fstat()");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return -1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* deleted/recreated, reopen */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen } else if (st1.st_ino == st2.st_ino &&
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen CMP_DEV_T(st1.st_dev, st2.st_dev)) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* the same file */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return 1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* new file, new locks. the old fd can keep its locks, they don't
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen matter anymore as no-one's going to modify the file. */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen mail_index_close_file(index);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return mail_index_try_open_only(index);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenint mail_index_refresh(struct mail_index *index)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen int ret;
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen ret = mail_index_map(index, MAIL_INDEX_SYNC_HANDLER_HEAD);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen return ret <= 0 ? -1 : 0;
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen}
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainenstruct mail_cache *mail_index_get_cache(struct mail_index *index)
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen{
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen return index->cache;
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen}
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainenvoid mail_index_set_error(struct mail_index *index, const char *fmt, ...)
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen{
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen va_list va;
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen i_free(index->error);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen if (fmt == NULL)
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen index->error = NULL;
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen else {
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen va_start(va, fmt);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen index->error = i_strdup_vprintf(fmt, va);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen va_end(va);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen i_error("%s", index->error);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen }
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen}
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainenbool mail_index_is_in_memory(struct mail_index *index)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return MAIL_INDEX_IS_IN_MEMORY(index);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenint mail_index_move_to_memory(struct mail_index *index)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mail_index_map *map;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (MAIL_INDEX_IS_IN_MEMORY(index))
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return index->map == NULL ? -1 : 0;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if ((index->flags & MAIL_INDEX_OPEN_FLAG_NEVER_IN_MEMORY) != 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return -1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* set the index as being into memory */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen i_free_and_null(index->dir);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen i_free(index->filepath);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen index->filepath = i_strdup("(in-memory index)");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (index->map == NULL) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* index was never even opened. just mark it as being in
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen memory and let the caller re-open the index. */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen i_assert(index->fd == -1);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return -1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* move index map to memory */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (!MAIL_INDEX_MAP_IS_IN_MEMORY(index->map)) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen map = mail_index_map_clone(index->map);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen mail_index_unmap(&index->map);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen index->map = map;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (index->log != NULL) {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen /* move transaction log to memory */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen mail_transaction_log_move_to_memory(index->log);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
9672bb2a11c37c275d695451accd824da5c9e485Timo Sirainen if (index->file_lock != NULL)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen file_lock_free(&index->file_lock);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (index->fd != -1) {
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (close(index->fd) < 0)
9672bb2a11c37c275d695451accd824da5c9e485Timo Sirainen mail_index_set_syscall_error(index, "close()");
9672bb2a11c37c275d695451accd824da5c9e485Timo Sirainen index->fd = -1;
9672bb2a11c37c275d695451accd824da5c9e485Timo Sirainen }
9672bb2a11c37c275d695451accd824da5c9e485Timo Sirainen return 0;
9672bb2a11c37c275d695451accd824da5c9e485Timo Sirainen}
9672bb2a11c37c275d695451accd824da5c9e485Timo Sirainen
9672bb2a11c37c275d695451accd824da5c9e485Timo Sirainenvoid mail_index_mark_corrupted(struct mail_index *index)
9672bb2a11c37c275d695451accd824da5c9e485Timo Sirainen{
9672bb2a11c37c275d695451accd824da5c9e485Timo Sirainen index->indexid = 0;
9672bb2a11c37c275d695451accd824da5c9e485Timo Sirainen
9672bb2a11c37c275d695451accd824da5c9e485Timo Sirainen index->map->hdr.flags |= MAIL_INDEX_HDR_FLAG_CORRUPTED;
9672bb2a11c37c275d695451accd824da5c9e485Timo Sirainen if (!index->readonly) {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen if (unlink(index->filepath) < 0 &&
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen errno != ENOENT && errno != ESTALE)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen mail_index_set_syscall_error(index, "unlink()");
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen (void)mail_transaction_log_unlink(index->log);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen }
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen}
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenbool mail_index_is_deleted(struct mail_index *index)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen{
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen return index->index_delete_requested || index->index_deleted;
9c2b0eb659540b9db8dd3a8a6a2515921fbe8eebTimo Sirainen}
892b3cbf0eba9ba455448adcf71864a409345c6dTimo Sirainen
892b3cbf0eba9ba455448adcf71864a409345c6dTimo Sirainenint mail_index_get_modification_time(struct mail_index *index, time_t *mtime_r)
892b3cbf0eba9ba455448adcf71864a409345c6dTimo Sirainen{
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen struct stat st;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen if (mail_transaction_log_get_mtime(index->log, mtime_r) < 0)
9c2b0eb659540b9db8dd3a8a6a2515921fbe8eebTimo Sirainen return -1;
9c2b0eb659540b9db8dd3a8a6a2515921fbe8eebTimo Sirainen
9c2b0eb659540b9db8dd3a8a6a2515921fbe8eebTimo Sirainen if (*mtime_r == 0) {
9c2b0eb659540b9db8dd3a8a6a2515921fbe8eebTimo Sirainen if (stat(index->filepath, &st) < 0) {
9c2b0eb659540b9db8dd3a8a6a2515921fbe8eebTimo Sirainen mail_index_set_syscall_error(index, "stat()");
9c2b0eb659540b9db8dd3a8a6a2515921fbe8eebTimo Sirainen return -1;
9c2b0eb659540b9db8dd3a8a6a2515921fbe8eebTimo Sirainen }
892b3cbf0eba9ba455448adcf71864a409345c6dTimo Sirainen *mtime_r = st.st_mtime;
9c2b0eb659540b9db8dd3a8a6a2515921fbe8eebTimo Sirainen }
9c2b0eb659540b9db8dd3a8a6a2515921fbe8eebTimo Sirainen return 0;
9c2b0eb659540b9db8dd3a8a6a2515921fbe8eebTimo Sirainen}
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
bfdf0fd7b6186f64cbdcbf1cb2bf9c42a9007b77Timo Sirainenvoid mail_index_fchown(struct mail_index *index, int fd, const char *path)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen{
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen mode_t mode;
bfdf0fd7b6186f64cbdcbf1cb2bf9c42a9007b77Timo Sirainen
bfdf0fd7b6186f64cbdcbf1cb2bf9c42a9007b77Timo Sirainen if (index->gid == (gid_t)-1) {
bfdf0fd7b6186f64cbdcbf1cb2bf9c42a9007b77Timo Sirainen /* no gid changing */
bfdf0fd7b6186f64cbdcbf1cb2bf9c42a9007b77Timo Sirainen return;
bfdf0fd7b6186f64cbdcbf1cb2bf9c42a9007b77Timo Sirainen } else if (fchown(fd, (uid_t)-1, index->gid) == 0) {
bfdf0fd7b6186f64cbdcbf1cb2bf9c42a9007b77Timo Sirainen /* success */
bfdf0fd7b6186f64cbdcbf1cb2bf9c42a9007b77Timo Sirainen return;
bfdf0fd7b6186f64cbdcbf1cb2bf9c42a9007b77Timo Sirainen } if ((index->mode & 0060) >> 3 == (index->mode & 0006)) {
bfdf0fd7b6186f64cbdcbf1cb2bf9c42a9007b77Timo Sirainen /* group and world permissions are the same, so group doesn't
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen really matter. ignore silently. */
bfdf0fd7b6186f64cbdcbf1cb2bf9c42a9007b77Timo Sirainen return;
bfdf0fd7b6186f64cbdcbf1cb2bf9c42a9007b77Timo Sirainen }
bfdf0fd7b6186f64cbdcbf1cb2bf9c42a9007b77Timo Sirainen if (errno != EPERM)
bfdf0fd7b6186f64cbdcbf1cb2bf9c42a9007b77Timo Sirainen mail_index_file_set_syscall_error(index, path, "fchown()");
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen else {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen mail_index_set_error(index, "%s",
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen eperm_error_get_chgrp("fchown", path, index->gid,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen index->gid_origin));
892b3cbf0eba9ba455448adcf71864a409345c6dTimo Sirainen }
892b3cbf0eba9ba455448adcf71864a409345c6dTimo Sirainen
892b3cbf0eba9ba455448adcf71864a409345c6dTimo Sirainen /* continue, but change permissions so that only the common
892b3cbf0eba9ba455448adcf71864a409345c6dTimo Sirainen subset of group and world is used. this makes sure no one
bfdf0fd7b6186f64cbdcbf1cb2bf9c42a9007b77Timo Sirainen gets any extra permissions. */
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen mode = ((index->mode & 0060) >> 3) & (index->mode & 0006);
892b3cbf0eba9ba455448adcf71864a409345c6dTimo Sirainen mode |= (mode << 3) | (index->mode & 0600);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (fchmod(fd, mode) < 0)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen mail_index_file_set_syscall_error(index, path, "fchmod()");
892b3cbf0eba9ba455448adcf71864a409345c6dTimo Sirainen}
892b3cbf0eba9ba455448adcf71864a409345c6dTimo Sirainen
892b3cbf0eba9ba455448adcf71864a409345c6dTimo Sirainenvoid mail_index_set_syscall_error(struct mail_index *index,
892b3cbf0eba9ba455448adcf71864a409345c6dTimo Sirainen const char *function)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen{
bfdf0fd7b6186f64cbdcbf1cb2bf9c42a9007b77Timo Sirainen mail_index_file_set_syscall_error(index, index->filepath, function);
bfdf0fd7b6186f64cbdcbf1cb2bf9c42a9007b77Timo Sirainen}
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
892b3cbf0eba9ba455448adcf71864a409345c6dTimo Sirainenvoid mail_index_file_set_syscall_error(struct mail_index *index,
892b3cbf0eba9ba455448adcf71864a409345c6dTimo Sirainen const char *filepath,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen const char *function)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen{
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen const char *errstr;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen i_assert(filepath != NULL);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen i_assert(function != NULL);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen if (ENOSPACE(errno)) {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen index->nodiskspace = TRUE;
f4c0b1874b0533bcf2df1d28d584ff02cfdae3faTimo Sirainen if ((index->flags & MAIL_INDEX_OPEN_FLAG_NEVER_IN_MEMORY) == 0)
f4c0b1874b0533bcf2df1d28d584ff02cfdae3faTimo Sirainen return;
f4c0b1874b0533bcf2df1d28d584ff02cfdae3faTimo Sirainen }
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
892b3cbf0eba9ba455448adcf71864a409345c6dTimo Sirainen if (errno == EACCES) {
892b3cbf0eba9ba455448adcf71864a409345c6dTimo Sirainen function = t_strcut(function, '(');
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (strcmp(function, "creat") == 0 ||
892b3cbf0eba9ba455448adcf71864a409345c6dTimo Sirainen strncmp(function, "file_dotlock_", 13) == 0)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen errstr = eacces_error_get_creating(function, filepath);
f4c0b1874b0533bcf2df1d28d584ff02cfdae3faTimo Sirainen else
f4c0b1874b0533bcf2df1d28d584ff02cfdae3faTimo Sirainen errstr = eacces_error_get(function, filepath);
892b3cbf0eba9ba455448adcf71864a409345c6dTimo Sirainen mail_index_set_error(index, "%s", errstr);
892b3cbf0eba9ba455448adcf71864a409345c6dTimo Sirainen } else {
bfdf0fd7b6186f64cbdcbf1cb2bf9c42a9007b77Timo Sirainen const char *suffix = errno != EFBIG ? "" :
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen " (process was started with ulimit -f limit)";
892b3cbf0eba9ba455448adcf71864a409345c6dTimo Sirainen mail_index_set_error(index, "%s failed with file %s: "
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen "%m%s", function, filepath, suffix);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen }
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen}
892b3cbf0eba9ba455448adcf71864a409345c6dTimo Sirainen
892b3cbf0eba9ba455448adcf71864a409345c6dTimo Sirainenconst char *mail_index_get_error_message(struct mail_index *index)
28cddf411c475eb8bb84b4023398bb12346ce5adTimo Sirainen{
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen return index->error;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen}
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainenvoid mail_index_reset_error(struct mail_index *index)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen{
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (index->error != NULL) {
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen i_free(index->error);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen index->error = NULL;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen }
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen index->nodiskspace = FALSE;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen index->index_lock_timeout = FALSE;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen}
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen