mail-index.c revision 06fc580f6baf83fe5bb94c64be8149d527b01a42
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen/* Copyright (c) 2003-2014 Dovecot authors, see the included COPYING file */
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainenstruct mail_index_module_register mail_index_module_register = { 0 };
2dd39e478269d6fb0bb26d12b394aa30ee965e38Timo Sirainenstatic void mail_index_close_nonopened(struct mail_index *index);
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainenstruct mail_index *mail_index_alloc(const char *dir, const char *prefix)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen pool_alloconly_create(MEMPOOL_GROWING"index extension", 1024);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen p_array_init(&index->extensions, index->extension_pool, 5);
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen mail_index_ext_register(index, MAIL_INDEX_EXT_KEYWORDS,
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainen index->keywords_pool = pool_alloconly_create("keywords", 512);
4ba9a1d3facc515b3feb5238a16bcf91f76fac61Timo Sirainen hash_table_create(&index->keywords_hash, index->keywords_pool, 0,
dfaefeabae939803ceb8c503101e86b5496541d1Timo Sirainen index->log = mail_transaction_log_alloc(index);
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainenvoid mail_index_free(struct mail_index **_index)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenvoid mail_index_set_fsync_mode(struct mail_index *index,
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainenvoid mail_index_set_permissions(struct mail_index *index,
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen mode_t mode, gid_t gid, const char *gid_origin)
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenvoid mail_index_set_lock_method(struct mail_index *index,
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen index->max_lock_timeout_secs = max_timeout_secs;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_index_set_ext_init_data(struct mail_index *index, uint32_t ext_id,
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainenuint32_t mail_index_ext_register(struct mail_index *index, const char *name,
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen if (*name == '\0' || strcmp(name, str_sanitize(name, -1)) != 0)
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen i_panic("mail_index_ext_register(%s): Invalid name", name);
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen if (default_record_size != 0 && default_record_align == 0) {
4b41116563110d00330896a568eff1078c382827Timo Sirainen if (mail_index_ext_lookup(index, name, &ext_id))
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen rext.name = p_strdup(index->extension_pool, name);
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen rext.index_idx = array_count(&index->extensions);
8a13b020f90e080570658b18c042e7e352c8b14fTimo Sirainenbool mail_index_ext_lookup(struct mail_index *index, const char *name,
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen const struct mail_index_registered_ext *extensions;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen unsigned int i, count;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen extensions = array_get(&index->extensions, &count);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (i = 0; i < count; i++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_index_register_expunge_handler(struct mail_index *index,
bd4d0a1a7c0626452b8d82f37e3ec07267ac9896Timo Sirainen rext = array_idx_modifiable(&index->extensions, ext_id);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(rext->expunge_handler == NULL || rext->expunge_handler == cb);
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainen rext->expunge_handler_call_always = call_always;
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainenvoid mail_index_unregister_expunge_handler(struct mail_index *index,
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen rext = array_idx_modifiable(&index->extensions, ext_id);
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainenvoid mail_index_register_sync_handler(struct mail_index *index, uint32_t ext_id,
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen rext = array_idx_modifiable(&index->extensions, ext_id);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen i_assert(rext->sync_handler.callback == NULL);
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainenvoid mail_index_unregister_sync_handler(struct mail_index *index,
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen rext = array_idx_modifiable(&index->extensions, ext_id);
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen i_assert(rext->sync_handler.callback != NULL);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainenvoid mail_index_register_sync_lost_handler(struct mail_index *index,
42507d758b053bb483de58fba55c73a9eb5d3fbaTimo Sirainen array_append(&index->sync_lost_handlers, &cb, 1);
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainenvoid mail_index_unregister_sync_lost_handler(struct mail_index *index,
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen mail_index_sync_lost_handler_t *const *handlers;
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen unsigned int i, count;
fcfe85637e1ee14a9fc39c41fd6ceca106301542Timo Sirainen handlers = array_get(&index->sync_lost_handlers, &count);
fcfe85637e1ee14a9fc39c41fd6ceca106301542Timo Sirainen for (i = 0; i < count; i++) {
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen array_delete(&index->sync_lost_handlers, i, 1);
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainenbool mail_index_keyword_lookup(struct mail_index *index,
3f91e60401495a4046c73992fabaa5e77200a451Timo Sirainen /* keywords_hash keeps a name => index mapping of keywords.
3f91e60401495a4046c73992fabaa5e77200a451Timo Sirainen Keywords are never removed from it, so the index values are valid
6b0d8106ae51ffc6ce45636b34d2e21cbefca7fdTimo Sirainen for the lifetime of the mail_index. */
6b0d8106ae51ffc6ce45636b34d2e21cbefca7fdTimo Sirainen if (hash_table_lookup_full(index->keywords_hash, keyword,
eb64c3586d854cddd693f0b811d897399076a441Timo Sirainen *idx_r = POINTER_CAST_TO(value, unsigned int);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainenvoid mail_index_keyword_lookup_or_create(struct mail_index *index,
0d86aa0d47f7393c669c084b34c0537b193688adTimo Sirainen unsigned int *idx_r)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (mail_index_keyword_lookup(index, keyword, idx_r))
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen keyword = keyword_dup = p_strdup(index->keywords_pool, keyword);
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen hash_table_insert(index->keywords_hash, keyword_dup,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen /* keep the array NULL-terminated, but the NULL itself invisible */
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen array_delete(&index->keywords, array_count(&index->keywords)-1, 1);
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainenconst ARRAY_TYPE(keywords) *mail_index_get_keywords(struct mail_index *index)
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainenmail_index_keywords_create(struct mail_index *index,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen const char *const keywords[])
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen /* @UNSAFE */
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* look up the keywords from index. they're never removed from there
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen so we can permanently store indexes to them. */
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen mail_index_keyword_lookup_or_create(index, keywords[src],
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen /* ignore if this is a duplicate */
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen for (i = 0; i < src; i++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmail_index_keywords_create_from_indexes(struct mail_index *index,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const unsigned int *indexes;
2d01cc1880cf2afd4fb1c8ad7fa6ce78e562e71eTimo Sirainen /* @UNSAFE */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* copy but skip duplicates */
194603b35061fea1ee8d171a7104b6985c610966Timo Sirainen for (i = 0; i < src; i++) {
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainenvoid mail_index_keywords_ref(struct mail_keywords *keywords)
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainenvoid mail_index_keywords_unref(struct mail_keywords **_keywords)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mail_index_try_open_only(struct mail_index *index)
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen /* Note that our caller must close index->fd by itself. */
e63bdfedcf61e1a9ee21990140cbd0d0638da7e1Timo Sirainen index->fd = nfs_safe_open(index->filepath, O_RDWR);
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen mail_index_set_syscall_error(index, "open()");
d54ab8987e482a8df250615b44f41fa040c38741Timo Sirainen /* have to create it */
e050e5c9b1688765f1fdfce9b7141f7b614383fdTimo Sirainen ret = mail_index_map(index, MAIL_INDEX_SYNC_HANDLER_HEAD);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen /* it's corrupted - recreate it */
b62140c5849297a800fee942026d9c3cb8c60206Timo Sirainen mail_index_set_syscall_error(index, "close()");
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainenint mail_index_create_tmp_file(struct mail_index *index,
a4f09749814b93e8ad3ec8a0dc18885b874d6f8cTimo Sirainen path = *path_r = t_strconcat(path_prefix, ".tmp", NULL);
a4f09749814b93e8ad3ec8a0dc18885b874d6f8cTimo Sirainen fd = open(path, O_RDWR|O_CREAT|O_EXCL, index->mode);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* stale temp file. unlink and recreate rather than overwriting,
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen just to make sure locking problems won't cause corruption */
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen fd = open(path, O_RDWR|O_CREAT|O_EXCL, index->mode);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen mail_index_file_set_syscall_error(index, path, "creat()");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int mail_index_open_files(struct mail_index *index,
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) == 0)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen /* if dovecot.index exists, read it first so that we can get
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen the correct indexid and log sequence */
4bbd396aa6198c84f3f7763b6e8a63a26e97e141Timo Sirainen /* Create a new indexid for us. If we're opening index
b83deefd2cf1e293373673eefb4d5cf60907978cTimo Sirainen into memory, index->map doesn't exist yet. */
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen ret = mail_transaction_log_create(index->log, FALSE);
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen /* log creation could have changed it if someone else
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen just created it. */
if (ret >= 0) {
if (ret == 0) {
if (ret == 0) {
if (ret < 0) {
int ret;
return ret;
int ret;
return 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;