diff options
Diffstat (limited to 'src/doveadm/doveadm-dump.c')
-rw-r--r-- | src/doveadm/doveadm-dump.c | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/src/doveadm/doveadm-dump.c b/src/doveadm/doveadm-dump.c new file mode 100644 index 0000000..eb08e96 --- /dev/null +++ b/src/doveadm/doveadm-dump.c @@ -0,0 +1,162 @@ +/* Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "array.h" +#include "istream.h" +#include "istream-multiplex.h" +#include "doveadm.h" +#include "doveadm-dump.h" + +#include <stdio.h> +#include <unistd.h> + +static ARRAY(const struct doveadm_cmd_dump *) dumps; + +void doveadm_dump_register(const struct doveadm_cmd_dump *dump) +{ + array_push_back(&dumps, &dump); +} + +static const struct doveadm_cmd_dump * +dump_find_name(const char *name) +{ + const struct doveadm_cmd_dump *dump; + + array_foreach_elem(&dumps, dump) { + if (strcmp(dump->name, name) == 0) + return dump; + } + return NULL; +} + +static const struct doveadm_cmd_dump * +dump_find_test(const char *path) +{ + const struct doveadm_cmd_dump *dump; + + array_foreach_elem(&dumps, dump) { + if (dump->test != NULL && dump->test(path)) + return dump; + } + return NULL; +} + +static void cmd_dump(struct doveadm_cmd_context *cctx) +{ + const struct doveadm_cmd_dump *dump; + const char *path, *type = NULL, *const *args = NULL; + const char *no_args = NULL; + + if (!doveadm_cmd_param_str(cctx, "path", &path)) + help_ver2(&doveadm_cmd_dump); + (void)doveadm_cmd_param_str(cctx, "type", &type); + (void)doveadm_cmd_param_array(cctx, "args", &args); + + dump = type != NULL ? dump_find_name(type) : dump_find_test(path); + if (dump == NULL) { + if (type != NULL) { + print_dump_types(); + i_fatal_status(EX_USAGE, "Unknown type: %s", type); + } else { + i_fatal_status(EX_DATAERR, + "Can't autodetect file type: %s", path); + } + } else { + if (type == NULL) + printf("Detected file type: %s\n", dump->name); + } + dump->cmd(path, args != NULL ? args : &no_args); +} + +struct doveadm_cmd_ver2 doveadm_cmd_dump = { + .name = "dump", + .cmd = cmd_dump, + .usage = "[-t <type>] <path> [<type-specific args>]", +DOVEADM_CMD_PARAMS_START +DOVEADM_CMD_PARAM('t', "type", CMD_PARAM_STR, 0) +DOVEADM_CMD_PARAM('\0', "path", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL) +DOVEADM_CMD_PARAM('\0', "args", CMD_PARAM_ARRAY, CMD_PARAM_FLAG_POSITIONAL) +DOVEADM_CMD_PARAMS_END +}; + +static void +cmd_dump_multiplex(const char *path, const char *const *args ATTR_UNUSED) +{ + const unsigned int channels_count = 256; + struct istream *file_input, *channels[channels_count]; + const unsigned char *data; + size_t size; + unsigned int i; + + file_input = i_stream_create_file(path, IO_BLOCK_SIZE); + /* A bit kludgy: istream-multiplex returns 0 if a wrong channel is + being read from. This causes a panic with blocking istreams. + Work around this by assuming that the file istream isn't blocking. */ + file_input->blocking = FALSE; + channels[0] = i_stream_create_multiplex(file_input, IO_BLOCK_SIZE); + i_stream_unref(&file_input); + + for (i = 1; i < channels_count; i++) + channels[i] = i_stream_multiplex_add_channel(channels[0], i); + + bool have_input; + do { + have_input = FALSE; + for (i = 0; i < channels_count; i++) { + if (i_stream_read_more(channels[i], &data, &size) > 0) { + printf("CHANNEL %u: %zu bytes:\n", i, size); + fwrite(data, 1, size, stdout); + printf("\n"); + have_input = TRUE; + i_stream_skip(channels[i], size); + } + } + } while (have_input); + + if (channels[0]->stream_errno != 0) + i_error("read() failed: %s", i_stream_get_error(channels[0])); + for (i = 0; i < channels_count; i++) + i_stream_unref(&channels[i]); +} + +struct doveadm_cmd_dump doveadm_cmd_dump_multiplex = { + "multiplex", + NULL, + cmd_dump_multiplex +}; + +static const struct doveadm_cmd_dump *dumps_builtin[] = { + &doveadm_cmd_dump_dbox, + &doveadm_cmd_dump_index, + &doveadm_cmd_dump_log, + &doveadm_cmd_dump_mailboxlog, + &doveadm_cmd_dump_thread, + &doveadm_cmd_dump_zlib, + &doveadm_cmd_dump_dcrypt_file, + &doveadm_cmd_dump_dcrypt_key, + &doveadm_cmd_dump_multiplex, +}; + +void print_dump_types(void) +{ + unsigned int i; + + fprintf(stderr, "Available dump types: %s", dumps_builtin[0]->name); + for (i = 1; i < N_ELEMENTS(dumps_builtin); i++) + fprintf(stderr, " %s", dumps_builtin[i]->name); + fprintf(stderr, "\n"); +} + +void doveadm_dump_init(void) +{ + unsigned int i; + + i_array_init(&dumps, N_ELEMENTS(dumps_builtin) + 8); + for (i = 0; i < N_ELEMENTS(dumps_builtin); i++) + doveadm_dump_register(dumps_builtin[i]); +} + +void doveadm_dump_deinit(void) +{ + array_free(&dumps); +} |