mail-index.c revision b79ec51bdeef6ef950eb5e890e65cc0491cf5fe9
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
573f0491a5733fe21fa062a455acb4790b4e0499Timo Sirainenstatic int mail_index_try_open_only(struct mail_index *index);
65f8fb656051f1059f7b5a2da9c5555adcc30439Timo Sirainenstruct mail_index *mail_index_alloc(const char *dir, const char *prefix)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen index->extension_pool = pool_alloconly_create("extension", 256);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen index->extensions = buffer_create_dynamic(index->extension_pool, 64);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen index->sync_handlers = buffer_create_dynamic(default_pool, 64);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen index->sync_lost_handlers = buffer_create_dynamic(default_pool, 64);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen index->expunge_handlers = buffer_create_dynamic(default_pool, 32);
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen mail_index_ext_register(index, "keywords", 128, 2, 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index->keywords_pool = pool_alloconly_create("keywords", 512);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen index->keywords_buf = buffer_create_dynamic(default_pool, 64);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen buffer_append_zero(index->keywords_buf, sizeof(const char *));
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainenvoid mail_index_set_permissions(struct mail_index *index,
dfaefeabae939803ceb8c503101e86b5496541d1Timo Sirainenuint32_t mail_index_ext_register(struct mail_index *index, const char *name,
9847ec56efa15fa063eea9988eee2d4ed9ec7d58Timo Sirainen unsigned int i;
d46a1e3f999dda802dc5137e883adcd7a6629cd3Timo Sirainen extensions = buffer_get_data(index->extensions, &ext_count);
d1e843e77f4760e303c53d9fce10123fc8d230a1Timo Sirainen sizeof(struct mail_index_sync_handler) == ext_count);
291ce16fffca75e8598a8c9dceb08613413dcb07Timo Sirainen /* see if it's already there */
291ce16fffca75e8598a8c9dceb08613413dcb07Timo Sirainen for (i = 0; i < ext_count; i++) {
08e9fd42eb8007e1f9db62c088eef74f906114a5Josef 'Jeff' Sipek if (strcmp(extensions[i].name, name) == 0)
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen ext.name = p_strdup(index->extension_pool, name);
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen buffer_append(index->extensions, &ext, sizeof(ext));
97ae33602db7d5bc8eede82512a965d49ab8853bTimo Sirainenvoid mail_index_register_expunge_handler(struct mail_index *index,
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen buffer_write(index->expunge_handlers, ext_id * sizeof(cb),
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainenvoid mail_index_register_sync_handler(struct mail_index *index, uint32_t ext_id,
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen memset(&h, 0, sizeof(h));
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen buffer_write(index->sync_handlers, ext_id * sizeof(h), &h, sizeof(h));
eecb235c14b49c01774134ea593c266f2d2c2be1Timo Sirainenvoid mail_index_register_sync_lost_handler(struct mail_index *index,
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen buffer_append(index->sync_lost_handlers, &cb, sizeof(cb));
98c217499d578495e982ea6010ebff831e9669aeMartti Rannanjärvistatic void mail_index_map_init_extbufs(struct mail_index_map *map,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen ext_size = initial_count * sizeof(struct mail_index_ext);
f1743785713e7632459d623d5df2108f4b93accbTimo Sirainen ext_id_map_size = initial_count * sizeof(uint32_t);
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen map->extensions = buffer_create_dynamic(map->extension_pool, ext_size);
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen buffer_create_dynamic(map->extension_pool, ext_id_map_size);
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainenuint32_t mail_index_map_lookup_ext(struct mail_index_map *map, const char *name)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen extensions = buffer_get_data(map->extensions, &size);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen for (i = 0; i < size; i++) {
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainenmail_index_map_register_ext(struct mail_index *index,
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen uint32_t idx, ext_id, empty_id = (uint32_t)-1;
cff1f182205e674285cf3ff446a0dcf7afea277dTimo Sirainen i_assert(mail_index_map_lookup_ext(map, name) == (uint32_t)-1);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen ext = buffer_append_space_unsafe(map->extensions, sizeof(*ext));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ext->name = p_strdup(map->extension_pool, name);
d3280fe317a4598c0868cc440e7a1191c06d0db3Timo Sirainen ext_id = mail_index_ext_register(index, name, hdr_size,
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen while (map->ext_id_map->used < ext_id * sizeof(uint32_t))
6469cf211a57433335641725dc236ebb2b9fdd3bTimo Sirainen buffer_append(map->ext_id_map, &empty_id, sizeof(empty_id));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen buffer_write(map->ext_id_map, ext_id * sizeof(uint32_t),
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainenstatic int size_check(size_t *size_left, size_t size)
aa47c9bd1d1fc70cd699c49fd1ca92dbc7615953Timo Sirainen size_t size = sizeof(struct mail_index_ext_header) + name_len;
aa47c9bd1d1fc70cd699c49fd1ca92dbc7615953Timo Sirainen return MAIL_INDEX_HEADER_SIZE_ALIGN(size) - size;
aa47c9bd1d1fc70cd699c49fd1ca92dbc7615953Timo Sirainenstatic int mail_index_read_extensions(struct mail_index *index,
c0d069950af1dbc6a4e5c3de3bf2e437796e3ae0Timo Sirainen unsigned int i, old_count;
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen /* extension headers always start from 64bit offsets, so if base header
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen doesn't happen to be 64bit aligned we'll skip some bytes */
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen offset = MAIL_INDEX_HEADER_SIZE_ALIGN(map->hdr.base_header_size);
2584e86cc2d8c31ba30a4109cf4ba09d1e37e28aTimo Sirainen if (offset >= map->hdr.header_size && map->extension_pool == NULL) {
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen /* nothing to do, skip allocatations and all */
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen old_count = index->extensions->used / sizeof(struct mail_index_ext);
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen mail_index_map_init_extbufs(map, old_count + 5);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (i = 0; i < old_count; i++)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen buffer_append(map->ext_id_map, &ext_id, sizeof(ext_id));
b2c1349cf07410aefab0f5b17153af9e5cfcf48fTimo Sirainen ext_hdr = CONST_PTR_OFFSET(map->hdr_base, offset);
dbe64f3893616a4005c8946be75d2dc8f6823d72Timo Sirainen if (!size_check(&size_left, sizeof(*ext_hdr)) ||
8a13b020f90e080570658b18c042e7e352c8b14fTimo Sirainen !size_check(&size_left, ext_hdr->name_size) ||
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen !size_check(&size_left, get_align(ext_hdr->name_size)) ||
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen "Header extension goes outside header",
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen offset += ext_hdr->name_size + get_align(ext_hdr->name_size);
f3bb2fbe87425dc89a839908985af496f7f65702Timo Sirainen name = t_strndup(CONST_PTR_OFFSET(map->hdr_base, name_offset),
bd1b2615928a1e8be190cb0405754f0aec8cac2fTimo Sirainen if (mail_index_map_lookup_ext(map, name) != (uint32_t)-1) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen "Duplicate header extension %s",
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainen offset += MAIL_INDEX_HEADER_SIZE_ALIGN(ext_hdr->hdr_size);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenint mail_index_map_read_keywords(struct mail_index *index,
0177594fa5217b02001f4ec8752154fd2b05c545Timo Sirainen const struct mail_index_keyword_header *kw_hdr;
0177594fa5217b02001f4ec8752154fd2b05c545Timo Sirainen const struct mail_index_keyword_header_rec *kw_rec;
0177594fa5217b02001f4ec8752154fd2b05c545Timo Sirainen unsigned int i, name_len;
2c70086138fe7ac9abf52cd4223c224fe0bbb488Timo Sirainen ext_id = mail_index_map_lookup_ext(map, "keywords");
1ae5d61ec366fdb2f3c5b150ca378d6141b0f4bdTimo Sirainen kw_hdr = CONST_PTR_OFFSET(map->hdr_base, ext->hdr_offset);
1ae5d61ec366fdb2f3c5b150ca378d6141b0f4bdTimo Sirainen name = (const char *)(kw_rec + kw_hdr->keywords_count);
1ae5d61ec366fdb2f3c5b150ca378d6141b0f4bdTimo Sirainen if ((size_t)(name - (const char *)kw_hdr) > ext->hdr_size) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen "keywords_count larger than header size",
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* make sure the header is valid */
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen name_len = (const char *)kw_hdr + ext->hdr_size - name;
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen for (i = 0; i < kw_hdr->keywords_count; i++) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
d938e9e4ec4c0f326dffd5ebe42c1ad893ce7e52Timo Sirainen "name_offset points outside allocated header",
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen "header doesn't end with NUL",
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen map->keywords_pool = pool_alloconly_create("keywords", 1024);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen /* Save keywords in memory. Only new keywords should come into the
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen mapping, so keep the existing keyword strings in memory to allow
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen mail_index_lookup_keywords() to safely return direct pointers
546335814920fb6b5b44c68c7803e654eefeae9dTimo Sirainen into them. */
546335814920fb6b5b44c68c7803e654eefeae9dTimo Sirainen if (kw_hdr->keywords_count < map->keywords_count) {
546335814920fb6b5b44c68c7803e654eefeae9dTimo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
4b41218f9e09386ad5d8f279355aad1dfb64392dTimo Sirainen "Keywords removed unexpectedly",
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen if (kw_hdr->keywords_count == map->keywords_count) {
eb1572d7c44ebc7b0b039d085c3dbab2ef7043ddTimo Sirainen /* nothing changed */
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen /* @UNSAFE */
42507d758b053bb483de58fba55c73a9eb5d3fbaTimo Sirainen keywords_list[i] = p_strdup(map->keywords_pool,
42507d758b053bb483de58fba55c73a9eb5d3fbaTimo Sirainenconst char *const *mail_index_get_keywords(struct mail_index *index)
817d027593510c3ba70ad542ce0011f5f6916d1eTimo Sirainen (void)mail_index_map_read_keywords(index, index->map);
6ae329de09afb7214c906d762320847e05469d53Timo Sirainenstatic int mail_index_check_header(struct mail_index *index,
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen const struct mail_index_header *hdr = &map->hdr;
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen unsigned char compat_data[sizeof(hdr->compat_data)];
fcfe85637e1ee14a9fc39c41fd6ceca106301542Timo Sirainen compat_data[0] = MAIL_INDEX_COMPAT_LITTLE_ENDIAN;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if (hdr->major_version != MAIL_INDEX_MAJOR_VERSION) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* major version change - handle silently(?) */
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen if (memcmp(hdr->compat_data, compat_data, sizeof(compat_data)) != 0) {
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen /* architecture change - handle silently(?) */
7baab0b0b60df7ce9093d0881cd322dff1e79491Timo Sirainen if ((map->hdr.flags & MAIL_INDEX_HDR_FLAG_CORRUPTED) != 0) {
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen /* we've already complained about it */
3857e2945a3b6744d603f0f5a656849ed8436ba3Timo Sirainen /* following some extra checks that only take a bit of CPU */
f90cbe597c41d5cc91debd371f8648bd8e6ffbc2Timo Sirainen if (hdr->uid_validity == 0 && hdr->next_uid != 1) {
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
33b469d1ca66dd2cc496d2d990b8b98e72952a29Timo Sirainen "uid_validity = 0, next_uid = %u",
6b0d8106ae51ffc6ce45636b34d2e21cbefca7fdTimo Sirainen if (hdr->record_size < sizeof(struct mail_index_record)) {
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
eb64c3586d854cddd693f0b811d897399076a441Timo Sirainen sizeof(struct mail_index_record));
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen if (hdr->recent_messages_count > hdr->messages_count ||
d81131d3bbb4f0befb62a661d1785cf8c84a17e2Timo Sirainen hdr->seen_messages_count > hdr->messages_count ||
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen hdr->deleted_messages_count > hdr->messages_count)
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen if (hdr->first_recent_uid_lowwater > hdr->next_uid ||
4e3bcf7fdaeef92dd07a2acb1ded58422a907e87Timo Sirainen hdr->first_unseen_uid_lowwater > hdr->next_uid ||
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen hdr->first_deleted_uid_lowwater > hdr->next_uid)
540555c5b435203e1c26c8e7b924b2643ae07ae3Timo Sirainen return mail_index_read_extensions(index, map);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainenstatic void mail_index_map_clear(struct mail_index *index,
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (munmap(map->mmap_base, map->mmap_size) < 0)
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen mail_index_set_syscall_error(index, "munmap()");
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainenvoid mail_index_unmap(struct mail_index *index, struct mail_index_map *map)
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainenstatic void mail_index_unmap_forced(struct mail_index *index,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainenstatic void mail_index_map_copy_hdr(struct mail_index_map *map,
21aaa6affb9f134112b75b5db737309fc35ef1cfMartti Rannanjärvi if (hdr->base_header_size < sizeof(map->hdr)) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* header smaller than ours, make a copy so our newer headers
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen won't have garbage in them */
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen memcpy(&map->hdr, hdr, hdr->base_header_size);
838e367716bbd5e44b4a1691db9cbf72af53e9f0Timo Sirainenstatic int mail_index_mmap(struct mail_index *index, struct mail_index_map *map)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen /* we had temporarily used a buffer, eg. for updating index */
13e130c3af3032982de6b1d13c6dcddda9164848Timo Sirainen mail_index_set_syscall_error(index, "mmap()");
310767ca33e7636d40ec45dee68a2c319a5fa3c0Timo Sirainen offsetof(struct mail_index_header, major_version) &&
310767ca33e7636d40ec45dee68a2c319a5fa3c0Timo Sirainen hdr->major_version != MAIL_INDEX_MAJOR_VERSION) {
310767ca33e7636d40ec45dee68a2c319a5fa3c0Timo Sirainen /* major version change - handle silently */
2c8ca7e88ec881c473fb90e5f647c1f563877164Timo Sirainen if (map->mmap_size < MAIL_INDEX_HEADER_MIN_SIZE) {
6c51e3c3dc8dc5dc6fef2280b7c2c9ebef3de8f0Aki Tuomi mail_index_set_error(index, "Corrupted index file %s: "
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen records_count = (map->mmap_size - hdr->header_size) /
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen "messages_count too large (%u > %u)",
2d01cc1880cf2afd4fb1c8ad7fa6ce78e562e71eTimo Sirainen map->records = PTR_OFFSET(map->mmap_base, map->hdr.header_size);
e2d268e9531227ead6a98466ecf3c046c857ef70Timo Sirainenstatic int mail_index_read_header(struct mail_index *index,
194603b35061fea1ee8d171a7104b6985c610966Timo Sirainen for (pos = 0; ret > 0 && pos < sizeof(*hdr); ) {
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainenstatic int mail_index_read_map(struct mail_index *index,
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen ret = mail_index_read_header(index, &hdr, &pos);
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen if (pos > (ssize_t)offsetof(struct mail_index_header, major_version) &&
e2d268e9531227ead6a98466ecf3c046c857ef70Timo Sirainen hdr.major_version != MAIL_INDEX_MAJOR_VERSION) {
e2d268e9531227ead6a98466ecf3c046c857ef70Timo Sirainen /* major version change - handle silently */
1eaaa2c9003cf3fbf672d597473e3f84e70d2ee6Timo Sirainen if (ret >= 0 && pos >= MAIL_INDEX_HEADER_MIN_SIZE &&
2d01cc1880cf2afd4fb1c8ad7fa6ce78e562e71eTimo Sirainen if (hdr.base_header_size < MAIL_INDEX_HEADER_MIN_SIZE ||
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
900bb5e316d030cdebff7ee128ce65881dfb27f7Timo Sirainen "Corrupted header sizes (base %u, full %u)",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen buffer_append(map->hdr_copy_buf, &hdr, hdr.base_header_size);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* @UNSAFE */
e63bdfedcf61e1a9ee21990140cbd0d0638da7e1Timo Sirainen data = buffer_append_space_unsafe(map->hdr_copy_buf,
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen records_size = hdr.messages_count * hdr.record_size;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen map->buffer = buffer_create_dynamic(default_pool,
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen /* @UNSAFE */
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen data = buffer_append_space_unsafe(map->buffer, records_size);
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen ret = pread_full(index->fd, data, records_size,
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen mail_index_set_syscall_error(index, "pread_full()");
0cce885512b836ce021260a58e7b4f099b36d0f1Timo Sirainen "Corrupted index file %s: File too small",
d0d37a769d7e54646de025a43d2cb888478cb218Timo Sirainen index->sync_log_file_offset = hdr.log_file_int_offset;
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainenstatic int mail_index_sync_from_transactions(struct mail_index *index,
b62140c5849297a800fee942026d9c3cb8c60206Timo Sirainen const struct mail_index_header *map_hdr = &(*map)->hdr;
05150df8fbda6b8fdfafcfb0aa9003f1da4ecacaTimo Sirainen /* read the real log position where we are supposed to be
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen ret = mail_index_read_header(index, &hdr, &pos);
05150df8fbda6b8fdfafcfb0aa9003f1da4ecacaTimo Sirainen mail_index_set_syscall_error(index, "pread()");
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen if (map_hdr->log_file_seq == hdr.log_file_seq &&
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen map_hdr->log_file_int_offset == hdr.log_file_int_offset) {
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen /* nothing to do */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (map_hdr->log_file_seq > hdr.log_file_seq ||
de58be41126e5d68008d2ea706d62ccdc1f29337Timo Sirainen map_hdr->log_file_int_offset > hdr.log_file_int_offset)) {
a4f09749814b93e8ad3ec8a0dc18885b874d6f8cTimo Sirainen /* we went too far, have to re-read the file */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen hdr.log_file_ext_offset != hdr.log_file_int_offset) {
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen /* too much trouble to get this right. */
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen /* sync everything there is */
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen log_view = mail_transaction_log_view_open(index->log);
268b72128fc3400912e9a6b83faf4950a367c2ffTimo Sirainen while ((ret = mail_transaction_log_view_next(log_view, &thdr, &tdata,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (mail_index_sync_record(&sync_map_ctx, thdr, tdata) < 0) {
d9a129b491613014ce5f31fe1ab20903e2899ea4Timo Sirainen mail_transaction_log_view_get_prev_pos(log_view, &prev_seq,
7631f16156aca373004953fe6b01a7f343fb47e0Timo Sirainen index->map->hdr.log_file_ext_offset = prev_offset;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen /* make sure log file offsets get copied. most of the other
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen fields should stay the same. */
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen i_assert(hdr.messages_count == (*map)->hdr.messages_count);
f46885a5b78b15a8d2419f6e5d13b643bd85e41fTimo Sirainenstatic int mail_index_read_map_with_retry(struct mail_index *index,
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen mail_index_sync_lost_handler_t *const *handlers;
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen unsigned int i;
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen /* we're most likely syncing the index and we really don't
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen want to read more than what was synced last time. */
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen /* sync this as a view from transaction log. */
7a2d48763b43c4fd8bc17c444271f0b802113a5fTimo Sirainen ret = mail_index_sync_from_transactions(index, map,
for (i = 0; i < size; i++)
for (i = 0; i < MAIL_INDEX_ESTALE_RETRY_COUNT; i++) {
return ret;
if (ret <= 0) {
if (ret == 0) {
int ret;
if (ret != 0)
return ret;
if (ret <= 0) {
return ret;
if (ret < 0) {
if (ret == 0)
struct mail_index_map *
unsigned int i, count;
NULL);
for (i = 0; i < count; i++) {
return mem_map;
unsigned int lock_id;
int ret;
*lock_id_r = 0;
if (ret <= 0)
return ret;
if (ret == 0) {
*lock_id_r = 0;
return ret;
const char *path;
int fd;
return fd;
const char *path;
int ret;
if (ret != 0) {
/* create it fully in index.tmp first */
if (ret == 0) {
if (ret < 0) {
return ret;
#ifndef WORDS_BIGENDIAN
unsigned int lock_id = 0;
if (ret > 0)
else if (ret == 0) {
} else if (ret < 0)
if (lock_id != 0) {
lock_id = 0;
if (lock_id == 0) {
int i = 0, ret;
if (ret <= 0)
if (ret == 0) {
if (ret <= 0)
return ret;
ret = 0;
if (ret > 0)
else if (ret == 0) {
if (ret == 0) {
if (lock_id != 0)
if (ret == 0) {
return ret;
unsigned int lock_id;
int ret;
const char *function)
const char *filepath,
const char *function)
return MAIL_INDEX_ERROR_DISKSPACE;
return MAIL_INDEX_ERROR_INTERNAL;
return MAIL_INDEX_ERROR_NONE;