doveadm-dump-thread.c revision 7cb128dc4cae2a03a742f63ba7afee23c78e3af0
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2007-2015 Dovecot authors, see the included COPYING file */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "lib.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "mmap-util.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "mail-index-private.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "mail-index-strmap.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "doveadm-dump.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
fc4b301e2dd86c096b9c41ad1b011b752fffd570Timo Sirainen#include <stdio.h>
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include <fcntl.h>
12ab808b472ed51923945efac4156a380bd58d57Timo Sirainen#include <unistd.h>
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen#include <sys/stat.h>
ec1a4f4306496380e9d96ee08a3718a669d0875aTimo Sirainen
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenstatic uint32_t max_likely_index;
7a5e2e937f0f388465c2938645ee971b4fd01bf1Timo Sirainen
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainenstatic size_t dump_hdr(const struct mail_index_strmap_header *hdr)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen{
08e7163a8d12979119fa56c92676af4ba6304f1aTimo Sirainen printf("version = %u\n", hdr->version);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen printf("uid validity = %u\n", hdr->uid_validity);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return sizeof(*hdr);
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen}
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainen
a78d5bd9772681a232de56b3dd6acefee66cc71bTimo Sirainenstatic int dump_record(const uint8_t **p, const uint8_t *end, uint32_t *uid)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen{
4e0204dbac352e271c79cfa6c74a71145a058de5Timo Sirainen uint32_t uid_diff, n, i, count, crc32, idx;
4e0204dbac352e271c79cfa6c74a71145a058de5Timo Sirainen size_t size;
4e0204dbac352e271c79cfa6c74a71145a058de5Timo Sirainen
4e0204dbac352e271c79cfa6c74a71145a058de5Timo Sirainen /* <uid diff> <n> <crc32>*count <str_idx>*count */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (mail_index_unpack_num(p, end, &uid_diff) < 0)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return -1;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen *uid += uid_diff;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen if (mail_index_unpack_num(p, end, &n) < 0)
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen return -1;
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen printf(" - uid %u: n=%u\n", *uid, n);
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen count = n < 2 ? n + 1 : n;
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen size = sizeof(crc32)*count + sizeof(idx)*count;
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen if (*p + size > end)
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen return -1;
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen for (i = 0; i < count; i++) {
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen if (i == 0)
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen printf(" - message-id: ");
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen else if (i == 1) {
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen if (n == 1)
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen printf(" - in-reply-to: ");
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen else
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen printf(" - references[1]: ");
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen } else {
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen printf(" - references[%u]: ", i);
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen }
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen memcpy(&crc32, *p + sizeof(crc32)*i, sizeof(crc32));
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen memcpy(&idx, *p + sizeof(crc32)*count + sizeof(idx)*i, sizeof(idx));
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen printf("crc32=%08x index=%u\n", crc32, idx);
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen if (idx > max_likely_index)
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen printf(" - index probably broken\n");
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen }
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen *p += size;
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen return 0;
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen}
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainenstatic int dump_block(const uint8_t *data, const uint8_t *end, uint32_t *uid)
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen{
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen const uint8_t *p;
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen uint32_t block_size;
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen if (data + 4 >= end)
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen return -1;
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen memcpy(&block_size, data, sizeof(block_size));
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen block_size = mail_index_offset_to_uint32(block_size) >> 2;
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen printf(" - block_size=%u\n", block_size);
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen if (block_size == 0) {
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen /* finished */
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen return -1;
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen }
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen if (data + sizeof(block_size) + block_size > end) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen printf(" - broken!\n");
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen return -1;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen p = data + sizeof(block_size);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen end = p + block_size;
1cfdcb36985904eff281fc6d7ea2d13b3c375980Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen *uid += 1;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen while (p != end) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (dump_record(&p, end, uid) < 0) {
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen printf(" - broken\n");
28cb56e6957f06717e876cecb7aabc820fdf632eTimo Sirainen return -1;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen }
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen }
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen return p - data;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen}
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainenstatic void cmd_dump_thread(int argc ATTR_UNUSED, char *argv[])
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen{
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen unsigned int pos;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen const void *map, *end;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen struct stat st;
3c3777721b56e065fac99a0f34e4cef4f293b517Timo Sirainen uint32_t uid;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen int fd, ret;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen
bbc30fd4fa86723f6a72309ad3a2a96f34eabd6cTimo Sirainen fd = open(argv[1], O_RDONLY);
bbc30fd4fa86723f6a72309ad3a2a96f34eabd6cTimo Sirainen if (fd < 0)
bbc30fd4fa86723f6a72309ad3a2a96f34eabd6cTimo Sirainen i_fatal("open(%s) failed: %m", argv[1]);
bbc30fd4fa86723f6a72309ad3a2a96f34eabd6cTimo Sirainen
bbc30fd4fa86723f6a72309ad3a2a96f34eabd6cTimo Sirainen if (fstat(fd, &st) < 0)
bbc30fd4fa86723f6a72309ad3a2a96f34eabd6cTimo Sirainen i_fatal("fstat(%s) failed: %m", argv[1]);
bbc30fd4fa86723f6a72309ad3a2a96f34eabd6cTimo Sirainen max_likely_index = (st.st_size / 8) * 2;
bbc30fd4fa86723f6a72309ad3a2a96f34eabd6cTimo Sirainen
bbc30fd4fa86723f6a72309ad3a2a96f34eabd6cTimo Sirainen map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
bbc30fd4fa86723f6a72309ad3a2a96f34eabd6cTimo Sirainen if (map == MAP_FAILED)
bbc30fd4fa86723f6a72309ad3a2a96f34eabd6cTimo Sirainen i_fatal("mmap() failed: %m");
bbc30fd4fa86723f6a72309ad3a2a96f34eabd6cTimo Sirainen end = CONST_PTR_OFFSET(map, st.st_size);
bbc30fd4fa86723f6a72309ad3a2a96f34eabd6cTimo Sirainen pos = dump_hdr(map);
bbc30fd4fa86723f6a72309ad3a2a96f34eabd6cTimo Sirainen uid = 0;
bbc30fd4fa86723f6a72309ad3a2a96f34eabd6cTimo Sirainen do {
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen printf("block at offset %u:\n", pos);
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen T_BEGIN {
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen ret = dump_block(CONST_PTR_OFFSET(map, pos), end, &uid);
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen pos += ret;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen } T_END;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen } while (ret > 0);
1cfdcb36985904eff281fc6d7ea2d13b3c375980Timo Sirainen i_close_fd(&fd);
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen}
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainenstatic bool test_dump_thread(const char *path)
1cfdcb36985904eff281fc6d7ea2d13b3c375980Timo Sirainen{
1cfdcb36985904eff281fc6d7ea2d13b3c375980Timo Sirainen const char *p;
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen p = strrchr(path, '.');
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen return p != NULL && strcmp(p, ".thread") == 0;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen}
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainenstruct doveadm_cmd_dump doveadm_cmd_dump_thread = {
b28a1c61a5d262fd16b46bebe47dbfb90ac9c5fcTimo Sirainen "thread",
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen test_dump_thread,
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen cmd_dump_thread
637ec4c33b4715737a41f7e58c9b6d1f693c27e2Timo Sirainen};
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen