diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:51:24 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:51:24 +0000 |
commit | f7548d6d28c313cf80e6f3ef89aed16a19815df1 (patch) | |
tree | a3f6f2a3f247293bee59ecd28e8cd8ceb6ca064a /src/doveadm/doveadm-dump-thread.c | |
parent | Initial commit. (diff) | |
download | dovecot-upstream.tar.xz dovecot-upstream.zip |
Adding upstream version 1:2.3.19.1+dfsg1.upstream/1%2.3.19.1+dfsg1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | src/doveadm/doveadm-dump-thread.c | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/src/doveadm/doveadm-dump-thread.c b/src/doveadm/doveadm-dump-thread.c new file mode 100644 index 0000000..026b07f --- /dev/null +++ b/src/doveadm/doveadm-dump-thread.c @@ -0,0 +1,139 @@ +/* Copyright (c) 2007-2018 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "mmap-util.h" +#include "mail-index-private.h" +#include "mail-index-strmap.h" +#include "doveadm-dump.h" + +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/stat.h> + +static uint32_t max_likely_index; + +static size_t dump_hdr(const struct mail_index_strmap_header *hdr) +{ + printf("version = %u\n", hdr->version); + printf("uid validity = %u\n", hdr->uid_validity); + return sizeof(*hdr); +} + +static int dump_record(const uint8_t **p, const uint8_t *end, uint32_t *uid) +{ + uint32_t uid_diff, n, i, count, crc32, idx; + size_t size; + + /* <uid diff> <n> <crc32>*count <str_idx>*count */ + if (mail_index_unpack_num(p, end, &uid_diff) < 0) + return -1; + *uid += uid_diff; + + if (mail_index_unpack_num(p, end, &n) < 0) + return -1; + printf(" - uid %u: n=%u\n", *uid, n); + + count = n < 2 ? n + 1 : n; + size = sizeof(crc32)*count + sizeof(idx)*count; + if (*p + size > end) + return -1; + for (i = 0; i < count; i++) { + if (i == 0) + printf(" - message-id: "); + else if (i == 1) { + if (n == 1) + printf(" - in-reply-to: "); + else + printf(" - references[1]: "); + } else { + printf(" - references[%u]: ", i); + } + memcpy(&crc32, *p + sizeof(crc32)*i, sizeof(crc32)); + memcpy(&idx, *p + sizeof(crc32)*count + sizeof(idx)*i, sizeof(idx)); + printf("crc32=%08x index=%u\n", crc32, idx); + if (idx > max_likely_index) + printf(" - index probably broken\n"); + } + *p += size; + return 0; +} + +static int dump_block(const uint8_t *data, const uint8_t *end, uint32_t *uid) +{ + const uint8_t *p; + uint32_t block_size; + + if (data + 4 >= end) + return -1; + + memcpy(&block_size, data, sizeof(block_size)); + block_size = mail_index_offset_to_uint32(block_size) >> 2; + printf(" - block_size=%u\n", block_size); + if (block_size == 0) { + /* finished */ + return -1; + } + if (data + sizeof(block_size) + block_size > end) { + printf(" - broken!\n"); + return -1; + } + p = data + sizeof(block_size); + end = p + block_size; + + *uid += 1; + while (p != end) { + if (dump_record(&p, end, uid) < 0) { + printf(" - broken\n"); + return -1; + } + } + return p - data; +} + +static void +cmd_dump_thread(const char *path, const char *const *args ATTR_UNUSED) +{ + unsigned int pos; + const void *map, *end; + struct stat st; + uint32_t uid; + int fd, ret; + + fd = open(path, O_RDONLY); + if (fd < 0) + i_fatal("open(%s) failed: %m", path); + + if (fstat(fd, &st) < 0) + i_fatal("fstat(%s) failed: %m", path); + max_likely_index = (st.st_size / 8) * 2; + + map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (map == MAP_FAILED) + i_fatal("mmap() failed: %m"); + end = CONST_PTR_OFFSET(map, st.st_size); + pos = dump_hdr(map); + uid = 0; + do { + printf("block at offset %u:\n", pos); + T_BEGIN { + ret = dump_block(CONST_PTR_OFFSET(map, pos), end, &uid); + pos += ret; + } T_END; + } while (ret > 0); + i_close_fd(&fd); +} + +static bool test_dump_thread(const char *path) +{ + const char *p; + + p = strrchr(path, '.'); + return p != NULL && strcmp(p, ".thread") == 0; +} + +struct doveadm_cmd_dump doveadm_cmd_dump_thread = { + "thread", + test_dump_thread, + cmd_dump_thread +}; |