mail-index.c revision 036626b19f14bef582f96e556913ae91b1d67881
5e0ce63bb65db34d7f48b34bbb5545fa791781c4Timo Sirainen/* Copyright (c) 2003-2010 Dovecot authors, see the included COPYING file */
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenstruct mail_index_module_register mail_index_module_register = { 0 };
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenstruct mail_index *mail_index_alloc(const char *dir, const char *prefix)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen pool_alloconly_create(MEMPOOL_GROWING"index extension", 1024);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen p_array_init(&index->extensions, index->extension_pool, 5);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen mail_index_ext_register(index, MAIL_INDEX_EXT_KEYWORDS,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen index->keywords_pool = pool_alloconly_create("keywords", 512);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen hash_table_create(default_pool, index->keywords_pool, 0,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen strcase_hash, (hash_cmp_callback_t *)strcasecmp);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen index->log = mail_transaction_log_alloc(index);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenvoid mail_index_free(struct mail_index **_index)
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenvoid mail_index_set_fsync_types(struct mail_index *index,
601f5f14c6cde28f0e0c6ca7c5d735315d3d48dfTimo Sirainenvoid mail_index_set_permissions(struct mail_index *index,
601f5f14c6cde28f0e0c6ca7c5d735315d3d48dfTimo Sirainen mode_t mode, gid_t gid, const char *gid_origin)
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainenvoid mail_index_set_lock_method(struct mail_index *index,
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen index->max_lock_timeout_secs = max_timeout_secs;
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainenuint32_t mail_index_ext_register(struct mail_index *index, const char *name,
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen if (*name == '\0' || strcmp(name, str_sanitize(name, -1)) != 0)
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen i_panic("mail_index_ext_register(%s): Invalid name", name);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen if (default_record_size != 0 && default_record_align == 0) {
548e394330621952db0f03dd667b70184c4a37b6Timo Sirainen if (mail_index_ext_lookup(index, name, &ext_id))
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen rext.name = p_strdup(index->extension_pool, name);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen rext.index_idx = array_count(&index->extensions);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainenbool mail_index_ext_lookup(struct mail_index *index, const char *name,
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen const struct mail_index_registered_ext *extensions;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen unsigned int i, count;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen extensions = array_get(&index->extensions, &count);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen for (i = 0; i < count; i++) {
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainenvoid mail_index_register_expunge_handler(struct mail_index *index,
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen rext = array_idx_modifiable(&index->extensions, ext_id);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen i_assert(rext->expunge_handler == NULL || rext->expunge_handler == cb);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen rext->expunge_handler_call_always = call_always;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenvoid mail_index_unregister_expunge_handler(struct mail_index *index,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen rext = array_idx_modifiable(&index->extensions, ext_id);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenvoid mail_index_register_sync_handler(struct mail_index *index, uint32_t ext_id,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen rext = array_idx_modifiable(&index->extensions, ext_id);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen i_assert(rext->sync_handler.callback == NULL);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenvoid mail_index_unregister_sync_handler(struct mail_index *index,
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen rext = array_idx_modifiable(&index->extensions, ext_id);
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen i_assert(rext->sync_handler.callback != NULL);
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainenvoid mail_index_register_sync_lost_handler(struct mail_index *index,
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen array_append(&index->sync_lost_handlers, &cb, 1);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenvoid mail_index_unregister_sync_lost_handler(struct mail_index *index,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen mail_index_sync_lost_handler_t *const *handlers;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen unsigned int i, count;
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen handlers = array_get(&index->sync_lost_handlers, &count);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen for (i = 0; i < count; i++) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen array_delete(&index->sync_lost_handlers, i, 1);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenbool mail_index_keyword_lookup(struct mail_index *index,
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen /* keywords_hash keeps a name => index mapping of keywords.
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen Keywords are never removed from it, so the index values are valid
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen for the lifetime of the mail_index. */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (hash_table_lookup_full(index->keywords_hash, keyword,
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen *idx_r = POINTER_CAST_TO(value, unsigned int);
37ab3cde96bfa4bc5304c0c348fc420aec79572dTimo Sirainenvoid mail_index_keyword_lookup_or_create(struct mail_index *index,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen unsigned int *idx_r)
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen if (mail_index_keyword_lookup(index, keyword, idx_r))
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen keyword = keyword_dup = p_strdup(index->keywords_pool, keyword);
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainenconst ARRAY_TYPE(keywords) *mail_index_get_keywords(struct mail_index *index)
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainenmail_index_keywords_create(struct mail_index *index,
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen const char *const keywords[])
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen /* @UNSAFE */
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen /* look up the keywords from index. they're never removed from there
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen so we can permanently store indexes to them. */
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen mail_index_keyword_lookup_or_create(index, keywords[src],
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen /* ignore if this is a duplicate */
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen for (i = 0; i < src; i++) {
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainenmail_index_keywords_create_from_indexes(struct mail_index *index,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const unsigned int *indexes;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen /* @UNSAFE */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* copy but skip duplicates */
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen for (i = 0; i < src; i++) {
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainenvoid mail_index_keywords_ref(struct mail_keywords *keywords)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainenvoid mail_index_keywords_unref(struct mail_keywords **_keywords)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainenint mail_index_try_open_only(struct mail_index *index)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* Note that our caller must close index->fd by itself. */
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen index->fd = nfs_safe_open(index->filepath, O_RDWR);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen return mail_index_set_syscall_error(index, "open()");
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* have to create it */
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(index->map == NULL || index->map->rec_map->lock_id == 0);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen ret = mail_index_map(index, MAIL_INDEX_SYNC_HANDLER_HEAD);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* it's corrupted - recreate it */
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen mail_index_set_syscall_error(index, "close()");
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainenint mail_index_create_tmp_file(struct mail_index *index, const char **path_r)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen path = *path_r = t_strconcat(index->filepath, ".tmp", NULL);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen fd = open(path, O_RDWR|O_CREAT|O_TRUNC, index->mode);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen mail_index_file_set_syscall_error(index, path, "creat()");
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainenstatic int mail_index_open_files(struct mail_index *index,
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) == 0)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* if dovecot.index exists, read it first so that we can get
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen the correct indexid and log sequence */
if (ret >= 0) {
if (ret == 0) {
if (ret == 0) {
if (ret < 0) {
int ret;
return ret;
int ret;
const char *path;
int last_errno = 0;
if (last_errno == 0)
int ret;
if (*mtime_r == 0) {
const char *function)
const char *filepath,
const char *function)
const char *errstr;