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