dovecot-2.2: dsync: Moved doveadm-specific code to doveadm direc...

dovecot at dovecot.org dovecot at dovecot.org
Tue Sep 16 09:32:19 UTC 2014


details:   http://hg.dovecot.org/dovecot-2.2/rev/fc79ac9cc378
changeset: 17810:fc79ac9cc378
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Sep 16 12:32:09 2014 +0300
description:
dsync: Moved doveadm-specific code to doveadm directory.

diffstat:

 src/doveadm/Makefile.am           |     4 +-
 src/doveadm/doveadm-dsync.c       |  1258 +++++++++++++++++++++++++++++++++++++
 src/doveadm/doveadm-dsync.h       |    10 +
 src/doveadm/doveadm-mail.c        |     2 +-
 src/doveadm/doveadm.c             |     2 +-
 src/doveadm/dsync/Makefile.am     |    10 +-
 src/doveadm/dsync/doveadm-dsync.c |  1258 -------------------------------------
 src/doveadm/dsync/doveadm-dsync.h |    10 -
 8 files changed, 1275 insertions(+), 1279 deletions(-)

diffs (truncated from 2643 to 300 lines):

diff -r d080dc2e1280 -r fc79ac9cc378 src/doveadm/Makefile.am
--- a/src/doveadm/Makefile.am	Tue Sep 16 12:04:07 2014 +0300
+++ b/src/doveadm/Makefile.am	Tue Sep 16 12:32:09 2014 +0300
@@ -34,7 +34,7 @@
 	../lib-otp/libotp.a
 
 libs = \
-	dsync/libdoveadm_dsync.la \
+	dsync/libdsync.la \
 	../lib-compression/libcompression.la
 
 doveadm_LDADD = \
@@ -59,6 +59,7 @@
 	$(LIBDOVECOT_DEPS)
 
 common = \
+	doveadm-dsync.c \
 	doveadm-mail.c \
 	doveadm-mail-altmove.c \
 	doveadm-mail-batch.c \
@@ -121,6 +122,7 @@
 pkginc_libdir = $(pkgincludedir)
 pkginc_lib_HEADERS = \
 	doveadm.h \
+	doveadm-dsync.h \
 	doveadm-dump.h \
 	doveadm-mail.h \
 	doveadm-mail-iter.h \
diff -r d080dc2e1280 -r fc79ac9cc378 src/doveadm/doveadm-dsync.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/doveadm/doveadm-dsync.c	Tue Sep 16 12:32:09 2014 +0300
@@ -0,0 +1,1258 @@
+/* Copyright (c) 2009-2014 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "lib-signals.h"
+#include "array.h"
+#include "execv-const.h"
+#include "fd-set-nonblock.h"
+#include "istream.h"
+#include "ostream.h"
+#include "iostream-ssl.h"
+#include "iostream-rawlog.h"
+#include "write-full.h"
+#include "str.h"
+#include "strescape.h"
+#include "var-expand.h"
+#include "settings-parser.h"
+#include "master-service.h"
+#include "master-service-ssl-settings.h"
+#include "mail-storage-service.h"
+#include "mail-user.h"
+#include "mail-namespace.h"
+#include "mailbox-list-private.h"
+#include "doveadm-settings.h"
+#include "doveadm-mail.h"
+#include "doveadm-print.h"
+#include "doveadm-server.h"
+#include "client-connection.h"
+#include "server-connection.h"
+#include "dsync/dsync-brain.h"
+#include "dsync/dsync-ibc.h"
+#include "doveadm-dsync.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/wait.h>
+
+#define DSYNC_COMMON_GETOPT_ARGS "+1dEfg:l:m:n:NPr:Rs:Ux:"
+#define DSYNC_REMOTE_CMD_EXIT_WAIT_SECS 30
+/* The broken_char is mainly set to get a proper error message when trying to
+   convert a mailbox with a name that can't be used properly translated between
+   vname/storage_name and would otherwise be mixed up with a normal "mailbox
+   doesn't exist" error message. This could be any control character, since
+   none of them are allowed to be created in regular mailbox names. */
+#define DSYNC_LIST_BROKEN_CHAR '\003'
+
+enum dsync_run_type {
+	DSYNC_RUN_TYPE_LOCAL,
+	DSYNC_RUN_TYPE_STREAM,
+	DSYNC_RUN_TYPE_CMD
+};
+
+struct dsync_cmd_context {
+	struct doveadm_mail_cmd_context ctx;
+	enum dsync_brain_sync_type sync_type;
+	const char *mailbox;
+	guid_128_t mailbox_guid;
+	const char *state_input, *rawlog_path;
+	ARRAY_TYPE(const_string) exclude_mailboxes;
+	ARRAY_TYPE(const_string) namespace_prefixes;
+
+	const char *remote_name;
+	const char *local_location;
+	pid_t remote_pid;
+	const char *const *remote_cmd_args;
+
+	int fd_in, fd_out, fd_err;
+	struct io *io_err;
+	struct istream *input, *err_stream;
+	struct ostream *output;
+	size_t input_orig_bufsize, output_orig_bufsize;
+
+	struct ssl_iostream_context *ssl_ctx;
+	struct ssl_iostream *ssl_iostream;
+
+	enum dsync_run_type run_type;
+	struct server_connection *tcp_conn;
+	const char *error;
+
+	unsigned int lock_timeout;
+
+	unsigned int lock:1;
+	unsigned int purge_remote:1;
+	unsigned int sync_visible_namespaces:1;
+	unsigned int default_replica_location:1;
+	unsigned int oneway:1;
+	unsigned int backup:1;
+	unsigned int reverse_backup:1;
+	unsigned int remote_user_prefix:1;
+	unsigned int no_mail_sync:1;
+	unsigned int local_location_from_arg:1;
+	unsigned int replicator_notify:1;
+};
+
+static bool legacy_dsync = FALSE;
+
+static void remote_error_input(struct dsync_cmd_context *ctx)
+{
+	const unsigned char *data;
+	size_t size;
+	const char *line;
+
+	switch (i_stream_read(ctx->err_stream)) {
+	case -2:
+		data = i_stream_get_data(ctx->err_stream, &size);
+		fprintf(stderr, "%.*s", (int)size, data);
+		i_stream_skip(ctx->err_stream, size);
+		break;
+	case -1:
+		if (ctx->io_err != NULL)
+			io_remove(&ctx->io_err);
+		break;
+	default:
+		while ((line = i_stream_next_line(ctx->err_stream)) != NULL)
+			fprintf(stderr, "%s\n", line);
+		break;
+	}
+}
+
+static void
+run_cmd(struct dsync_cmd_context *ctx, const char *const *args)
+{
+	int fd_in[2], fd_out[2], fd_err[2];
+
+	ctx->remote_cmd_args = p_strarray_dup(ctx->ctx.pool, args);
+
+	if (pipe(fd_in) < 0 || pipe(fd_out) < 0 || pipe(fd_err) < 0)
+		i_fatal("pipe() failed: %m");
+
+	ctx->remote_pid = fork();
+	switch (ctx->remote_pid) {
+	case -1:
+		i_fatal("fork() failed: %m");
+	case 0:
+		/* child, which will execute the proxy server. stdin/stdout
+		   goes to pipes which we'll pass to proxy client. */
+		if (dup2(fd_in[0], STDIN_FILENO) < 0 ||
+		    dup2(fd_out[1], STDOUT_FILENO) < 0 ||
+		    dup2(fd_err[1], STDERR_FILENO) < 0)
+			i_fatal("dup2() failed: %m");
+
+		i_close_fd(&fd_in[0]);
+		i_close_fd(&fd_in[1]);
+		i_close_fd(&fd_out[0]);
+		i_close_fd(&fd_out[1]);
+		i_close_fd(&fd_err[0]);
+		i_close_fd(&fd_err[1]);
+
+		execvp_const(args[0], args);
+	default:
+		/* parent */
+		break;
+	}
+
+	i_close_fd(&fd_in[0]);
+	i_close_fd(&fd_out[1]);
+	i_close_fd(&fd_err[1]);
+	ctx->fd_in = fd_out[0];
+	ctx->fd_out = fd_in[1];
+	ctx->fd_err = fd_err[0];
+
+	if (ctx->remote_user_prefix) {
+		const char *prefix =
+			t_strdup_printf("%s\n", ctx->ctx.cur_username);
+		if (write_full(ctx->fd_out, prefix, strlen(prefix)) < 0)
+			i_fatal("write(remote out) failed: %m");
+	}
+
+	fd_set_nonblock(ctx->fd_err, TRUE);
+	ctx->err_stream = i_stream_create_fd(ctx->fd_err, IO_BLOCK_SIZE, FALSE);
+	i_stream_set_return_partial_line(ctx->err_stream, TRUE);
+}
+
+static void
+mirror_get_remote_cmd_line(const char *const *argv,
+			   const char *const **cmd_args_r)
+{
+	ARRAY_TYPE(const_string) cmd_args;
+	unsigned int i;
+	const char *p;
+
+	i_assert(argv[0] != NULL);
+
+	t_array_init(&cmd_args, 16);
+	for (i = 0; argv[i] != NULL; i++) {
+		p = argv[i];
+		array_append(&cmd_args, &p, 1);
+	}
+
+	if (legacy_dsync) {
+		/* we're executing dsync */
+		p = "server";
+	} else {
+		/* we're executing doveadm */
+		p = "dsync-server";
+	}
+	array_append(&cmd_args, &p, 1);
+	array_append_zero(&cmd_args);
+	*cmd_args_r = array_idx(&cmd_args, 0);
+}
+
+static const char *const *
+get_ssh_cmd_args(const char *host, const char *login, const char *mail_user)
+{
+	static struct var_expand_table static_tab[] = {
+		{ 'u', NULL, "user" },
+		{ '\0', NULL, "login" },
+		{ '\0', NULL, "host" },
+		{ '\0', NULL, NULL }
+	};
+	struct var_expand_table *tab;
+	ARRAY_TYPE(const_string) cmd_args;
+	string_t *str, *str2;
+	const char *value, *const *args;
+
+	tab = t_malloc(sizeof(static_tab));
+	memcpy(tab, static_tab, sizeof(static_tab));
+
+	tab[0].value = mail_user;
+	tab[1].value = login;
+	tab[2].value = host;
+
+	t_array_init(&cmd_args, 8);
+	str = t_str_new(128);
+	str2 = t_str_new(128);
+	args = t_strsplit(doveadm_settings->dsync_remote_cmd, " ");
+	for (; *args != NULL; args++) {
+		if (strchr(*args, '%') == NULL)
+			value = *args;
+		else {
+			/* some automation: if parameter's all %variables
+			   expand to empty, but the %variable isn't the only
+			   text in the parameter, skip it. */
+			str_truncate(str, 0);
+			str_truncate(str2, 0);
+			var_expand(str, *args, tab);
+			var_expand(str2, *args, static_tab);
+			if (strcmp(str_c(str), str_c(str2)) == 0 &&
+			    str_len(str) > 0)
+				continue;
+			value = t_strdup(str_c(str));
+		}
+		array_append(&cmd_args, &value, 1);
+	}
+	array_append_zero(&cmd_args);
+	return array_idx(&cmd_args, 0);
+}
+
+static bool mirror_get_remote_cmd(struct dsync_cmd_context *ctx,
+				  const char *user,
+				  const char *const **cmd_args_r)
+{
+	const char *p, *host, *const *argv = ctx->ctx.args;
+
+	if (argv[1] != NULL) {
+		/* more than one parameter, so it contains a full command
+		   (e.g. ssh host dsync) */
+		mirror_get_remote_cmd_line(argv, cmd_args_r);
+		return TRUE;
+	}
+
+	/* if it begins with /[a-z0-9]+:/, it's a mail location
+	   (e.g. mdbox:~/mail) */
+	for (p = argv[0]; *p != '\0'; p++) {
+		if (!i_isalnum(*p)) {
+			if (*p == ':')
+				return FALSE;


More information about the dovecot-cvs mailing list