Skip to content

Commit

Permalink
doveadm dump log: Use istream for reading the file.
Browse files Browse the repository at this point in the history
Cleans up the code a bit and removes the 1MB record limit.
  • Loading branch information
sirainen committed Mar 30, 2017
1 parent d6baf55 commit 8dca8b4
Showing 1 changed file with 46 additions and 48 deletions.
94 changes: 46 additions & 48 deletions src/doveadm/doveadm-dump-log.c
@@ -1,6 +1,7 @@
/* Copyright (c) 2007-2017 Dovecot authors, see the included COPYING file */

#include "lib.h"
#include "istream.h"
#include "hex-binary.h"
#include "mail-index-private.h"
#include "mail-transaction-log.h"
Expand All @@ -10,22 +11,26 @@

static struct mail_transaction_ext_intro prev_intro;

static void dump_hdr(int fd, uint64_t *modseq_r)
static void dump_hdr(struct istream *input, uint64_t *modseq_r)
{
struct mail_transaction_log_header hdr;
ssize_t ret;

ret = read(fd, &hdr, sizeof(hdr));
if (ret != sizeof(hdr)) {
const unsigned char *data;
size_t size;
int ret;

ret = i_stream_read_bytes(input, &data, &size, sizeof(hdr));
if (ret < 0 && input->stream_errno != 0)
i_fatal("read() failed: %s", i_stream_get_error(input));
if (ret <= 0) {
i_fatal("file hdr read() %"PRIuSIZE_T" != %"PRIuSIZE_T,
ret, sizeof(hdr));
size, sizeof(hdr));
}
memcpy(&hdr, data, sizeof(hdr));
if (hdr.hdr_size < sizeof(hdr)) {
memset(PTR_OFFSET(&hdr, hdr.hdr_size), 0,
sizeof(hdr) - hdr.hdr_size);
}
if (lseek(fd, hdr.hdr_size, SEEK_SET) < 0)
i_fatal("lseek() failed: %m");
i_stream_skip(input, hdr.hdr_size);

printf("version = %u.%u\n", hdr.major_version, hdr.minor_version);
printf("hdr size = %u\n", hdr.hdr_size);
Expand Down Expand Up @@ -480,77 +485,70 @@ static void log_record_print(const struct mail_transaction_header *hdr,
}
}

static int dump_record(int fd, uint64_t *modseq)
static int dump_record(struct istream *input, uint64_t *modseq)
{
off_t offset;
ssize_t ret;
struct mail_transaction_header hdr;
unsigned int orig_size;

offset = lseek(fd, 0, SEEK_CUR);
if (offset == -1)
i_fatal("lseek() failed: %m");

ret = read(fd, &hdr, sizeof(hdr));
if (ret == 0)
return 0;

if (ret != sizeof(hdr)) {
const unsigned char *data;
size_t size;
int ret;

ret = i_stream_read_bytes(input, &data, &size, sizeof(hdr));
if (ret < 0 && input->stream_errno != 0)
i_fatal("read() failed: %s", i_stream_get_error(input));
if (ret <= 0) {
if (size == 0)
return 0;
i_fatal("rec hdr read() %"PRIuSIZE_T" != %"PRIuSIZE_T,
ret, sizeof(hdr));
size, sizeof(hdr));
}
memcpy(&hdr, data, sizeof(hdr));

orig_size = hdr.size;
hdr.size = mail_index_offset_to_uint32(hdr.size);
if (hdr.size == 0) {
if (hdr.size < sizeof(hdr)) {
printf("record: offset=%"PRIuUOFF_T", "
"type=%s, size=broken (%x)\n",
offset, log_record_type(hdr.type), orig_size);
input->v_offset, log_record_type(hdr.type), orig_size);
return 0;
}

printf("record: offset=%"PRIuUOFF_T", type=%s, size=%u",
offset, log_record_type(hdr.type), hdr.size);
input->v_offset, log_record_type(hdr.type), hdr.size);
if (*modseq > 0 && mail_transaction_header_has_modseq(&hdr)) {
*modseq += 1;
printf(", modseq=%llu", (unsigned long long)*modseq);
}
printf("\n");

if (hdr.size < sizeof(hdr)) {
i_fatal("Invalid header size %u", hdr.size);
} else if (hdr.size < 1024*1024) {
unsigned char *buf = t_malloc(hdr.size);

ret = read(fd, buf, hdr.size - sizeof(hdr));
if (ret != (ssize_t)(hdr.size - sizeof(hdr))) {
i_fatal("rec data read() %"PRIuSIZE_T" != %"PRIuSIZE_T,
ret, hdr.size - sizeof(hdr));
}
log_record_print(&hdr, buf, (size_t)ret, modseq);
} else {
if (lseek(fd, hdr.size - sizeof(hdr), SEEK_CUR) < 0)
i_fatal("lseek() failed: %m");
}
i_stream_skip(input, sizeof(hdr));
size_t data_size = hdr.size - sizeof(hdr);
ret = i_stream_read_bytes(input, &data, &size, data_size);
if (ret < 0 && input->stream_errno != 0)
i_fatal("read() failed: %s", i_stream_get_error(input));
if (ret <= 0) {
i_fatal("rec data read() %"PRIuSIZE_T" != %"PRIuSIZE_T,
size, data_size);
}
log_record_print(&hdr, data, data_size, modseq);
i_stream_skip(input, data_size);
return 1;
}

static void cmd_dump_log(int argc ATTR_UNUSED, char *argv[])
{
struct istream *input;
uint64_t modseq;
int fd, ret;
int ret;

fd = open(argv[1], O_RDONLY);
if (fd < 0)
i_fatal("open(%s) failed: %m", argv[1]);

dump_hdr(fd, &modseq);
input = i_stream_create_file(argv[1], (size_t)-1);
dump_hdr(input, &modseq);
do {
T_BEGIN {
ret = dump_record(fd, &modseq);
ret = dump_record(input, &modseq);
} T_END;
} while (ret > 0);
i_close_fd(&fd);
i_stream_unref(&input);
}

static bool test_dump_log(const char *path)
Expand Down

0 comments on commit 8dca8b4

Please sign in to comment.