bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen#include "lib.h"
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen#include "hex-dec.h"
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen#include "istream.h"
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen#include "index/dbox-common/dbox-file.h"
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen#include "doveadm-dump.h"
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen#include <stdio.h>
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen#include <fcntl.h>
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen#include <unistd.h>
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainenstatic void
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainendump_timestamp(struct istream *input, const char *name, const char *value)
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen{
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen time_t t;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen if (strcmp(value, "0") == 0)
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen t = 0;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen else {
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen t = hex2dec((const void *)value, strlen(value));
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen if (t == 0) {
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen i_fatal("Invalid %s at %"PRIuUOFF_T": %s",
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen name, input->v_offset, value);
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen }
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen }
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen printf("%s = %ld (%s)\n", name, (long)t, unixdate2str(t));
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen}
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainenstatic uoff_t
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainendump_size(struct istream *input, const char *name, const char *value)
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen{
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen uoff_t size;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen if (strcmp(value, "0") == 0)
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen size = 0;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen else {
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen size = hex2dec((const void *)value, strlen(value));
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen if (size == 0) {
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen i_fatal("Invalid %s at %"PRIuUOFF_T": %s",
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen name, input->v_offset, value);
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen }
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen }
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen printf("%s = %"PRIuUOFF_T"\n", name, size);
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen return size;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen}
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainenstatic unsigned int dump_file_hdr(struct istream *input)
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen{
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen const char *line, *const *arg, *version;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen unsigned int msg_hdr_size = 0;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen if ((line = i_stream_read_next_line(input)) == NULL)
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen i_fatal("Empty file");
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen arg = t_strsplit(line, " ");
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen /* check version */
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen version = *arg;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen if (version == NULL || !str_is_numeric(version, ' '))
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen i_fatal("%s is not a dbox file", i_stream_get_name(input));
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen if (strcmp(version, "2") != 0)
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen i_fatal("Unsupported dbox file version %s", version);
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen arg++;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen for (; *arg != NULL; arg++) {
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen switch (**arg) {
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen case DBOX_HEADER_MSG_HEADER_SIZE:
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen msg_hdr_size = hex2dec((const void *)(*arg + 1),
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen strlen(*arg + 1));
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen if (msg_hdr_size == 0) {
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen i_fatal("Invalid msg_header_size header: %s",
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen *arg + 1);
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen }
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen printf("file.msg_header_size = %u\n", msg_hdr_size);
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen break;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen case DBOX_HEADER_CREATE_STAMP:
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen dump_timestamp(input, "file.create_stamp", *arg + 1);
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen break;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen default:
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen printf("file.unknown-%c = %s\n", **arg, *arg + 1);
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen break;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen }
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen }
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen if (msg_hdr_size == 0)
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen i_fatal("Missing msg_header_size in file header");
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen return msg_hdr_size;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen}
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainenstatic bool
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainendump_msg_hdr(struct istream *input, unsigned int hdr_size, uoff_t *msg_size_r)
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen{
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen struct dbox_message_header hdr;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen const unsigned char *data;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen size_t size;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen uoff_t msg_size;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen
534e41e436a7546f36f61e0dc49c0c191d850f6bPhil Carmody if (i_stream_read_bytes(input, &data, &size, hdr_size) <= 0) {
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen if (size == 0)
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen return FALSE;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen i_fatal("Partial message header read at %"PRIuUOFF_T": "
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen "%"PRIuSIZE_T" bytes", input->v_offset, size);
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen }
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen printf("offset %"PRIuUOFF_T":\n", input->v_offset);
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen if (hdr_size < sizeof(hdr))
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen i_fatal("file.hdr_size too small: %u", hdr_size);
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen memcpy(&hdr, data, sizeof(hdr));
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen if (memcmp(hdr.magic_pre, DBOX_MAGIC_PRE, sizeof(hdr.magic_pre)) != 0)
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen i_fatal("dbox wrong pre-magic at %"PRIuUOFF_T, input->v_offset);
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen msg_size = dump_size(input, "msg.size",
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen t_strndup(hdr.message_size_hex, sizeof(hdr.message_size_hex)));
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen i_stream_skip(input, hdr_size);
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen *msg_size_r = msg_size;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen return TRUE;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen}
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainenstatic void dump_msg_metadata(struct istream *input)
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen{
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen struct dbox_metadata_header hdr;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen const unsigned char *data;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen size_t size;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen const char *line;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen /* verify magic */
534e41e436a7546f36f61e0dc49c0c191d850f6bPhil Carmody if (i_stream_read_bytes(input, &data, &size, sizeof(hdr)) <= 0) {
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen i_fatal("dbox missing metadata at %"PRIuUOFF_T,
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen input->v_offset);
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen }
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen memcpy(&hdr, data, sizeof(hdr));
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen if (memcmp(hdr.magic_post, DBOX_MAGIC_POST, sizeof(hdr.magic_post)) != 0)
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen i_fatal("dbox wrong post-magic at %"PRIuUOFF_T, input->v_offset);
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen i_stream_skip(input, sizeof(hdr));
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen /* dump the metadata */
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen for (;;) {
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen if ((line = i_stream_read_next_line(input)) == NULL)
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen i_fatal("dbox metadata ended unexpectedly at EOF");
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen if (*line == '\0')
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen break;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen switch (*line) {
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen case DBOX_METADATA_GUID:
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen printf("msg.guid = %s\n", line + 1);
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen break;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen case DBOX_METADATA_POP3_UIDL:
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen printf("msg.pop3-uidl = %s\n", line + 1);
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen break;
147a788fea2a88f7125b27226451271d55cf5b01Timo Sirainen case DBOX_METADATA_POP3_ORDER:
147a788fea2a88f7125b27226451271d55cf5b01Timo Sirainen printf("msg.pop3-order = %s\n", line + 1);
147a788fea2a88f7125b27226451271d55cf5b01Timo Sirainen break;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen case DBOX_METADATA_RECEIVED_TIME:
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen dump_timestamp(input, "msg.received", line + 1);
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen break;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen case DBOX_METADATA_PHYSICAL_SIZE:
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen (void)dump_size(input, "msg.physical-size", line + 1);
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen break;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen case DBOX_METADATA_VIRTUAL_SIZE:
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen (void)dump_size(input, "msg.virtual-size", line + 1);
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen break;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen case DBOX_METADATA_EXT_REF:
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen printf("msg.ext-ref = %s\n", line + 1);
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen break;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen case DBOX_METADATA_ORIG_MAILBOX:
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen printf("msg.orig-mailbox = %s\n", line + 1);
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen break;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen case DBOX_METADATA_OLDV1_EXPUNGED:
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen case DBOX_METADATA_OLDV1_FLAGS:
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen case DBOX_METADATA_OLDV1_KEYWORDS:
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen case DBOX_METADATA_OLDV1_SAVE_TIME:
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen case DBOX_METADATA_OLDV1_SPACE:
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen printf("msg.obsolete-%c = %s\n", *line, line + 1);
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen break;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen }
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen }
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen}
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainenstatic bool dump_msg(struct istream *input, unsigned int hdr_size)
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen{
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen uoff_t msg_size;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen if (!dump_msg_hdr(input, hdr_size, &msg_size))
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen return FALSE;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen i_stream_skip(input, msg_size);
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen dump_msg_metadata(input);
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen return TRUE;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen}
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainenstatic void cmd_dump_dbox(int argc ATTR_UNUSED, char *argv[])
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen{
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen struct istream *input;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen int fd;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen unsigned int hdr_size;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen bool ret;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen fd = open(argv[1], O_RDONLY);
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen if (fd < 0)
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen i_fatal("open(%s) failed: %m", argv[1]);
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen
bace943c67e6cd14ce6c994f533d82a3caad5bf1Timo Sirainen input = i_stream_create_fd_autoclose(&fd, (size_t)-1);
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen i_stream_set_name(input, argv[1]);
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen hdr_size = dump_file_hdr(input);
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen do {
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen printf("\n");
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen T_BEGIN {
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen ret = dump_msg(input, hdr_size);
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen } T_END;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen } while (ret);
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen i_stream_destroy(&input);
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen}
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainenstatic bool test_dump_dbox(const char *path)
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen{
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen const char *p;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen p = strrchr(path, '/');
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen if (p == NULL)
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen p = path;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen else
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen p++;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen return strncmp(p, "m.", 2) == 0 || strncmp(p, "u.", 2) == 0;
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen}
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainenstruct doveadm_cmd_dump doveadm_cmd_dump_dbox = {
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen "dbox",
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen test_dump_dbox,
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen cmd_dump_dbox
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen};