mail-index.c revision 7b524faf719c9998dd586708d6ee0faa307a6c02
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "lib.h"
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen#include "buffer.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "file-lock.h"
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen#include "mmap-util.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "read-full.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "write-full.h"
abf015c9682f0f723db87a7c97bc284ef814818fTimo Sirainen#include "mail-index-private.h"
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen#include "mail-transaction-log.h"
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen#include "mail-cache.h"
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen#include <stdio.h>
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include <stddef.h>
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include <time.h>
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include <sys/stat.h>
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainenstatic int mail_index_try_open_only(struct mail_index *index);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstruct mail_index *mail_index_alloc(const char *dir, const char *prefix)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct mail_index *index;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen index = i_new(struct mail_index, 1);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen index->dir = i_strdup(dir);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen index->prefix = i_strdup(prefix);
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen index->fd = -1;
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen index->extra_infos_pool =
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen pool_alloconly_create("extra_infos_pool", 256);
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen index->extra_infos =
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen buffer_create_dynamic(index->extra_infos_pool,
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen 64, (size_t)-1);
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen index->mode = 0600;
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen index->gid = (gid_t)-1;
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen return index;
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen}
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainenvoid mail_index_free(struct mail_index *index)
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen{
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen mail_index_close(index);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen pool_unref(index->extra_infos_pool);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen i_free(index->error);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen i_free(index->dir);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen i_free(index->prefix);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen i_free(index);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen}
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainenvoid mail_index_set_permissions(struct mail_index *index,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mode_t mode, gid_t gid)
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen{
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen index->mode = mode & 0666;
49621bf0ef1d55aaaa2dc7d76011cbfeabdcfbe1Timo Sirainen index->gid = gid;
fa2433aebcf3fccfa30ca9eed9b1a9166cf92ee2Timo Sirainen}
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenuint32_t mail_index_register_record_extra(struct mail_index *index,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const char *name, uint32_t hdr_size,
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen uint16_t record_size)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen{
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen const struct mail_index_extra_record_info *einfos;
3482fee0e3733456512ba110780824e6daa7ff9fTimo Sirainen struct mail_index_extra_record_info info;
3482fee0e3733456512ba110780824e6daa7ff9fTimo Sirainen size_t extra_count;
3482fee0e3733456512ba110780824e6daa7ff9fTimo Sirainen unsigned int i;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
12797080b552a3c1727b73b61cc7427bec0c7472Timo Sirainen einfos = buffer_get_data(index->extra_infos, &extra_count);
49fd8c950e3da2ed32506e617a4b1480a07f874fTimo Sirainen extra_count /= sizeof(*einfos);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* see if it's there already */
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen for (i = 0; i < extra_count; i++) {
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen if (strcmp(einfos[i].name, name) == 0) {
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen i_assert(einfos[i].hdr_size == hdr_size);
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen i_assert(einfos[i].record_size == record_size);
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen return i;
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen }
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen }
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen i_assert(hdr_size % 4 == 0);
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainen i_assert(record_size % 4 == 0);
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen memset(&info, 0, sizeof(info));
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen info.name = p_strdup(index->extra_infos_pool, name);
e438c85a6b0f77889e25913bbbba808d6078282dStephan Bosch info.hdr_size = hdr_size;
e438c85a6b0f77889e25913bbbba808d6078282dStephan Bosch info.record_size = record_size;
5a9912dcadfd467c5ea54bdc3331eef359f0b1c5Timo Sirainen
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen buffer_append(index->extra_infos, &info, sizeof(info));
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen return extra_count;
38f227941bcf673e0e523c1ac7267bca9cbcd2c4Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainenstatic void mail_index_map_create_extra_infos(struct mail_index_map *map,
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen unsigned int initial_count)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen{
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen size_t extra_infos_size, extra_infos_id_map_size, size;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen extra_infos_size = initial_count *
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen sizeof(struct mail_index_extra_record_info);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen extra_infos_id_map_size = initial_count * sizeof(uint32_t);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if (map->extra_records_pool == NULL) {
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen size = extra_infos_size + extra_infos_id_map_size +
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen initial_count * 20;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen map->extra_records_pool =
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen pool_alloconly_create("extra_infos",
2eb2cf8eeb763bd5ca9b6848dce32f0303e88ec1Timo Sirainen nearest_power(size));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen map->extra_infos = buffer_create_dynamic(map->extra_records_pool,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen extra_infos_size, (size_t)-1);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen map->extra_infos_id_map = buffer_create_dynamic(map->extra_records_pool,
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen extra_infos_id_map_size,
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen (size_t)-1);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen}
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainenuint32_t mail_index_map_register_extra_info(struct mail_index *index,
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen struct mail_index_map *map,
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen const char *name,
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen uint32_t hdr_offset,
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen uint32_t hdr_size,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen uint32_t record_size)
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const struct mail_index_extra_record_info *last_einfo;
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen struct mail_index_extra_record_info *einfo;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen size_t size;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen uint32_t idx, data_id;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if (map->extra_infos == NULL) {
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen mail_index_map_create_extra_infos(map, 5);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen last_einfo = NULL;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen idx = 0;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen } else {
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen last_einfo = buffer_get_data(map->extra_infos, &size);
1f5597beba229acd914e30a6da3c0e62d83b6e8fTimo Sirainen idx = size / sizeof(*last_einfo);
7af5f78e9fee296e42430d94ef252ff0333d8024Timo Sirainen if (idx == 0)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen last_einfo = NULL;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen else
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen last_einfo += idx - 1;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen }
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen einfo = buffer_append_space_unsafe(map->extra_infos, sizeof(*einfo));
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen memset(einfo, 0, sizeof(*einfo));
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen
7af5f78e9fee296e42430d94ef252ff0333d8024Timo Sirainen einfo->name = p_strdup(map->extra_records_pool, name);
7af5f78e9fee296e42430d94ef252ff0333d8024Timo Sirainen einfo->hdr_offset = hdr_offset;
7af5f78e9fee296e42430d94ef252ff0333d8024Timo Sirainen einfo->hdr_size = hdr_size;
7af5f78e9fee296e42430d94ef252ff0333d8024Timo Sirainen einfo->record_size = record_size;
7af5f78e9fee296e42430d94ef252ff0333d8024Timo Sirainen
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen if (last_einfo != NULL) {
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen einfo->record_offset = last_einfo->record_offset +
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen last_einfo->record_size;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen } else {
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen einfo->record_offset = sizeof(struct mail_index_record);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen }
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen data_id = mail_index_register_record_extra(index, name,
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen hdr_size, record_size);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen buffer_write(map->extra_infos_id_map, data_id * sizeof(uint32_t),
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen &idx, sizeof(idx));
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen return idx;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen}
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainenstatic int mail_index_read_extra_infos(struct mail_index *index,
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen struct mail_index_map *map)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen{
1f5597beba229acd914e30a6da3c0e62d83b6e8fTimo Sirainen const struct mail_index_extra_record_info_header *einfo_hdr;
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen unsigned int i, old_count;
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen const char *name;
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen uint32_t data_id, offset, name_offset;
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen
1f5597beba229acd914e30a6da3c0e62d83b6e8fTimo Sirainen offset = map->hdr->base_header_size;
1f5597beba229acd914e30a6da3c0e62d83b6e8fTimo Sirainen if (offset == map->hdr->header_size &&
1f5597beba229acd914e30a6da3c0e62d83b6e8fTimo Sirainen map->extra_records_pool == NULL) {
1f5597beba229acd914e30a6da3c0e62d83b6e8fTimo Sirainen /* nothing to do, skip allocatations and all */
1f5597beba229acd914e30a6da3c0e62d83b6e8fTimo Sirainen return 1;
1f5597beba229acd914e30a6da3c0e62d83b6e8fTimo Sirainen }
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen old_count = index->extra_infos->used /
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen sizeof(struct mail_index_extra_record_info);
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen if (map->extra_records_pool != NULL)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen p_clear(map->extra_records_pool);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen mail_index_map_create_extra_infos(map, old_count + 5);
417642ddac19708bea6dd2c2bbeaf6a9578d521bTimo Sirainen data_id = (uint32_t)-1;
417642ddac19708bea6dd2c2bbeaf6a9578d521bTimo Sirainen for (i = 0; i < old_count; i++) {
417642ddac19708bea6dd2c2bbeaf6a9578d521bTimo Sirainen buffer_append(map->extra_infos_id_map,
417642ddac19708bea6dd2c2bbeaf6a9578d521bTimo Sirainen &data_id, sizeof(data_id));
417642ddac19708bea6dd2c2bbeaf6a9578d521bTimo Sirainen }
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen name = map->hdr_base;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen while (offset < map->hdr->header_size) {
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen name_offset = offset;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen while (offset < map->hdr->header_size && name[offset] != '\0')
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen offset++;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (offset == map->hdr->header_size) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen "Header extension name doesn't end with NUL",
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen index->filepath);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return -1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen offset++;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen while (offset < map->hdr->header_size && (offset % 4) != 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen offset++;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen einfo_hdr = CONST_PTR_OFFSET(map->hdr_base, offset);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (offset + sizeof(*einfo_hdr) > map->hdr->header_size ||
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen offset + sizeof(*einfo_hdr) + einfo_hdr->hdr_size >
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen map->hdr->header_size) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen "Header extension goes outside header",
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen index->filepath);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return -1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail_index_map_register_extra_info(index, map,
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen name + name_offset,
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen offset + sizeof(*einfo_hdr),
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen einfo_hdr->hdr_size,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen einfo_hdr->record_size);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen offset += sizeof(*einfo_hdr) + einfo_hdr->hdr_size;
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen }
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen return 1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic int mail_index_check_header(struct mail_index *index,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct mail_index_map *map)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const struct mail_index_header *hdr = map->hdr;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen unsigned char compat_data[sizeof(hdr->compat_data)];
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainen memset(compat_data, 0, sizeof(compat_data));
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen#ifndef WORDS_BIGENDIAN
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen compat_data[0] = MAIL_INDEX_COMPAT_LITTLE_ENDIAN;
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainen#endif
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainen compat_data[1] = sizeof(uoff_t);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen compat_data[2] = sizeof(time_t);
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (hdr->major_version != MAIL_INDEX_MAJOR_VERSION) {
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen /* major version change - handle silently(?) */
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen return -1;
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen }
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen if (memcmp(hdr->compat_data, compat_data, sizeof(compat_data)) != 0) {
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen /* architecture change - handle silently(?) */
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen return -1;
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen }
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen if ((map->hdr->flags & MAIL_INDEX_HDR_FLAG_CORRUPTED) != 0) {
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen /* we've already complained about it */
e30b9e07f9657c35ca09ac36d57d60cbe2ebbc66Timo Sirainen return -1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen /* following some extra checks that only take a bit of CPU */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (hdr->uid_validity == 0 && hdr->next_uid != 1) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen "uid_validity = 0, next_uid = %u",
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen index->filepath, hdr->next_uid);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return -1;
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (hdr->keywords_mask_size != sizeof(keywords_mask_t)) {
e438c85a6b0f77889e25913bbbba808d6078282dStephan Bosch mail_index_set_error(index, "Corrupted index file %s: "
e438c85a6b0f77889e25913bbbba808d6078282dStephan Bosch "keywords_mask_size mismatch: %d != %d",
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen index->filepath, hdr->keywords_mask_size,
4c261fb48e6e36570a0841aa51ca483024d6a0a6Timo Sirainen (int)sizeof(keywords_mask_t));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return -1;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen }
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (hdr->record_size < sizeof(struct mail_index_record)) {
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen "record_size too small: %u < %"PRIuSIZE_T,
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen index->filepath, hdr->record_size,
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen sizeof(struct mail_index_record));
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen return -1;
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen }
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen if (hdr->next_uid == 0)
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen return 0;
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch if (hdr->recent_messages_count > hdr->messages_count ||
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen hdr->seen_messages_count > hdr->messages_count ||
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen hdr->deleted_messages_count > hdr->messages_count)
5a9912dcadfd467c5ea54bdc3331eef359f0b1c5Timo Sirainen return 0;
5a9912dcadfd467c5ea54bdc3331eef359f0b1c5Timo Sirainen if (hdr->first_recent_uid_lowwater > hdr->next_uid ||
5a9912dcadfd467c5ea54bdc3331eef359f0b1c5Timo Sirainen hdr->first_unseen_uid_lowwater > hdr->next_uid ||
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen hdr->first_deleted_uid_lowwater > hdr->next_uid)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen return 0;
18c209a06941ef583b08b173dadfbe4571995bf9Timo Sirainen
4c261fb48e6e36570a0841aa51ca483024d6a0a6Timo Sirainen return mail_index_read_extra_infos(index, map);
4c261fb48e6e36570a0841aa51ca483024d6a0a6Timo Sirainen}
18c209a06941ef583b08b173dadfbe4571995bf9Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic void mail_index_map_clear(struct mail_index *index,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct mail_index_map *map)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if (map->buffer != NULL) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_assert(map->mmap_base == NULL);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen buffer_free(map->buffer);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen map->buffer = NULL;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen } else if (map->mmap_base != NULL) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_assert(map->buffer == NULL);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (munmap(map->mmap_base, map->mmap_size) < 0)
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen mail_index_set_syscall_error(index, "munmap()");
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen map->mmap_base = NULL;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (map->refcount > 0) {
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen map->mmap_size = 0;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen map->mmap_used_size = 0;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen map->hdr = NULL;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen map->records = NULL;
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen map->records_count = 0;
b9dc21a94401638c00e40b695998875e1563ce77Timo Sirainen }
b9dc21a94401638c00e40b695998875e1563ce77Timo Sirainen}
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainenvoid mail_index_unmap(struct mail_index *index, struct mail_index_map *map)
27ca6cb0548c6478005c77d04be641356ec7d83cTimo Sirainen{
27ca6cb0548c6478005c77d04be641356ec7d83cTimo Sirainen if (--map->refcount > 0)
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen return;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen i_assert(map->refcount == 0);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail_index_map_clear(index, map);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen if (map->extra_records_pool != NULL)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen pool_unref(map->extra_records_pool);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen buffer_free(map->hdr_copy_buf);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen i_free(map);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen}
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainenstatic void mail_index_unmap_forced(struct mail_index *index,
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen struct mail_index_map *map)
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen{
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen mail_index_map_clear(index, map);
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen mail_index_unmap(index, map);
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen}
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainenstatic int mail_index_mmap(struct mail_index *index, struct mail_index_map *map)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const struct mail_index_header *hdr;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct mail_index_header *mhdr;
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen unsigned int records_count;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen i_assert(!map->write_to_disk);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen if (map->buffer != NULL) {
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen /* we had temporarily used a buffer, eg. for updating index */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen buffer_free(map->buffer);
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen map->buffer = NULL;
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen }
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen map->mmap_base = index->lock_type != F_WRLCK ?
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen mmap_ro_file(index->fd, &map->mmap_size) :
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen mmap_rw_file(index->fd, &map->mmap_size);
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen if (map->mmap_base == MAP_FAILED) {
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen map->mmap_base = NULL;
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen mail_index_set_syscall_error(index, "mmap()");
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen return -1;
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (map->mmap_size < MAIL_INDEX_HEADER_MIN_SIZE) {
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen "File too small (%"PRIuSIZE_T")",
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen index->filepath, map->mmap_size);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return 0;
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen }
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen hdr = map->mmap_base;
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen map->hdr = hdr;
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen map->mmap_used_size = hdr->header_size +
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen hdr->messages_count * hdr->record_size;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen if (map->mmap_used_size > map->mmap_size) {
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen records_count = (map->mmap_size - hdr->header_size) /
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen hdr->record_size;
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen "messages_count too large (%u > %u)",
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen index->filepath, hdr->messages_count,
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen records_count);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return 0;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen if (map->hdr->base_header_size < sizeof(*map->hdr)) {
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen /* header smaller than ours, make a copy so our newer headers
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen won't have garbage in them */
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen buffer_reset(map->hdr_copy_buf);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen buffer_append(map->hdr_copy_buf,
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen map->hdr, map->hdr->base_header_size);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen buffer_append_zero(map->hdr_copy_buf, sizeof(*map->hdr) -
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen map->hdr->base_header_size);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen mhdr = buffer_get_modifyable_data(map->hdr_copy_buf, NULL);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen mhdr->base_header_size = sizeof(*map->hdr);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen mhdr->header_size = map->hdr_copy_buf->used;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen map->hdr = mhdr;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen }
b55f914c0ade77252cfd798ea8eb9a84bda56315Timo Sirainen
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen map->hdr_base = map->mmap_base;
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen map->records = PTR_OFFSET(map->mmap_base, map->hdr->header_size);
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen map->records_count = map->hdr->messages_count;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen return 1;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen}
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainenstatic int mail_index_read_map(struct mail_index *index,
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen struct mail_index_map *map, int *retry_r)
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen{
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen struct mail_index_header hdr, *hdrp;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen void *data = NULL;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen ssize_t ret;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen size_t pos, records_size;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen i_assert(map->mmap_base == NULL);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen *retry_r = FALSE;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen memset(&hdr, 0, sizeof(hdr));
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen ret = 1;
b55f914c0ade77252cfd798ea8eb9a84bda56315Timo Sirainen for (pos = 0; ret > 0 && pos < sizeof(hdr); ) {
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen ret = pread(index->fd, PTR_OFFSET(&hdr, pos),
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen sizeof(hdr) - pos, pos);
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen if (ret > 0)
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen pos += ret;
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen }
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen if (ret >= 0 && pos >= MAIL_INDEX_HEADER_MIN_SIZE &&
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen (ret > 0 || pos >= hdr.base_header_size)) {
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen if (hdr.base_header_size < MAIL_INDEX_HEADER_MIN_SIZE ||
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen hdr.header_size < hdr.base_header_size) {
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen "Corrupted header sizes (base %u, full %u)",
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen index->filepath, hdr.base_header_size,
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen hdr.header_size);
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen return 0;
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen }
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen buffer_reset(map->hdr_copy_buf);
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen if (hdr.base_header_size < sizeof(hdr)) {
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen buffer_append_zero(map->hdr_copy_buf, sizeof(hdr) +
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen hdr.header_size -
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen hdr.base_header_size);
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen buffer_write(map->hdr_copy_buf, 0,
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen &hdr, hdr.base_header_size);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen /* @UNSAFE */
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen ret = pread_full(index->fd,
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen PTR_OFFSET(map->hdr_copy_buf->data,
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen sizeof(hdr)),
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen hdr.header_size - hdr.base_header_size,
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen hdr.base_header_size);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen hdrp = buffer_get_modifyable_data(map->hdr_copy_buf,
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen NULL);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen hdrp->base_header_size = sizeof(hdr);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen hdrp->header_size = map->hdr_copy_buf->used;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen } else {
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen buffer_append(map->hdr_copy_buf, &hdr, pos);
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen buffer_append_zero(map->hdr_copy_buf,
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen hdr.header_size - pos);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen /* @UNSAFE */
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen ret = pread_full(index->fd,
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen PTR_OFFSET(map->hdr_copy_buf->data,
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen pos),
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen hdr.header_size - pos, pos);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen }
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen }
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (ret > 0) {
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen records_size = hdr.messages_count * hdr.record_size;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen if (map->buffer == NULL) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen map->buffer = buffer_create_dynamic(default_pool,
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen records_size,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen (size_t)-1);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen }
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen /* @UNSAFE */
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen buffer_set_used_size(map->buffer, 0);
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen data = buffer_append_space_unsafe(map->buffer, records_size);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ret = pread_full(index->fd, data, records_size,
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen hdr.header_size);
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen }
216cd45a5f47c9bd46fe67c1b3bd6b1a42f6e39cTimo Sirainen
216cd45a5f47c9bd46fe67c1b3bd6b1a42f6e39cTimo Sirainen if (ret < 0) {
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen if (errno == ESTALE) {
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen *retry_r = TRUE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return 0;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen mail_index_set_syscall_error(index, "pread_full()");
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen return -1;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (ret == 0) {
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen mail_index_set_error(index,
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen "Corrupted index file %s: File too small",
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen index->filepath);
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen return -1;
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen }
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen map->records = data;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen map->records_count = hdr.messages_count;
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen
216cd45a5f47c9bd46fe67c1b3bd6b1a42f6e39cTimo Sirainen map->hdr = map->hdr_copy_buf->data;
216cd45a5f47c9bd46fe67c1b3bd6b1a42f6e39cTimo Sirainen map->hdr_base = map->hdr_copy_buf->data;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen return 1;
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainenstatic int mail_index_read_map_with_retry(struct mail_index *index,
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen struct mail_index_map *map)
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen{
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen int i, ret, retry;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen for (i = 0; i < MAIL_INDEX_ESTALE_RETRY_COUNT; i++) {
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen ret = mail_index_read_map(index, map, &retry);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen if (ret != 0 || !retry)
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen return ret;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen /* ESTALE - reopen index file */
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen if (close(index->fd) < 0)
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen mail_index_set_syscall_error(index, "close()");
20dca965f48c1d7600a268d380c0b5fb5f1011d5Timo Sirainen index->fd = -1;
20dca965f48c1d7600a268d380c0b5fb5f1011d5Timo Sirainen
20dca965f48c1d7600a268d380c0b5fb5f1011d5Timo Sirainen ret = mail_index_try_open_only(index);
20dca965f48c1d7600a268d380c0b5fb5f1011d5Timo Sirainen if (ret <= 0) {
20dca965f48c1d7600a268d380c0b5fb5f1011d5Timo Sirainen if (ret == 0) {
20dca965f48c1d7600a268d380c0b5fb5f1011d5Timo Sirainen /* the file was lost */
20dca965f48c1d7600a268d380c0b5fb5f1011d5Timo Sirainen errno = ENOENT;
20dca965f48c1d7600a268d380c0b5fb5f1011d5Timo Sirainen mail_index_set_syscall_error(index, "open()");
20dca965f48c1d7600a268d380c0b5fb5f1011d5Timo Sirainen }
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen return -1;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen }
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen }
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen /* Too many ESTALE retries */
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen mail_index_set_syscall_error(index, "read_map()");
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen return -1;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen}
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainenstatic int mail_index_map_try_existing(struct mail_index_map *map)
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen{
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen const struct mail_index_header *hdr;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen size_t used_size;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen if (MAIL_INDEX_MAP_IS_IN_MEMORY(map))
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen return 0;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen hdr = map->mmap_base;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen /* always check corrupted-flag to avoid errors later */
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen if ((hdr->flags & MAIL_INDEX_HDR_FLAG_CORRUPTED) != 0)
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen return -1;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen used_size = hdr->header_size + hdr->messages_count * hdr->record_size;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen if (map->mmap_size >= used_size && map->hdr == hdr) {
7f472e15b5f19a3536634863950c80a88079da23Timo Sirainen map->records_count = hdr->messages_count;
7f472e15b5f19a3536634863950c80a88079da23Timo Sirainen return 1;
0139fcb57a88f6ed27a1bb4a1bd537b04fd2b5d6Timo Sirainen }
0139fcb57a88f6ed27a1bb4a1bd537b04fd2b5d6Timo Sirainen return 0;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainenint mail_index_map(struct mail_index *index, int force)
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen{
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen struct mail_index_map *map;
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen int ret;
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen
9aceb071780a949f4e8bf41d3cf80735d9ac7fdfTimo Sirainen if (!force && index->map != NULL) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ret = mail_index_map_try_existing(index->map);
1503ac7619d97193d6690292b5f9523552c5d6ceTimo Sirainen if (ret != 0)
1503ac7619d97193d6690292b5f9523552c5d6ceTimo Sirainen return ret;
1503ac7619d97193d6690292b5f9523552c5d6ceTimo Sirainen }
1503ac7619d97193d6690292b5f9523552c5d6ceTimo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (index->map != NULL && index->map->refcount > 1) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* this map is already used by some views and they may have
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen pointers into it. leave them and create a new mapping. */
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen index->map->refcount--;
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainen index->map = NULL;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen map = index->map;
b00c511e4675c4a1270d92924fc445cfb8631cf3Timo Sirainen if (map == NULL) {
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen map = i_new(struct mail_index_map, 1);
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen map->refcount = 1;
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen map->hdr_copy_buf =
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen buffer_create_dynamic(default_pool,
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen sizeof(*map->hdr), (size_t)-1);
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen } else if (MAIL_INDEX_MAP_IS_IN_MEMORY(map)) {
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen if (map->write_to_disk) {
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen /* we have modified this mapping and it's waiting to
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen be written to disk once we drop exclusive lock.
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen mapping couldn't have changed, so do nothing. */
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen return 1;
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen }
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen /* FIXME: we need to re-read header */
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen } else if (map->mmap_base != NULL) {
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen i_assert(map->buffer == NULL);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (munmap(map->mmap_base, map->mmap_size) < 0)
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen mail_index_set_syscall_error(index, "munmap()");
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen map->mmap_base = NULL;
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen }
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen index->hdr = NULL;
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen index->map = NULL;
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen if (!index->mmap_disable) {
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen if ((ret = mail_index_mmap(index, map)) <= 0) {
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen mail_index_unmap_forced(index, map);
20dca965f48c1d7600a268d380c0b5fb5f1011d5Timo Sirainen return ret;
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen }
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen } else {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (mail_index_read_map_with_retry(index, map) < 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail_index_unmap_forced(index, map);
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen return -1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen }
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen ret = mail_index_check_header(index, map);
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen if (ret < 0) {
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen mail_index_unmap_forced(index, map);
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen return 0;
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (ret == 0)
20dca965f48c1d7600a268d380c0b5fb5f1011d5Timo Sirainen index->fsck = TRUE;
20dca965f48c1d7600a268d380c0b5fb5f1011d5Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen map->log_file_seq = map->hdr->log_file_seq;
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen map->log_file_offset = map->hdr->log_file_offset;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen map->base_header_size = map->hdr->base_header_size;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen index->hdr = map->hdr;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen index->map = map;
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen return 1;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen}
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstruct mail_index_map *
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenmail_index_map_to_memory(struct mail_index_map *map, uint32_t new_record_size)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen struct mail_index_map *mem_map;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct mail_index_header *hdr;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct mail_index_extra_record_info *einfos;
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen void *src, *dest;
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen size_t size, copy_size;
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen unsigned int i, count;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen if (MAIL_INDEX_MAP_IS_IN_MEMORY(map) &&
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen map->hdr->record_size == new_record_size) {
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen map->refcount++;
e438c85a6b0f77889e25913bbbba808d6078282dStephan Bosch return map;
5a9912dcadfd467c5ea54bdc3331eef359f0b1c5Timo Sirainen }
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen size = map->records_count * new_record_size;
e438c85a6b0f77889e25913bbbba808d6078282dStephan Bosch
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen mem_map = i_new(struct mail_index_map, 1);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mem_map->refcount = 1;
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen mem_map->buffer = buffer_create_dynamic(default_pool, size, (size_t)-1);
c56500d4363beba4ffa954069ab30f4401849156Timo Sirainen if (map->hdr->record_size == new_record_size)
c56500d4363beba4ffa954069ab30f4401849156Timo Sirainen buffer_append(mem_map->buffer, map->records, size);
c56500d4363beba4ffa954069ab30f4401849156Timo Sirainen else {
c56500d4363beba4ffa954069ab30f4401849156Timo Sirainen copy_size = I_MIN(map->hdr->record_size, new_record_size);
c56500d4363beba4ffa954069ab30f4401849156Timo Sirainen src = map->records;
c56500d4363beba4ffa954069ab30f4401849156Timo Sirainen for (i = 0; i < map->records_count; i++) {
c56500d4363beba4ffa954069ab30f4401849156Timo Sirainen dest = buffer_append_space_unsafe(mem_map->buffer,
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen new_record_size);
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen memcpy(dest, src, copy_size);
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen src = PTR_OFFSET(src, map->hdr->record_size);
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen }
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen }
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen mem_map->records = buffer_get_modifyable_data(mem_map->buffer, NULL);
02a6291366caff79793db35d479e2a062bec2af4Timo Sirainen mem_map->records_count = map->records_count;
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen mem_map->hdr_copy_buf = buffer_create_dynamic(default_pool,
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen map->hdr->header_size,
573085b4b25b0bbae8d27969df2c91702eefa23eTimo Sirainen (size_t)-1);
0ee3fdb5e94ae6f34cb873ca3c9858342621e55fTimo Sirainen buffer_append(mem_map->hdr_copy_buf, map->hdr, map->hdr->header_size);
0ee3fdb5e94ae6f34cb873ca3c9858342621e55fTimo Sirainen
0ee3fdb5e94ae6f34cb873ca3c9858342621e55fTimo Sirainen hdr = buffer_get_modifyable_data(mem_map->hdr_copy_buf, NULL);
0ee3fdb5e94ae6f34cb873ca3c9858342621e55fTimo Sirainen hdr->record_size = new_record_size;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mem_map->hdr = hdr;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk /* copy extra_infos */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (map->extra_infos_id_map != NULL) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen count = map->extra_infos_id_map->used / sizeof(uint32_t);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail_index_map_create_extra_infos(mem_map, count);
1b04762685272a53643ac2179939537a44c7c044Timo Sirainen
1b04762685272a53643ac2179939537a44c7c044Timo Sirainen buffer_append_buf(mem_map->extra_infos, map->extra_infos,
1b04762685272a53643ac2179939537a44c7c044Timo Sirainen 0, (size_t)-1);
1b04762685272a53643ac2179939537a44c7c044Timo Sirainen buffer_append_buf(mem_map->extra_infos_id_map,
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen map->extra_infos_id_map, 0, (size_t)-1);
303e375b7e76278f4ec541f49af0476d3e4ee710Timo Sirainen
303e375b7e76278f4ec541f49af0476d3e4ee710Timo Sirainen /* fix the name pointers to use our own pool */
303e375b7e76278f4ec541f49af0476d3e4ee710Timo Sirainen einfos = buffer_get_modifyable_data(mem_map->extra_infos, NULL);
303e375b7e76278f4ec541f49af0476d3e4ee710Timo Sirainen for (i = 0; i < count; i++) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen einfos[i].name = p_strdup(mem_map->extra_records_pool,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen einfos[i].name);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen return mem_map;
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen}
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen
1388b590dbd85245b591346f860bc1319953318aTimo Sirainenint mail_index_map_get_extra_info_idx(struct mail_index_map *map,
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen uint32_t data_id, uint32_t *idx_r)
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen{
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen const uint32_t *id_map;
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen if (map->extra_infos_id_map == NULL ||
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen map->extra_infos_id_map->used / sizeof(*id_map) <= data_id)
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen return 0;
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen id_map = map->extra_infos_id_map->data;
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen *idx_r = id_map[data_id];
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen return *idx_r != (uint32_t)-1;
12797080b552a3c1727b73b61cc7427bec0c7472Timo Sirainen}
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainenstatic int mail_index_try_open_only(struct mail_index *index)
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen{
12797080b552a3c1727b73b61cc7427bec0c7472Timo Sirainen int i;
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen for (i = 0; i < 3; i++) {
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen index->fd = open(index->filepath, O_RDWR);
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen if (index->fd == -1 && errno == EACCES) {
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen index->fd = open(index->filepath, O_RDONLY);
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen index->readonly = TRUE;
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen }
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen if (index->fd != -1 || errno != ESTALE)
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen break;
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen /* May happen with some OSes with NFS. Try again, although
8abe071cb14a622b9d84b00a9269f96d01a576f6Timo Sirainen there's still a race condition with another computer
8abe071cb14a622b9d84b00a9269f96d01a576f6Timo Sirainen creating the index file again. However, we can't try forever
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen as ESTALE happens also if index directory has been deleted
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen from server.. */
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen }
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen if (index->fd == -1) {
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen if (errno != ENOENT)
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen return mail_index_set_syscall_error(index, "open()");
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen /* have to create it */
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen return 0;
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen }
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen return 1;
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen}
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainenstatic int
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainenmail_index_try_open(struct mail_index *index, unsigned int *lock_id_r)
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen{
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen unsigned int lock_id;
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen int ret;
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen if (lock_id_r != NULL)
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen *lock_id_r = 0;
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen
0992011130e9d0a498ca860ddbe4028398a530c5Timo Sirainen ret = mail_index_try_open_only(index);
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen if (ret <= 0)
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen return ret;
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen
0992011130e9d0a498ca860ddbe4028398a530c5Timo Sirainen if (mail_index_lock_shared(index, FALSE, &lock_id) < 0) {
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen (void)close(index->fd);
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen index->fd = -1;
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen return -1;
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen }
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen ret = mail_index_map(index, FALSE);
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen if (ret == 0) {
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen /* it's corrupted - recreate it */
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen mail_index_unlock(index, lock_id);
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen if (lock_id_r != NULL)
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen *lock_id_r = 0;
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen (void)close(index->fd);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen index->fd = -1;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen } else {
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (lock_id_r != NULL)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen *lock_id_r = lock_id;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen else
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen mail_index_unlock(index, lock_id);
3c932c0a21349f23dd38c50c12b3a24717dfbc28Timo Sirainen }
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen return ret;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
3c932c0a21349f23dd38c50c12b3a24717dfbc28Timo Sirainenint mail_index_write_base_header(struct mail_index *index,
3c932c0a21349f23dd38c50c12b3a24717dfbc28Timo Sirainen const struct mail_index_header *hdr)
3c932c0a21349f23dd38c50c12b3a24717dfbc28Timo Sirainen{
3c932c0a21349f23dd38c50c12b3a24717dfbc28Timo Sirainen size_t hdr_size;
3c932c0a21349f23dd38c50c12b3a24717dfbc28Timo Sirainen
3c932c0a21349f23dd38c50c12b3a24717dfbc28Timo Sirainen hdr_size = I_MIN(sizeof(*hdr), hdr->base_header_size);
3c932c0a21349f23dd38c50c12b3a24717dfbc28Timo Sirainen
1cb065514fcfe00b684ee274239e3f0390c7fc47Timo Sirainen if (!MAIL_INDEX_MAP_IS_IN_MEMORY(index->map)) {
1cb065514fcfe00b684ee274239e3f0390c7fc47Timo Sirainen memcpy(index->map->mmap_base, hdr, hdr_size);
1cb065514fcfe00b684ee274239e3f0390c7fc47Timo Sirainen if (msync(index->map->mmap_base, hdr_size, MS_SYNC) < 0)
1cb065514fcfe00b684ee274239e3f0390c7fc47Timo Sirainen return mail_index_set_syscall_error(index, "msync()");
1cb065514fcfe00b684ee274239e3f0390c7fc47Timo Sirainen } else {
1cb065514fcfe00b684ee274239e3f0390c7fc47Timo Sirainen if (pwrite_full(index->fd, hdr, hdr_size, 0) < 0) {
1cb065514fcfe00b684ee274239e3f0390c7fc47Timo Sirainen mail_index_set_syscall_error(index, "pwrite_full()");
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen return -1;
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen }
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen
f934b271c69c7b3e5e3bca23ff9b3ab6187262c2Timo Sirainen buffer_write(index->map->hdr_copy_buf, 0, hdr, hdr_size);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen i_assert(index->hdr == index->map->hdr_copy_buf->data);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen }
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
f38485358ffc04c3466b917770575e29deef24c3Timo Sirainen return 0;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen}
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainenint mail_index_create_tmp_file(struct mail_index *index, const char **path_r)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen{
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen const char *path;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen int fd;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen path = *path_r = t_strconcat(index->filepath, ".tmp", NULL);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen fd = open(path, O_RDWR|O_CREAT|O_TRUNC, index->mode);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (fd == -1)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen return mail_index_file_set_syscall_error(index, path, "open()");
878a83a906e1be6354b563ead096955a22ad5fbeTimo Sirainen
878a83a906e1be6354b563ead096955a22ad5fbeTimo Sirainen if (index->gid != (gid_t)-1 &&
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen fchown(index->fd, (uid_t)-1, index->gid) < 0) {
b879ed8dd4b5850987e6b89a92f794d87c6be7d7Timo Sirainen mail_index_file_set_syscall_error(index, path, "fchown()");
b879ed8dd4b5850987e6b89a92f794d87c6be7d7Timo Sirainen return -1;
b879ed8dd4b5850987e6b89a92f794d87c6be7d7Timo Sirainen }
b879ed8dd4b5850987e6b89a92f794d87c6be7d7Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return fd;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen}
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
705f6fbad395e6f014838e797b7dbcaceafd2f1dTimo Sirainenstatic int mail_index_create(struct mail_index *index,
12797080b552a3c1727b73b61cc7427bec0c7472Timo Sirainen struct mail_index_header *hdr)
12797080b552a3c1727b73b61cc7427bec0c7472Timo Sirainen{
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen const char *path;
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen uint32_t seq;
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen uoff_t offset;
8f5b34c22e4c3bfb35ca13c4744867eb5ddbd3d6Timo Sirainen int ret;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen /* log file lock protects index creation */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (mail_transaction_log_sync_lock(index->log, &seq, &offset) < 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return -1;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen ret = mail_index_try_open(index, NULL);
2eb0402a28bd0422e0170160808c67d6c7274689Timo Sirainen if (ret != 0) {
97180ea9c26c4de0807daaad21e03c80643b09fdTimo Sirainen mail_transaction_log_sync_unlock(index->log);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen return ret < 0 ? -1 : 0;
2eb0402a28bd0422e0170160808c67d6c7274689Timo Sirainen }
2eb0402a28bd0422e0170160808c67d6c7274689Timo Sirainen
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen /* create it fully in index.tmp first */
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen index->fd = mail_index_create_tmp_file(index, &path);
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen if (index->fd == -1)
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen ret = -1;
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen else if (write_full(index->fd, hdr, sizeof(*hdr)) < 0) {
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen mail_index_file_set_syscall_error(index, path, "write_full()");
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen ret = -1;
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen } else {
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen ret = mail_index_map(index, FALSE);
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen }
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen if (ret == 0) {
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen /* it's corrupted even while we just created it,
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen should never happen unless someone pokes the file directly */
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen mail_index_set_error(index,
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen "Newly created index file is corrupted: %s", path);
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen ret = -1;
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen }
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen if (ret < 0) {
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen if (unlink(path) < 0 && errno != ENOENT) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail_index_file_set_syscall_error(index, path,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen "unlink()");
9b78c0d5e13141f4df6c6e483f854e5acb861288Timo Sirainen }
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen } else {
dbe06905918a415a34c5621b9fdf45be0b9c8e64Timo Sirainen /* make it visible to others */
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen if (rename(path, index->filepath) < 0) {
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen mail_index_set_error(index, "rename(%s, %s) failed: %m",
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen path, index->filepath);
49fd8c950e3da2ed32506e617a4b1480a07f874fTimo Sirainen ret = -1;
49fd8c950e3da2ed32506e617a4b1480a07f874fTimo Sirainen }
8d5c97bf940e43e8ec6e9f1ec8655f3b20edafbeTimo Sirainen }
8d5c97bf940e43e8ec6e9f1ec8655f3b20edafbeTimo Sirainen
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen mail_transaction_log_sync_unlock(index->log);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen return ret;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen}
d5eb47a791ec56149fd711cd8e44efc8babeaae5Timo Sirainen
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainenstatic void mail_index_header_init(struct mail_index_header *hdr)
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen{
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen time_t now = time(NULL);
762e17079d29d9f1838114ff5fec9ceaba8eb6a8Timo Sirainen
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen memset(hdr, 0, sizeof(*hdr));
50349cd047ca9e7c100cbeb70acfe26672649959Timo Sirainen
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen hdr->major_version = MAIL_INDEX_MAJOR_VERSION;
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen hdr->minor_version = MAIL_INDEX_MINOR_VERSION;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen hdr->base_header_size = sizeof(*hdr);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen hdr->header_size = sizeof(*hdr);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen hdr->record_size = sizeof(struct mail_index_record);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen hdr->keywords_mask_size = sizeof(keywords_mask_t);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen#ifndef WORDS_BIGENDIAN
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen hdr->compat_data[0] = MAIL_INDEX_COMPAT_LITTLE_ENDIAN;
d2ca20a479e76af8557b4a74b0b51e4de0e3c9e3Timo Sirainen#endif
d2ca20a479e76af8557b4a74b0b51e4de0e3c9e3Timo Sirainen hdr->compat_data[1] = sizeof(uoff_t);
d2ca20a479e76af8557b4a74b0b51e4de0e3c9e3Timo Sirainen hdr->compat_data[2] = sizeof(time_t);
674f541b16689c0ed090dac32db94463c5af3977Timo Sirainen
674f541b16689c0ed090dac32db94463c5af3977Timo Sirainen hdr->indexid = now;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
674f541b16689c0ed090dac32db94463c5af3977Timo Sirainen hdr->next_uid = 1;
faca2afa3576c50caf28e0f009555325d2a49e0bTimo Sirainen}
faca2afa3576c50caf28e0f009555325d2a49e0bTimo Sirainen
faca2afa3576c50caf28e0f009555325d2a49e0bTimo Sirainen/* returns -1 = error, 0 = won't create, 1 = ok */
faca2afa3576c50caf28e0f009555325d2a49e0bTimo Sirainenstatic int mail_index_open_files(struct mail_index *index,
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen enum mail_index_open_flags flags)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen{
dbe06905918a415a34c5621b9fdf45be0b9c8e64Timo Sirainen struct mail_index_header hdr;
674f541b16689c0ed090dac32db94463c5af3977Timo Sirainen unsigned int lock_id = 0;
d2ca20a479e76af8557b4a74b0b51e4de0e3c9e3Timo Sirainen int ret;
d2ca20a479e76af8557b4a74b0b51e4de0e3c9e3Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen ret = mail_index_try_open(index, &lock_id);
9b78c0d5e13141f4df6c6e483f854e5acb861288Timo Sirainen if (ret > 0)
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen hdr = *index->hdr;
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen else if (ret == 0) {
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen /* doesn't exist, or corrupted */
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) == 0)
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen return 0;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen mail_index_header_init(&hdr);
9b78c0d5e13141f4df6c6e483f854e5acb861288Timo Sirainen index->hdr = &hdr;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen } else if (ret < 0)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen return -1;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen index->indexid = hdr.indexid;
49fd8c950e3da2ed32506e617a4b1480a07f874fTimo Sirainen
49fd8c950e3da2ed32506e617a4b1480a07f874fTimo Sirainen index->log = mail_transaction_log_open_or_create(index);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen if (index->log == NULL)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen return -1;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (index->fd == -1) {
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen if (lock_id != 0) {
9b78c0d5e13141f4df6c6e483f854e5acb861288Timo Sirainen mail_index_unlock(index, lock_id);
9b78c0d5e13141f4df6c6e483f854e5acb861288Timo Sirainen lock_id = 0;
9b78c0d5e13141f4df6c6e483f854e5acb861288Timo Sirainen }
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen if (mail_index_create(index, &hdr) < 0)
9b78c0d5e13141f4df6c6e483f854e5acb861288Timo Sirainen return -1;
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen }
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen if (lock_id == 0) {
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen if (mail_index_lock_shared(index, FALSE, &lock_id) < 0)
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen return -1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
50b9773bebe5c66485728e21e4da6e99db388c92Timo Sirainen
50b9773bebe5c66485728e21e4da6e99db388c92Timo Sirainen index->cache = mail_cache_open_or_create(index);
50b9773bebe5c66485728e21e4da6e99db388c92Timo Sirainen if (index->cache == NULL)
50b9773bebe5c66485728e21e4da6e99db388c92Timo Sirainen return -1;
50b9773bebe5c66485728e21e4da6e99db388c92Timo Sirainen
50b9773bebe5c66485728e21e4da6e99db388c92Timo Sirainen mail_index_unlock(index, lock_id);
50b9773bebe5c66485728e21e4da6e99db388c92Timo Sirainen return 1;
50b9773bebe5c66485728e21e4da6e99db388c92Timo Sirainen}
50b9773bebe5c66485728e21e4da6e99db388c92Timo Sirainen
50b9773bebe5c66485728e21e4da6e99db388c92Timo Sirainenint mail_index_open(struct mail_index *index, enum mail_index_open_flags flags)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen{
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen int i = 0, ret;
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (index->opened)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return 0;
c5a6a6565be93224fc26522eda855b0990f256e8Timo Sirainen
f934b271c69c7b3e5e3bca23ff9b3ab6187262c2Timo Sirainen index->filepath = i_strconcat(index->dir, "/", index->prefix, NULL);
72f2a851238e5661695c63bff0e9a9e800ba577aTimo Sirainen
c5a6a6565be93224fc26522eda855b0990f256e8Timo Sirainen do {
c5a6a6565be93224fc26522eda855b0990f256e8Timo Sirainen index->shared_lock_count = 0;
c5a6a6565be93224fc26522eda855b0990f256e8Timo Sirainen index->excl_lock_count = 0;
c5a6a6565be93224fc26522eda855b0990f256e8Timo Sirainen index->lock_type = F_UNLCK;
50b9773bebe5c66485728e21e4da6e99db388c92Timo Sirainen index->lock_id = 2;
50b9773bebe5c66485728e21e4da6e99db388c92Timo Sirainen
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen index->nodiskspace = FALSE;
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen index->index_lock_timeout = FALSE;
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen index->log_locked = FALSE;
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen index->mmap_disable =
9ba7e76c20be775f368254e3059a6189fe789f16Timo Sirainen (flags & MAIL_INDEX_OPEN_FLAG_MMAP_DISABLE) != 0;
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen index->mmap_no_write =
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen (flags & MAIL_INDEX_OPEN_FLAG_MMAP_NO_WRITE) != 0;
9ba7e76c20be775f368254e3059a6189fe789f16Timo Sirainen index->fcntl_locks_disable =
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen (flags & MAIL_INDEX_OPEN_FLAG_FCNTL_LOCKS_DISABLE) != 0;
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen index->readonly = FALSE;
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen
705f6fbad395e6f014838e797b7dbcaceafd2f1dTimo Sirainen ret = mail_index_open_files(index, flags);
b7835adbfddd8c92b51d6653fb759f963302fa78Timo Sirainen if (ret <= 0)
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen break;
9ba7e76c20be775f368254e3059a6189fe789f16Timo Sirainen
bd63b5b860658b01b1f46f26d406e1e4a9dc019aTimo Sirainen index->opened = TRUE;
8552b0cad8ffe9ccb8270577ba28b8010c89af11Timo Sirainen if (index->fsck) {
98c3aa2587ad3e81e1548a3a4f79b2a24566cec3Timo Sirainen index->fsck = FALSE;
9ba7e76c20be775f368254e3059a6189fe789f16Timo Sirainen ret = mail_index_fsck(index);
72f2a851238e5661695c63bff0e9a9e800ba577aTimo Sirainen if (ret == 0) {
9ba7e76c20be775f368254e3059a6189fe789f16Timo Sirainen /* completely broken, reopen */
38f227941bcf673e0e523c1ac7267bca9cbcd2c4Timo Sirainen if (i++ < 3)
38f227941bcf673e0e523c1ac7267bca9cbcd2c4Timo Sirainen continue;
38f227941bcf673e0e523c1ac7267bca9cbcd2c4Timo Sirainen /* too many tries */
38f227941bcf673e0e523c1ac7267bca9cbcd2c4Timo Sirainen ret = -1;
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen }
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen }
c56500d4363beba4ffa954069ab30f4401849156Timo Sirainen break;
c56500d4363beba4ffa954069ab30f4401849156Timo Sirainen } while (1);
c56500d4363beba4ffa954069ab30f4401849156Timo Sirainen
c56500d4363beba4ffa954069ab30f4401849156Timo Sirainen if (ret <= 0)
c56500d4363beba4ffa954069ab30f4401849156Timo Sirainen mail_index_close(index);
c56500d4363beba4ffa954069ab30f4401849156Timo Sirainen
c56500d4363beba4ffa954069ab30f4401849156Timo Sirainen return ret;
c56500d4363beba4ffa954069ab30f4401849156Timo Sirainen}
c56500d4363beba4ffa954069ab30f4401849156Timo Sirainen
c56500d4363beba4ffa954069ab30f4401849156Timo Sirainenvoid mail_index_close(struct mail_index *index)
c56500d4363beba4ffa954069ab30f4401849156Timo Sirainen{
c56500d4363beba4ffa954069ab30f4401849156Timo Sirainen if (index->log != NULL) {
c56500d4363beba4ffa954069ab30f4401849156Timo Sirainen mail_transaction_log_close(index->log);
c56500d4363beba4ffa954069ab30f4401849156Timo Sirainen index->log = NULL;
c56500d4363beba4ffa954069ab30f4401849156Timo Sirainen }
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (index->map != NULL) {
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen mail_index_unmap(index, index->map);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen index->map = NULL;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen }
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (index->cache != NULL) {
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen mail_cache_free(index->cache);
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen index->cache = NULL;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen }
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen if (index->fd != -1) {
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen if (close(index->fd) < 0)
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen mail_index_set_syscall_error(index, "close()");
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen index->fd = -1;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen }
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
2984b6b095294c50c4626aef74a02d2e04472640Timo Sirainen i_free(index->copy_lock_path);
984e5c91288139f8a2582be705ee7ef0d157a3f6Timo Sirainen index->copy_lock_path = NULL;
984e5c91288139f8a2582be705ee7ef0d157a3f6Timo Sirainen i_free(index->filepath);
984e5c91288139f8a2582be705ee7ef0d157a3f6Timo Sirainen index->filepath = NULL;
984e5c91288139f8a2582be705ee7ef0d157a3f6Timo Sirainen
984e5c91288139f8a2582be705ee7ef0d157a3f6Timo Sirainen index->indexid = 0;
984e5c91288139f8a2582be705ee7ef0d157a3f6Timo Sirainen index->opened = FALSE;
984e5c91288139f8a2582be705ee7ef0d157a3f6Timo Sirainen}
20dca965f48c1d7600a268d380c0b5fb5f1011d5Timo Sirainen
984e5c91288139f8a2582be705ee7ef0d157a3f6Timo Sirainenint mail_index_reopen(struct mail_index *index, int fd)
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen{
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen struct mail_index_map *old_map;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen unsigned int old_shared_locks, old_lock_id, lock_id = 0;
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen int ret, old_fd, old_lock_type;
49fd8c950e3da2ed32506e617a4b1480a07f874fTimo Sirainen
49fd8c950e3da2ed32506e617a4b1480a07f874fTimo Sirainen old_map = index->map;
49fd8c950e3da2ed32506e617a4b1480a07f874fTimo Sirainen old_fd = index->fd;
49fd8c950e3da2ed32506e617a4b1480a07f874fTimo Sirainen
49fd8c950e3da2ed32506e617a4b1480a07f874fTimo Sirainen index->map = NULL;
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen index->hdr = NULL;
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen /* new file, new locks. the old fd can keep it's locks, they don't
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen matter anymore as no-one's going to modify the file. */
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen old_lock_type = index->lock_type;
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen old_lock_id = index->lock_id;
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen old_shared_locks = index->shared_lock_count;
12797080b552a3c1727b73b61cc7427bec0c7472Timo Sirainen
12797080b552a3c1727b73b61cc7427bec0c7472Timo Sirainen if (index->lock_type == F_RDLCK)
12797080b552a3c1727b73b61cc7427bec0c7472Timo Sirainen index->lock_type = F_UNLCK;
12797080b552a3c1727b73b61cc7427bec0c7472Timo Sirainen index->lock_id += 2;
12797080b552a3c1727b73b61cc7427bec0c7472Timo Sirainen index->shared_lock_count = 0;
12797080b552a3c1727b73b61cc7427bec0c7472Timo Sirainen
12797080b552a3c1727b73b61cc7427bec0c7472Timo Sirainen if (fd != -1) {
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen index->fd = fd;
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen ret = 0;
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen } else {
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen i_assert(index->excl_lock_count == 0);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen ret = mail_index_try_open_only(index);
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen if (ret > 0)
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen ret = mail_index_lock_shared(index, FALSE, &lock_id);
9ba7e76c20be775f368254e3059a6189fe789f16Timo Sirainen else if (ret == 0) {
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen /* index file is lost */
3482fee0e3733456512ba110780824e6daa7ff9fTimo Sirainen ret = -1;
3482fee0e3733456512ba110780824e6daa7ff9fTimo Sirainen }
3482fee0e3733456512ba110780824e6daa7ff9fTimo Sirainen }
3482fee0e3733456512ba110780824e6daa7ff9fTimo Sirainen
3482fee0e3733456512ba110780824e6daa7ff9fTimo Sirainen if (ret == 0) {
3482fee0e3733456512ba110780824e6daa7ff9fTimo Sirainen if (mail_index_map(index, FALSE) <= 0)
3482fee0e3733456512ba110780824e6daa7ff9fTimo Sirainen ret = -1;
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen }
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (lock_id != 0)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen mail_index_unlock(index, lock_id);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (ret == 0) {
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen mail_index_unmap(index, old_map);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (close(old_fd) < 0)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen mail_index_set_syscall_error(index, "close()");
6494ec1398bbc56e63beba727e2c4538ba5521a7Timo Sirainen } else {
6494ec1398bbc56e63beba727e2c4538ba5521a7Timo Sirainen if (index->map != NULL)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen mail_index_unmap(index, index->map);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (index->fd != -1) {
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (close(index->fd) < 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail_index_set_syscall_error(index, "close()");
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen }
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen index->map = old_map;
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen index->hdr = index->map->hdr;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen index->fd = old_fd;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen index->lock_type = old_lock_type;
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen index->lock_id = old_lock_id;
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen index->shared_lock_count = old_shared_locks;
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen }
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen return ret;
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen}
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen
abb9b8f14e83baca887cf12210bfe480f6cde7a6Timo Sirainenint mail_index_refresh(struct mail_index *index)
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen{
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen struct stat st1, st2;
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainen if (fstat(index->fd, &st1) < 0)
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainen return mail_index_set_syscall_error(index, "fstat()");
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (stat(index->filepath, &st2) < 0) {
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen mail_index_set_syscall_error(index, "stat()");
44fea1d434a885f08b399459748b001a89f61c77Timo Sirainen if (errno != ENOENT)
44fea1d434a885f08b399459748b001a89f61c77Timo Sirainen return -1;
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen /* lost it? recreate */
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen (void)mail_index_mark_corrupted(index);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen return -1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (st1.st_ino != st2.st_ino ||
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen !CMP_DEV_T(st1.st_dev, st2.st_dev)) {
c56500d4363beba4ffa954069ab30f4401849156Timo Sirainen if (mail_index_reopen(index, -1) < 0)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen return -1;
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen return 1;
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen } else {
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen return 0;
57ff998a443881c8959a8e65f6325cf19fefc1d0Timo Sirainen }
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen}
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenstruct mail_cache *mail_index_get_cache(struct mail_index *index)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen{
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen return index->cache;
57ff998a443881c8959a8e65f6325cf19fefc1d0Timo Sirainen}
57ff998a443881c8959a8e65f6325cf19fefc1d0Timo Sirainen
57ff998a443881c8959a8e65f6325cf19fefc1d0Timo Sirainenint mail_index_set_error(struct mail_index *index, const char *fmt, ...)
57ff998a443881c8959a8e65f6325cf19fefc1d0Timo Sirainen{
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen va_list va;
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen i_free(index->error);
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen if (fmt == NULL)
3482fee0e3733456512ba110780824e6daa7ff9fTimo Sirainen index->error = NULL;
3482fee0e3733456512ba110780824e6daa7ff9fTimo Sirainen else {
3482fee0e3733456512ba110780824e6daa7ff9fTimo Sirainen va_start(va, fmt);
3482fee0e3733456512ba110780824e6daa7ff9fTimo Sirainen index->error = i_strdup_vprintf(fmt, va);
3482fee0e3733456512ba110780824e6daa7ff9fTimo Sirainen va_end(va);
3482fee0e3733456512ba110780824e6daa7ff9fTimo Sirainen
3482fee0e3733456512ba110780824e6daa7ff9fTimo Sirainen i_error("%s", index->error);
3482fee0e3733456512ba110780824e6daa7ff9fTimo Sirainen }
3482fee0e3733456512ba110780824e6daa7ff9fTimo Sirainen
3482fee0e3733456512ba110780824e6daa7ff9fTimo Sirainen return -1;
3482fee0e3733456512ba110780824e6daa7ff9fTimo Sirainen}
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenvoid mail_index_set_inconsistent(struct mail_index *index)
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen{
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen index->indexid = 0;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen}
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainenvoid mail_index_mark_corrupted(struct mail_index *index)
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen{
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen struct mail_index_header hdr;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen mail_index_set_inconsistent(index);
b00c511e4675c4a1270d92924fc445cfb8631cf3Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (index->readonly)
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen return;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen /* make sure we can write the header */
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen if (!MAIL_INDEX_MAP_IS_IN_MEMORY(index->map)) {
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen if (mprotect(index->map->mmap_base, sizeof(hdr),
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen PROT_READ | PROT_WRITE) < 0) {
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen mail_index_set_syscall_error(index, "mprotect()");
63fc74d46d781e87edb6388e51a5bf942c5f8eabTimo Sirainen return;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen }
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen }
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen hdr = *index->hdr;
b00c511e4675c4a1270d92924fc445cfb8631cf3Timo Sirainen hdr.flags |= MAIL_INDEX_HDR_FLAG_CORRUPTED;
b00c511e4675c4a1270d92924fc445cfb8631cf3Timo Sirainen if (mail_index_write_base_header(index, &hdr) == 0) {
b00c511e4675c4a1270d92924fc445cfb8631cf3Timo Sirainen if (fsync(index->fd) < 0)
b00c511e4675c4a1270d92924fc445cfb8631cf3Timo Sirainen mail_index_set_syscall_error(index, "fsync()");
b00c511e4675c4a1270d92924fc445cfb8631cf3Timo Sirainen }
b00c511e4675c4a1270d92924fc445cfb8631cf3Timo Sirainen}
b00c511e4675c4a1270d92924fc445cfb8631cf3Timo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainenint mail_index_set_syscall_error(struct mail_index *index,
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen const char *function)
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen{
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen i_assert(function != NULL);
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen
b00c511e4675c4a1270d92924fc445cfb8631cf3Timo Sirainen if (ENOSPACE(errno)) {
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen index->nodiskspace = TRUE;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen return -1;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen }
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen return mail_index_set_error(index, "%s failed with index file %s: %m",
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen function, index->filepath);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen}
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen
b00c511e4675c4a1270d92924fc445cfb8631cf3Timo Sirainenint mail_index_file_set_syscall_error(struct mail_index *index,
b00c511e4675c4a1270d92924fc445cfb8631cf3Timo Sirainen const char *filepath,
b00c511e4675c4a1270d92924fc445cfb8631cf3Timo Sirainen const char *function)
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen{
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen i_assert(filepath != NULL);
ba02cf1dae8acbe439f79085603bb93a870cce34Timo Sirainen i_assert(function != NULL);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen if (ENOSPACE(errno)) {
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen index->nodiskspace = TRUE;
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen return -1;
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen }
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen return mail_index_set_error(index, "%s failed with file %s: %m",
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen function, filepath);
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen}
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainenenum mail_index_error mail_index_get_last_error(struct mail_index *index)
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainen{
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen if (index->nodiskspace)
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen return MAIL_INDEX_ERROR_DISKSPACE;
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen if (index->error != NULL)
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen return MAIL_INDEX_ERROR_INTERNAL;
95d9395d15540b3a96f75c7f9fd73e6d8ad5e897Timo Sirainen
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen return MAIL_INDEX_ERROR_NONE;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen}
1b04762685272a53643ac2179939537a44c7c044Timo Sirainen
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainenconst char *mail_index_get_error_message(struct mail_index *index)
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen{
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen return index->error;
38f227941bcf673e0e523c1ac7267bca9cbcd2c4Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainenvoid mail_index_reset_error(struct mail_index *index)
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen{
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen if (index->error != NULL) {
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen i_free(index->error);
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen index->error = NULL;
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen }
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen index->nodiskspace = FALSE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen index->index_lock_timeout = FALSE;
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen}
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainenuint32_t mail_index_uint32_to_offset(uint32_t offset)
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen{
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen unsigned char buf[4];
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen i_assert(offset < 0x40000000);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen i_assert((offset & 3) == 0);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen offset >>= 2;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen buf[0] = 0x80 | ((offset & 0x0fe00000) >> 21);
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen buf[1] = 0x80 | ((offset & 0x001fc000) >> 14);
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen buf[2] = 0x80 | ((offset & 0x00003f80) >> 7);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen buf[3] = 0x80 | (offset & 0x0000007f);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen return *((uint32_t *) buf);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen}
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenuint32_t mail_index_offset_to_uint32(uint32_t offset)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen{
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen const unsigned char *buf = (const unsigned char *) &offset;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if ((offset & 0x80808080) != 0x80808080)
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen return 0;
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen return (((uint32_t)buf[3] & 0x7f) << 2) |
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen (((uint32_t)buf[2] & 0x7f) << 9) |
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen (((uint32_t)buf[1] & 0x7f) << 16) |
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen (((uint32_t)buf[0] & 0x7f) << 23);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen}
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen