bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen#include "lib.h"
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen#include "buffer.h"
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen#include "hex-binary.h"
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen#include "guid.h"
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen#include "doveadm-dump.h"
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen#include "doveadm-fts.h"
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen#include <stdio.h>
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen#include <unistd.h>
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen#include <fcntl.h>
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainenstruct fts_expunge_log_record {
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen uint32_t checksum;
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen uint32_t record_size;
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen guid_128_t guid;
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen};
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainenstatic int dump_record(int fd, buffer_t *buf)
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen{
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen struct fts_expunge_log_record rec;
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen off_t offset;
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen void *data;
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen const uint32_t *expunges, *uids;
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen ssize_t ret;
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen size_t data_size;
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen unsigned int i, uids_count;
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen offset = lseek(fd, 0, SEEK_CUR);
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen ret = read(fd, &rec, sizeof(rec));
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen if (ret == 0)
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen return 0;
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen if (ret != sizeof(rec))
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen i_fatal("rec read() %d != %d", (int)ret, (int)sizeof(rec));
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen
739f4f284b4a137c9291a00a23d197b1cd42099dTimo Sirainen if (rec.record_size < sizeof(rec) + sizeof(uint32_t) ||
739f4f284b4a137c9291a00a23d197b1cd42099dTimo Sirainen rec.record_size > INT_MAX) {
739f4f284b4a137c9291a00a23d197b1cd42099dTimo Sirainen i_fatal("Invalid record_size=%u at offset %"PRIuUOFF_T,
739f4f284b4a137c9291a00a23d197b1cd42099dTimo Sirainen rec.record_size, offset);
739f4f284b4a137c9291a00a23d197b1cd42099dTimo Sirainen }
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen data_size = rec.record_size - sizeof(rec);
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen buffer_set_used_size(buf, 0);
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen data = buffer_append_space_unsafe(buf, data_size);
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen ret = read(fd, data, data_size);
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen if (ret != (ssize_t)data_size)
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen i_fatal("rec read() %d != %d", (int)ret, (int)data_size);
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen printf("#%"PRIuUOFF_T":\n", offset);
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen printf(" checksum = %8x\n", rec.checksum);
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen printf(" size .... = %u\n", rec.record_size);
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen printf(" mailbox . = %s\n", guid_128_to_string(rec.guid));
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen expunges = CONST_PTR_OFFSET(data, data_size - sizeof(uint32_t));
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen printf(" expunges = %u\n", *expunges);
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen printf(" uids .... = ");
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen uids = data;
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen uids_count = (rec.record_size - sizeof(rec) - sizeof(uint32_t)) /
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen sizeof(uint32_t);
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen for (i = 0; i < uids_count; i += 2) {
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen if (i != 0)
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen printf(",");
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen if (uids[i] == uids[i+1])
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen printf("%u", uids[i]);
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen else
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen printf("%u-%u", uids[i], uids[i+1]);
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen }
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen printf("\n");
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen return 1;
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen}
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainenstatic void cmd_dump_fts_expunge_log(int argc ATTR_UNUSED, char *argv[])
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen{
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen buffer_t *buf;
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen int fd, ret;
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen fd = open(argv[1], O_RDONLY);
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen if (fd < 0)
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen i_fatal("open(%s) failed: %m", argv[1]);
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen buf = buffer_create_dynamic(default_pool, 1024);
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen do {
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen T_BEGIN {
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen ret = dump_record(fd, buf);
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen } T_END;
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen } while (ret > 0);
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen buffer_free(&buf);
4307c886579381dbb1897ea1388ae6978c96f560Timo Sirainen i_close_fd(&fd);
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen}
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainenstatic bool test_dump_fts_expunge_log(const char *path)
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen{
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen const char *p;
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen
0b9392b670e00a9595a5c619334d6b2ed1527ceeTimo Sirainen if ((p = strrchr(path, '/')) != NULL)
0b9392b670e00a9595a5c619334d6b2ed1527ceeTimo Sirainen p++;
0b9392b670e00a9595a5c619334d6b2ed1527ceeTimo Sirainen else
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen p = path;
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen return strcmp(p, "dovecot-expunges.log") == 0;
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen}
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen
0b3e92b6043435c5aa9f1cf1d04b632f3e19abd9Phil Carmodystatic const struct doveadm_cmd_dump doveadm_cmd_dump_fts_expunge_log = {
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen "fts-expunge-log",
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen test_dump_fts_expunge_log,
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen cmd_dump_fts_expunge_log
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen};
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainenvoid doveadm_dump_fts_expunge_log_init(void)
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen{
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen doveadm_dump_register(&doveadm_cmd_dump_fts_expunge_log);
cc2954ad6d8ba0509b870d773ba4b6b16353763cTimo Sirainen}