mail-index.c revision c53e8ee216904ffe6de4f6518d9f9f5107b7610e
2e37d45867d081db150ab78dad303b9077aea24fTimo Sirainen/* Copyright (c) 2003-2007 Dovecot authors, see the included COPYING file */
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainenstruct mail_index_module_register mail_index_module_register = { 0 };
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainenstruct mail_index *mail_index_alloc(const char *dir, const char *prefix)
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen pool_alloconly_create(MEMPOOL_GROWING"index extension", 1024);
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen p_array_init(&index->extensions, index->extension_pool, 5);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen mail_index_ext_register(index, "keywords", 128, 2, 1);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen index->keywords_pool = pool_alloconly_create("keywords", 512);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen hash_create(default_pool, index->keywords_pool, 0,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen strcase_hash, (hash_cmp_callback_t *)strcasecmp);
51fb710488efa419a2964335c30451c62b9633b1Timo Sirainen index->log = mail_transaction_log_alloc(index);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainenvoid mail_index_free(struct mail_index **_index)
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainenvoid mail_index_set_permissions(struct mail_index *index,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainenuint32_t mail_index_ext_register(struct mail_index *index, const char *name,
ba8498efbf886ca8b69fdb20c0ba2f5dba9416e3Timo Sirainen if (strcmp(name, str_sanitize(name, -1)) != 0)
93a7d1ee4b518b5c85f9721dc6539e4dab6aae00Timo Sirainen i_panic("mail_index_ext_register(%s): Invalid name", name);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen if (mail_index_ext_lookup(index, name, &ext_id))
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen rext.name = p_strdup(index->extension_pool, name);
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen rext.index_idx = array_count(&index->extensions);
04052d7cacaa866a3f00afb4e104fa46c04c1dd7Timo Sirainenbool mail_index_ext_lookup(struct mail_index *index, const char *name,
380dbb60ae291cbe39d1f710284562ca9167150bTimo Sirainen const struct mail_index_registered_ext *extensions;
380dbb60ae291cbe39d1f710284562ca9167150bTimo Sirainen unsigned int i, count;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen extensions = array_get(&index->extensions, &count);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen for (i = 0; i < count; i++) {
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainenvoid mail_index_register_expunge_handler(struct mail_index *index,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen rext = array_idx_modifiable(&index->extensions, ext_id);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen i_assert(rext->expunge_handler == NULL || rext->expunge_handler == cb);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen rext->expunge_handler_call_always = call_always;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenvoid mail_index_unregister_expunge_handler(struct mail_index *index,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen rext = array_idx_modifiable(&index->extensions, ext_id);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenvoid mail_index_register_sync_handler(struct mail_index *index, uint32_t ext_id,
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen rext = array_idx_modifiable(&index->extensions, ext_id);
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen i_assert(rext->sync_handler.callback == NULL);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainenvoid mail_index_unregister_sync_handler(struct mail_index *index,
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen rext = array_idx_modifiable(&index->extensions, ext_id);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen i_assert(rext->sync_handler.callback != NULL);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenvoid mail_index_register_sync_lost_handler(struct mail_index *index,
401b0787fff2dc986a5321ddb32acb1947ff66b0Timo Sirainen array_append(&index->sync_lost_handlers, &cb, 1);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenvoid mail_index_unregister_sync_lost_handler(struct mail_index *index,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen mail_index_sync_lost_handler_t *const *handlers;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen unsigned int i, count;
50e20db49f29917fe9adcf1b56b11badf28bd0e4Timo Sirainen handlers = array_get(&index->sync_lost_handlers, &count);
50e20db49f29917fe9adcf1b56b11badf28bd0e4Timo Sirainen for (i = 0; i < count; i++) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen array_delete(&index->sync_lost_handlers, i, 1);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenbool mail_index_keyword_lookup(struct mail_index *index,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen /* keywords_hash keeps a name => index mapping of keywords.
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen Keywords are never removed from it, so the index values are valid
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen for the lifetime of the mail_index. */
c6f894e1522f7b0b6068c228900914073c145175Timo Sirainen if (hash_lookup_full(index->keywords_hash, keyword, NULL, &value)) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen *idx_r = POINTER_CAST_TO(value, unsigned int);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenvoid mail_index_keyword_lookup_or_create(struct mail_index *index,
401b0787fff2dc986a5321ddb32acb1947ff66b0Timo Sirainen unsigned int *idx_r)
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen if (mail_index_keyword_lookup(index, keyword, idx_r))
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen keyword = keyword_dup = p_strdup(index->keywords_pool, keyword);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen hash_insert(index->keywords_hash, keyword_dup, POINTER_CAST(*idx_r));
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainenconst ARRAY_TYPE(keywords) *mail_index_get_keywords(struct mail_index *index)
a7f5035eebbd138a5436a2eb2ce1fa5fd3d269fbTimo Sirainenint mail_index_try_open_only(struct mail_index *index)
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen /* Note that our caller must close index->fd by itself. */
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen index->fd = nfs_safe_open(index->filepath, O_RDWR);
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen return mail_index_set_syscall_error(index, "open()");
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen /* have to create it */
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen i_assert(index->map == NULL || index->map->rec_map->lock_id == 0);
d477acb83e14a776ece4ca94dcd1869e75d0c6eeTimo Sirainen ret = mail_index_map(index, MAIL_INDEX_SYNC_HANDLER_HEAD);
15f526e5ac611b4532568d131fcd0abf664abe41Timo Sirainen /* it's corrupted - recreate it */
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen mail_index_set_syscall_error(index, "close()");
4fc74bba3548987b7e8597491cd9fafc1f701be6Timo Sirainenint mail_index_create_tmp_file(struct mail_index *index, const char **path_r)
0f62889d833767acf9c2ad010c3269806b4cfae3Timo Sirainen path = *path_r = t_strconcat(index->filepath, ".tmp", NULL);
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen fd = open(path, O_RDWR|O_CREAT|O_TRUNC, index->mode);
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen return mail_index_file_set_syscall_error(index, path, "open()");
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen if (index->gid != (gid_t)-1 && fchown(fd, (uid_t)-1, index->gid) < 0) {
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen mail_index_file_set_syscall_error(index, path, "fchown()");
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainenstatic int mail_index_open_files(struct mail_index *index,
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) == 0)
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen /* if dovecot.index exists, read it first so that we can get
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen the correct indexid and log sequence */
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen /* Create a new indexid for us. If we're opening index
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen into memory, index->map doesn't exist yet. */
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen ret = mail_transaction_log_create(index->log);
1d22eaac93de41319918a1fc6de42bb302e25c1aTimo Sirainen ret = index->map != NULL ? 0 : mail_index_try_open(index);
5d60e31c7b701b606067a20bc88dcc8a6de7bbd6Timo Sirainen /* doesn't exist / corrupted */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ret = mail_transaction_log_create(index->log);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen /* open/create failed, fallback to in-memory indexes */
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) == 0)
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen index->cache = created ? mail_cache_create(index) :
5d60e31c7b701b606067a20bc88dcc8a6de7bbd6Timo Sirainenint mail_index_open(struct mail_index *index, enum mail_index_open_flags flags,
MAIL_INDEX_HDR_FLAG_CORRUPTED) != 0) {
return ret;
int ret;
const char *function)
const char *filepath,
const char *function)
#ifdef WORDS_BIGENDIAN