changeset 21838:660b5830a05e

doveadm dump log: Use istream for reading the file. Cleans up the code a bit and removes the 1MB record limit.
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Mon, 27 Mar 2017 16:26:09 +0300
parents 97e01a0ad4bc
children b4ed312463fd
files src/doveadm/doveadm-dump-log.c
diffstat 1 files changed, 43 insertions(+), 45 deletions(-) [+]
line wrap: on
line diff
--- a/src/doveadm/doveadm-dump-log.c	Wed Mar 29 13:28:36 2017 +0300
+++ b/src/doveadm/doveadm-dump-log.c	Mon Mar 27 16:26:09 2017 +0300
@@ -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"
@@ -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;
+	const unsigned char *data;
+	size_t size;
+	int ret;
 
-	ret = read(fd, &hdr, sizeof(hdr));
-	if (ret != sizeof(hdr)) {
+	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);
@@ -480,77 +485,70 @@
 	}
 }
 
-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");
+	const unsigned char *data;
+	size_t size;
+	int ret;
 
-	ret = read(fd, &hdr, sizeof(hdr));
-	if (ret == 0)
-		return 0;
-
-	if (ret != sizeof(hdr)) {
+	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)