mail-index-map.c revision 3675a7e9bd3775ba13fe8bc93915902513a0f1a4
97a9a944b5887e91042b019776c41d5dd74557aferikabele/* Copyright (c) 2003-2007 Dovecot authors, see the included COPYING file */
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowenstatic void mail_index_map_init_extbufs(struct mail_index_map *map,
2e545ce2450a9953665f701bb05350f0d3f26275nd unsigned int initial_count)
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd /* try to use the existing pool's size for initial_count so
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd we don't grow it unneededly */
06ba4a61654b3763ad65f52283832ebf058fdf1cslive p_array_init(&map->extensions, map->extension_pool, initial_count);
06ba4a61654b3763ad65f52283832ebf058fdf1cslive p_array_init(&map->ext_id_map, map->extension_pool, initial_count);
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndbool mail_index_map_lookup_ext(struct mail_index_map *map, const char *name,
c44eeebd065e2c8cd028016b45c58afb480aaf8fdruggeri unsigned int i, size;
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd for (i = 0; i < size; i++) {
117c1f888a14e73cdd821dc6c23eb0411144a41cndunsigned int mail_index_map_ext_hdr_offset(unsigned int name_len)
e7939daf37fd0b91dff4506bde6c9be22046fa21jorton size_t size = sizeof(struct mail_index_ext_header) + name_len;
c57fa68c99b9e13aeafaf473e4feefaff590edb2jortonmail_index_map_register_ext(struct mail_index_map *map,
117c1f888a14e73cdd821dc6c23eb0411144a41cnd ext->index_idx = mail_index_ext_register(map->index, name,
117c1f888a14e73cdd821dc6c23eb0411144a41cnd /* Update index ext_id -> map ext_id mapping. Fill non-used
117c1f888a14e73cdd821dc6c23eb0411144a41cnd ext_ids with (uint32_t)-1 */
9cb641b95a976f28161ff3eb5dc71105a8f75ddeminfrin while (array_count(&map->ext_id_map) < ext->index_idx)
cb89c9a75694a1cde836412059863a69d1349addkbrandint mail_index_map_ext_get_next(struct mail_index_map *map,
cb89c9a75694a1cde836412059863a69d1349addkbrand unsigned int *offset_p,
cb89c9a75694a1cde836412059863a69d1349addkbrand const char **name_r)
117c1f888a14e73cdd821dc6c23eb0411144a41cnd /* Extension header contains:
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd - struct mail_index_ext_header
c44eeebd065e2c8cd028016b45c58afb480aaf8fdruggeri - name (not 0-terminated)
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd - 64bit alignment padding
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar - extension header contents
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar - 64bit alignment padding
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar return -1;
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar offset += mail_index_map_ext_hdr_offset(ext_hdr->name_size);
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar return -1;
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar *name_r = t_strndup(CONST_PTR_OFFSET(map->hdr_base, name_offset),
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar /* we allow only plain ASCII names, so this extension
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar is most likely broken */
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar /* finally make sure that the hdr_size is small enough.
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar do this last so that we could return a usable name. */
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar offset += MAIL_INDEX_HEADER_SIZE_ALIGN(ext_hdr->hdr_size);
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar return -1;
1f1b6bf13313fdd14a45e52e553d3ff28689b717coarint mail_index_map_ext_hdr_check(const struct mail_index_header *hdr,
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar if ((ext_hdr->record_size == 0 && ext_hdr->hdr_size == 0) ||
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar (ext_hdr->record_align == 0 && ext_hdr->record_size != 0)) {
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar return -1;
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar return -1;
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar if (ext_hdr->record_offset + ext_hdr->record_size > hdr->record_size) {
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar "outside record size (%u+%u > %u)",
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar return -1;
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar ((ext_hdr->record_offset % ext_hdr->record_align) != 0 ||
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar *error_r = t_strdup_printf("Record field alignmentation %u "
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar return -1;
1f1b6bf13313fdd14a45e52e553d3ff28689b717coarstatic int mail_index_map_parse_extensions(struct mail_index_map *map)
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar /* extension headers always start from 64bit offsets, so if base header
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar doesn't happen to be 64bit aligned we'll skip some bytes */
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar offset = MAIL_INDEX_HEADER_SIZE_ALIGN(map->hdr.base_header_size);
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar if (offset >= map->hdr.header_size && map->extension_pool == NULL) {
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar /* nothing to do, skip allocatations and all */
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar for (i = 0; i < old_count; i++)
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar mail_index_set_error(index, "Corrupted index file %s: "
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar "Header extension #%d (%s) goes outside header",
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar return -1;
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar mail_index_set_error(index, "Corrupted index file %s: "
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar "Broken extension #%d (%s): %s",
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar return -1;
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar mail_index_set_error(index, "Corrupted index file %s: "
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar "Duplicate header extension %s",
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar return -1;
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar mail_index_map_register_ext(map, name, ext_offset, ext_hdr);
1f1b6bf13313fdd14a45e52e553d3ff28689b717coarint mail_index_map_parse_keywords(struct mail_index_map *map)
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar const char *name;
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar if (!mail_index_map_lookup_ext(map, "keywords", &idx)) {
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar /* Extension header contains:
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar - struct mail_index_keyword_header
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar - struct mail_index_keyword_header_rec * keywords_count
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar - const char names[] * keywords_count
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar kw_hdr = CONST_PTR_OFFSET(map->hdr_base, ext->hdr_offset);
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar name = (const char *)(kw_rec + kw_hdr->keywords_count);
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar old_count = !array_is_created(&map->keyword_idx_map) ? 0 :
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar /* Keywords can only be added into same mapping. Removing requires a
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar new mapping (recreating the index file) */
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar /* nothing changed */
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar /* make sure the header is valid */
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar mail_index_set_error(index, "Corrupted index file %s: "
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar "Keywords removed unexpectedly",
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar return -1;
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar if ((size_t)(name - (const char *)kw_hdr) > ext->hdr_size) {
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar mail_index_set_error(index, "Corrupted index file %s: "
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar "keywords_count larger than header size",
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar return -1;
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar name_area_end_offset = (const char *)kw_hdr + ext->hdr_size - name;
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar mail_index_set_error(index, "Corrupted index file %s: "
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar "name_offset points outside allocated header",
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar return -1;
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar mail_index_set_error(index, "Corrupted index file %s: "
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar "Keyword header doesn't end with NUL",
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar return -1;
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar /* create file -> index mapping */
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar i_array_init(&map->keyword_idx_map, kw_hdr->keywords_count);
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar /* Check that existing headers are still the same. It's behind DEBUG
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar since it's pretty useless waste of CPU normally. */
1f1b6bf13313fdd14a45e52e553d3ff28689b717coar for (i = 0; i < array_count(&map->keyword_idx_map); i++) {
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd const unsigned int *old_idx;
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd unsigned int idx;
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd "Keywords changed unexpectedly",
06ba4a61654b3763ad65f52283832ebf058fdf1cslive /* Register the newly seen keywords */
e487d6c09669296f94a5190cc34586a98e624a00nd unsigned int idx;
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd "Empty keyword name in header",
9a58dc6a2b26ec128b1270cf48810e705f1a90dbsf return -1;
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd mail_index_keyword_lookup_or_create(index, keyword, &idx);
06ba4a61654b3763ad65f52283832ebf058fdf1cslivestatic bool mail_index_check_header_compat(struct mail_index *index,
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd /* major version change - handle silently(?) */
281c0b44de97d9942428ff51bc2be0e8e61ed87bkess if ((hdr->flags & MAIL_INDEX_HDR_FLAG_CORRUPTED) != 0) {
281c0b44de97d9942428ff51bc2be0e8e61ed87bkess /* we've already complained about it */
281c0b44de97d9942428ff51bc2be0e8e61ed87bkess /* architecture change */
281c0b44de97d9942428ff51bc2be0e8e61ed87bkess mail_index_set_error(index, "Rebuilding index file %s: "
281c0b44de97d9942428ff51bc2be0e8e61ed87bkess "CPU architecture changed",
281c0b44de97d9942428ff51bc2be0e8e61ed87bkess if (hdr->base_header_size < MAIL_INDEX_HEADER_MIN_SIZE ||
281c0b44de97d9942428ff51bc2be0e8e61ed87bkess mail_index_set_error(index, "Corrupted index file %s: "
281c0b44de97d9942428ff51bc2be0e8e61ed87bkess "Corrupted header sizes (base %u, full %u)",
281c0b44de97d9942428ff51bc2be0e8e61ed87bkess mail_index_set_error(index, "Corrupted index file %s: "
281c0b44de97d9942428ff51bc2be0e8e61ed87bkess "indexid changed: %u -> %u",
281c0b44de97d9942428ff51bc2be0e8e61ed87bkessint mail_index_map_check_header(struct mail_index_map *map)
281c0b44de97d9942428ff51bc2be0e8e61ed87bkess if (!mail_index_check_header_compat(index, hdr, (uoff_t)-1))
281c0b44de97d9942428ff51bc2be0e8e61ed87bkess return -1;
281c0b44de97d9942428ff51bc2be0e8e61ed87bkess /* following some extra checks that only take a bit of CPU */
281c0b44de97d9942428ff51bc2be0e8e61ed87bkess if (hdr->record_size < sizeof(struct mail_index_record)) {
281c0b44de97d9942428ff51bc2be0e8e61ed87bkess mail_index_set_error(index, "Corrupted index file %s: "
281c0b44de97d9942428ff51bc2be0e8e61ed87bkess sizeof(struct mail_index_record));
0844fff26cb7719e0f0a368d88544156ed6374b6sf /* upgrade silently from v1.0 */
0844fff26cb7719e0f0a368d88544156ed6374b6sf /* last message's UID must be smaller than next_uid.
0844fff26cb7719e0f0a368d88544156ed6374b6sf also make sure it's not zero. */
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndstatic void mail_index_map_copy_hdr(struct mail_index_map *map,
9a58dc6a2b26ec128b1270cf48810e705f1a90dbsf /* header smaller than ours, make a copy so our newer headers
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd won't have garbage in them */
06ba4a61654b3763ad65f52283832ebf058fdf1cslive /* FIXME: backwards compatibility, remove later. In case this index is
06ba4a61654b3763ad65f52283832ebf058fdf1cslive accessed with Dovecot v1.0, avoid recent message counter errors. */
97a9a944b5887e91042b019776c41d5dd74557aferikabelestatic int mail_index_mmap(struct mail_index_map *map, uoff_t file_size)
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd /* too large file to map into memory */
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd return -1;
06ba4a61654b3763ad65f52283832ebf058fdf1cslive rec_map->mmap_base = mmap(NULL, file_size, PROT_READ | PROT_WRITE,
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd /* major version change - handle silently */
9da97ff0bac3a0ff56a9cdebe6e5ab563636aa86jailletc if (!mail_index_check_header_compat(index, hdr, rec_map->mmap_size)) {
6bf23e5b5269a4780ed2be820a969831d1cc785fkbrand /* Can't use this file */
06ba4a61654b3763ad65f52283832ebf058fdf1cslive mail_index_set_error(index, "Corrupted index file %s: "
06ba4a61654b3763ad65f52283832ebf058fdf1cslive "messages_count too large (%u > %u)",
06ba4a61654b3763ad65f52283832ebf058fdf1cslive rec_map->records = PTR_OFFSET(rec_map->mmap_base, map->hdr.header_size);
e487d6c09669296f94a5190cc34586a98e624a00ndstatic int mail_index_read_header(struct mail_index *index,
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd /* try to read the whole header, but it's not necessarily an error to
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd read less since the older versions of the index format could be
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd smaller. Request reading up to buf_size, but accept if we only got
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd the header. */
031e53981ec261154d2ee4c83bf321af203d3e24kbrand } while (ret > 0 && pos < sizeof(struct mail_index_header));
6bf23e5b5269a4780ed2be820a969831d1cc785fkbrand const void *buf;
6bf23e5b5269a4780ed2be820a969831d1cc785fkbrand ret = mail_index_read_header(index, read_buf, sizeof(read_buf), &pos);
6bf23e5b5269a4780ed2be820a969831d1cc785fkbrand if (pos > (ssize_t)offsetof(struct mail_index_header, major_version) &&
031e53981ec261154d2ee4c83bf321af203d3e24kbrand /* major version change - handle silently */
6c4ef4a72d9897e53365b94103f4bd819fd0d3acnd if (!mail_index_check_header_compat(index, hdr, file_size)) {
031e53981ec261154d2ee4c83bf321af203d3e24kbrand /* Can't use this file */
031e53981ec261154d2ee4c83bf321af203d3e24kbrand /* place the base header into memory. */
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd /* @UNSAFE: read the rest of the header into memory */
06ba4a61654b3763ad65f52283832ebf058fdf1cslive if (ret > 0) {
6bf23e5b5269a4780ed2be820a969831d1cc785fkbrand /* header read, read the records now. */
6bf23e5b5269a4780ed2be820a969831d1cc785fkbrand records_size = (size_t)hdr->messages_count * hdr->record_size;
6bf23e5b5269a4780ed2be820a969831d1cc785fkbrand records_size / hdr->record_size != hdr->messages_count)) {
6bf23e5b5269a4780ed2be820a969831d1cc785fkbrand records_size = (size_t)records_count * hdr->record_size;
6bf23e5b5269a4780ed2be820a969831d1cc785fkbrand mail_index_set_error(index, "Corrupted index file %s: "
6bf23e5b5269a4780ed2be820a969831d1cc785fkbrand "messages_count too large (%u > %u)",
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd /* @UNSAFE */
06ba4a61654b3763ad65f52283832ebf058fdf1cslive data = buffer_append_space_unsafe(map->rec_map->buffer,
f6066dc0a6ad0432b74774e290c04c3cc4aa2dafrbowen ret = pread_full(index->fd, data, records_size - extra,
06ba4a61654b3763ad65f52283832ebf058fdf1cslive if (ret < 0) {
97a9a944b5887e91042b019776c41d5dd74557aferikabele /* a new index file was renamed over this one. */
1c0dfae82e30aa9fe4a22f00a83abd827b7a63bfsf if (ret == 0) {
97a9a944b5887e91042b019776c41d5dd74557aferikabele "Corrupted index file %s: File too small",
06ba4a61654b3763ad65f52283832ebf058fdf1cslivestatic int mail_index_read_map(struct mail_index_map *map, uoff_t file_size,
06ba4a61654b3763ad65f52283832ebf058fdf1cslive unsigned int *lock_id)
06ba4a61654b3763ad65f52283832ebf058fdf1cslive unsigned int i, count;
06ba4a61654b3763ad65f52283832ebf058fdf1cslive /* notify all "sync lost" handlers */
06ba4a61654b3763ad65f52283832ebf058fdf1cslive handlers = array_get(&index->sync_lost_handlers, &count);
1c0dfae82e30aa9fe4a22f00a83abd827b7a63bfsf for (i = 0; i < count; i++)
1c0dfae82e30aa9fe4a22f00a83abd827b7a63bfsf for (i = 0;; i++) {
1c0dfae82e30aa9fe4a22f00a83abd827b7a63bfsf /* fstat() below failed */
06ba4a61654b3763ad65f52283832ebf058fdf1cslive /* ESTALE - reopen index file */
06ba4a61654b3763ad65f52283832ebf058fdf1cslive if (ret <= 0) {
06ba4a61654b3763ad65f52283832ebf058fdf1cslive if (ret == 0) {
06ba4a61654b3763ad65f52283832ebf058fdf1cslive /* the file was lost */
1c0dfae82e30aa9fe4a22f00a83abd827b7a63bfsf return -1;
06ba4a61654b3763ad65f52283832ebf058fdf1cslivestatic void mail_index_header_init(struct mail_index *index,
61d0f219eba8ce646ffd6f2738a60e36e66cf654rbowen hdr->compat_flags |= MAIL_INDEX_COMPAT_LITTLE_ENDIAN;
cc094350da96eecbed411d410393716ada05c402igalicstruct mail_index_map *mail_index_map_alloc(struct mail_index *index)
e487d6c09669296f94a5190cc34586a98e624a00nd /* a bit kludgy way to do this, but it initializes everything
97a9a944b5887e91042b019776c41d5dd74557aferikabele nicely and correctly */
97a9a944b5887e91042b019776c41d5dd74557aferikabelestatic int mail_index_map_latest_file(struct mail_index *index)
97a9a944b5887e91042b019776c41d5dd74557aferikabele unsigned int lock_id;
06ba4a61654b3763ad65f52283832ebf058fdf1cslive if (ret <= 0) {
97a9a944b5887e91042b019776c41d5dd74557aferikabele /* the index file is lost/broken. let's hope that we can
97a9a944b5887e91042b019776c41d5dd74557aferikabele build it from the transaction log. */
06ba4a61654b3763ad65f52283832ebf058fdf1cslive /* the index file is still open, lock it */
3bfe5718442b1bc7401a4d513762858997bcf708sf nfs_flush_attr_cache_fd_locked(index->filepath, index->fd);
3bfe5718442b1bc7401a4d513762858997bcf708sf return -1;
3bfe5718442b1bc7401a4d513762858997bcf708sf /* mmaping seems to be slower than just reading the file, so even if
173e5f4d5ec46b5febb74ce860d753bb1faaba0fsf mmap isn't disabled don't use it unless the file is large enough */
173e5f4d5ec46b5febb74ce860d753bb1faaba0fsf use_mmap = !index->mmap_disable && file_size != (uoff_t)-1 &&
e7939daf37fd0b91dff4506bde6c9be22046fa21jorton ret = mail_index_read_map(new_map, file_size, &lock_id);
e7939daf37fd0b91dff4506bde6c9be22046fa21jorton /* make sure the header is ok before using this mapping */
e7939daf37fd0b91dff4506bde6c9be22046fa21jorton /* fsck and try again */
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd /* fsck replaced the map */
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd if (ret <= 0) {
06ba4a61654b3763ad65f52283832ebf058fdf1cslive index->last_read_log_file_seq = new_map->hdr.log_file_seq;
ffc28236b928ae15fc998df17ad4a8fb12b137bcrbowen /* first try updating the existing mapping from transaction log. */
ffc28236b928ae15fc998df17ad4a8fb12b137bcrbowen if (index->map->hdr.indexid != 0 && index->indexid != 0) {
ffc28236b928ae15fc998df17ad4a8fb12b137bcrbowen /* we're not creating the index, or opening transaction log.
9a58dc6a2b26ec128b1270cf48810e705f1a90dbsf sync this as a view from transaction log. */
ffc28236b928ae15fc998df17ad4a8fb12b137bcrbowen if (ret == 0) {
ffc28236b928ae15fc998df17ad4a8fb12b137bcrbowen /* try to open and read the latest index. if it fails for
ffc28236b928ae15fc998df17ad4a8fb12b137bcrbowen any reason, we'll fallback to updating the existing mapping
ffc28236b928ae15fc998df17ad4a8fb12b137bcrbowen from transaction logs (which we'll also do even if the
ffc28236b928ae15fc998df17ad4a8fb12b137bcrbowen reopening succeeds) */
ffc28236b928ae15fc998df17ad4a8fb12b137bcrbowen /* if we're creating the index file, we don't have any
e7939daf37fd0b91dff4506bde6c9be22046fa21jorton logs yet */
e7939daf37fd0b91dff4506bde6c9be22046fa21jorton if (index->log->head != NULL && index->indexid != 0) {
e7939daf37fd0b91dff4506bde6c9be22046fa21jorton /* and update the map with the latest changes from
e7939daf37fd0b91dff4506bde6c9be22046fa21jorton transaction log */
e7939daf37fd0b91dff4506bde6c9be22046fa21jortonstatic void mail_index_record_map_free(struct mail_index_map *map,
58caaee3494bc4873ae3b89a954beab99143be2cjorton if (munmap(rec_map->mmap_base, rec_map->mmap_size) < 0)
ad6b0682327d02eb005f5b8a99ef94fe0b73ea47jorton mail_index_set_syscall_error(map->index, "munmap()");
ad6b0682327d02eb005f5b8a99ef94fe0b73ea47jortonstatic void mail_index_record_map_unlink(struct mail_index_map *map)
ad6b0682327d02eb005f5b8a99ef94fe0b73ea47jorton unsigned int i, count;
ad6b0682327d02eb005f5b8a99ef94fe0b73ea47jorton for (i = 0; i < count; i++) {
c57fa68c99b9e13aeafaf473e4feefaff590edb2jortonstatic void mail_index_map_copy_records(struct mail_index_record_map *dest,
c57fa68c99b9e13aeafaf473e4feefaff590edb2jorton unsigned int record_size)
c57fa68c99b9e13aeafaf473e4feefaff590edb2jorton dest->buffer = buffer_create_dynamic(default_pool, I_MIN(size, 1024));
01f52ba6a87aa39d3873a441369828875c471823trawick dest->records = buffer_get_modifiable_data(dest->buffer, NULL);
c57fa68c99b9e13aeafaf473e4feefaff590edb2jorton /* if the map is ever written back to disk, we need to keep track of
c57fa68c99b9e13aeafaf473e4feefaff590edb2jorton what has changed. */
c57fa68c99b9e13aeafaf473e4feefaff590edb2jortonstatic void mail_index_map_copy_header(struct mail_index_map *dest,
c57fa68c99b9e13aeafaf473e4feefaff590edb2jorton /* use src->hdr copy directly, because if we got here
c57fa68c99b9e13aeafaf473e4feefaff590edb2jorton from syncing it has the latest changes. */
c57fa68c99b9e13aeafaf473e4feefaff590edb2jorton I_MIN(sizeof(dest->hdr), src->hdr.base_header_size));
01f52ba6a87aa39d3873a441369828875c471823trawick buffer_write(dest->hdr_copy_buf, src->hdr.base_header_size,
c57fa68c99b9e13aeafaf473e4feefaff590edb2jorton dest->hdr_base = buffer_get_modifiable_data(dest->hdr_copy_buf, NULL);
c57fa68c99b9e13aeafaf473e4feefaff590edb2jorton i_assert(dest->hdr_copy_buf->used == dest->hdr.header_size);
817a2329f22ff84555a29b23248894b999a7336fjimstruct mail_index_map *mail_index_map_clone(const struct mail_index_map *map)
817a2329f22ff84555a29b23248894b999a7336fjim unsigned int i, count;
817a2329f22ff84555a29b23248894b999a7336fjim mem_map->rec_map = mail_index_record_map_alloc(mem_map);
817a2329f22ff84555a29b23248894b999a7336fjim /* copy extensions */
817a2329f22ff84555a29b23248894b999a7336fjim array_append_array(&mem_map->extensions, &map->extensions);
817a2329f22ff84555a29b23248894b999a7336fjim array_append_array(&mem_map->ext_id_map, &map->ext_id_map);
817a2329f22ff84555a29b23248894b999a7336fjim /* fix the name pointers to use our own pool */
817a2329f22ff84555a29b23248894b999a7336fjim extensions = array_get_modifiable(&mem_map->extensions, &count);
0237f43ab925775250e266e479d0a337ff374a4btakashi for (i = 0; i < count; i++) {
0237f43ab925775250e266e479d0a337ff374a4btakashi extensions[i].name = p_strdup(mem_map->extension_pool,
0237f43ab925775250e266e479d0a337ff374a4btakashi /* copy keyword map */
434a9abc415b2a75ad9ac513ff5ffccedbb3c1e9kbrandvoid mail_index_record_map_move_to_private(struct mail_index_map *map)
434a9abc415b2a75ad9ac513ff5ffccedbb3c1e9kbrandvoid mail_index_map_move_to_memory(struct mail_index_map *map)
434a9abc415b2a75ad9ac513ff5ffccedbb3c1e9kbrand new_map = array_count(&map->rec_map->maps) == 1 ? map->rec_map :