From dovecot at dovecot.org Mon Apr 2 21:49:16 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 02 Apr 2012 21:49:16 +0300 Subject: dovecot-2.1: imap: Enabling SPECIAL-USE selection option should ... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/7f4c35fcae80 changeset: 14368:7f4c35fcae80 user: Timo Sirainen date: Mon Apr 02 21:49:05 2012 +0300 description: imap: Enabling SPECIAL-USE selection option should also enable the same return option. diffstat: src/imap/cmd-list.c | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-) diffs (17 lines): diff -r 6a8b78450202 -r 7f4c35fcae80 src/imap/cmd-list.c --- a/src/imap/cmd-list.c Fri Mar 30 05:20:08 2012 +0300 +++ b/src/imap/cmd-list.c Mon Apr 02 21:49:05 2012 +0300 @@ -115,9 +115,10 @@ MAILBOX_LIST_ITER_RETURN_SUBSCRIBED; } else if (strcasecmp(str, "RECURSIVEMATCH") == 0) list_flags |= MAILBOX_LIST_ITER_SELECT_RECURSIVEMATCH; - else if (strcasecmp(str, "SPECIAL-USE") == 0) - list_flags |= MAILBOX_LIST_ITER_SELECT_SPECIALUSE; - else if (strcasecmp(str, "REMOTE") == 0) { + else if (strcasecmp(str, "SPECIAL-USE") == 0) { + list_flags |= MAILBOX_LIST_ITER_SELECT_SPECIALUSE | + MAILBOX_LIST_ITER_RETURN_SPECIALUSE; + } else if (strcasecmp(str, "REMOTE") == 0) { /* not supported, ignore */ } else { /* skip also optional list value */ From dovecot at dovecot.org Tue Apr 3 00:09:09 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 03 Apr 2012 00:09:09 +0300 Subject: dovecot-2.1: director: Changes to PING handling. Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/168e3b5cb6e8 changeset: 14369:168e3b5cb6e8 user: Timo Sirainen date: Mon Apr 02 23:28:22 2012 +0300 description: director: Changes to PING handling. Use larger ping timeouts. While waiting for sync keep doing rapid pings until the sync is finished, not just once. diffstat: src/director/director-connection.c | 63 +++++++++++++++++++++---------------- src/director/director-connection.h | 3 +- src/director/director.c | 11 +++++- 3 files changed, 46 insertions(+), 31 deletions(-) diffs (203 lines): diff -r 7f4c35fcae80 -r 168e3b5cb6e8 src/director/director-connection.c --- a/src/director/director-connection.c Mon Apr 02 21:49:05 2012 +0300 +++ b/src/director/director-connection.c Mon Apr 02 23:28:22 2012 +0300 @@ -23,13 +23,13 @@ #define MAX_OUTBUF_SIZE (1024*1024*10) #define OUTBUF_FLUSH_THRESHOLD (1024*128) /* Max idling time while connecting/handshaking before disconnecting */ -#define DIRECTOR_CONNECTION_INIT_TIMEOUT_MSECS (2*1000) +#define DIRECTOR_CONNECTION_INIT_TIMEOUT_MSECS (10*1000) /* How long to wait for PONG after PING request */ -#define DIRECTOR_CONNECTION_PING_TIMEOUT_MSECS (2*1000) +#define DIRECTOR_CONNECTION_PING_TIMEOUT_MSECS (10*1000) /* How long to wait to send PING when connection is idle */ #define DIRECTOR_CONNECTION_PING_INTERVAL_MSECS (15*1000) /* How long to wait before sending PING while waiting for SYNC reply */ -#define DIRECTOR_CONNECTION_SYNC_TIMEOUT_MSECS 1000 +#define DIRECTOR_CONNECTION_PING_SYNC_INTERVAL_MSECS 1000 /* If outgoing director connection exists for less than this many seconds, mark the host as failed so we won't try to reconnect to it immediately */ #define DIRECTOR_SUCCESS_MIN_CONNECT_SECS 10 @@ -61,7 +61,7 @@ unsigned int ignore_host_events:1; unsigned int handshake_sending_hosts:1; unsigned int ping_waiting:1; - unsigned int sync_ping:1; + unsigned int synced:1; }; static void director_connection_ping(struct director_connection *conn); @@ -636,6 +636,19 @@ return TRUE; } +static void +director_connection_set_ping_timeout(struct director_connection *conn) +{ + unsigned int msecs; + + msecs = conn->synced || !conn->handshake_received ? + DIRECTOR_CONNECTION_PING_INTERVAL_MSECS : + DIRECTOR_CONNECTION_PING_SYNC_INTERVAL_MSECS; + + timeout_remove(&conn->to_ping); + conn->to_ping = timeout_add(msecs, director_connection_ping, conn); +} + static void director_handshake_cmd_done(struct director_connection *conn) { struct director *dir = conn->dir; @@ -668,10 +681,7 @@ director_sync_send(dir, dir->self_host, dir->sync_seq, DIRECTOR_VERSION_MINOR); } - if (conn->to_ping != NULL) - timeout_remove(&conn->to_ping); - conn->to_ping = timeout_add(DIRECTOR_CONNECTION_PING_INTERVAL_MSECS, - director_connection_ping, conn); + director_connection_set_ping_timeout(conn); } static bool @@ -893,11 +903,9 @@ { if (!conn->ping_waiting) return TRUE; + conn->ping_waiting = FALSE; - conn->ping_waiting = FALSE; - timeout_remove(&conn->to_ping); - conn->to_ping = timeout_add(DIRECTOR_CONNECTION_PING_INTERVAL_MSECS, - director_connection_ping, conn); + director_connection_set_ping_timeout(conn); return TRUE; } @@ -971,8 +979,6 @@ char *line; bool ret; - if (conn->to_ping != NULL) - timeout_reset(conn->to_ping); switch (i_stream_read(conn->input)) { case 0: return; @@ -1007,6 +1013,8 @@ } } director_sync_thaw(dir); + if (conn != NULL) + timeout_reset(conn->to_ping); } static void director_connection_send_directors(struct director_connection *conn, @@ -1056,6 +1064,7 @@ if (o_stream_get_buffer_used_size(conn->output) >= OUTBUF_FLUSH_THRESHOLD) { if ((ret = o_stream_flush(conn->output)) <= 0) { /* continue later */ + timeout_reset(conn->to_ping); return ret; } } @@ -1068,6 +1077,7 @@ ret = o_stream_flush(conn->output); o_stream_uncork(conn->output); + timeout_reset(conn->to_ping); return ret; } @@ -1224,8 +1234,7 @@ user_directory_iter_deinit(&conn->user_iter); if (conn->to != NULL) timeout_remove(&conn->to); - if (conn->to_ping != NULL) - timeout_remove(&conn->to_ping); + timeout_remove(&conn->to_ping); if (conn->io != NULL) io_remove(&conn->io); i_stream_unref(&conn->input); @@ -1298,12 +1307,10 @@ static void director_connection_ping(struct director_connection *conn) { - conn->sync_ping = FALSE; if (conn->ping_waiting) return; - if (conn->to_ping != NULL) - timeout_remove(&conn->to_ping); + timeout_remove(&conn->to_ping); conn->to_ping = timeout_add(DIRECTOR_CONNECTION_PING_TIMEOUT_MSECS, director_connection_ping_timeout, conn); director_connection_send(conn, "PING\n"); @@ -1344,18 +1351,18 @@ o_stream_uncork(conn->output); } -void director_connection_wait_sync(struct director_connection *conn) +void director_connection_set_synced(struct director_connection *conn, + bool synced) { - /* switch to faster ping timeout. avoid reseting the timeout if it's - already fast. */ - if (conn->ping_waiting || conn->sync_ping) + if (conn->synced == synced) + return; + conn->synced = synced; + + /* switch ping timeout, unless we're already waiting for PONG */ + if (conn->ping_waiting) return; - if (conn->to_ping != NULL) - timeout_remove(&conn->to_ping); - conn->to_ping = timeout_add(DIRECTOR_CONNECTION_SYNC_TIMEOUT_MSECS, - director_connection_ping, conn); - conn->sync_ping = TRUE; + director_connection_set_ping_timeout(conn); } void director_connections_deinit(struct director *dir) diff -r 7f4c35fcae80 -r 168e3b5cb6e8 src/director/director-connection.h --- a/src/director/director-connection.h Mon Apr 02 21:49:05 2012 +0300 +++ b/src/director/director-connection.h Mon Apr 02 23:28:22 2012 +0300 @@ -14,7 +14,8 @@ void director_connection_send(struct director_connection *conn, const char *data); -void director_connection_wait_sync(struct director_connection *conn); +void director_connection_set_synced(struct director_connection *conn, + bool synced); void director_connection_send_except(struct director_connection *conn, struct director_host *skip_host, const char *data); diff -r 7f4c35fcae80 -r 168e3b5cb6e8 src/director/director.c --- a/src/director/director.c Mon Apr 02 21:49:05 2012 +0300 +++ b/src/director/director.c Mon Apr 02 23:28:22 2012 +0300 @@ -230,6 +230,10 @@ timeout_remove(&dir->to_reconnect); } + if (dir->left != NULL) + director_connection_set_synced(dir->left, TRUE); + if (dir->right != NULL) + director_connection_set_synced(dir->right, TRUE); if (dir->to_sync != NULL) timeout_remove(&dir->to_sync); dir->ring_synced = TRUE; @@ -310,9 +314,12 @@ director_connection_get_name(dir->right)); } + /* send PINGs to our connections more rapidly until we've synced again. + if the connection has actually died, we don't need to wait (and + delay requests) for as long to detect it */ if (dir->left != NULL) - director_connection_wait_sync(dir->left); - director_connection_wait_sync(dir->right); + director_connection_set_synced(dir->left, FALSE); + director_connection_set_synced(dir->right, FALSE); director_sync_send(dir, dir->self_host, dir->sync_seq, DIRECTOR_VERSION_MINOR); } From dovecot at dovecot.org Tue Apr 3 00:09:09 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 03 Apr 2012 00:09:09 +0300 Subject: dovecot-2.1: director: List of director connections belongs to s... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/c760ac046203 changeset: 14370:c760ac046203 user: Timo Sirainen date: Mon Apr 02 23:39:48 2012 +0300 description: director: List of director connections belongs to struct director. diffstat: src/director/director-connection.c | 40 ++++++++++++------------------------- src/director/director-connection.h | 6 +---- src/director/director.c | 26 ++++++++++++++++++++++- src/director/director.h | 2 +- 4 files changed, 39 insertions(+), 35 deletions(-) diffs (185 lines): diff -r 168e3b5cb6e8 -r c760ac046203 src/director/director-connection.c --- a/src/director/director-connection.c Mon Apr 02 23:28:22 2012 +0300 +++ b/src/director/director-connection.c Mon Apr 02 23:39:48 2012 +0300 @@ -7,7 +7,6 @@ #include "istream.h" #include "ostream.h" #include "str.h" -#include "llist.h" #include "master-service.h" #include "mail-host.h" #include "director.h" @@ -35,8 +34,6 @@ #define DIRECTOR_SUCCESS_MIN_CONNECT_SECS 10 struct director_connection { - struct director_connection *prev, *next; - struct director *dir; char *name; time_t created; @@ -1116,7 +1113,7 @@ director_connection_output, conn); conn->to_ping = timeout_add(DIRECTOR_CONNECTION_INIT_TIMEOUT_MSECS, director_connection_init_timeout, conn); - DLLIST_PREPEND(&dir->connections, conn); + array_append(&dir->connections, &conn, 1); return conn; } @@ -1212,8 +1209,9 @@ void director_connection_deinit(struct director_connection **_conn) { - struct director_connection *conn = *_conn; + struct director_connection *const *conns, *conn = *_conn; struct director *dir = conn->dir; + unsigned int i, count; *_conn = NULL; @@ -1224,7 +1222,14 @@ conn->created + DIRECTOR_SUCCESS_MIN_CONNECT_SECS > ioloop_time) conn->host->last_failed = ioloop_time; - DLLIST_REMOVE(&dir->connections, conn); + conns = array_get(&dir->connections, &count); + for (i = 0; i < count; i++) { + if (conns[i] == conn) { + array_delete(&dir->connections, i, 1); + break; + } + } + i_assert(i < count); if (dir->left == conn) dir->left = NULL; if (dir->right == conn) @@ -1328,17 +1333,9 @@ return conn->host; } -struct director_connection * -director_connection_find_outgoing(struct director *dir, - struct director_host *host) +bool director_connection_is_incoming(struct director_connection *conn) { - struct director_connection *conn; - - for (conn = dir->connections; conn != NULL; conn = conn->next) { - if (conn->host == host && !conn->in) - return conn; - } - return NULL; + return conn->in; } void director_connection_cork(struct director_connection *conn) @@ -1364,14 +1361,3 @@ director_connection_set_ping_timeout(conn); } - -void director_connections_deinit(struct director *dir) -{ - struct director_connection *conn; - - while (dir->connections != NULL) { - conn = dir->connections; - dir->connections = conn->next; - director_connection_deinit(&conn); - } -} diff -r 168e3b5cb6e8 -r c760ac046203 src/director/director-connection.h --- a/src/director/director-connection.h Mon Apr 02 23:28:22 2012 +0300 +++ b/src/director/director-connection.h Mon Apr 02 23:39:48 2012 +0300 @@ -23,13 +23,9 @@ const char *director_connection_get_name(struct director_connection *conn); struct director_host * director_connection_get_host(struct director_connection *conn); -struct director_connection * -director_connection_find_outgoing(struct director *dir, - struct director_host *host); +bool director_connection_is_incoming(struct director_connection *conn); void director_connection_cork(struct director_connection *conn); void director_connection_uncork(struct director_connection *conn); -void director_connections_deinit(struct director *dir); - #endif diff -r 168e3b5cb6e8 -r c760ac046203 src/director/director.c --- a/src/director/director.c Mon Apr 02 23:28:22 2012 +0300 +++ b/src/director/director.c Mon Apr 02 23:39:48 2012 +0300 @@ -81,12 +81,26 @@ i_unreached(); } +static bool +director_has_outgoing_connection(struct director *dir, + struct director_host *host) +{ + struct director_connection *const *connp; + + array_foreach(&dir->connections, connp) { + if (director_connection_get_host(*connp) == host && + !director_connection_is_incoming(*connp)) + return TRUE; + } + return FALSE; +} + int director_connect_host(struct director *dir, struct director_host *host) { unsigned int port; int fd; - if (director_connection_find_outgoing(dir, host) != NULL) + if (director_has_outgoing_connection(dir, host)) return 0; if (dir->debug) { @@ -669,6 +683,7 @@ dir->state_change_callback = callback; i_array_init(&dir->dir_hosts, 16); i_array_init(&dir->pending_requests, 16); + i_array_init(&dir->connections, 8); dir->users = user_directory_init(set->director_user_expire, set->director_username_hash); dir->mail_hosts = mail_hosts_init(); @@ -682,10 +697,16 @@ { struct director *dir = *_dir; struct director_host *const *hostp; + struct director_connection *conn, *const *connp; *_dir = NULL; - director_connections_deinit(dir); + while (array_count(&dir->connections) > 0) { + connp = array_idx(&dir->connections, 0); + conn = *connp; + director_connection_deinit(&conn); + } + user_directory_deinit(&dir->users); mail_hosts_deinit(&dir->mail_hosts); mail_hosts_deinit(&dir->orig_config_hosts); @@ -703,5 +724,6 @@ director_host_free(*hostp); array_free(&dir->pending_requests); array_free(&dir->dir_hosts); + array_free(&dir->connections); i_free(dir); } diff -r 168e3b5cb6e8 -r c760ac046203 src/director/director.h --- a/src/director/director.h Mon Apr 02 23:28:22 2012 +0300 +++ b/src/director/director.h Mon Apr 02 23:39:48 2012 +0300 @@ -29,7 +29,7 @@ struct director_host *self_host; struct director_connection *left, *right; /* all director connections */ - struct director_connection *connections; + ARRAY_DEFINE(connections, struct director_connection *); struct timeout *to_reconnect; struct timeout *to_sync; From dovecot at dovecot.org Tue Apr 3 00:23:12 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 03 Apr 2012 00:23:12 +0300 Subject: dovecot-2.1: director: Improved error logging for handling inval... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/d6cd93e32b37 changeset: 14371:d6cd93e32b37 user: Timo Sirainen date: Tue Apr 03 00:23:02 2012 +0300 description: director: Improved error logging for handling invalid commands/parameters. diffstat: src/director/director-connection.c | 103 ++++++++++++++++++++++-------------- 1 files changed, 63 insertions(+), 40 deletions(-) diffs (251 lines): diff -r c760ac046203 -r d6cd93e32b37 src/director/director-connection.c --- a/src/director/director-connection.c Mon Apr 02 23:39:48 2012 +0300 +++ b/src/director/director-connection.c Tue Apr 03 00:23:02 2012 +0300 @@ -50,6 +50,9 @@ struct user_directory_iter *user_iter; + /* set during command execution */ + const char *cur_cmd, *cur_line; + unsigned int in:1; unsigned int connected:1; unsigned int version_received:1; @@ -64,19 +67,32 @@ static void director_connection_ping(struct director_connection *conn); static void director_connection_disconnected(struct director_connection **conn); +static void ATTR_FORMAT(2, 3) +director_cmd_error(struct director_connection *conn, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + i_error("director(%s): Command %s: %s (input: %s)", conn->name, + conn->cur_cmd, t_strdup_vprintf(fmt, args), conn->cur_line); + va_end(args); +} + static bool director_args_parse_ip_port(struct director_connection *conn, const char *const *args, struct ip_addr *ip_r, unsigned int *port_r) { + if (args[0] == NULL || args[1] == NULL) { + director_cmd_error(conn, "Missing IP+port parameters"); + return FALSE; + } if (net_addr2ip(args[0], ip_r) < 0) { - i_error("director(%s): Command has invalid IP address: %s", - conn->name, args[0]); + director_cmd_error(conn, "Invalid IP address: %s", args[0]); return FALSE; } if (str_to_uint(args[1], port_r) < 0) { - i_error("director(%s): Command has invalid port: %s", - conn->name, args[1]); + director_cmd_error(conn, "Invalid port: %s", args[1]); return FALSE; } return TRUE; @@ -276,8 +292,7 @@ str_to_uint(args[0], &username_hash) < 0 || net_addr2ip(args[1], &ip) < 0 || str_to_uint(args[2], ×tamp) < 0) { - i_error("director(%s): Invalid USER handshake args", - conn->name); + director_cmd_error(conn, "Invalid parameters"); return FALSE; } weak = args[3] != NULL && args[3][0] == 'w'; @@ -305,7 +320,7 @@ if (str_array_length(args) != 2 || str_to_uint(args[0], &username_hash) < 0 || net_addr2ip(args[1], &ip) < 0) { - i_error("director(%s): Invalid USER args", conn->name); + director_cmd_error(conn, "Invalid parameters"); return FALSE; } @@ -356,9 +371,9 @@ struct mail_host *const *hostp; unsigned int remote_ring_completed; - if (args == NULL || str_to_uint(args[0], &remote_ring_completed) < 0) { - i_error("director(%s): Invalid HOST-HAND-START args", - conn->name); + if (args[0] == NULL || + str_to_uint(args[0], &remote_ring_completed) < 0) { + director_cmd_error(conn, "Invalid parameters"); return FALSE; } @@ -391,8 +406,7 @@ net_addr2ip(args[0], &ip) < 0 || str_to_uint(args[1], &port) < 0 || str_to_uint(args[2], &seq) < 0) { - i_error("director(%s): Command is missing parameters: %s", - conn->name, t_strarray_join(args, " ")); + director_cmd_error(conn, "Invalid parameters"); return -1; } *_args = args + 3; @@ -433,7 +447,7 @@ if (str_array_length(args) != 2 || str_to_uint(args[0], &username_hash) < 0 || net_addr2ip(args[1], &ip) < 0) { - i_error("director(%s): Invalid USER-WEAK args", conn->name); + director_cmd_error(conn, "Invalid parameters"); return FALSE; } @@ -474,7 +488,7 @@ if (str_array_length(args) != 2 || net_addr2ip(args[0], &ip) < 0 || str_to_uint(args[1], &vhost_count) < 0) { - i_error("director(%s): Invalid HOST args", conn->name); + director_cmd_error(conn, "Invalid parameters"); return FALSE; } if (conn->ignore_host_events) { @@ -532,7 +546,7 @@ if (str_array_length(args) != 1 || net_addr2ip(args[0], &ip) < 0) { - i_error("director(%s): Invalid HOST-REMOVE args", conn->name); + director_cmd_error(conn, "Invalid parameters"); return FALSE; } @@ -556,7 +570,7 @@ if (str_array_length(args) != 1 || net_addr2ip(args[0], &ip) < 0) { - i_error("director(%s): Invalid HOST-FLUSH args", conn->name); + director_cmd_error(conn, "Invalid parameters"); return FALSE; } @@ -582,7 +596,7 @@ if (str_array_length(args) != 2 || str_to_uint(args[0], &username_hash) < 0 || net_addr2ip(args[1], &ip) < 0) { - i_error("director(%s): Invalid USER-MOVE args", conn->name); + director_cmd_error(conn, "Invalid parameters"); return FALSE; } @@ -602,7 +616,7 @@ if (str_array_length(args) != 1 || str_to_uint(args[0], &username_hash) < 0) { - i_error("director(%s): Invalid USER-KILLED args", conn->name); + director_cmd_error(conn, "Invalid parameters"); return FALSE; } @@ -623,8 +637,7 @@ if (str_array_length(args) != 1 || str_to_uint(args[0], &username_hash) < 0) { - i_error("director(%s): Invalid USER-KILLED-EVERYWHERE args", - conn->name); + director_cmd_error(conn, "Invalid parameters"); return FALSE; } @@ -706,17 +719,15 @@ return TRUE; } if (!conn->version_received) { - i_error("director(%s): Incompatible protocol", conn->name); + director_cmd_error(conn, "Incompatible protocol"); return FALSE; } - if (strcmp(cmd, "ME") == 0 && !conn->me_received && - str_array_length(args) == 2) + if (strcmp(cmd, "ME") == 0 && !conn->me_received) return director_cmd_me(conn, args); /* only outgoing connections get a CONNECT reference */ - if (!conn->in && strcmp(cmd, "CONNECT") == 0 && - str_array_length(args) == 2) { + if (!conn->in && strcmp(cmd, "CONNECT") == 0) { /* remote wants us to connect elsewhere */ if (!director_args_parse_ip_port(conn, args, &ip, &port)) return FALSE; @@ -827,7 +838,7 @@ if (str_array_length(args) < 3 || !director_args_parse_ip_port(conn, args, &ip, &port) || str_to_uint(args[2], &seq) < 0) { - i_error("director(%s): Invalid SYNC args", conn->name); + director_cmd_error(conn, "Invalid parameters"); return FALSE; } if (args[3] != NULL) @@ -856,7 +867,7 @@ if (str_array_length(args) != 2 || !director_args_parse_ip_port(conn, args, &ip, &port)) { - i_error("director(%s): Invalid CONNECT args", conn->name); + director_cmd_error(conn, "Invalid parameters"); return FALSE; } @@ -907,18 +918,9 @@ } static bool -director_connection_handle_line(struct director_connection *conn, - const char *line) +director_connection_handle_cmd(struct director_connection *conn, + const char *cmd, const char *const *args) { - const char *cmd, *const *args; - - args = t_strsplit(line, "\t"); - cmd = args[0]; args++; - if (cmd == NULL) { - i_error("director(%s): Received empty line", conn->name); - return FALSE; - } - /* ping/pong is always handled */ if (strcmp(cmd, "PING") == 0) { director_connection_send(conn, "PONG\n"); @@ -965,11 +967,32 @@ if (strcmp(cmd, "CONNECT") == 0) return director_cmd_connect(conn, args); - i_error("director(%s): Unknown command (in this state): %s", - conn->name, cmd); + director_cmd_error(conn, "Unknown command %s", cmd); return FALSE; } +static bool +director_connection_handle_line(struct director_connection *conn, + const char *line) +{ + const char *cmd, *const *args; + bool ret; + + args = t_strsplit(line, "\t"); + cmd = args[0]; args++; + if (cmd == NULL) { + i_error("director(%s): Received empty line", conn->name); + return FALSE; + } + + conn->cur_cmd = cmd; + conn->cur_line = line; + ret = director_connection_handle_cmd(conn, cmd, args); + conn->cur_cmd = NULL; + conn->cur_line = NULL; + return ret; +} + static void director_connection_input(struct director_connection *conn) { struct director *dir = conn->dir; From dovecot at dovecot.org Tue Apr 3 00:50:23 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 03 Apr 2012 00:50:23 +0300 Subject: dovecot-2.1: director: Handle all commands during handshake. Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/544a8c4705e5 changeset: 14372:544a8c4705e5 user: Timo Sirainen date: Tue Apr 03 00:50:12 2012 +0300 description: director: Handle all commands during handshake. Previously the sender might have sent these commands, but the receiver wouldn't have handled them and instead just disconnected. diffstat: src/director/director-connection.c | 166 +++++++++++++++++++++++------------- src/director/director-connection.h | 1 + src/director/director.c | 8 +- 3 files changed, 114 insertions(+), 61 deletions(-) diffs (truncated from 317 to 300 lines): diff -r d6cd93e32b37 -r 544a8c4705e5 src/director/director-connection.c --- a/src/director/director-connection.c Tue Apr 03 00:23:02 2012 +0300 +++ b/src/director/director-connection.c Tue Apr 03 00:50:12 2012 +0300 @@ -1,5 +1,28 @@ /* Copyright (c) 2010-2012 Dovecot authors, see the included COPYING file */ +/* + Handshaking: + + Incoming director connections send: + + VERSION + ME + + DONE + + Outgoing director connections send: + + VERSION + ME + [0..n] DIRECTOR + HOST-HAND-START + [0..n] HOST + HOST-HAND-END + [0..n] USER + + DONE +*/ + #include "lib.h" #include "ioloop.h" #include "array.h" @@ -33,6 +56,9 @@ mark the host as failed so we won't try to reconnect to it immediately */ #define DIRECTOR_SUCCESS_MIN_CONNECT_SECS 10 +#define CMD_IS_USER_HANDHAKE(args) \ + (str_array_length(args) > 2) + struct director_connection { struct director *dir; char *name; @@ -109,6 +135,10 @@ if (!director_args_parse_ip_port(conn, args, &ip, &port)) return FALSE; + if (conn->me_received) { + director_cmd_error(conn, "Duplicate ME"); + return FALSE; + } if (!conn->in && (!net_ip_compare(&conn->host->ip, &ip) || conn->host->port != port)) { @@ -317,6 +347,8 @@ struct mail_host *host; struct user *user; + /* NOTE: if more parameters are added, update also + CMD_IS_USER_HANDHAKE() macro */ if (str_array_length(args) != 2 || str_to_uint(args[0], &username_hash) < 0 || net_addr2ip(args[1], &ip) < 0) { @@ -694,7 +726,7 @@ director_connection_set_ping_timeout(conn); } -static bool +static int director_connection_handle_handshake(struct director_connection *conn, const char *cmd, const char *const *args) { @@ -708,29 +740,33 @@ i_error("director(%s): Wrong protocol in socket " "(%s vs %s)", conn->name, args[0], DIRECTOR_VERSION_NAME); - return FALSE; + return -1; } else if (atoi(args[1]) != DIRECTOR_VERSION_MAJOR) { i_error("director(%s): Incompatible protocol version: " "%u vs %u", conn->name, atoi(args[1]), DIRECTOR_VERSION_MAJOR); - return FALSE; + return -1; } conn->version_received = TRUE; - return TRUE; + return 1; } if (!conn->version_received) { director_cmd_error(conn, "Incompatible protocol"); - return FALSE; + return -1; } - if (strcmp(cmd, "ME") == 0 && !conn->me_received) - return director_cmd_me(conn, args); + if (strcmp(cmd, "ME") == 0) + return director_cmd_me(conn, args) ? 1 : -1; - /* only outgoing connections get a CONNECT reference */ - if (!conn->in && strcmp(cmd, "CONNECT") == 0) { + if (strcmp(cmd, "CONNECT") == 0) { /* remote wants us to connect elsewhere */ if (!director_args_parse_ip_port(conn, args, &ip, &port)) - return FALSE; + return -1; + if (conn->in) { + director_cmd_error(conn, + "Incoming connections can't request CONNECT"); + return -1; + } conn->dir->right = NULL; host = director_host_get(conn->dir, &ip, port); @@ -740,53 +776,44 @@ if (conn->dir->debug) i_debug("Received CONNECT reference to %s", host->name); (void)director_connect_host(conn->dir, host); - return FALSE; + return 1; } - /* only incoming connections get DIRECTOR and HOST lists */ - if (conn->in && strcmp(cmd, "DIRECTOR") == 0 && conn->me_received) - return director_cmd_director(conn, args); + /* Only VERSION and CONNECT commands are allowed before ME */ + if (!conn->me_received) { + director_cmd_error(conn, "Expecting ME command first"); + return -1; + } - if (strcmp(cmd, "HOST") == 0) { - /* allow hosts from all connections always, - this could be an host update */ - if (conn->handshake_sending_hosts) - return director_cmd_host_handshake(conn, args); - else - return director_cmd_host(conn, args); + /* incoming connections get a HOST list */ + if (conn->handshake_sending_hosts) { + if (strcmp(cmd, "HOST") == 0) + return director_cmd_host_handshake(conn, args) ? 1 : -1; + if (strcmp(cmd, "HOST-HAND-END") == 0) { + conn->ignore_host_events = FALSE; + conn->handshake_sending_hosts = FALSE; + return 1; + } + director_cmd_error(conn, "Unexpected command during host list"); + return -1; } - if (conn->handshake_sending_hosts && - strcmp(cmd, "HOST-HAND-END") == 0) { - conn->ignore_host_events = FALSE; - conn->handshake_sending_hosts = FALSE; - return TRUE; + if (strcmp(cmd, "HOST-HAND-START") == 0) { + if (!conn->in) { + director_cmd_error(conn, + "Host list is only for incoming connections"); + return -1; + } + return director_cmd_host_hand_start(conn, args) ? 1 : -1; } - if (conn->in && strcmp(cmd, "HOST-HAND-START") == 0 && - conn->me_received) - return director_cmd_host_hand_start(conn, args); - /* only incoming connections get a full USER list, but outgoing - connections can also receive USER updates during handshake and - it wouldn't be safe to ignore them. */ - if (!conn->me_received) { - /* no USER updates until ME */ - } else if (conn->in && strcmp(cmd, "USER") == 0) { - return director_handshake_cmd_user(conn, args); - } else if (!conn->in) { - if (strcmp(cmd, "USER") == 0) - return director_cmd_user(conn, args); - if (strcmp(cmd, "USER-WEAK") == 0) - return director_cmd_user_weak(conn, args); + if (conn->in && strcmp(cmd, "USER") == 0 && CMD_IS_USER_HANDHAKE(args)) + return director_handshake_cmd_user(conn, args) ? 1 : -1; + + /* both get DONE */ + if (strcmp(cmd, "DONE") == 0) { + director_handshake_cmd_done(conn); + return 1; } - /* both get DONE */ - if (strcmp(cmd, "DONE") == 0 && !conn->handshake_received && - !conn->handshake_sending_hosts) { - director_handshake_cmd_done(conn); - return TRUE; - } - i_error("director(%s): Invalid handshake command: %s " - "(in=%d me_received=%d)", conn->name, cmd, - conn->in, conn->me_received); - return FALSE; + return 0; } static void @@ -806,6 +833,9 @@ /* stale SYNC event */ return; } + /* sync_seq increases when we get disconnected, so we must be + successfully connected to both directions */ + i_assert(dir->left != NULL && dir->right != NULL); dir->ring_min_version = minor_version; if (!dir->ring_handshaked) { @@ -921,6 +951,8 @@ director_connection_handle_cmd(struct director_connection *conn, const char *cmd, const char *const *args) { + int ret; + /* ping/pong is always handled */ if (strcmp(cmd, "PING") == 0) { director_connection_send(conn, "PONG\n"); @@ -930,7 +962,10 @@ return director_cmd_pong(conn); if (!conn->handshake_received) { - if (!director_connection_handle_handshake(conn, cmd, args)) { + ret = director_connection_handle_handshake(conn, cmd, args); + if (ret > 0) + return TRUE; + if (ret < 0) { /* invalid commands during handshake, we probably don't want to reconnect here */ if (conn->dir->debug) { @@ -941,7 +976,7 @@ conn->host->last_failed = ioloop_time; return FALSE; } - return TRUE; + /* allow also other commands during handshake */ } if (strcmp(cmd, "USER") == 0) @@ -1103,21 +1138,27 @@ static int director_connection_output(struct director_connection *conn) { - if (conn->user_iter != NULL) + if (conn->user_iter != NULL) { + /* still handshaking USER list */ return director_connection_send_users(conn); - else - return o_stream_flush(conn->output); + } + return o_stream_flush(conn->output); } static void director_connection_init_timeout(struct director_connection *conn) { + unsigned int secs = ioloop_time - conn->created; + if (conn->host != NULL) conn->host->last_failed = ioloop_time; - if (!conn->connected) - i_error("director(%s): Connect timed out", conn->name); - else - i_error("director(%s): Handshaking timed out", conn->name); + if (!conn->connected) { + i_error("director(%s): Connect timed out (%u secs)", + conn->name, secs); + } else { + i_error("director(%s): Handshaking timed out (%u secs)", + conn->name, secs); + } director_connection_disconnected(&conn); } @@ -1356,6 +1397,11 @@ return conn->host; } +bool director_connection_is_handshaked(struct director_connection *conn) +{ + return conn->handshake_received; +} + bool director_connection_is_incoming(struct director_connection *conn) { return conn->in; diff -r d6cd93e32b37 -r 544a8c4705e5 src/director/director-connection.h --- a/src/director/director-connection.h Tue Apr 03 00:23:02 2012 +0300 +++ b/src/director/director-connection.h Tue Apr 03 00:50:12 2012 +0300 @@ -23,6 +23,7 @@ const char *director_connection_get_name(struct director_connection *conn); struct director_host * director_connection_get_host(struct director_connection *conn); +bool director_connection_is_handshaked(struct director_connection *conn); bool director_connection_is_incoming(struct director_connection *conn); void director_connection_cork(struct director_connection *conn); diff -r d6cd93e32b37 -r 544a8c4705e5 src/director/director.c --- a/src/director/director.c Tue Apr 03 00:23:02 2012 +0300 From dovecot at dovecot.org Tue Apr 3 05:58:44 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 03 Apr 2012 05:58:44 +0300 Subject: dovecot-2.1: director: Redesigned connection handling and error ... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/b43ae3805f5f changeset: 14373:b43ae3805f5f user: Timo Sirainen date: Tue Apr 03 05:58:29 2012 +0300 description: director: Redesigned connection handling and error handling. Director now accepts all connections from everywhere and syncs them until the handshaking is finished. At that point it finally decides if this is a connection that should be used as our left/right connection, or if it should be disconnected. This should make connecting more reliable, especially if one of the directors sends broken handshake or has other trouble. diffstat: src/director/director-connection.c | 539 ++++++++++++++++++++++-------------- src/director/director-connection.h | 4 +- src/director/director.c | 40 +- src/director/director.h | 4 + 4 files changed, 357 insertions(+), 230 deletions(-) diffs (truncated from 929 to 300 lines): diff -r 544a8c4705e5 -r b43ae3805f5f src/director/director-connection.c --- a/src/director/director-connection.c Tue Apr 03 00:50:12 2012 +0300 +++ b/src/director/director-connection.c Tue Apr 03 05:58:29 2012 +0300 @@ -7,8 +7,10 @@ VERSION ME - + DONE + Outgoing director connections send: @@ -21,6 +23,9 @@ [0..n] USER DONE + + */ #include "lib.h" @@ -44,10 +49,16 @@ #define MAX_INBUF_SIZE 1024 #define MAX_OUTBUF_SIZE (1024*1024*10) #define OUTBUF_FLUSH_THRESHOLD (1024*128) -/* Max idling time while connecting/handshaking before disconnecting */ -#define DIRECTOR_CONNECTION_INIT_TIMEOUT_MSECS (10*1000) -/* How long to wait for PONG after PING request */ -#define DIRECTOR_CONNECTION_PING_TIMEOUT_MSECS (10*1000) +/* Max idling time before "ME" command must have been received, + or we'll disconnect. */ +#define DIRECTOR_CONNECTION_ME_TIMEOUT_MSECS (2*1000) +/* Max idling time before "DONE" command must have been received, + or we'll disconnect. */ +#define DIRECTOR_CONNECTION_DONE_TIMEOUT_MSECS (30*1000) +/* How long to wait for PONG for an idling connection */ +#define DIRECTOR_CONNECTION_PING_IDLE_TIMEOUT_MSECS (2*1000) +/* Maximum time to wait for PONG reply */ +#define DIRECTOR_CONNECTION_PONG_TIMEOUT_MSECS (60*1000) /* How long to wait to send PING when connection is idle */ #define DIRECTOR_CONNECTION_PING_INTERVAL_MSECS (15*1000) /* How long to wait before sending PING while waiting for SYNC reply */ @@ -56,6 +67,14 @@ mark the host as failed so we won't try to reconnect to it immediately */ #define DIRECTOR_SUCCESS_MIN_CONNECT_SECS 10 +#if DIRECTOR_CONNECTION_DONE_TIMEOUT_MSECS <= DIRECTOR_CONNECTION_PING_TIMEOUT_MSECS +# error DIRECTOR_CONNECTION_DONE_TIMEOUT_MSECS is too low +#endif + +#if DIRECTOR_CONNECTION_PONG_TIMEOUT_MSECS <= DIRECTOR_CONNECTION_PING_IDLE_TIMEOUT_MSECS +# error DIRECTOR_CONNECTION_PONG_TIMEOUT_MSECS is too low +#endif + #define CMD_IS_USER_HANDHAKE(args) \ (str_array_length(args) > 2) @@ -72,7 +91,7 @@ struct io *io; struct istream *input; struct ostream *output; - struct timeout *to, *to_ping; + struct timeout *to, *to_ping, *to_pong; struct user_directory_iter *user_iter; @@ -88,9 +107,10 @@ unsigned int handshake_sending_hosts:1; unsigned int ping_waiting:1; unsigned int synced:1; + unsigned int wrong_host:1; + unsigned int verifying_left:1; }; -static void director_connection_ping(struct director_connection *conn); static void director_connection_disconnected(struct director_connection **conn); static void ATTR_FORMAT(2, 3) @@ -104,6 +124,172 @@ va_end(args); } +static void +director_connection_init_timeout(struct director_connection *conn) +{ + unsigned int secs = ioloop_time - conn->created; + + if (!conn->connected) { + i_error("director(%s): Connect timed out (%u secs)", + conn->name, secs); + } else if (!conn->me_received) { + i_error("director(%s): Handshaking ME timed out (%u secs)", + conn->name, secs); + } else { + i_error("director(%s): Handshaking DONE timed out (%u secs)", + conn->name, secs); + } + director_connection_disconnected(&conn); +} + +static void +director_connection_set_ping_timeout(struct director_connection *conn) +{ + unsigned int msecs; + + msecs = conn->synced || !conn->handshake_received ? + DIRECTOR_CONNECTION_PING_INTERVAL_MSECS : + DIRECTOR_CONNECTION_PING_SYNC_INTERVAL_MSECS; + + timeout_remove(&conn->to_ping); + conn->to_ping = timeout_add(msecs, director_connection_ping, conn); +} + +static void director_connection_send_connect(struct director_connection *conn, + struct director_host *host) +{ + const char *connect_str; + + connect_str = t_strdup_printf("CONNECT\t%s\t%u\n", + net_ip2addr(&host->ip), host->port); + director_connection_send(conn, connect_str); + (void)o_stream_flush(conn->output); + o_stream_uncork(conn->output); +} + +static void director_connection_assigned(struct director_connection *conn) +{ + struct director *dir = conn->dir; + + if (dir->left != NULL && dir->right != NULL) { + /* we're connected to both directors. see if the ring is + finished by sending a SYNC. if we get it back, it's done. */ + dir->sync_seq++; + director_set_ring_unsynced(dir); + director_sync_send(dir, dir->self_host, dir->sync_seq, + DIRECTOR_VERSION_MINOR); + } + director_connection_set_ping_timeout(conn); +} + +static bool director_connection_assign_left(struct director_connection *conn) +{ + struct director *dir = conn->dir; + + i_assert(conn->in); + i_assert(dir->left != conn); + + /* make sure this is the correct incoming connection */ + if (conn->host->self) { + i_error("Connection from self, dropping"); + return FALSE; + } else if (dir->left == NULL) { + /* no conflicts yet */ + } else if (dir->left->host == conn->host) { + i_info("Dropping existing connection %s " + "in favor of its new connection %s", + dir->left->host->name, conn->host->name); + director_connection_deinit(&dir->left); + } else if (dir->left->verifying_left) { + /* we're waiting to verify if our current left is still + working. if we don't receive a PONG, the current left + gets disconnected and a new left gets assigned. if we do + receive a PONG, we'll wait until the current left + disconnects us and then reassign the new left. */ + return TRUE; + } else if (director_host_cmp_to_self(dir->left->host, conn->host, + dir->self_host) < 0) { + /* the old connection is the correct one. + refer the client there (FIXME: do we ever get here?) */ + i_warning("Director connection %s tried to connect to " + "us, should use %s instead", + conn->name, dir->left->host->name); + director_connection_send_connect(conn, dir->left->host); + return FALSE; + } else { + /* this new connection is the correct one, but wait until the + old connection gets disconnected before using this one. + that guarantees that the director inserting itself into + the ring has finished handshaking its left side, so the + switch will be fast. */ + return TRUE; + } + dir->left = conn; + i_free(conn->name); + conn->name = i_strdup_printf("%s/left", conn->host->name); + director_connection_assigned(conn); + return TRUE; +} + +static void director_assign_left(struct director *dir) +{ + struct director_connection *conn, *const *connp; + + array_foreach(&dir->connections, connp) { + conn = *connp; + + if (conn->in && conn->handshake_received && conn != dir->left) { + /* either use this or disconnect it */ + if (!director_connection_assign_left(conn)) { + /* we don't want this */ + director_connection_deinit(&dir->left); + director_assign_left(dir); + break; + } + } + } +} + +static bool director_has_outgoing_connections(struct director *dir) +{ + struct director_connection *const *connp; + + array_foreach(&dir->connections, connp) { + if (!(*connp)->in) + return TRUE; + } + return FALSE; +} + +static bool director_connection_assign_right(struct director_connection *conn) +{ + struct director *dir = conn->dir; + + i_assert(!conn->in); + + if (dir->right != NULL) { + /* see if we should disconnect or keep the existing + connection. */ + if (director_host_cmp_to_self(conn->host, dir->right->host, + dir->self_host) <= 0) { + /* the old connection is the correct one */ + i_warning("Aborting incorrect outgoing connection to %s " + "(already connected to correct one: %s)", + conn->host->name, dir->right->host->name); + conn->wrong_host = TRUE; + return FALSE; + } + i_info("Replacing right director connection %s with %s", + dir->right->host->name, conn->host->name); + director_connection_deinit(&dir->right); + } + dir->right = conn; + i_free(conn->name); + conn->name = i_strdup_printf("%s/right", conn->host->name); + director_connection_assigned(conn); + return TRUE; +} + static bool director_args_parse_ip_port(struct director_connection *conn, const char *const *args, @@ -128,7 +314,6 @@ const char *const *args) { struct director *dir = conn->dir; - struct director_host *host; const char *connect_str; struct ip_addr ip; unsigned int port; @@ -148,75 +333,55 @@ net_ip2addr(&ip), port); return FALSE; } - host = director_host_get(dir, &ip, port); - /* the host is up now, make sure we can connect to it immediately - if needed */ - host->last_failed = 0; conn->me_received = TRUE; + timeout_remove(&conn->to_ping); + conn->to_ping = timeout_add(DIRECTOR_CONNECTION_DONE_TIMEOUT_MSECS, + director_connection_init_timeout, conn); + if (!conn->in) return TRUE; - i_free(conn->name); - conn->name = i_strdup_printf("%s/left", host->name); - conn->host = host; + /* Incoming connection: + + a) we don't have an established ring yet. make sure we're connecting + to our right side (which might become our left side). + + b) it's our current "left" connection. the previous connection + is most likely dead. + + c) we have an existing ring. tell our current "left" to connect to + it with CONNECT command. + + d) the incoming connection doesn't belong to us at all, refer it + elsewhere with CONNECT. however, before disconnecting it verify + first that our left side is actually still functional. + */ + conn->host = director_host_get(dir, &ip, port); /* make sure we don't keep old sequence values across restarts */ From dovecot at dovecot.org Wed Apr 4 03:45:00 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 04 Apr 2012 03:45:00 +0300 Subject: dovecot-2.1: lib-index: Don't assert-crash with broken extension... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/47526bf86c57 changeset: 14374:47526bf86c57 user: Timo Sirainen date: Wed Apr 04 03:44:04 2012 +0300 description: lib-index: Don't assert-crash with broken extension record intros in log. diffstat: src/lib-index/mail-index-map.c | 10 +++++++--- 1 files changed, 7 insertions(+), 3 deletions(-) diffs (27 lines): diff -r b43ae3805f5f -r 47526bf86c57 src/lib-index/mail-index-map.c --- a/src/lib-index/mail-index-map.c Tue Apr 03 05:58:29 2012 +0300 +++ b/src/lib-index/mail-index-map.c Wed Apr 04 03:44:04 2012 +0300 @@ -174,6 +174,12 @@ return -1; } + if (ext_hdr->record_offset == 0) { + /* if we get here from extension introduction, record_offset=0 + and hdr->record_size hasn't been updated yet */ + return 0; + } + if (ext_hdr->record_offset + ext_hdr->record_size > hdr->record_size) { *error_r = t_strdup_printf("Record field points " "outside record size (%u+%u > %u)", @@ -210,9 +216,7 @@ return -1; } - /* if we get here from extension introduction, record_offset=0 and - hdr->record_size hasn't been updated yet */ - if (ext_hdr->record_offset != 0 && ext_hdr->record_size != 0) { + if (ext_hdr->record_size != 0) { if (mail_index_map_ext_hdr_check_record(hdr, ext_hdr, error_r) < 0) return -1; From dovecot at dovecot.org Wed Apr 4 03:46:27 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 04 Apr 2012 03:46:27 +0300 Subject: dovecot-2.0: lib-index: Don't assert-crash with broken extension... Message-ID: details: http://hg.dovecot.org/dovecot-2.0/rev/a45cfc1971e8 changeset: 13080:a45cfc1971e8 user: Timo Sirainen date: Wed Apr 04 03:44:04 2012 +0300 description: lib-index: Don't assert-crash with broken extension record intros in log. diffstat: src/lib-index/mail-index-map.c | 10 +++++++--- 1 files changed, 7 insertions(+), 3 deletions(-) diffs (27 lines): diff -r ff1364d4d528 -r a45cfc1971e8 src/lib-index/mail-index-map.c --- a/src/lib-index/mail-index-map.c Thu Mar 22 18:28:04 2012 +0200 +++ b/src/lib-index/mail-index-map.c Wed Apr 04 03:44:04 2012 +0300 @@ -174,6 +174,12 @@ return -1; } + if (ext_hdr->record_offset == 0) { + /* if we get here from extension introduction, record_offset=0 + and hdr->record_size hasn't been updated yet */ + return 0; + } + if (ext_hdr->record_offset + ext_hdr->record_size > hdr->record_size) { *error_r = t_strdup_printf("Record field points " "outside record size (%u+%u > %u)", @@ -210,9 +216,7 @@ return -1; } - /* if we get here from extension introduction, record_offset=0 and - hdr->record_size hasn't been updated yet */ - if (ext_hdr->record_offset != 0 && ext_hdr->record_size != 0) { + if (ext_hdr->record_size != 0) { if (mail_index_map_ext_hdr_check_record(hdr, ext_hdr, error_r) < 0) return -1; From dovecot at dovecot.org Wed Apr 4 03:47:59 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 04 Apr 2012 03:47:59 +0300 Subject: dovecot-2.1: doveadm mailbox delete: -s parameter wasn't working. Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/411344f9daf3 changeset: 14375:411344f9daf3 user: Timo Sirainen date: Wed Apr 04 03:47:52 2012 +0300 description: doveadm mailbox delete: -s parameter wasn't working. diffstat: src/doveadm/doveadm-mail-mailbox.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diffs (22 lines): diff -r 47526bf86c57 -r 411344f9daf3 src/doveadm/doveadm-mail-mailbox.c --- a/src/doveadm/doveadm-mail-mailbox.c Wed Apr 04 03:44:04 2012 +0300 +++ b/src/doveadm/doveadm-mail-mailbox.c Wed Apr 04 03:47:52 2012 +0300 @@ -371,6 +371,9 @@ case 'r': ctx->recursive = TRUE; break; + case 's': + ctx->ctx.subscriptions = TRUE; + break; default: return FALSE; } @@ -385,7 +388,7 @@ ctx->ctx.ctx.v.init = cmd_mailbox_delete_init; ctx->ctx.ctx.v.run = cmd_mailbox_delete_run; ctx->ctx.ctx.v.parse_arg = cmd_mailbox_delete_parse_arg; - ctx->ctx.ctx.getopt_args = "r"; + ctx->ctx.ctx.getopt_args = "rs"; p_array_init(&ctx->mailboxes, ctx->ctx.ctx.pool, 16); return &ctx->ctx.ctx; } From dovecot at dovecot.org Wed Apr 4 04:31:27 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 04 Apr 2012 04:31:27 +0300 Subject: dovecot-2.1: lib-storage: Fixed setting usable/unusable flags fo... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/4fe357d34faf changeset: 14376:4fe357d34faf user: Timo Sirainen date: Wed Apr 04 04:31:09 2012 +0300 description: lib-storage: Fixed setting usable/unusable flags for shared namespaces. If a namespace doesn't have a root that exists, mark it as unusable. This avoids ACL plugin from autocreating that directory. diffstat: src/lib-storage/index/shared/shared-storage.c | 19 ++++++++++++++++++- 1 files changed, 18 insertions(+), 1 deletions(-) diffs (36 lines): diff -r 411344f9daf3 -r 4fe357d34faf src/lib-storage/index/shared/shared-storage.c --- a/src/lib-storage/index/shared/shared-storage.c Wed Apr 04 03:47:52 2012 +0300 +++ b/src/lib-storage/index/shared/shared-storage.c Wed Apr 04 04:31:09 2012 +0300 @@ -120,6 +120,19 @@ str_append(location, username); } +static bool shared_namespace_exists(struct mail_namespace *ns) +{ + const char *path; + struct stat st; + + path = mailbox_list_get_path(ns->list, NULL, MAILBOX_LIST_PATH_TYPE_DIR); + if (path == NULL) { + /* we can't know if this exists */ + return TRUE; + } + return stat(path, &st) == 0; +} + int shared_storage_get_namespace(struct mail_namespace **_ns, const char **_name) { @@ -310,7 +323,11 @@ mail_namespace_destroy(new_ns); return -1; } - ns->flags |= NAMESPACE_FLAG_USABLE; + if ((new_ns->flags & NAMESPACE_FLAG_UNUSABLE) == 0 && + !shared_namespace_exists(new_ns)) { + /* this user doesn't have a usable storage */ + new_ns->flags |= NAMESPACE_FLAG_UNUSABLE; + } *_name = mailbox_list_get_storage_name(new_ns->list, t_strconcat(new_ns->prefix, name, NULL)); *_ns = new_ns; From dovecot at dovecot.org Wed Apr 4 04:33:46 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 04 Apr 2012 04:33:46 +0300 Subject: dovecot-2.1: lib-storage: Previous change incorrectly reverted s... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/2bcab08dc994 changeset: 14377:2bcab08dc994 user: Timo Sirainen date: Wed Apr 04 04:33:41 2012 +0300 description: lib-storage: Previous change incorrectly reverted setting parent shared namespace usable. diffstat: src/lib-storage/index/shared/shared-storage.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diffs (13 lines): diff -r 4fe357d34faf -r 2bcab08dc994 src/lib-storage/index/shared/shared-storage.c --- a/src/lib-storage/index/shared/shared-storage.c Wed Apr 04 04:31:09 2012 +0300 +++ b/src/lib-storage/index/shared/shared-storage.c Wed Apr 04 04:33:41 2012 +0300 @@ -328,6 +328,9 @@ /* this user doesn't have a usable storage */ new_ns->flags |= NAMESPACE_FLAG_UNUSABLE; } + /* mark the shared namespace root as usable, since it now has + child namespaces */ + ns->flags |= NAMESPACE_FLAG_USABLE; *_name = mailbox_list_get_storage_name(new_ns->list, t_strconcat(new_ns->prefix, name, NULL)); *_ns = new_ns; From dovecot at dovecot.org Wed Apr 4 04:34:13 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 04 Apr 2012 04:34:13 +0300 Subject: dovecot-2.0: lib-storage: Fixed setting usable/unusable flags fo... Message-ID: details: http://hg.dovecot.org/dovecot-2.0/rev/b15889b82258 changeset: 13081:b15889b82258 user: Timo Sirainen date: Wed Apr 04 04:34:08 2012 +0300 description: lib-storage: Fixed setting usable/unusable flags for shared namespaces. If a namespace doesn't have a root that exists, mark it as unusable. This avoids ACL plugin from autocreating that directory. diffstat: src/lib-storage/index/shared/shared-storage.c | 20 ++++++++++++++++++++ 1 files changed, 20 insertions(+), 0 deletions(-) diffs (37 lines): diff -r a45cfc1971e8 -r b15889b82258 src/lib-storage/index/shared/shared-storage.c --- a/src/lib-storage/index/shared/shared-storage.c Wed Apr 04 03:44:04 2012 +0300 +++ b/src/lib-storage/index/shared/shared-storage.c Wed Apr 04 04:34:08 2012 +0300 @@ -119,6 +119,19 @@ str_append(location, username); } +static bool shared_namespace_exists(struct mail_namespace *ns) +{ + const char *path; + struct stat st; + + path = mailbox_list_get_path(ns->list, NULL, MAILBOX_LIST_PATH_TYPE_DIR); + if (path == NULL) { + /* we can't know if this exists */ + return TRUE; + } + return stat(path, &st) == 0; +} + int shared_storage_get_namespace(struct mail_namespace **_ns, const char **_name) { @@ -307,6 +320,13 @@ mail_namespace_destroy(new_ns); return -1; } + if ((new_ns->flags & NAMESPACE_FLAG_UNUSABLE) == 0 && + !shared_namespace_exists(new_ns)) { + /* this user doesn't have a usable storage */ + new_ns->flags |= NAMESPACE_FLAG_UNUSABLE; + } + /* mark the shared namespace root as usable, since it now has + child namespaces */ ns->flags |= NAMESPACE_FLAG_USABLE; *_name = mail_namespace_fix_sep(new_ns, name); *_ns = new_ns; From dovecot at dovecot.org Wed Apr 4 05:35:12 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 04 Apr 2012 05:35:12 +0300 Subject: dovecot-2.1: sdbox: If copying with link() fails with ENOENT, fa... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/cc734436c140 changeset: 14378:cc734436c140 user: Timo Sirainen date: Wed Apr 04 05:15:49 2012 +0300 description: sdbox: If copying with link() fails with ENOENT, fallback to trying regular copying. This also fixes missing error reporting for that case. diffstat: src/lib-storage/index/dbox-single/sdbox-copy.c | 9 ++++++--- 1 files changed, 6 insertions(+), 3 deletions(-) diffs (19 lines): diff -r 2bcab08dc994 -r cc734436c140 src/lib-storage/index/dbox-single/sdbox-copy.c --- a/src/lib-storage/index/dbox-single/sdbox-copy.c Wed Apr 04 04:33:41 2012 +0300 +++ b/src/lib-storage/index/dbox-single/sdbox-copy.c Wed Apr 04 05:15:49 2012 +0300 @@ -104,9 +104,12 @@ if (ret < 0) { if (ECANTLINK(errno)) ret = 0; - else if (errno == ENOENT) - mail_set_expunged(mail); - else { + else if (errno == ENOENT) { + /* try if the fallback copying code can still + read the file (the mail could still have the + stream open) */ + ret = 0; + } else { mail_storage_set_critical( _ctx->transaction->box->storage, "link(%s, %s) failed: %m", From dovecot at dovecot.org Wed Apr 4 05:35:12 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 04 Apr 2012 05:35:12 +0300 Subject: dovecot-2.1: maildir: Remember the mail's GUID/filename in memor... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/96ce9c0c6f05 changeset: 14379:96ce9c0c6f05 user: Timo Sirainen date: Wed Apr 04 05:34:11 2012 +0300 description: maildir: Remember the mail's GUID/filename in memory once it's fetched once. This allows retrieving it later even if the message gets expunged. diffstat: src/lib-storage/index/index-mail.h | 2 +- src/lib-storage/index/maildir/maildir-mail.c | 21 ++++++++++++++++----- 2 files changed, 17 insertions(+), 6 deletions(-) diffs (67 lines): diff -r cc734436c140 -r 96ce9c0c6f05 src/lib-storage/index/index-mail.h --- a/src/lib-storage/index/index-mail.h Wed Apr 04 05:15:49 2012 +0300 +++ b/src/lib-storage/index/index-mail.h Wed Apr 04 05:34:11 2012 +0300 @@ -77,7 +77,7 @@ uint32_t parse_line_num; struct message_part *parts; - const char *envelope, *body, *bodystructure, *uid_string, *guid; + const char *envelope, *body, *bodystructure, *guid, *filename; const char *from_envelope; struct message_part_envelope_data *envelope_data; diff -r cc734436c140 -r 96ce9c0c6f05 src/lib-storage/index/maildir/maildir-mail.c --- a/src/lib-storage/index/maildir/maildir-mail.c Wed Apr 04 05:15:49 2012 +0300 +++ b/src/lib-storage/index/maildir/maildir-mail.c Wed Apr 04 05:34:11 2012 +0300 @@ -482,6 +482,11 @@ /* use GUID from uidlist if it exists */ i_assert(!_mail->saving); + if (mail->data.guid != NULL) { + *value_r = mail->data.guid; + return 0; + } + /* first make sure that we have a refreshed uidlist */ if (maildir_mail_get_fname(mbox, _mail, &fname) <= 0) return -1; @@ -490,7 +495,8 @@ MAILDIR_UIDLIST_REC_EXT_GUID); if (guid != NULL) { if (*guid != '\0') { - *value_r = p_strdup(mail->data_pool, guid); + *value_r = mail->data.guid = + p_strdup(mail->data_pool, guid); return 0; } @@ -503,9 +509,14 @@ } /* default to base filename: */ + if (maildir_mail_get_special(_mail, MAIL_FETCH_UIDL_FILE_NAME, + value_r) < 0) + return -1; + mail->data.guid = mail->data.filename; + return 0; case MAIL_FETCH_UIDL_FILE_NAME: - if (mail->data.guid != NULL) { - *value_r = mail->data.guid; + if (mail->data.filename != NULL) { + *value_r = mail->data.filename; return 0; } if (fname != NULL) { @@ -521,10 +532,10 @@ fname = fname != NULL ? fname + 1 : path; } end = strchr(fname, MAILDIR_INFO_SEP); - mail->data.guid = end == NULL ? + mail->data.filename = end == NULL ? p_strdup(mail->data_pool, fname) : p_strdup_until(mail->data_pool, fname, end); - *value_r = mail->data.guid; + *value_r = mail->data.filename; return 0; case MAIL_FETCH_UIDL_BACKEND: uidl = maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid, From dovecot at dovecot.org Wed Apr 4 05:35:12 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 04 Apr 2012 05:35:12 +0300 Subject: dovecot-2.1: lib-lda: mail_deliver()'s dest_mail now prefetches ... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/c93601fa444e changeset: 14380:c93601fa444e user: Timo Sirainen date: Wed Apr 04 05:34:51 2012 +0300 description: lib-lda: mail_deliver()'s dest_mail now prefetches message's GUID. This fixes copying an already expunged mail with maildir. diffstat: src/lib-lda/mail-deliver.c | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-) diffs (25 lines): diff -r 96ce9c0c6f05 -r c93601fa444e src/lib-lda/mail-deliver.c --- a/src/lib-lda/mail-deliver.c Wed Apr 04 05:34:11 2012 +0300 +++ b/src/lib-lda/mail-deliver.c Wed Apr 04 05:34:51 2012 +0300 @@ -268,7 +268,7 @@ struct mailbox_header_lookup_ctx *headers_ctx; struct mail_keywords *kw; enum mail_error error; - const char *mailbox_name, *errstr; + const char *mailbox_name, *errstr, *guid; struct mail_transaction_commit_changes changes; const struct seq_range *range; bool default_save; @@ -338,7 +338,11 @@ t = mailbox_transaction_begin(box, 0); ctx->dest_mail = mail_alloc(t, MAIL_FETCH_STREAM_BODY, NULL); - if (!mail_set_uid(ctx->dest_mail, range[0].seq1)) { + /* copying needs the message body. with maildir we also + need to get the GUID in case the message gets + expunged */ + if (!mail_set_uid(ctx->dest_mail, range[0].seq1) || + mail_get_special(ctx->dest_mail, MAIL_FETCH_GUID, &guid) < 0) { mail_free(&ctx->dest_mail); mailbox_transaction_rollback(&t); } From dovecot at dovecot.org Wed Apr 4 06:10:39 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 04 Apr 2012 06:10:39 +0300 Subject: dovecot-2.1: ldap: Treat =key the same as =key=, just like v2.0. Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/9930c75b989a changeset: 14381:9930c75b989a user: Timo Sirainen date: Wed Apr 04 06:10:33 2012 +0300 description: ldap: Treat =key the same as =key=, just like v2.0. diffstat: src/auth/db-ldap.c | 11 +++++++---- src/auth/db-ldap.h | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diffs (40 lines): diff -r c93601fa444e -r 9930c75b989a src/auth/db-ldap.c --- a/src/auth/db-ldap.c Wed Apr 04 05:34:51 2012 +0300 +++ b/src/auth/db-ldap.c Wed Apr 04 06:10:33 2012 +0300 @@ -1032,9 +1032,12 @@ } templ = strchr(name, '='); - if (templ == NULL) - templ = ""; - else { + if (templ == NULL) { + if (*ldap_attr == '\0') { + /* =foo static value */ + templ = ""; + } + } else { *templ++ = '\0'; str_truncate(tmp_str, 0); var_expand_with_funcs(tmp_str, templ, NULL, @@ -1245,7 +1248,7 @@ values = ctx->val_1_arr; } - if (*field->value == '\0') { + if (field->value == NULL) { /* use the LDAP attribute's value */ } else { /* template */ diff -r c93601fa444e -r 9930c75b989a src/auth/db-ldap.h --- a/src/auth/db-ldap.h Wed Apr 04 05:34:51 2012 +0300 +++ b/src/auth/db-ldap.h Wed Apr 04 06:10:33 2012 +0300 @@ -122,7 +122,7 @@ struct ldap_field { /* Dovecot field name. */ const char *name; - /* Field value template with %vars. "" = same as LDAP value. */ + /* Field value template with %vars. NULL = same as LDAP value. */ const char *value; /* LDAP attribute name, or "" if this is a static field. */ const char *ldap_attr_name; From dovecot at dovecot.org Wed Apr 4 06:12:35 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 04 Apr 2012 06:12:35 +0300 Subject: dovecot-2.1: lib-storage: When doing a userdb lookup, use the us... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/2250f11695bc changeset: 14382:2250f11695bc user: Timo Sirainen date: Wed Apr 04 06:12:24 2012 +0300 description: lib-storage: When doing a userdb lookup, use the user's service instead of "lib-storage". diffstat: src/lib-storage/mail-user.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 9930c75b989a -r 2250f11695bc src/lib-storage/mail-user.c --- a/src/lib-storage/mail-user.c Wed Apr 04 06:10:33 2012 +0300 +++ b/src/lib-storage/mail-user.c Wed Apr 04 06:12:24 2012 +0300 @@ -272,7 +272,7 @@ int ret; memset(&info, 0, sizeof(info)); - info.service = "lib-storage"; + info.service = user->service; if (user->local_ip != NULL) info.local_ip = *user->local_ip; if (user->remote_ip != NULL) From dovecot at dovecot.org Wed Apr 4 06:16:23 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 04 Apr 2012 06:16:23 +0300 Subject: dovecot-2.1: ldap: Removed warning about changed user_* settings. Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/324df4134049 changeset: 14383:324df4134049 user: Timo Sirainen date: Wed Apr 04 06:16:18 2012 +0300 description: ldap: Removed warning about changed user_* settings. This warning can happen even with recommended settings when symlinking the passdb's ldap config to userdb ldap config. diffstat: src/auth/db-ldap.c | 27 --------------------------- src/auth/db-ldap.h | 3 +-- src/auth/passdb-ldap.c | 1 - 3 files changed, 1 insertions(+), 30 deletions(-) diffs (68 lines): diff -r 2250f11695bc -r 324df4134049 src/auth/db-ldap.c --- a/src/auth/db-ldap.c Wed Apr 04 06:12:24 2012 +0300 +++ b/src/auth/db-ldap.c Wed Apr 04 06:16:18 2012 +0300 @@ -1464,33 +1464,6 @@ pool_unref(&conn->pool); } -void db_ldap_check_userdb_warning(struct ldap_connection *conn) -{ - const struct ldap_settings *def = &default_ldap_settings; - const char *set_name; - - if (worker || conn->userdb_used || conn->set.userdb_warning_disable) - return; - - if (strcmp(conn->set.user_attrs, def->user_attrs) != 0) - set_name = "user_attrs"; - else if (strcmp(conn->set.user_filter, def->user_filter) != 0) - set_name = "user_filter"; - else if (strcmp(conn->set.iterate_attrs, def->iterate_attrs) != 0) - set_name = "iterate_attrs"; - else if (strcmp(conn->set.iterate_filter, def->iterate_filter) != 0) - set_name = "iterate_filter"; - else - set_name = NULL; - - if (set_name != NULL) { - i_warning("ldap: Ignoring changed %s in %s, " - "because userdb ldap not used. " - "(If this is intentional, set userdb_warning_disable=yes)", - set_name, conn->config_path); - } -} - #ifndef BUILTIN_LDAP /* Building a plugin */ extern struct passdb_module_interface passdb_ldap_plugin; diff -r 2250f11695bc -r 324df4134049 src/auth/db-ldap.h --- a/src/auth/db-ldap.h Wed Apr 04 06:12:24 2012 +0300 +++ b/src/auth/db-ldap.h Wed Apr 04 06:16:18 2012 +0300 @@ -63,7 +63,7 @@ const char *iterate_filter; const char *default_pass_scheme; - bool userdb_warning_disable; + bool userdb_warning_disable; /* deprecated for now at least */ /* ... */ int ldap_deref, ldap_scope; @@ -172,7 +172,6 @@ struct ldap_connection *db_ldap_init(const char *config_path, bool userdb); void db_ldap_unref(struct ldap_connection **conn); -void db_ldap_check_userdb_warning(struct ldap_connection *conn); int db_ldap_connect(struct ldap_connection *conn); void db_ldap_enable_input(struct ldap_connection *conn, bool enable); diff -r 2250f11695bc -r 324df4134049 src/auth/passdb-ldap.c --- a/src/auth/passdb-ldap.c Wed Apr 04 06:12:24 2012 +0300 +++ b/src/auth/passdb-ldap.c Wed Apr 04 06:16:18 2012 +0300 @@ -432,7 +432,6 @@ /* Credential lookups can't be done with authentication binds */ _module->iface.lookup_credentials = NULL; } - db_ldap_check_userdb_warning(module->conn); } static void passdb_ldap_deinit(struct passdb_module *_module) From dovecot at dovecot.org Wed Apr 4 06:25:06 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 04 Apr 2012 06:25:06 +0300 Subject: dovecot-2.1: Makefile: Link libdovecot-storage.so with LINKED_ST... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/8b91367bc3e1 changeset: 14384:8b91367bc3e1 user: Timo Sirainen date: Wed Apr 04 06:25:00 2012 +0300 description: Makefile: Link libdovecot-storage.so with LINKED_STORAGE_LDADD. diffstat: src/lib-storage/Makefile.am | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 324df4134049 -r 8b91367bc3e1 src/lib-storage/Makefile.am --- a/src/lib-storage/Makefile.am Wed Apr 04 06:16:18 2012 +0300 +++ b/src/lib-storage/Makefile.am Wed Apr 04 06:25:00 2012 +0300 @@ -86,7 +86,7 @@ pkglib_LTLIBRARIES = libdovecot-storage.la libdovecot_storage_la_SOURCES = -libdovecot_storage_la_LIBADD = $(shlibs) $(MODULE_LIBS) +libdovecot_storage_la_LIBADD = $(shlibs) $(LINKED_STORAGE_LDADD) $(MODULE_LIBS) libdovecot_storage_la_DEPENDENCIES = $(shlibs) libdovecot_storage_la_LDFLAGS = -export-dynamic From dovecot at dovecot.org Wed Apr 4 07:26:57 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 04 Apr 2012 07:26:57 +0300 Subject: dovecot-2.1: doveadm user: Added -m parameter to show some of th... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/601014feade4 changeset: 14385:601014feade4 user: Timo Sirainen date: Wed Apr 04 07:26:37 2012 +0300 description: doveadm user: Added -m parameter to show some of the mail settings. diffstat: src/doveadm/doveadm-auth.c | 114 ++++++++++++++++++++++++++++++++++++-------- 1 files changed, 93 insertions(+), 21 deletions(-) diffs (168 lines): diff -r 8b91367bc3e1 -r 601014feade4 src/doveadm/doveadm-auth.c --- a/src/doveadm/doveadm-auth.c Wed Apr 04 06:25:00 2012 +0300 +++ b/src/doveadm/doveadm-auth.c Wed Apr 04 07:26:37 2012 +0300 @@ -7,10 +7,14 @@ #include "base64.h" #include "str.h" #include "wildcard-match.h" +#include "master-service.h" #include "auth-client.h" #include "auth-master.h" #include "auth-server-connection.h" +#include "mail-storage-service.h" +#include "mail-user.h" #include "doveadm.h" +#include "doveadm-print.h" #include #include @@ -245,19 +249,74 @@ doveadm_exit_code = EX_NOPERM; } +static void cmd_user_mail_input_field(const char *key, const char *value, + const char *show_field) +{ + if (show_field == NULL) { + doveadm_print(key); + doveadm_print(value); + } else if (strcmp(show_field, key) == 0) { + printf("%s\n", value); + } +} + +static int cmd_user_mail_input(struct mail_storage_service_ctx *storage_service, + const struct authtest_input *input, + const char *show_field) +{ + struct mail_storage_service_input service_input; + struct mail_storage_service_user *service_user; + struct mail_user *user; + const struct mail_storage_settings *mail_set; + const char *error; + int ret; + + memset(&service_input, 0, sizeof(service_input)); + service_input.module = "mail"; + service_input.service = input->info.service; + service_input.username = input->username; + service_input.local_ip = input->info.local_ip; + service_input.local_port = input->info.local_port; + service_input.remote_ip = input->info.remote_ip; + service_input.remote_port = input->info.remote_port; + + if ((ret = mail_storage_service_lookup_next(storage_service, &service_input, + &service_user, &user, + &error)) <= 0) + return ret == 0 ? 0 : -1; + + if (show_field == NULL) { + doveadm_print_init(DOVEADM_PRINT_TYPE_TAB); + doveadm_print_header_simple("field"); + doveadm_print_header_simple("value"); + } + + cmd_user_mail_input_field("uid", user->set->mail_uid, show_field); + cmd_user_mail_input_field("gid", user->set->mail_gid, show_field); + cmd_user_mail_input_field("home", user->set->mail_home, show_field); + + mail_set = mail_user_set_get_storage_set(user); + cmd_user_mail_input_field("mail", mail_set->mail_location, show_field); + + mail_user_unref(&user); + mail_storage_service_user_free(&service_user); + return 1; +} + static void cmd_user(int argc, char *argv[]) { const char *auth_socket_path = NULL; struct authtest_input input; const char *show_field = NULL; + struct mail_storage_service_ctx *storage_service = NULL; unsigned int i; - bool have_wildcards; - int c; + bool have_wildcards, mail_fields = FALSE, first = TRUE; + int c, ret; memset(&input, 0, sizeof(input)); input.info.service = "doveadm"; - while ((c = getopt(argc, argv, "a:f:x:")) > 0) { + while ((c = getopt(argc, argv, "a:f:mx:")) > 0) { switch (c) { case 'a': auth_socket_path = optarg; @@ -265,6 +324,9 @@ case 'f': show_field = optarg; break; + case 'm': + mail_fields = TRUE; + break; case 'x': auth_user_info_parse(&input.info, optarg); break; @@ -285,27 +347,37 @@ } } - if (have_wildcards) + if (have_wildcards) { cmd_user_list(auth_socket_path, &input, argv + optind); - else { - bool first = TRUE; + return; + } - while ((input.username = argv[optind++]) != NULL) { - if (first) - first = FALSE; - else - putchar('\n'); - switch (cmd_user_input(auth_socket_path, &input, - show_field)) { - case -1: - doveadm_exit_code = EX_TEMPFAIL; - break; - case 0: - doveadm_exit_code = EX_NOUSER; - break; - } + if (mail_fields) { + storage_service = mail_storage_service_init(master_service, NULL, + MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT | + MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP); + } + + while ((input.username = argv[optind++]) != NULL) { + if (first) + first = FALSE; + else + putchar('\n'); + + ret = mail_fields ? + cmd_user_mail_input(storage_service, &input, show_field) : + cmd_user_input(auth_socket_path, &input, show_field); + switch (ret) { + case -1: + doveadm_exit_code = EX_TEMPFAIL; + break; + case 0: + doveadm_exit_code = EX_NOUSER; + break; } } + if (storage_service != NULL) + mail_storage_service_deinit(&storage_service); } struct doveadm_cmd doveadm_cmd_auth = { @@ -315,5 +387,5 @@ struct doveadm_cmd doveadm_cmd_user = { cmd_user, "user", - "[-a ] [-x ] [-f field] [...]" + "[-a ] [-x ] [-f field] [-m] [...]" }; From dovecot at dovecot.org Wed Apr 4 07:46:32 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 04 Apr 2012 07:46:32 +0300 Subject: dovecot-2.1: lib-storage: Require at least one namespace to be n... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/1a33cc98666a changeset: 14386:1a33cc98666a user: Timo Sirainen date: Wed Apr 04 07:46:09 2012 +0300 description: lib-storage: Require at least one namespace to be non-hidden diffstat: src/lib-storage/mail-namespace.c | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-) diffs (31 lines): diff -r 601014feade4 -r 1a33cc98666a src/lib-storage/mail-namespace.c --- a/src/lib-storage/mail-namespace.c Wed Apr 04 07:26:37 2012 +0300 +++ b/src/lib-storage/mail-namespace.c Wed Apr 04 07:46:09 2012 +0300 @@ -189,6 +189,7 @@ { struct mail_namespace *ns, *inbox_ns = NULL; unsigned int subscriptions_count = 0; + bool visible_namespaces = FALSE; char ns_sep, list_sep = '\0'; for (ns = namespaces; ns != NULL; ns = ns->next) { @@ -201,6 +202,8 @@ } if (namespace_set_alias_for(ns, namespaces, error_r) < 0) return FALSE; + if ((ns->flags & NAMESPACE_FLAG_HIDDEN) == 0) + visible_namespaces = TRUE; if ((ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0) { if (inbox_ns != NULL) { *error_r = "There can be only one namespace with " @@ -249,6 +252,10 @@ *error_r = "no list=yes namespaces"; return FALSE; } + if (!visible_namespaces) { + *error_r = "no hidden=no namespaces"; + return FALSE; + } if (subscriptions_count == 0) { *error_r = "no subscriptions=yes namespaces"; return FALSE; From dovecot at dovecot.org Wed Apr 4 09:12:52 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 04 Apr 2012 09:12:52 +0300 Subject: dovecot-2.1: pop3-migration: Error message improvement. Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/52ad5a66ee58 changeset: 14387:52ad5a66ee58 user: Timo Sirainen date: Wed Apr 04 09:12:29 2012 +0300 description: pop3-migration: Error message improvement. diffstat: src/plugins/pop3-migration/pop3-migration-plugin.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (14 lines): diff -r 1a33cc98666a -r 52ad5a66ee58 src/plugins/pop3-migration/pop3-migration-plugin.c --- a/src/plugins/pop3-migration/pop3-migration-plugin.c Wed Apr 04 07:46:09 2012 +0300 +++ b/src/plugins/pop3-migration/pop3-migration-plugin.c Wed Apr 04 09:12:29 2012 +0300 @@ -120,8 +120,8 @@ struct sha1_ctxt sha1_ctx; if (mail_get_hdr_stream(mail, &hdr_size, &input) < 0) { - i_error("pop3_migration: Failed to get header for msg %u", - mail->seq); + i_error("pop3_migration: Failed to get header for msg %u: %s", + mail->seq, mailbox_get_last_error(mail->box, NULL)); return -1; } input2 = i_stream_create_limit(input, hdr_size.physical_size); From dovecot at dovecot.org Wed Apr 4 09:42:46 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 04 Apr 2012 09:42:46 +0300 Subject: dovecot-2.1: doveadm status: Don't include the fields parameter ... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/19e9a83ca8dc changeset: 14388:19e9a83ca8dc user: Timo Sirainen date: Wed Apr 04 09:40:24 2012 +0300 description: doveadm status: Don't include the fields parameter as a mailbox in search query. diffstat: src/doveadm/doveadm-mail-mailbox-status.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 52ad5a66ee58 -r 19e9a83ca8dc src/doveadm/doveadm-mail-mailbox-status.c --- a/src/doveadm/doveadm-mail-mailbox-status.c Wed Apr 04 09:12:29 2012 +0300 +++ b/src/doveadm/doveadm-mail-mailbox-status.c Wed Apr 04 09:40:24 2012 +0300 @@ -182,7 +182,7 @@ doveadm_mail_help_name("mailbox status"); status_parse_fields(ctx, t_strsplit_spaces(fields, " ")); - ctx->search_args = doveadm_mail_mailbox_search_args_build(args); + ctx->search_args = doveadm_mail_mailbox_search_args_build(args+1); if (!ctx->total_sum) { doveadm_print_header("mailbox", "mailbox", From dovecot at dovecot.org Wed Apr 4 09:42:46 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 04 Apr 2012 09:42:46 +0300 Subject: dovecot-2.1: dovadm mail commands: When mailbox parameter has no... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/200af5e4c44f changeset: 14389:200af5e4c44f user: Timo Sirainen date: Wed Apr 04 09:41:15 2012 +0300 description: dovadm mail commands: When mailbox parameter has no wildcard, use SEARCH_MAILBOX. diffstat: src/doveadm/doveadm-mail-mailbox.c | 8 +++++++- 1 files changed, 7 insertions(+), 1 deletions(-) diffs (23 lines): diff -r 19e9a83ca8dc -r 200af5e4c44f src/doveadm/doveadm-mail-mailbox.c --- a/src/doveadm/doveadm-mail-mailbox.c Wed Apr 04 09:40:24 2012 +0300 +++ b/src/doveadm/doveadm-mail-mailbox.c Wed Apr 04 09:41:15 2012 +0300 @@ -139,12 +139,18 @@ { struct mail_search_args *search_args; struct mail_search_arg *arg; + enum mail_search_arg_type type; unsigned int i; doveadm_mailbox_args_check(args); search_args = mail_search_build_init(); for (i = 0; args[i] != NULL; i++) { - arg = mail_search_build_add(search_args, SEARCH_MAILBOX_GLOB); + if (strchr(args[i], '*') != NULL || + strchr(args[i], '%') != NULL) + type = SEARCH_MAILBOX_GLOB; + else + type = SEARCH_MAILBOX; + arg = mail_search_build_add(search_args, type); arg->value.str = p_strdup(search_args->pool, args[i]); } if (i > 1) { From dovecot at dovecot.org Wed Apr 4 09:42:46 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 04 Apr 2012 09:42:46 +0300 Subject: dovecot-2.1: doveadm: When AND-search includes mailbox names, do... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/1b6fb6363e7f changeset: 14390:1b6fb6363e7f user: Timo Sirainen date: Wed Apr 04 09:42:34 2012 +0300 description: doveadm: When AND-search includes mailbox names, don't bother going through them by list iteration. diffstat: src/doveadm/doveadm-mailbox-list-iter.c | 63 +++++++++++++++++++++++++------- 1 files changed, 48 insertions(+), 15 deletions(-) diffs (141 lines): diff -r 200af5e4c44f -r 1b6fb6363e7f src/doveadm/doveadm-mailbox-list-iter.c --- a/src/doveadm/doveadm-mailbox-list-iter.c Wed Apr 04 09:41:15 2012 +0300 +++ b/src/doveadm/doveadm-mailbox-list-iter.c Wed Apr 04 09:42:34 2012 +0300 @@ -10,18 +10,24 @@ #include "doveadm-mailbox-list-iter.h" struct doveadm_mailbox_list_iter { + struct mail_user *user; struct doveadm_mail_cmd_context *ctx; struct mail_search_args *search_args; enum mailbox_list_iter_flags iter_flags; struct mailbox_list_iterate_context *iter; + + struct mailbox_info info; + ARRAY_TYPE(const_string) patterns; + unsigned int pattern_idx; + bool only_selectable; }; static int search_args_get_mailbox_patterns(const struct mail_search_arg *args, ARRAY_TYPE(const_string) *patterns, - bool *have_guid_r) + bool *have_guid, bool *have_wildcards) { const struct mail_search_arg *subargs; @@ -35,12 +41,15 @@ subargs = args->value.subargs; for (; subargs != NULL; subargs = subargs->next) { if (!search_args_get_mailbox_patterns(subargs, - patterns, have_guid_r)) + patterns, have_guid, + have_wildcards)) return 0; } break; + case SEARCH_MAILBOX_GLOB: + *have_wildcards = TRUE; + /* fall through */ case SEARCH_MAILBOX: - case SEARCH_MAILBOX_GLOB: if (args->match_not) { array_clear(patterns); return 0; @@ -48,7 +57,7 @@ array_append(patterns, &args->value.str, 1); break; case SEARCH_MAILBOX_GUID: - *have_guid_r = TRUE; + *have_guid = TRUE; break; default: break; @@ -66,31 +75,36 @@ { static const char *all_pattern = "*"; struct doveadm_mailbox_list_iter *iter; - ARRAY_TYPE(const_string) patterns; - bool have_guid = FALSE; + bool have_guid = FALSE, have_wildcards = FALSE; iter = i_new(struct doveadm_mailbox_list_iter, 1); iter->ctx = ctx; iter->search_args = search_args; + iter->user = user; + i_array_init(&iter->patterns, 16); + search_args_get_mailbox_patterns(search_args->args, &iter->patterns, + &have_guid, &have_wildcards); - t_array_init(&patterns, 16); - search_args_get_mailbox_patterns(search_args->args, &patterns, - &have_guid); - if (array_count(&patterns) == 0) { + if (array_count(&iter->patterns) == 0) { iter_flags |= MAILBOX_LIST_ITER_SKIP_ALIASES; if (have_guid) ns_mask |= NAMESPACE_SHARED | NAMESPACE_PUBLIC; - array_append(&patterns, &all_pattern, 1); - } else { + array_append(&iter->patterns, &all_pattern, 1); + } else if (have_wildcards) { iter_flags |= MAILBOX_LIST_ITER_STAR_WITHIN_NS; ns_mask |= NAMESPACE_SHARED | NAMESPACE_PUBLIC; + } else { + /* just return the listed mailboxes without actually + iterating through. this also allows accessing mailboxes + without lookup ACL right */ + return iter; } - (void)array_append_space(&patterns); + (void)array_append_space(&iter->patterns); iter->only_selectable = TRUE; iter->iter_flags = iter_flags; iter->iter = mailbox_list_iter_init_namespaces(user->namespaces, - array_idx(&patterns, 0), + array_idx(&iter->patterns, 0), ns_mask, iter_flags); return iter; } @@ -130,10 +144,13 @@ *_iter = NULL; - if ((ret = mailbox_list_iter_deinit(&iter->iter)) < 0) { + if (iter->iter == NULL) + ret = 0; + else if ((ret = mailbox_list_iter_deinit(&iter->iter)) < 0) { i_error("Listing mailboxes failed"); doveadm_mail_failed_error(iter->ctx, MAIL_ERROR_TEMP); } + array_free(&iter->patterns); i_free(iter); return ret; } @@ -142,6 +159,22 @@ doveadm_mailbox_list_iter_next(struct doveadm_mailbox_list_iter *iter) { const struct mailbox_info *info; + const char *const *patterns; + unsigned int count; + + while (iter->iter == NULL) { + patterns = array_get(&iter->patterns, &count); + if (iter->pattern_idx == count) + return NULL; + + iter->info.name = patterns[iter->pattern_idx++]; + iter->info.ns = mail_namespace_find(iter->user->namespaces, + iter->info.name); + if (iter->info.ns != NULL) + return &iter->info; + /* FIXME: maybe fail?.. or just wait for v2.2 to get rid of + this error condition */ + } while ((info = mailbox_list_iter_next(iter->iter)) != NULL) { char sep = mail_namespace_get_sep(info->ns); From dovecot at dovecot.org Wed Apr 4 09:48:54 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 04 Apr 2012 09:48:54 +0300 Subject: dovecot-2.1: lib-storage: Human search builder now uses SEARCH_M... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/7a414d055b3c changeset: 14391:7a414d055b3c user: Timo Sirainen date: Wed Apr 04 09:48:46 2012 +0300 description: lib-storage: Human search builder now uses SEARCH_MAILBOX_GLOB only when wildcards are used. diffstat: src/lib-storage/mail-search-register-human.c | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diffs (19 lines): diff -r 1b6fb6363e7f -r 7a414d055b3c src/lib-storage/mail-search-register-human.c --- a/src/lib-storage/mail-search-register-human.c Wed Apr 04 09:42:34 2012 +0300 +++ b/src/lib-storage/mail-search-register-human.c Wed Apr 04 09:48:46 2012 +0300 @@ -136,10 +136,14 @@ { struct mail_search_arg *sarg; - sarg = mail_search_build_str(ctx, SEARCH_MAILBOX_GLOB); + sarg = mail_search_build_str(ctx, SEARCH_MAILBOX); if (sarg == NULL) return NULL; + if (strchr(sarg->value.str, '*') != NULL || + strchr(sarg->value.str, '%') != NULL) + sarg->type = SEARCH_MAILBOX_GLOB; + if (!uni_utf8_str_is_valid(sarg->value.str)) { ctx->_error = p_strconcat(ctx->pool, "Mailbox name not valid UTF-8: ", From dovecot at dovecot.org Wed Apr 4 10:07:47 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 04 Apr 2012 10:07:47 +0300 Subject: dovecot-2.1: Maildir++: Return nonexistent subscribed mailbox wi... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/f03e81b702a8 changeset: 14392:f03e81b702a8 user: Timo Sirainen date: Wed Apr 04 10:07:41 2012 +0300 description: Maildir++: Return nonexistent subscribed mailbox with nonexistent flag. e.g. LIST (SUBSCRIBED) "" * diffstat: src/lib-storage/list/mailbox-list-maildir-iter.c | 6 +++++- src/lib-storage/list/mailbox-list-subscriptions.c | 7 +++++-- src/lib-storage/list/mailbox-list-subscriptions.h | 3 ++- 3 files changed, 12 insertions(+), 4 deletions(-) diffs (60 lines): diff -r 7a414d055b3c -r f03e81b702a8 src/lib-storage/list/mailbox-list-maildir-iter.c --- a/src/lib-storage/list/mailbox-list-maildir-iter.c Wed Apr 04 09:48:46 2012 +0300 +++ b/src/lib-storage/list/mailbox-list-maildir-iter.c Wed Apr 04 10:07:41 2012 +0300 @@ -440,7 +440,11 @@ if ((flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0) { /* Listing only subscribed mailboxes. Flags are set later if needed. */ - mailbox_list_subscriptions_fill(&ctx->ctx, ctx->tree_ctx); + bool default_nonexistent = + (flags & MAILBOX_LIST_ITER_RETURN_NO_FLAGS) == 0; + + mailbox_list_subscriptions_fill(&ctx->ctx, ctx->tree_ctx, + default_nonexistent); } if ((flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) == 0 || diff -r 7a414d055b3c -r f03e81b702a8 src/lib-storage/list/mailbox-list-subscriptions.c --- a/src/lib-storage/list/mailbox-list-subscriptions.c Wed Apr 04 09:48:46 2012 +0300 +++ b/src/lib-storage/list/mailbox-list-subscriptions.c Wed Apr 04 10:07:41 2012 +0300 @@ -185,7 +185,8 @@ } void mailbox_list_subscriptions_fill(struct mailbox_list_iterate_context *ctx, - struct mailbox_tree_context *tree) + struct mailbox_tree_context *tree, + bool default_nonexistent) { struct mailbox_list_iter_update_context update_ctx; struct mailbox_tree_iterate_context *iter; @@ -197,6 +198,8 @@ update_ctx.tree_ctx = tree; update_ctx.glob = ctx->glob; update_ctx.leaf_flags = MAILBOX_SUBSCRIBED; + if (default_nonexistent) + update_ctx.leaf_flags |= MAILBOX_NONEXISTENT; update_ctx.parent_flags = MAILBOX_CHILD_SUBSCRIBED; update_ctx.match_parents = (ctx->flags & MAILBOX_LIST_ITER_SELECT_RECURSIVEMATCH) != 0; @@ -226,7 +229,7 @@ array_create(&ctx->ctx.module_contexts, pool, sizeof(void *), 5); ctx->tree = mailbox_tree_init(sep); - mailbox_list_subscriptions_fill(&ctx->ctx, ctx->tree); + mailbox_list_subscriptions_fill(&ctx->ctx, ctx->tree, FALSE); ctx->info.ns = list->ns; /* the tree usually has only those entries we want to iterate through, diff -r 7a414d055b3c -r f03e81b702a8 src/lib-storage/list/mailbox-list-subscriptions.h --- a/src/lib-storage/list/mailbox-list-subscriptions.h Wed Apr 04 09:48:46 2012 +0300 +++ b/src/lib-storage/list/mailbox-list-subscriptions.h Wed Apr 04 10:07:41 2012 +0300 @@ -17,7 +17,8 @@ /* Add subscriptions matching the iteration to the given tree */ void mailbox_list_subscriptions_fill(struct mailbox_list_iterate_context *ctx, - struct mailbox_tree_context *tree); + struct mailbox_tree_context *tree, + bool default_nonexistent); /* Iterate through subscriptions, call mailbox_list.get_mailbox_flags() if necessary for mailboxes to get their flags. */ From dovecot at dovecot.org Wed Apr 4 11:08:37 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 04 Apr 2012 11:08:37 +0300 Subject: dovecot-2.1: layout=fs: Fixed iteration with mail_full_filesyste... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/86e6dc46a80e changeset: 14393:86e6dc46a80e user: Timo Sirainen date: Wed Apr 04 11:07:05 2012 +0300 description: layout=fs: Fixed iteration with mail_full_filesystem_access=yes diffstat: src/lib-storage/list/mailbox-list-fs-iter.c | 28 +++++++++++++++++++++------- 1 files changed, 21 insertions(+), 7 deletions(-) diffs (66 lines): diff -r f03e81b702a8 -r 86e6dc46a80e src/lib-storage/list/mailbox-list-fs-iter.c --- a/src/lib-storage/list/mailbox-list-fs-iter.c Wed Apr 04 10:07:41 2012 +0300 +++ b/src/lib-storage/list/mailbox-list-fs-iter.c Wed Apr 04 11:07:05 2012 +0300 @@ -112,6 +112,21 @@ i_error("rename(%s, %s) failed: %m", src, str_c(dest)); } +static const char * +dir_get_storage_name(struct list_dir_context *dir, const char *fname) +{ + if (*dir->storage_name == '\0') { + /* regular root */ + return fname; + } else if (strcmp(dir->storage_name, "/") == 0) { + /* full_filesystem_access=yes "/" root */ + return t_strconcat("/", fname, NULL); + } else { + /* child */ + return t_strconcat(dir->storage_name, "/", fname, NULL); + } +} + static int dir_entry_get(struct fs_list_iterate_context *ctx, const char *dir_path, struct list_dir_context *dir, const struct dirent *d) @@ -144,8 +159,7 @@ } /* check the pattern */ - storage_name = *dir->storage_name == '\0' ? d->d_name : - t_strconcat(dir->storage_name, "/", d->d_name, NULL); + storage_name = dir_get_storage_name(dir, d->d_name); vname = mailbox_list_get_vname(ctx->ctx.list, storage_name); if (!uni_utf8_str_is_valid(vname)) { fs_list_rename_invalid(ctx, storage_name); @@ -205,8 +219,9 @@ if (*path == '~') { if (!mailbox_list_try_get_absolute_path(ctx->ctx.list, &path)) { - /* couldn't expand ~user/ */ - return FALSE; + /* a) couldn't expand ~user/ + b) mailbox is under our mail root, we changed + path to storage_name */ } /* NOTE: the path may have been translated to a storage_name instead of path */ @@ -374,7 +389,7 @@ if (*p == '/') last = p; } - if (p == last && *pattern == '/') + if (p == last+1 && *pattern == '/') root = "/"; else { root = mailbox_list_get_storage_name(ctx->ctx.list, @@ -560,8 +575,7 @@ const char *storage_name, *vname, *child_dir_name; dir = ctx->dir; - storage_name = *dir->storage_name == '\0' ? entry->fname : - t_strconcat(dir->storage_name, "/", entry->fname, NULL); + storage_name = dir_get_storage_name(dir, entry->fname); vname = mailbox_list_get_vname(ctx->ctx.list, storage_name); ctx->info.name = p_strdup(ctx->info_pool, vname); From dovecot at dovecot.org Wed Apr 4 11:08:37 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 04 Apr 2012 11:08:37 +0300 Subject: dovecot-2.1: lib-storage: Minor code cleanup. Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/f267a2b3f424 changeset: 14394:f267a2b3f424 user: Timo Sirainen date: Wed Apr 04 11:08:32 2012 +0300 description: lib-storage: Minor code cleanup. diffstat: src/lib-storage/mail-user.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 86e6dc46a80e -r f267a2b3f424 src/lib-storage/mail-user.c --- a/src/lib-storage/mail-user.c Wed Apr 04 11:07:05 2012 +0300 +++ b/src/lib-storage/mail-user.c Wed Apr 04 11:08:32 2012 +0300 @@ -341,7 +341,7 @@ { const char *home, *path = *pathp; - if (mail_user_get_home(user, &home) < 0) + if (mail_user_get_home(user, &home) <= 0) return -1; path = home_expand_tilde(path, home); From dovecot at dovecot.org Mon Apr 9 07:52:36 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 09 Apr 2012 07:52:36 +0300 Subject: dovecot-2.1: director: Don't try to send the new SYNC parameter ... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/084064444f89 changeset: 14395:084064444f89 user: Timo Sirainen date: Mon Apr 09 07:52:25 2012 +0300 description: director: Don't try to send the new SYNC parameter to old director versions. This should allow adding new directors to an old director ring without anything breaking. Once all directors have upgraded they start using the new features. diffstat: src/director/director-connection.c | 8 ++++++++ src/director/director-connection.h | 2 ++ src/director/director.c | 3 ++- 3 files changed, 12 insertions(+), 1 deletions(-) diffs (57 lines): diff -r f267a2b3f424 -r 084064444f89 src/director/director-connection.c --- a/src/director/director-connection.c Wed Apr 04 11:08:32 2012 +0300 +++ b/src/director/director-connection.c Mon Apr 09 07:52:25 2012 +0300 @@ -82,6 +82,7 @@ struct director *dir; char *name; time_t created; + unsigned int minor_version; /* for incoming connections the director host isn't known until ME-line is received */ @@ -890,6 +891,7 @@ DIRECTOR_VERSION_MAJOR); return -1; } + conn->minor_version = atoi(args[2]); conn->version_received = TRUE; return 1; } @@ -1528,6 +1530,12 @@ return conn->in; } +unsigned int +director_connection_get_minor_version(struct director_connection *conn) +{ + return conn->minor_version; +} + void director_connection_cork(struct director_connection *conn) { o_stream_cork(conn->output); diff -r f267a2b3f424 -r 084064444f89 src/director/director-connection.h --- a/src/director/director-connection.h Wed Apr 04 11:08:32 2012 +0300 +++ b/src/director/director-connection.h Mon Apr 09 07:52:25 2012 +0300 @@ -23,6 +23,8 @@ director_connection_get_host(struct director_connection *conn); bool director_connection_is_handshaked(struct director_connection *conn); bool director_connection_is_incoming(struct director_connection *conn); +unsigned int +director_connection_get_minor_version(struct director_connection *conn); void director_connection_cork(struct director_connection *conn); void director_connection_uncork(struct director_connection *conn); diff -r f267a2b3f424 -r 084064444f89 src/director/director.c --- a/src/director/director.c Wed Apr 04 11:08:32 2012 +0300 +++ b/src/director/director.c Mon Apr 09 07:52:25 2012 +0300 @@ -263,7 +263,8 @@ str = t_str_new(128); str_printfa(str, "SYNC\t%s\t%u\t%u", net_ip2addr(&host->ip), host->port, seq); - if (minor_version > 0) { + if (minor_version > 0 && + director_connection_get_minor_version(dir->right) > 0) { /* only minor_version>0 supports this parameter */ str_printfa(str, "\t%u", minor_version); } From dovecot at dovecot.org Mon Apr 9 08:18:12 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 09 Apr 2012 08:18:12 +0300 Subject: dovecot-2.1: director: Don't communicate with directors that rec... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/366b9e5fc85c changeset: 14396:366b9e5fc85c user: Timo Sirainen date: Mon Apr 09 08:17:52 2012 +0300 description: director: Don't communicate with directors that recently sent invalid input. Track network and protocol failures separately. If a director had sent invalid protocol data within last 60 seconds, don't try to connect to it and don't allow it to connect to us. diffstat: src/director/director-connection.c | 56 ++++++++++++++++++++++++++----------- src/director/director-host.h | 5 ++- src/director/director.c | 14 ++++++-- src/director/director.h | 4 ++ src/director/doveadm-connection.c | 6 +++- 5 files changed, 61 insertions(+), 24 deletions(-) diffs (229 lines): diff -r 084064444f89 -r 366b9e5fc85c src/director/director-connection.c --- a/src/director/director-connection.c Mon Apr 09 07:52:25 2012 +0300 +++ b/src/director/director-connection.c Mon Apr 09 08:17:52 2012 +0300 @@ -65,7 +65,7 @@ #define DIRECTOR_CONNECTION_PING_SYNC_INTERVAL_MSECS 1000 /* If outgoing director connection exists for less than this many seconds, mark the host as failed so we won't try to reconnect to it immediately */ -#define DIRECTOR_SUCCESS_MIN_CONNECT_SECS 10 +#define DIRECTOR_SUCCESS_MIN_CONNECT_SECS 40 #if DIRECTOR_CONNECTION_DONE_TIMEOUT_MSECS <= DIRECTOR_CONNECTION_PING_TIMEOUT_MSECS # error DIRECTOR_CONNECTION_DONE_TIMEOUT_MSECS is too low @@ -113,6 +113,7 @@ }; static void director_connection_disconnected(struct director_connection **conn); +static void director_connection_protocol_error(struct director_connection **conn); static void ATTR_FORMAT(2, 3) director_cmd_error(struct director_connection *conn, const char *fmt, ...) @@ -318,6 +319,7 @@ const char *connect_str; struct ip_addr ip; unsigned int port; + time_t next_comm_attempt; if (!director_args_parse_ip_port(conn, args, &ip, &port)) return FALSE; @@ -362,10 +364,19 @@ /* make sure we don't keep old sequence values across restarts */ conn->host->last_seq = 0; - if (dir->left == NULL) { + next_comm_attempt = conn->host->last_protocol_failure + + DIRECTOR_PROTOCOL_FAILURE_RETRY_SECS; + if (next_comm_attempt > ioloop_time) { + /* the director recently sent invalid protocol data, + don't try retrying yet */ + i_error("director(%s): Remote sent invalid protocol data recently, " + "waiting %u secs before allowing further communication", + conn->name, (unsigned int)(next_comm_attempt-ioloop_time)); + return FALSE; + } else if (dir->left == NULL) { /* a) - just in case the left is also our right side reset its failed state, so we can connect to it */ - conn->host->last_failed = 0; + conn->host->last_network_failure = 0; if (!director_has_outgoing_connections(dir)) director_connect(dir); } else if (dir->left->host == conn->host) { @@ -548,9 +559,9 @@ host = director_host_lookup(conn->dir, &ip, port); if (host != NULL) { - /* already have this. just reset its last_failed timestamp, - since it might be up now. */ - host->last_failed = 0; + /* already have this. just reset its last_network_failure + timestamp, since it might be up now. */ + host->last_network_failure = 0; return TRUE; } @@ -853,7 +864,7 @@ /* the host is up now, make sure we can connect to it immediately if needed */ - conn->host->last_failed = 0; + conn->host->last_network_failure = 0; conn->handshake_received = TRUE; if (conn->in) { @@ -1024,7 +1035,7 @@ host = director_host_get(conn->dir, &ip, port); /* reset failure timestamp so we'll actually try to connect there. */ - host->last_failed = 0; + host->last_network_failure = 0; /* remote suggests us to connect elsewhere */ if (dir->right != NULL && @@ -1193,7 +1204,7 @@ /* buffer full */ i_error("BUG: Director %s sent us more than %d bytes", conn->name, MAX_INBUF_SIZE); - director_connection_disconnected(&conn); + director_connection_protocol_error(&conn); return; } @@ -1208,7 +1219,7 @@ i_debug("director(%s): Invalid input, disconnecting", conn->name); } - director_connection_disconnected(&conn); + director_connection_protocol_error(&conn); break; } } @@ -1394,13 +1405,6 @@ if (dir->debug && conn->host != NULL) i_debug("Disconnecting from %s", conn->host->name); - if (conn->host != NULL && !conn->wrong_host && - (!conn->handshake_received || - conn->created + DIRECTOR_SUCCESS_MIN_CONNECT_SECS > ioloop_time)) { - /* avoid reconnecting back here immediately */ - conn->host->last_failed = ioloop_time; - } - conns = array_get(&dir->connections, &count); for (i = 0; i < count; i++) { if (conns[i] == conn) { @@ -1449,6 +1453,24 @@ struct director_connection *conn = *_conn; struct director *dir = conn->dir; + if (conn->created + DIRECTOR_SUCCESS_MIN_CONNECT_SECS > ioloop_time) { + /* connection didn't exist for very long, assume it has a + network problem */ + conn->host->last_network_failure = ioloop_time; + } + + director_connection_deinit(_conn); + if (dir->right == NULL) + director_connect(dir); +} + +void director_connection_protocol_error(struct director_connection **_conn) +{ + struct director_connection *conn = *_conn; + struct director *dir = conn->dir; + + conn->host->last_protocol_failure = ioloop_time; + director_connection_deinit(_conn); if (dir->right == NULL) director_connect(dir); diff -r 084064444f89 -r 366b9e5fc85c src/director/director-host.h --- a/src/director/director-host.h Mon Apr 09 07:52:25 2012 +0300 +++ b/src/director/director-host.h Mon Apr 09 08:17:52 2012 +0300 @@ -17,8 +17,9 @@ it can be ignored (or: it must be ignored to avoid potential command loops) */ unsigned int last_seq; - /* Last time host was detected to be down/broken */ - time_t last_failed; + /* Last time host was detected to be down */ + time_t last_network_failure; + time_t last_protocol_failure; /* we are this director */ unsigned int self:1; }; diff -r 084064444f89 -r 366b9e5fc85c src/director/director.c --- a/src/director/director.c Mon Apr 09 07:52:25 2012 +0300 +++ b/src/director/director.c Mon Apr 09 08:17:52 2012 +0300 @@ -110,13 +110,13 @@ port = dir->test_port != 0 ? dir->test_port : host->port; fd = net_connect_ip(&host->ip, port, &dir->self_ip); if (fd == -1) { - host->last_failed = ioloop_time; + host->last_network_failure = ioloop_time; i_error("connect(%s) failed: %m", host->name); return -1; } /* Reset timestamp so that director_connect() won't skip this host while we're still trying to connect to it */ - host->last_failed = 0; + host->last_network_failure = 0; director_connection_init_out(dir, fd, host); return 0; @@ -151,9 +151,15 @@ for (i = 1; i < count; i++) { unsigned int idx = (self_idx + i) % count; - if (hosts[idx]->last_failed + + if (hosts[idx]->last_network_failure + DIRECTOR_RECONNECT_RETRY_SECS > ioloop_time) { - /* failed recently, don't try retrying here */ + /* connection failed recently, don't try retrying here */ + continue; + } + if (hosts[idx]->last_protocol_failure + + DIRECTOR_PROTOCOL_FAILURE_RETRY_SECS > ioloop_time) { + /* the director recently sent invalid protocol data, + don't try retrying yet */ continue; } diff -r 084064444f89 -r 366b9e5fc85c src/director/director.h --- a/src/director/director.h Mon Apr 09 07:52:25 2012 +0300 +++ b/src/director/director.h Mon Apr 09 08:17:52 2012 +0300 @@ -11,6 +11,10 @@ /* weak users supported in protocol v1.1+ */ #define DIRECTOR_VERSION_WEAK_USERS 1 +/* Minimum time between even attempting to communicate with a director that + failed due to a protocol error. */ +#define DIRECTOR_PROTOCOL_FAILURE_RETRY_SECS 60 + struct director; struct mail_host; struct user; diff -r 084064444f89 -r 366b9e5fc85c src/director/doveadm-connection.c --- a/src/director/doveadm-connection.c Mon Apr 09 07:52:25 2012 +0300 +++ b/src/director/doveadm-connection.c Mon Apr 09 08:17:52 2012 +0300 @@ -99,6 +99,7 @@ string_t *str = t_str_new(1024); const char *type; bool left, right; + time_t last_failed; array_foreach(&dir->dir_hosts, hostp) { const struct director_host *host = *hostp; @@ -116,9 +117,12 @@ type = "right"; else type = ""; + + last_failed = I_MAX(host->last_network_failure, + host->last_protocol_failure); str_printfa(str, "%s\t%u\t%s\t%lu\n", net_ip2addr(&host->ip), host->port, type, - (unsigned long)host->last_failed); + (unsigned long)last_failed); } str_append_c(str, '\n'); o_stream_send(conn->output, str_data(str), str_len(str)); From dovecot at dovecot.org Mon Apr 9 09:53:20 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 09 Apr 2012 09:53:20 +0300 Subject: dovecot-2.1: imap: Don't allow FETCH items list to be empty. Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/19e09ab09383 changeset: 14397:19e09ab09383 user: Timo Sirainen date: Mon Apr 09 09:53:13 2012 +0300 description: imap: Don't allow FETCH items list to be empty. diffstat: src/imap/cmd-fetch.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diffs (15 lines): diff -r 366b9e5fc85c -r 19e09ab09383 src/imap/cmd-fetch.c --- a/src/imap/cmd-fetch.c Mon Apr 09 08:17:52 2012 +0300 +++ b/src/imap/cmd-fetch.c Mon Apr 09 09:53:13 2012 +0300 @@ -57,6 +57,11 @@ } else { *next_arg_r = arg + 1; arg = imap_arg_as_list(arg); + if (IMAP_ARG_IS_EOL(arg)) { + client_send_command_error(ctx->cmd, + "FETCH list is empty."); + return FALSE; + } while (imap_arg_get_atom(arg, &str)) { str = t_str_ucase(str); arg++; From dovecot at dovecot.org Mon Apr 9 11:47:23 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 09 Apr 2012 11:47:23 +0300 Subject: dovecot-2.0: doveadm user: Added -m parameter to show some of th... Message-ID: details: http://hg.dovecot.org/dovecot-2.0/rev/ae2802b68594 changeset: 13082:ae2802b68594 user: Timo Sirainen date: Mon Apr 09 11:47:13 2012 +0300 description: doveadm user: Added -m parameter to show some of the mail settings. diffstat: src/doveadm/doveadm-auth.c | 117 ++++++++++++++++++++++++++++++++++++-------- 1 files changed, 94 insertions(+), 23 deletions(-) diffs (171 lines): diff -r b15889b82258 -r ae2802b68594 src/doveadm/doveadm-auth.c --- a/src/doveadm/doveadm-auth.c Wed Apr 04 04:34:08 2012 +0300 +++ b/src/doveadm/doveadm-auth.c Mon Apr 09 11:47:13 2012 +0300 @@ -7,10 +7,14 @@ #include "base64.h" #include "str.h" #include "wildcard-match.h" +#include "master-service.h" #include "auth-client.h" #include "auth-master.h" #include "auth-server-connection.h" +#include "mail-storage-service.h" +#include "mail-user.h" #include "doveadm.h" +#include "doveadm-print.h" #include #include @@ -245,19 +249,74 @@ exit(1); } +static void cmd_user_mail_input_field(const char *key, const char *value, + const char *show_field) +{ + if (show_field == NULL) { + doveadm_print(key); + doveadm_print(value); + } else if (strcmp(show_field, key) == 0) { + printf("%s\n", value); + } +} + +static int cmd_user_mail_input(struct mail_storage_service_ctx *storage_service, + const struct authtest_input *input, + const char *show_field) +{ + struct mail_storage_service_input service_input; + struct mail_storage_service_user *service_user; + struct mail_user *user; + const struct mail_storage_settings *mail_set; + const char *error; + int ret; + + memset(&service_input, 0, sizeof(service_input)); + service_input.module = "mail"; + service_input.service = input->info.service; + service_input.username = input->username; + service_input.local_ip = input->info.local_ip; + service_input.local_port = input->info.local_port; + service_input.remote_ip = input->info.remote_ip; + service_input.remote_port = input->info.remote_port; + + if ((ret = mail_storage_service_lookup_next(storage_service, &service_input, + &service_user, &user, + &error)) <= 0) + return ret == 0 ? 0 : -1; + + if (show_field == NULL) { + doveadm_print_init("tab"); + doveadm_print_header_simple("field"); + doveadm_print_header_simple("value"); + } + + cmd_user_mail_input_field("uid", user->set->mail_uid, show_field); + cmd_user_mail_input_field("gid", user->set->mail_gid, show_field); + cmd_user_mail_input_field("home", user->set->mail_home, show_field); + + mail_set = mail_user_set_get_storage_set(user); + cmd_user_mail_input_field("mail", mail_set->mail_location, show_field); + + mail_user_unref(&user); + mail_storage_service_user_free(&service_user); + return 1; +} + static void cmd_user(int argc, char *argv[]) { const char *auth_socket_path = NULL; struct authtest_input input; const char *show_field = NULL; + struct mail_storage_service_ctx *storage_service = NULL; unsigned int i; - bool have_wildcards; - int c; + bool have_wildcards, mail_fields = FALSE, first = TRUE, notfound = FALSE; + int c, ret; memset(&input, 0, sizeof(input)); input.info.service = "doveadm"; - while ((c = getopt(argc, argv, "a:f:x:")) > 0) { + while ((c = getopt(argc, argv, "a:f:mx:")) > 0) { switch (c) { case 'a': auth_socket_path = optarg; @@ -265,6 +324,9 @@ case 'f': show_field = optarg; break; + case 'm': + mail_fields = TRUE; + break; case 'x': auth_user_info_parse(&input.info, optarg); break; @@ -285,29 +347,38 @@ } } - if (have_wildcards) + if (have_wildcards) { cmd_user_list(auth_socket_path, argv + optind); - else { - bool first = TRUE; - bool notfound = FALSE; + return; + } - while ((input.username = argv[optind++]) != NULL) { - if (first) - first = FALSE; - else - putchar('\n'); - switch (cmd_user_input(auth_socket_path, &input, - show_field)) { - case -1: - exit(1); - case 0: - notfound = TRUE; - break; - } + if (mail_fields) { + storage_service = mail_storage_service_init(master_service, NULL, + MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT | + MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP); + } + + while ((input.username = argv[optind++]) != NULL) { + if (first) + first = FALSE; + else + putchar('\n'); + + ret = mail_fields ? + cmd_user_mail_input(storage_service, &input, show_field) : + cmd_user_input(auth_socket_path, &input, show_field); + switch (ret) { + case -1: + exit(1); + case 0: + notfound = TRUE; + break; } - if (notfound) - exit(2); } + if (notfound) + exit(2); + if (storage_service != NULL) + mail_storage_service_deinit(&storage_service); } struct doveadm_cmd doveadm_cmd_auth = { @@ -317,5 +388,5 @@ struct doveadm_cmd doveadm_cmd_user = { cmd_user, "user", - "[-a ] [-x ] [-f field] [...]" + "[-a ] [-x ] [-f field] [-m] [...]" }; From dovecot at dovecot.org Mon Apr 9 11:53:57 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 09 Apr 2012 11:53:57 +0300 Subject: dovecot-2.1: lib-storage: Set mail_user.service earlier. Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/2bf504b33d64 changeset: 14398:2bf504b33d64 user: Timo Sirainen date: Mon Apr 09 11:53:46 2012 +0300 description: lib-storage: Set mail_user.service earlier. diffstat: src/lib-storage/mail-user.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diffs (28 lines): diff -r 19e09ab09383 -r 2bf504b33d64 src/lib-storage/mail-user.c --- a/src/lib-storage/mail-user.c Mon Apr 09 09:53:13 2012 +0300 +++ b/src/lib-storage/mail-user.c Mon Apr 09 11:53:46 2012 +0300 @@ -50,6 +50,7 @@ user->set_info = set_info; user->unexpanded_set = settings_dup(set_info, set, pool); user->set = settings_dup(set_info, set, pool); + user->service = master_service_get_name(master_service); /* check settings so that the duplicated structure will again contain the parsed fields */ @@ -113,7 +114,6 @@ mail_set = mail_user_set_get_storage_set(user); user->mail_debug = mail_set->mail_debug; - user->service = master_service_get_name(master_service); user->initialized = TRUE; hook_mail_user_created(user); @@ -166,6 +166,8 @@ const struct ip_addr *local_ip, const struct ip_addr *remote_ip) { + i_assert(service != NULL); + user->service = p_strdup(user->pool, service); if (local_ip != NULL && local_ip->family != 0) { user->local_ip = p_new(user->pool, struct ip_addr, 1); From dovecot at dovecot.org Mon Apr 9 12:22:10 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 09 Apr 2012 12:22:10 +0300 Subject: dovecot-2.1: lib-index: Minor code cleanup. Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/30f8ef8696f0 changeset: 14399:30f8ef8696f0 user: Timo Sirainen date: Tue Apr 03 14:45:10 2012 +0300 description: lib-index: Minor code cleanup. diffstat: src/lib-index/mail-transaction-log-file.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (13 lines): diff -r 2bf504b33d64 -r 30f8ef8696f0 src/lib-index/mail-transaction-log-file.c --- a/src/lib-index/mail-transaction-log-file.c Mon Apr 09 11:53:46 2012 +0300 +++ b/src/lib-index/mail-transaction-log-file.c Tue Apr 03 14:45:10 2012 +0300 @@ -945,8 +945,8 @@ modseq_ext_len) == 0) { /* modseq tracking started */ *cur_modseq += 1; - return; } + return; } else { /* not tracking modseqs */ return; From dovecot at dovecot.org Mon Apr 9 13:04:37 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 09 Apr 2012 13:04:37 +0300 Subject: dovecot-2.1: lib-storage: If mailbox deletion crashed, undelete ... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/a109580dea25 changeset: 14400:a109580dea25 user: Timo Sirainen date: Mon Apr 09 13:04:19 2012 +0300 description: lib-storage: If mailbox deletion crashed, undelete the mailbox when opening it. The deletion is assumed to be crashed if it was started over 5 minutes ago. diffstat: src/lib-storage/mail-storage.c | 59 +++++++++++++++++++++-------------------- 1 files changed, 30 insertions(+), 29 deletions(-) diffs (85 lines): diff -r 30f8ef8696f0 -r a109580dea25 src/lib-storage/mail-storage.c --- a/src/lib-storage/mail-storage.c Tue Apr 03 14:45:10 2012 +0300 +++ b/src/lib-storage/mail-storage.c Mon Apr 09 13:04:19 2012 +0300 @@ -914,9 +914,37 @@ return 0; } +static bool mailbox_try_undelete(struct mailbox *box) +{ + time_t mtime; + + if (mail_index_get_modification_time(box->index, &mtime) < 0) + return FALSE; + if (mtime + MAILBOX_DELETE_RETRY_SECS > time(NULL)) + return FALSE; + + if (mailbox_mark_index_deleted(box, FALSE) < 0) + return FALSE; + box->mailbox_deleted = FALSE; + return TRUE; +} + int mailbox_open(struct mailbox *box) { - return mailbox_open_full(box, NULL); + if (mailbox_open_full(box, NULL) < 0) { + if (!box->mailbox_deleted) + return -1; + + /* mailbox has been marked as deleted. if this deletion + started (and crashed) a long time ago, it can be confusing + to user that the mailbox can't be opened. so we'll just + undelete it and reopen. */ + if(!mailbox_try_undelete(box)) + return -1; + if (mailbox_open_full(box, NULL) < 0) + return -1; + } + return 0; } int mailbox_open_stream(struct mailbox *box, struct istream *input) @@ -1043,21 +1071,6 @@ return 0; } -static bool mailbox_try_undelete(struct mailbox *box) -{ - time_t mtime; - - if (mail_index_get_modification_time(box->index, &mtime) < 0) - return FALSE; - if (mtime + MAILBOX_DELETE_RETRY_SECS > time(NULL)) - return FALSE; - - if (mailbox_mark_index_deleted(box, FALSE) < 0) - return FALSE; - box->mailbox_deleted = FALSE; - return TRUE; -} - int mailbox_delete(struct mailbox *box) { int ret; @@ -1077,19 +1090,7 @@ if (mailbox_open(box) < 0) { if (mailbox_get_last_mail_error(box) != MAIL_ERROR_NOTFOUND) return -1; - if (!box->mailbox_deleted) { - /* \noselect mailbox */ - } else { - /* if deletion happened a long time ago, it means it - crashed while doing it. undelete the mailbox in - that case. */ - if (!mailbox_try_undelete(box)) - return -1; - - /* retry */ - if (mailbox_open(box) < 0) - return -1; - } + /* \noselect mailbox */ } ret = box->v.delete(box); From dovecot at dovecot.org Mon Apr 9 13:05:05 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 09 Apr 2012 13:05:05 +0300 Subject: dovecot-2.0: lib-storage: If mailbox deletion crashed, undelete ... Message-ID: details: http://hg.dovecot.org/dovecot-2.0/rev/777f393ba12f changeset: 13083:777f393ba12f user: Timo Sirainen date: Mon Apr 09 13:04:59 2012 +0300 description: lib-storage: If mailbox deletion crashed, undelete the mailbox when opening it. The deletion is assumed to be crashed if it was started over 5 minutes ago. diffstat: src/lib-storage/mail-storage.c | 59 +++++++++++++++++++++-------------------- 1 files changed, 30 insertions(+), 29 deletions(-) diffs (85 lines): diff -r ae2802b68594 -r 777f393ba12f src/lib-storage/mail-storage.c --- a/src/lib-storage/mail-storage.c Mon Apr 09 11:47:13 2012 +0300 +++ b/src/lib-storage/mail-storage.c Mon Apr 09 13:04:59 2012 +0300 @@ -632,9 +632,37 @@ return 0; } +static bool mailbox_try_undelete(struct mailbox *box) +{ + time_t mtime; + + if (mail_index_get_modification_time(box->index, &mtime) < 0) + return FALSE; + if (mtime + MAILBOX_DELETE_RETRY_SECS > time(NULL)) + return FALSE; + + if (mailbox_mark_index_deleted(box, FALSE) < 0) + return FALSE; + box->mailbox_deleted = FALSE; + return TRUE; +} + int mailbox_open(struct mailbox *box) { - return mailbox_open_full(box, NULL); + if (mailbox_open_full(box, NULL) < 0) { + if (!box->mailbox_deleted) + return -1; + + /* mailbox has been marked as deleted. if this deletion + started (and crashed) a long time ago, it can be confusing + to user that the mailbox can't be opened. so we'll just + undelete it and reopen. */ + if(!mailbox_try_undelete(box)) + return -1; + if (mailbox_open_full(box, NULL) < 0) + return -1; + } + return 0; } int mailbox_open_stream(struct mailbox *box, struct istream *input) @@ -757,21 +785,6 @@ return 0; } -static bool mailbox_try_undelete(struct mailbox *box) -{ - time_t mtime; - - if (mail_index_get_modification_time(box->index, &mtime) < 0) - return FALSE; - if (mtime + MAILBOX_DELETE_RETRY_SECS > time(NULL)) - return FALSE; - - if (mailbox_mark_index_deleted(box, FALSE) < 0) - return FALSE; - box->mailbox_deleted = FALSE; - return TRUE; -} - int mailbox_delete(struct mailbox *box) { enum mail_error error; @@ -788,19 +801,7 @@ (void)mail_storage_get_last_error(box->storage, &error); if (error != MAIL_ERROR_NOTFOUND) return -1; - if (!box->mailbox_deleted) { - /* \noselect mailbox */ - } else { - /* if deletion happened a long time ago, it means it - crashed while doing it. undelete the mailbox in - that case. */ - if (!mailbox_try_undelete(box)) - return -1; - - /* retry */ - if (mailbox_open(box) < 0) - return -1; - } + /* \noselect mailbox */ } ret = box->v.delete(box); From dovecot at dovecot.org Mon Apr 9 13:12:35 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 09 Apr 2012 13:12:35 +0300 Subject: dovecot-2.1: director: Fixed disconnecting unwanted connection. Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/3771ff9c04d2 changeset: 14401:3771ff9c04d2 user: Timo Sirainen date: Mon Apr 09 13:12:29 2012 +0300 description: director: Fixed disconnecting unwanted connection. diffstat: src/director/director-connection.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r a109580dea25 -r 3771ff9c04d2 src/director/director-connection.c --- a/src/director/director-connection.c Mon Apr 09 13:04:19 2012 +0300 +++ b/src/director/director-connection.c Mon Apr 09 13:12:29 2012 +0300 @@ -244,7 +244,7 @@ /* either use this or disconnect it */ if (!director_connection_assign_left(conn)) { /* we don't want this */ - director_connection_deinit(&dir->left); + director_connection_deinit(&conn); director_assign_left(dir); break; } From dovecot at dovecot.org Mon Apr 9 13:21:26 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 09 Apr 2012 13:21:26 +0300 Subject: dovecot-2.0: Added tag 2.0.20 for changeset cec3271fc830 Message-ID: details: http://hg.dovecot.org/dovecot-2.0/rev/25fdc7e5f970 changeset: 13085:25fdc7e5f970 user: Timo Sirainen date: Mon Apr 09 13:13:44 2012 +0300 description: Added tag 2.0.20 for changeset cec3271fc830 diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff -r cec3271fc830 -r 25fdc7e5f970 .hgtags --- a/.hgtags Mon Apr 09 13:13:44 2012 +0300 +++ b/.hgtags Mon Apr 09 13:13:44 2012 +0300 @@ -70,3 +70,4 @@ 53cccb1b4168f9c8322145d0e8d1636021f2efff 2.0.17 346526718aad285ce6a055fb2472c716f49e5dda 2.0.18 4b680f5055c7b838d3252328736c5e2419731dfa 2.0.19 +cec3271fc830bcef11462f222ffbb30844d587eb 2.0.20 From dovecot at dovecot.org Mon Apr 9 13:21:26 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 09 Apr 2012 13:21:26 +0300 Subject: dovecot-2.0: Released v2.0.20. Message-ID: details: http://hg.dovecot.org/dovecot-2.0/rev/cec3271fc830 changeset: 13084:cec3271fc830 user: Timo Sirainen date: Mon Apr 09 13:13:44 2012 +0300 description: Released v2.0.20. diffstat: NEWS | 9 +++++++++ configure.in | 2 +- 2 files changed, 10 insertions(+), 1 deletions(-) diffs (26 lines): diff -r 777f393ba12f -r cec3271fc830 NEWS --- a/NEWS Mon Apr 09 13:04:59 2012 +0300 +++ b/NEWS Mon Apr 09 13:13:44 2012 +0300 @@ -1,3 +1,12 @@ +v2.0.20 2012-04-09 Timo Sirainen + + + doveadm user: Added -m parameter to show some of the mail settings. + - doveadm import didn't import messages' flags + - Make sure IMAP clients can't create directories when accessing + nonexistent users' mailboxes via shared namespace. + - Dovecot auth clients authenticating via TCP socket could have failed + with bogus "PID already in use" errors. + v2.0.19 2012-03-15 Timo Sirainen - IMAP: ENABLE CONDSTORE/QRESYNC + STATUS for a mailbox might not diff -r 777f393ba12f -r cec3271fc830 configure.in --- a/configure.in Mon Apr 09 13:04:59 2012 +0300 +++ b/configure.in Mon Apr 09 13:13:44 2012 +0300 @@ -1,5 +1,5 @@ AC_PREREQ([2.59]) -AC_INIT([Dovecot],[2.0.19],[dovecot at dovecot.org]) +AC_INIT([Dovecot],[2.0.20],[dovecot at dovecot.org]) AC_CONFIG_SRCDIR([src]) AM_INIT_AUTOMAKE([foreign]) From dovecot at dovecot.org Mon Apr 9 13:21:26 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 09 Apr 2012 13:21:26 +0300 Subject: dovecot-2.0: Added signature for changeset cec3271fc830 Message-ID: details: http://hg.dovecot.org/dovecot-2.0/rev/26c31cbb8b7b changeset: 13086:26c31cbb8b7b user: Timo Sirainen date: Mon Apr 09 13:13:47 2012 +0300 description: Added signature for changeset cec3271fc830 diffstat: .hgsigs | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff -r 25fdc7e5f970 -r 26c31cbb8b7b .hgsigs --- a/.hgsigs Mon Apr 09 13:13:44 2012 +0300 +++ b/.hgsigs Mon Apr 09 13:13:47 2012 +0300 @@ -33,3 +33,4 @@ 53cccb1b4168f9c8322145d0e8d1636021f2efff 0 iEYEABECAAYFAk8G/18ACgkQyUhSUUBVisl6NQCgpZXFFmbO06eA0cjsUPrMxsLqlVAAn0OcG9df71+/3q/EP4TfFb5fUkgu 346526718aad285ce6a055fb2472c716f49e5dda 0 iEYEABECAAYFAk84L6AACgkQyUhSUUBViskcPACfSRM+K7pQesMLEkV0m9uiMXJYoqcAn0vTpk0vkkF15Y+C0fPdkCS47aio 4b680f5055c7b838d3252328736c5e2419731dfa 0 iEYEABECAAYFAk9iBAEACgkQyUhSUUBVismySACgkhAfpqvzdWpm17r+5jqShqx4cdwAnA+yd4UeUvLGR70HCsU+mCfiFzn6 +cec3271fc830bcef11462f222ffbb30844d587eb 0 iEYEABECAAYFAk+CtlgACgkQyUhSUUBVisluUACfQ5uxj42hv/1X5Q+9PYWzk1q6fC0An0ErX8xpjdLAMu38AOqbhOAmVBQc From dovecot at dovecot.org Mon Apr 9 13:21:30 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 09 Apr 2012 13:21:30 +0300 Subject: dovecot-2.1: Released v2.1.4. Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/2c21c940e19d changeset: 14402:2c21c940e19d user: Timo Sirainen date: Mon Apr 09 13:13:24 2012 +0300 description: Released v2.1.4. diffstat: NEWS | 17 +++++++++++++++++ configure.in | 2 +- 2 files changed, 18 insertions(+), 1 deletions(-) diffs (34 lines): diff -r 3771ff9c04d2 -r 2c21c940e19d NEWS --- a/NEWS Mon Apr 09 13:12:29 2012 +0300 +++ b/NEWS Mon Apr 09 13:13:24 2012 +0300 @@ -1,3 +1,20 @@ +v2.1.4 2012-04-09 Timo Sirainen + + + Added mail_temp_scan_interval setting and changed its default value + from 8 hours to 1 week. + + Added pop3-migration plugin for easily doing a transparent IMAP+POP3 + migration to Dovecot: http://wiki2.dovecot.org/Migration/Dsync + + doveadm user: Added -m parameter to show some of the mail settings. + - Proxying SSL connections crashed in v2.1.[23] + - fts-solr: Indexing mail bodies was broken. + - director: Several changes to significantly improve error handling + - doveadm import didn't import messages' flags + - mail_full_filesystem_access=yes was broken + - Make sure IMAP clients can't create directories when accessing + nonexistent users' mailboxes via shared namespace. + - Dovecot auth clients authenticating via TCP socket could have failed + with bogus "PID already in use" errors. + v2.1.3 2012-03-16 Timo Sirainen - mdbox was broken in v2.1.2 diff -r 3771ff9c04d2 -r 2c21c940e19d configure.in --- a/configure.in Mon Apr 09 13:12:29 2012 +0300 +++ b/configure.in Mon Apr 09 13:13:24 2012 +0300 @@ -1,5 +1,5 @@ AC_PREREQ([2.59]) -AC_INIT([Dovecot],[2.1.3],[dovecot at dovecot.org]) +AC_INIT([Dovecot],[2.1.4],[dovecot at dovecot.org]) AC_CONFIG_SRCDIR([src]) AM_INIT_AUTOMAKE([foreign]) From dovecot at dovecot.org Mon Apr 9 13:21:30 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 09 Apr 2012 13:21:30 +0300 Subject: dovecot-2.1: Added tag 2.1.4 for changeset 2c21c940e19d Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/1fe529f50259 changeset: 14403:1fe529f50259 user: Timo Sirainen date: Mon Apr 09 13:13:26 2012 +0300 description: Added tag 2.1.4 for changeset 2c21c940e19d diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff -r 2c21c940e19d -r 1fe529f50259 .hgtags --- a/.hgtags Mon Apr 09 13:13:24 2012 +0300 +++ b/.hgtags Mon Apr 09 13:13:26 2012 +0300 @@ -80,3 +80,4 @@ 04b0acc03f1eaa0353888a75a452e5c8e61e4c94 2.1.1 744e0d7f1b255a9339060f761b850303121f14df 2.1.2 b9adfd52cb66d5d89d291b76b9845d6361216d12 2.1.3 +2c21c940e19d97a772128a7f281cea302e157d73 2.1.4 From dovecot at dovecot.org Mon Apr 9 13:21:30 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 09 Apr 2012 13:21:30 +0300 Subject: dovecot-2.1: Added signature for changeset 2c21c940e19d Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/97cba128896f changeset: 14404:97cba128896f user: Timo Sirainen date: Mon Apr 09 13:13:32 2012 +0300 description: Added signature for changeset 2c21c940e19d diffstat: .hgsigs | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff -r 1fe529f50259 -r 97cba128896f .hgsigs --- a/.hgsigs Mon Apr 09 13:13:26 2012 +0300 +++ b/.hgsigs Mon Apr 09 13:13:32 2012 +0300 @@ -43,3 +43,4 @@ 04b0acc03f1eaa0353888a75a452e5c8e61e4c94 0 iEYEABECAAYFAk9F+k0ACgkQyUhSUUBViskLmwCfUt/aex6wOIEohJKnRGA4diF5WxoAn2zlMxSaPX/b0LBmV1P46GAMqZbO 744e0d7f1b255a9339060f761b850303121f14df 0 iEYEABECAAYFAk9h/8oACgkQyUhSUUBVism2OQCfWh62w8pMxJaf1oYx2A+2PxQvBocAn29RFDgZblGRLn7iMCPw6We1yiIw b9adfd52cb66d5d89d291b76b9845d6361216d12 0 iEYEABECAAYFAk9jbugACgkQyUhSUUBVislSgwCgpo3f0bsSujItBum/M6js8SzF06YAmwftHlwaOstKeALdjLR5vtF2c5F7 +2c21c940e19d97a772128a7f281cea302e157d73 0 iEYEABECAAYFAk+CtkYACgkQyUhSUUBVisknxgCfTJw2YPGJ17HbHRGmbwmCyLqepbMAn17j7IYzUfEU0xkXhCgwEAmk7XO4 From dovecot at dovecot.org Tue Apr 10 09:53:20 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 10 Apr 2012 09:53:20 +0300 Subject: dovecot-2.1: pop3c: Removed extra "R " prefix from POP3 server e... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/35e232e961d3 changeset: 14405:35e232e961d3 user: Timo Sirainen date: Tue Apr 10 09:52:00 2012 +0300 description: pop3c: Removed extra "R " prefix from POP3 server error messages. diffstat: src/lib-storage/index/pop3c/pop3c-client.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 97cba128896f -r 35e232e961d3 src/lib-storage/index/pop3c/pop3c-client.c --- a/src/lib-storage/index/pop3c/pop3c-client.c Mon Apr 09 13:13:32 2012 +0300 +++ b/src/lib-storage/index/pop3c/pop3c-client.c Tue Apr 10 09:52:00 2012 +0300 @@ -663,7 +663,7 @@ *reply_r = line + 3; ret = 0; } else if (strncasecmp(line, "-ERR", 4) == 0) { - *reply_r = line + 3; + *reply_r = line + 4; ret = -1; } else { *reply_r = line; From dovecot at dovecot.org Tue Apr 10 09:53:20 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 10 Apr 2012 09:53:20 +0300 Subject: dovecot-2.1: pop3c: "TOP msgnum 0" was missing the 0 parameter. Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/0b59dbb1a288 changeset: 14406:0b59dbb1a288 user: Timo Sirainen date: Tue Apr 10 09:52:35 2012 +0300 description: pop3c: "TOP msgnum 0" was missing the 0 parameter. diffstat: src/lib-storage/index/pop3c/pop3c-mail.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 35e232e961d3 -r 0b59dbb1a288 src/lib-storage/index/pop3c/pop3c-mail.c --- a/src/lib-storage/index/pop3c/pop3c-mail.c Tue Apr 10 09:52:00 2012 +0300 +++ b/src/lib-storage/index/pop3c/pop3c-mail.c Tue Apr 10 09:52:35 2012 +0300 @@ -113,7 +113,7 @@ if (get_body || (capa & POP3C_CAPABILITY_TOP) == 0) cmd = t_strdup_printf("RETR %u\r\n", _mail->seq); else - cmd = t_strdup_printf("TOP %u\r\n", _mail->seq); + cmd = t_strdup_printf("TOP %u 0\r\n", _mail->seq); if (pop3c_client_cmd_stream(mbox->client, cmd, &input, &error) < 0) { mail_storage_set_error(mbox->box.storage, From dovecot at dovecot.org Tue Apr 10 10:09:46 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 10 Apr 2012 10:09:46 +0300 Subject: dovecot-2.1: lib-storage: mail_user_try_home_expand() now looks ... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/20e1aa322b1e changeset: 14407:20e1aa322b1e user: Timo Sirainen date: Tue Apr 10 10:09:39 2012 +0300 description: lib-storage: mail_user_try_home_expand() now looks up home only when needed. Before a recent code cleanup the lookup was always done, but if the home didn't exist it still just happened to return success. The cleanup changed it to return failure, which broke the original behavior. diffstat: src/lib-storage/mail-user.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diffs (15 lines): diff -r 0b59dbb1a288 -r 20e1aa322b1e src/lib-storage/mail-user.c --- a/src/lib-storage/mail-user.c Tue Apr 10 09:52:35 2012 +0300 +++ b/src/lib-storage/mail-user.c Tue Apr 10 10:09:39 2012 +0300 @@ -343,6 +343,11 @@ { const char *home, *path = *pathp; + if (strncmp(path, "~/", 2) != 0) { + /* no need to expand home */ + return 0; + } + if (mail_user_get_home(user, &home) <= 0) return -1; From dovecot at dovecot.org Tue Apr 10 17:57:22 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 10 Apr 2012 17:57:22 +0300 Subject: dovecot-2.1: dict file: Optionally use fcntl/flock locking, inst... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/a1c0e4046d81 changeset: 14408:a1c0e4046d81 user: Timo Sirainen date: Tue Apr 10 17:57:09 2012 +0300 description: dict file: Optionally use fcntl/flock locking, instead of dotlocks. diffstat: src/lib-dict/dict-file.c | 142 +++++++++++++++++++++++++++++++++++++++------- 1 files changed, 120 insertions(+), 22 deletions(-) diffs (235 lines): diff -r 20e1aa322b1e -r a1c0e4046d81 src/lib-dict/dict-file.c --- a/src/lib-dict/dict-file.c Tue Apr 10 10:09:39 2012 +0300 +++ b/src/lib-dict/dict-file.c Tue Apr 10 17:57:09 2012 +0300 @@ -3,12 +3,14 @@ #include "lib.h" #include "array.h" #include "hash.h" +#include "file-lock.h" #include "file-dotlock.h" #include "nfs-workarounds.h" #include "istream.h" #include "ostream.h" #include "dict-private.h" +#include #include #include #include @@ -17,10 +19,13 @@ struct file_dict { struct dict dict; pool_t hash_pool; + enum file_lock_method lock_method; char *path; struct hash_table *hash; int fd; + + bool refreshed; }; struct file_dict_iterate_path { @@ -75,8 +80,17 @@ const char *base_dir ATTR_UNUSED) { struct file_dict *dict; - + dict = i_new(struct file_dict, 1); + if (strncmp(uri, "lock=fcntl ", 11) == 0) { + dict->lock_method = FILE_LOCK_METHOD_FCNTL; + uri += 11; + } else if (strncmp(uri, "lock=flock ", 11) == 0) { + dict->lock_method = FILE_LOCK_METHOD_FLOCK; + uri += 11; + } else { + dict->lock_method = FILE_LOCK_METHOD_DOTLOCK; + } dict->dict = *driver; dict->path = i_strdup(uri); dict->hash_pool = pool_alloconly_create("file dict", 1024); @@ -126,10 +140,9 @@ return FALSE; } -static int file_dict_refresh(struct file_dict *dict) +static int file_dict_open_latest(struct file_dict *dict) { - struct istream *input; - char *key, *value; + int open_type; if (!file_dict_need_refresh(dict)) return 0; @@ -138,13 +151,29 @@ if (close(dict->fd) < 0) i_error("close(%s) failed: %m", dict->path); } - dict->fd = open(dict->path, O_RDONLY); + + open_type = dict->lock_method == FILE_LOCK_METHOD_DOTLOCK ? + O_RDONLY : O_RDWR; + dict->fd = open(dict->path, open_type); if (dict->fd == -1) { if (errno == ENOENT) return 0; i_error("open(%s) failed: %m", dict->path); return -1; } + dict->refreshed = FALSE; + return 1; +} + +static int file_dict_refresh(struct file_dict *dict) +{ + struct istream *input; + char *key, *value; + + if (file_dict_open_latest(dict) < 0) + return -1; + if (dict->refreshed) + return 0; hash_table_clear(dict->hash, TRUE); p_clear(dict->hash_pool); @@ -157,6 +186,7 @@ hash_table_insert(dict->hash, key, value); } i_stream_destroy(&input); + dict->refreshed = TRUE; return 0; } @@ -381,35 +411,92 @@ return fd_copy_stat_permissions(&src_st, dest_fd, dest_path); } +static int +file_dict_lock(struct file_dict *dict, struct file_lock **lock_r) +{ + int fd, ret; + + if (file_dict_open_latest(dict) < 0) + return -1; + + if (dict->fd == -1) { + /* quota file doesn't exist yet, we need to create it */ + fd = open(dict->path, O_CREAT | O_RDWR, 0600); + if (fd == -1) { + i_error("creat(%s) failed: %m", dict->path); + return -1; + } + (void)fd_copy_parent_dir_permissions(dict->path, fd, dict->path); + (void)close(fd); + } + + do { + if (file_wait_lock(dict->fd, dict->path, F_WRLCK, + dict->lock_method, + file_dict_dotlock_settings.timeout, + lock_r) <= 0) { + i_error("file_wait_lock(%s) failed: %m", dict->path); + return -1; + } + /* check again if we need to reopen the file because it was + just replaced */ + } while ((ret = file_dict_open_latest(dict)) > 0); + + return ret < 0 ? -1 : 0; +} + static int file_dict_write_changes(struct file_dict_transaction_context *ctx) { struct file_dict *dict = (struct file_dict *)ctx->ctx.dict; - struct dotlock *dotlock; + struct dotlock *dotlock = NULL; + struct file_lock *lock = NULL; + const char *temp_path = NULL; struct hash_iterate_context *iter; struct ostream *output; void *key, *value; - int fd; + int fd = -1; - fd = file_dotlock_open(&file_dict_dotlock_settings, dict->path, 0, - &dotlock); - if (fd == -1) { - i_error("file dict commit: file_dotlock_open(%s) failed: %m", - dict->path); - return -1; + switch (dict->lock_method) { + case FILE_LOCK_METHOD_FCNTL: + case FILE_LOCK_METHOD_FLOCK: + if (file_dict_lock(dict, &lock) < 0) + return -1; + temp_path = t_strdup_printf("%s.tmp", dict->path); + fd = creat(temp_path, 0600); + if (fd == -1) { + i_error("file dict commit: creat(%s) failed: %m", + temp_path); + return -1; + } + break; + case FILE_LOCK_METHOD_DOTLOCK: + fd = file_dotlock_open(&file_dict_dotlock_settings, dict->path, 0, + &dotlock); + if (fd == -1) { + i_error("file dict commit: file_dotlock_open(%s) failed: %m", + dict->path); + return -1; + } + temp_path = file_dotlock_get_lock_path(dotlock); + break; } + /* refresh once more now that we're locked */ if (file_dict_refresh(dict) < 0) { - file_dotlock_delete(&dotlock); + if (dotlock != NULL) + file_dotlock_delete(&dotlock); + else { + (void)close(fd); + file_unlock(&lock); + } return -1; } if (dict->fd != -1) { /* preserve the permissions */ - (void)fd_copy_permissions(dict->fd, dict->path, fd, - file_dotlock_get_lock_path(dotlock)); + (void)fd_copy_permissions(dict->fd, dict->path, fd, temp_path); } else { /* get initial permissions from parent directory */ - (void)fd_copy_parent_dir_permissions(dict->path, fd, - file_dotlock_get_lock_path(dotlock)); + (void)fd_copy_parent_dir_permissions(dict->path, fd, temp_path); } file_dict_apply_changes(ctx); @@ -425,10 +512,21 @@ hash_table_iterate_deinit(&iter); o_stream_destroy(&output); - if (file_dotlock_replace(&dotlock, - DOTLOCK_REPLACE_FLAG_DONT_CLOSE_FD) < 0) { - (void)close(fd); - return -1; + if (dotlock != NULL) { + if (file_dotlock_replace(&dotlock, + DOTLOCK_REPLACE_FLAG_DONT_CLOSE_FD) < 0) { + (void)close(fd); + return -1; + } + } else { + if (rename(temp_path, dict->path) < 0) { + i_error("rename(%s, %s) failed: %m", + temp_path, dict->path); + file_unlock(&lock); + (void)close(fd); + return -1; + } + file_lock_free(&lock); } if (dict->fd != -1) From dovecot at dovecot.org Tue Apr 10 17:57:48 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 10 Apr 2012 17:57:48 +0300 Subject: dovecot-2.0: dict file: Optionally use fcntl/flock locking, inst... Message-ID: details: http://hg.dovecot.org/dovecot-2.0/rev/dcd7a2dd39ae changeset: 13087:dcd7a2dd39ae user: Timo Sirainen date: Tue Apr 10 17:57:09 2012 +0300 description: dict file: Optionally use fcntl/flock locking, instead of dotlocks. diffstat: src/lib-dict/dict-file.c | 142 +++++++++++++++++++++++++++++++++++++++------- 1 files changed, 120 insertions(+), 22 deletions(-) diffs (235 lines): diff -r 26c31cbb8b7b -r dcd7a2dd39ae src/lib-dict/dict-file.c --- a/src/lib-dict/dict-file.c Mon Apr 09 13:13:47 2012 +0300 +++ b/src/lib-dict/dict-file.c Tue Apr 10 17:57:09 2012 +0300 @@ -3,12 +3,14 @@ #include "lib.h" #include "array.h" #include "hash.h" +#include "file-lock.h" #include "file-dotlock.h" #include "nfs-workarounds.h" #include "istream.h" #include "ostream.h" #include "dict-private.h" +#include #include #include #include @@ -17,10 +19,13 @@ struct file_dict { struct dict dict; pool_t hash_pool; + enum file_lock_method lock_method; char *path; struct hash_table *hash; int fd; + + bool refreshed; }; struct file_dict_iterate_path { @@ -75,8 +80,17 @@ const char *base_dir ATTR_UNUSED) { struct file_dict *dict; - + dict = i_new(struct file_dict, 1); + if (strncmp(uri, "lock=fcntl ", 11) == 0) { + dict->lock_method = FILE_LOCK_METHOD_FCNTL; + uri += 11; + } else if (strncmp(uri, "lock=flock ", 11) == 0) { + dict->lock_method = FILE_LOCK_METHOD_FLOCK; + uri += 11; + } else { + dict->lock_method = FILE_LOCK_METHOD_DOTLOCK; + } dict->dict = *driver; dict->path = i_strdup(uri); dict->hash_pool = pool_alloconly_create("file dict", 1024); @@ -126,10 +140,9 @@ return FALSE; } -static int file_dict_refresh(struct file_dict *dict) +static int file_dict_open_latest(struct file_dict *dict) { - struct istream *input; - char *key, *value; + int open_type; if (!file_dict_need_refresh(dict)) return 0; @@ -138,13 +151,29 @@ if (close(dict->fd) < 0) i_error("close(%s) failed: %m", dict->path); } - dict->fd = open(dict->path, O_RDONLY); + + open_type = dict->lock_method == FILE_LOCK_METHOD_DOTLOCK ? + O_RDONLY : O_RDWR; + dict->fd = open(dict->path, open_type); if (dict->fd == -1) { if (errno == ENOENT) return 0; i_error("open(%s) failed: %m", dict->path); return -1; } + dict->refreshed = FALSE; + return 1; +} + +static int file_dict_refresh(struct file_dict *dict) +{ + struct istream *input; + char *key, *value; + + if (file_dict_open_latest(dict) < 0) + return -1; + if (dict->refreshed) + return 0; hash_table_clear(dict->hash, TRUE); p_clear(dict->hash_pool); @@ -157,6 +186,7 @@ hash_table_insert(dict->hash, key, value); } i_stream_destroy(&input); + dict->refreshed = TRUE; return 0; } @@ -381,35 +411,92 @@ return fd_copy_stat_permissions(&src_st, dest_fd, dest_path); } +static int +file_dict_lock(struct file_dict *dict, struct file_lock **lock_r) +{ + int fd, ret; + + if (file_dict_open_latest(dict) < 0) + return -1; + + if (dict->fd == -1) { + /* quota file doesn't exist yet, we need to create it */ + fd = open(dict->path, O_CREAT | O_RDWR, 0600); + if (fd == -1) { + i_error("creat(%s) failed: %m", dict->path); + return -1; + } + (void)fd_copy_parent_dir_permissions(dict->path, fd, dict->path); + (void)close(fd); + } + + do { + if (file_wait_lock(dict->fd, dict->path, F_WRLCK, + dict->lock_method, + file_dict_dotlock_settings.timeout, + lock_r) <= 0) { + i_error("file_wait_lock(%s) failed: %m", dict->path); + return -1; + } + /* check again if we need to reopen the file because it was + just replaced */ + } while ((ret = file_dict_open_latest(dict)) > 0); + + return ret < 0 ? -1 : 0; +} + static int file_dict_write_changes(struct file_dict_transaction_context *ctx) { struct file_dict *dict = (struct file_dict *)ctx->ctx.dict; - struct dotlock *dotlock; + struct dotlock *dotlock = NULL; + struct file_lock *lock = NULL; + const char *temp_path = NULL; struct hash_iterate_context *iter; struct ostream *output; void *key, *value; - int fd; + int fd = -1; - fd = file_dotlock_open(&file_dict_dotlock_settings, dict->path, 0, - &dotlock); - if (fd == -1) { - i_error("file dict commit: file_dotlock_open(%s) failed: %m", - dict->path); - return -1; + switch (dict->lock_method) { + case FILE_LOCK_METHOD_FCNTL: + case FILE_LOCK_METHOD_FLOCK: + if (file_dict_lock(dict, &lock) < 0) + return -1; + temp_path = t_strdup_printf("%s.tmp", dict->path); + fd = creat(temp_path, 0600); + if (fd == -1) { + i_error("file dict commit: creat(%s) failed: %m", + temp_path); + return -1; + } + break; + case FILE_LOCK_METHOD_DOTLOCK: + fd = file_dotlock_open(&file_dict_dotlock_settings, dict->path, 0, + &dotlock); + if (fd == -1) { + i_error("file dict commit: file_dotlock_open(%s) failed: %m", + dict->path); + return -1; + } + temp_path = file_dotlock_get_lock_path(dotlock); + break; } + /* refresh once more now that we're locked */ if (file_dict_refresh(dict) < 0) { - file_dotlock_delete(&dotlock); + if (dotlock != NULL) + file_dotlock_delete(&dotlock); + else { + (void)close(fd); + file_unlock(&lock); + } return -1; } if (dict->fd != -1) { /* preserve the permissions */ - (void)fd_copy_permissions(dict->fd, dict->path, fd, - file_dotlock_get_lock_path(dotlock)); + (void)fd_copy_permissions(dict->fd, dict->path, fd, temp_path); } else { /* get initial permissions from parent directory */ - (void)fd_copy_parent_dir_permissions(dict->path, fd, - file_dotlock_get_lock_path(dotlock)); + (void)fd_copy_parent_dir_permissions(dict->path, fd, temp_path); } file_dict_apply_changes(ctx); @@ -425,10 +512,21 @@ hash_table_iterate_deinit(&iter); o_stream_destroy(&output); - if (file_dotlock_replace(&dotlock, - DOTLOCK_REPLACE_FLAG_DONT_CLOSE_FD) < 0) { - (void)close(fd); - return -1; + if (dotlock != NULL) { + if (file_dotlock_replace(&dotlock, + DOTLOCK_REPLACE_FLAG_DONT_CLOSE_FD) < 0) { + (void)close(fd); + return -1; + } + } else { + if (rename(temp_path, dict->path) < 0) { + i_error("rename(%s, %s) failed: %m", + temp_path, dict->path); + file_unlock(&lock); + (void)close(fd); + return -1; + } + file_lock_free(&lock); } if (dict->fd != -1) From dovecot at dovecot.org Tue Apr 10 18:05:47 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 10 Apr 2012 18:05:47 +0300 Subject: dovecot-2.1: dict file: Bugfix for previous lock change and chan... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/bf5ae73e9475 changeset: 14409:bf5ae73e9475 user: Timo Sirainen date: Tue Apr 10 18:05:36 2012 +0300 description: dict file: Bugfix for previous lock change and changed its configuration syntax. diffstat: src/lib-dict/dict-file.c | 38 +++++++++++++++++++++++--------------- 1 files changed, 23 insertions(+), 15 deletions(-) diffs (61 lines): diff -r a1c0e4046d81 -r bf5ae73e9475 src/lib-dict/dict-file.c --- a/src/lib-dict/dict-file.c Tue Apr 10 17:57:09 2012 +0300 +++ b/src/lib-dict/dict-file.c Tue Apr 10 18:05:36 2012 +0300 @@ -80,19 +80,25 @@ const char *base_dir ATTR_UNUSED) { struct file_dict *dict; + const char *p; dict = i_new(struct file_dict, 1); - if (strncmp(uri, "lock=fcntl ", 11) == 0) { - dict->lock_method = FILE_LOCK_METHOD_FCNTL; - uri += 11; - } else if (strncmp(uri, "lock=flock ", 11) == 0) { - dict->lock_method = FILE_LOCK_METHOD_FLOCK; - uri += 11; + dict->lock_method = FILE_LOCK_METHOD_DOTLOCK; + + p = strchr(uri, ':'); + if (p == NULL) { + /* no parameters */ + dict->path = i_strdup(uri); } else { - dict->lock_method = FILE_LOCK_METHOD_DOTLOCK; + dict->path = i_strdup_until(uri, p++); + if (strcmp(p, "lock=fcntl") == 0) + dict->lock_method = FILE_LOCK_METHOD_FCNTL; + else if (strcmp(p, "lock=flock") == 0) + dict->lock_method = FILE_LOCK_METHOD_FLOCK; + else + i_error("dict file: Invalid parameter: %s", p+1); } dict->dict = *driver; - dict->path = i_strdup(uri); dict->hash_pool = pool_alloconly_create("file dict", 1024); dict->hash = hash_table_create(default_pool, dict->hash_pool, 0, str_hash, (hash_cmp_callback_t *)strcmp); @@ -178,14 +184,16 @@ hash_table_clear(dict->hash, TRUE); p_clear(dict->hash_pool); - input = i_stream_create_fd(dict->fd, (size_t)-1, FALSE); - while ((key = i_stream_read_next_line(input)) != NULL && - (value = i_stream_read_next_line(input)) != NULL) { - key = p_strdup(dict->hash_pool, key); - value = p_strdup(dict->hash_pool, value); - hash_table_insert(dict->hash, key, value); + if (dict->fd != -1) { + input = i_stream_create_fd(dict->fd, (size_t)-1, FALSE); + while ((key = i_stream_read_next_line(input)) != NULL && + (value = i_stream_read_next_line(input)) != NULL) { + key = p_strdup(dict->hash_pool, key); + value = p_strdup(dict->hash_pool, value); + hash_table_insert(dict->hash, key, value); + } + i_stream_destroy(&input); } - i_stream_destroy(&input); dict->refreshed = TRUE; return 0; } From dovecot at dovecot.org Tue Apr 10 18:05:55 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 10 Apr 2012 18:05:55 +0300 Subject: dovecot-2.0: dict file: Bugfix for previous lock change and chan... Message-ID: details: http://hg.dovecot.org/dovecot-2.0/rev/ee99143fd9df changeset: 13088:ee99143fd9df user: Timo Sirainen date: Tue Apr 10 18:05:36 2012 +0300 description: dict file: Bugfix for previous lock change and changed its configuration syntax. diffstat: src/lib-dict/dict-file.c | 38 +++++++++++++++++++++++--------------- 1 files changed, 23 insertions(+), 15 deletions(-) diffs (61 lines): diff -r dcd7a2dd39ae -r ee99143fd9df src/lib-dict/dict-file.c --- a/src/lib-dict/dict-file.c Tue Apr 10 17:57:09 2012 +0300 +++ b/src/lib-dict/dict-file.c Tue Apr 10 18:05:36 2012 +0300 @@ -80,19 +80,25 @@ const char *base_dir ATTR_UNUSED) { struct file_dict *dict; + const char *p; dict = i_new(struct file_dict, 1); - if (strncmp(uri, "lock=fcntl ", 11) == 0) { - dict->lock_method = FILE_LOCK_METHOD_FCNTL; - uri += 11; - } else if (strncmp(uri, "lock=flock ", 11) == 0) { - dict->lock_method = FILE_LOCK_METHOD_FLOCK; - uri += 11; + dict->lock_method = FILE_LOCK_METHOD_DOTLOCK; + + p = strchr(uri, ':'); + if (p == NULL) { + /* no parameters */ + dict->path = i_strdup(uri); } else { - dict->lock_method = FILE_LOCK_METHOD_DOTLOCK; + dict->path = i_strdup_until(uri, p++); + if (strcmp(p, "lock=fcntl") == 0) + dict->lock_method = FILE_LOCK_METHOD_FCNTL; + else if (strcmp(p, "lock=flock") == 0) + dict->lock_method = FILE_LOCK_METHOD_FLOCK; + else + i_error("dict file: Invalid parameter: %s", p+1); } dict->dict = *driver; - dict->path = i_strdup(uri); dict->hash_pool = pool_alloconly_create("file dict", 1024); dict->hash = hash_table_create(default_pool, dict->hash_pool, 0, str_hash, (hash_cmp_callback_t *)strcmp); @@ -178,14 +184,16 @@ hash_table_clear(dict->hash, TRUE); p_clear(dict->hash_pool); - input = i_stream_create_fd(dict->fd, (size_t)-1, FALSE); - while ((key = i_stream_read_next_line(input)) != NULL && - (value = i_stream_read_next_line(input)) != NULL) { - key = p_strdup(dict->hash_pool, key); - value = p_strdup(dict->hash_pool, value); - hash_table_insert(dict->hash, key, value); + if (dict->fd != -1) { + input = i_stream_create_fd(dict->fd, (size_t)-1, FALSE); + while ((key = i_stream_read_next_line(input)) != NULL && + (value = i_stream_read_next_line(input)) != NULL) { + key = p_strdup(dict->hash_pool, key); + value = p_strdup(dict->hash_pool, value); + hash_table_insert(dict->hash, key, value); + } + i_stream_destroy(&input); } - i_stream_destroy(&input); dict->refreshed = TRUE; return 0; } From dovecot at dovecot.org Wed Apr 11 12:35:24 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 11 Apr 2012 12:35:24 +0300 Subject: dovecot-2.1: --enable-devel-checks: If DEBUG_SILENT environment ... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/7ec8f6515b0d changeset: 14410:7ec8f6515b0d user: Timo Sirainen date: Wed Apr 11 12:35:19 2012 +0300 description: --enable-devel-checks: If DEBUG_SILENT environment is set, hide "Growing pool" warnings. diffstat: src/lib/data-stack.c | 2 +- src/lib/mempool-alloconly.c | 3 ++- src/master/master-settings.c | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diffs (37 lines): diff -r bf5ae73e9475 -r 7ec8f6515b0d src/lib/data-stack.c --- a/src/lib/data-stack.c Tue Apr 10 18:05:36 2012 +0300 +++ b/src/lib/data-stack.c Wed Apr 11 12:35:19 2012 +0300 @@ -371,7 +371,7 @@ ret = STACK_BLOCK_DATA(current_block); #ifdef DEBUG - if (warn) { + if (warn && getenv("DEBUG_SILENT") == NULL) { /* warn after allocation, so if i_warning() wants to allocate more memory we don't go to infinite loop */ i_warning("Growing data stack with: %"PRIuSIZE_T, diff -r bf5ae73e9475 -r 7ec8f6515b0d src/lib/mempool-alloconly.c --- a/src/lib/mempool-alloconly.c Tue Apr 10 18:05:36 2012 +0300 +++ b/src/lib/mempool-alloconly.c Wed Apr 11 12:35:19 2012 +0300 @@ -143,7 +143,8 @@ new_apool = p_new(&apool.pool, struct alloconly_pool, 1); *new_apool = apool; #ifdef DEBUG - if (strncmp(name, MEMPOOL_GROWING, strlen(MEMPOOL_GROWING)) == 0) { + if (strncmp(name, MEMPOOL_GROWING, strlen(MEMPOOL_GROWING)) == 0 || + getenv("DEBUG_SILENT") != NULL) { name += strlen(MEMPOOL_GROWING); new_apool->disable_warning = TRUE; } diff -r bf5ae73e9475 -r 7ec8f6515b0d src/master/master-settings.c --- a/src/master/master-settings.c Tue Apr 10 18:05:36 2012 +0300 +++ b/src/master/master-settings.c Wed Apr 11 12:35:19 2012 +0300 @@ -203,7 +203,7 @@ # define ENV_SYSTEMD "" #endif #ifdef DEBUG -# define ENV_GDB " GDB" +# define ENV_GDB " GDB DEBUG_SILENT" #else # define ENV_GDB "" #endif From dovecot at dovecot.org Wed Apr 11 14:44:52 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 11 Apr 2012 14:44:52 +0300 Subject: dovecot-2.1: layout=fs: LIST may have shown mailbox as \HasNoChi... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/b016e771d8ab changeset: 14411:b016e771d8ab user: Timo Sirainen date: Wed Apr 11 14:29:37 2012 +0300 description: layout=fs: LIST may have shown mailbox as \HasNoChildren when it did. This probably only happened with mbox. diffstat: src/lib-storage/list/mailbox-list-fs-iter.c | 11 ++++++----- 1 files changed, 6 insertions(+), 5 deletions(-) diffs (23 lines): diff -r 7ec8f6515b0d -r b016e771d8ab src/lib-storage/list/mailbox-list-fs-iter.c --- a/src/lib-storage/list/mailbox-list-fs-iter.c Wed Apr 11 12:35:19 2012 +0300 +++ b/src/lib-storage/list/mailbox-list-fs-iter.c Wed Apr 11 14:29:37 2012 +0300 @@ -323,13 +323,14 @@ dir->info_flags = info_flags; p_array_init(&dir->entries, pool, 16); - if ((dir->info_flags & MAILBOX_CHILDREN) == 0) { - /* start with the assumption of not having children */ + if (fs_list_dir_read(ctx, dir) < 0) + ctx->ctx.failed = TRUE; + + if ((dir->info_flags & (MAILBOX_CHILDREN | MAILBOX_NOCHILDREN | + MAILBOX_NOINFERIORS)) == 0) { + /* assume this directory has no children */ dir->info_flags |= MAILBOX_NOCHILDREN; } - - if (fs_list_dir_read(ctx, dir) < 0) - ctx->ctx.failed = TRUE; return dir; } From dovecot at dovecot.org Wed Apr 11 14:44:52 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 11 Apr 2012 14:44:52 +0300 Subject: dovecot-2.1: mbox: Deleting a mailbox didn't delete its index fi... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/c67ea0d68b77 changeset: 14412:c67ea0d68b77 user: Timo Sirainen date: Wed Apr 11 14:44:45 2012 +0300 description: mbox: Deleting a mailbox didn't delete its index files. diffstat: src/lib-storage/index/index-storage.c | 11 +++++++---- 1 files changed, 7 insertions(+), 4 deletions(-) diffs (21 lines): diff -r b016e771d8ab -r c67ea0d68b77 src/lib-storage/index/index-storage.c --- a/src/lib-storage/index/index-storage.c Wed Apr 11 14:29:37 2012 +0300 +++ b/src/lib-storage/index/index-storage.c Wed Apr 11 14:44:45 2012 +0300 @@ -519,10 +519,13 @@ return index_storage_mailbox_delete_dir(box, FALSE); } - /* specifically support symlinked shared mailboxes. a deletion will - simply remove the symlink, not actually expunge any mails */ - if (mailbox_list_delete_symlink(box->list, box->name) == 0) - return 0; + if ((box->list->flags & MAILBOX_LIST_FLAG_MAILBOX_FILES) == 0) { + /* specifically support symlinked shared mailboxes. a deletion + will simply remove the symlink, not actually expunge any + mails */ + if (mailbox_list_delete_symlink(box->list, box->name) == 0) + return 0; + } /* we can't easily atomically delete all mails and the mailbox. so: 1) expunge all mails From dovecot at dovecot.org Wed Apr 11 15:03:09 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 11 Apr 2012 15:03:09 +0300 Subject: dovecot-2.1: mbox: Make sure each mailbox creation generates a d... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/85966c47f172 changeset: 14413:85966c47f172 user: Timo Sirainen date: Wed Apr 11 15:02:53 2012 +0300 description: mbox: Make sure each mailbox creation generates a different UIDVALIDITY. diffstat: src/lib-storage/index/mbox/mbox-storage.h | 1 + src/lib-storage/index/mbox/mbox-sync.c | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletions(-) diffs (48 lines): diff -r c67ea0d68b77 -r 85966c47f172 src/lib-storage/index/mbox/mbox-storage.h --- a/src/lib-storage/index/mbox/mbox-storage.h Wed Apr 11 14:44:45 2012 +0300 +++ b/src/lib-storage/index/mbox/mbox-storage.h Wed Apr 11 15:02:53 2012 +0300 @@ -14,6 +14,7 @@ #define MBOX_SUBSCRIPTION_FILE_NAME ".subscriptions" #define MBOX_INDEX_PREFIX "dovecot.index" #define MBOX_INDEX_DIR_NAME ".imap" +#define MBOX_UIDVALIDITY_FNAME "dovecot-uidvalidity" struct mbox_index_header { uint64_t sync_size; diff -r c67ea0d68b77 -r 85966c47f172 src/lib-storage/index/mbox/mbox-sync.c --- a/src/lib-storage/index/mbox/mbox-sync.c Wed Apr 11 14:44:45 2012 +0300 +++ b/src/lib-storage/index/mbox/mbox-sync.c Wed Apr 11 15:02:53 2012 +0300 @@ -45,6 +45,7 @@ #include "istream-raw-mbox.h" #include "mbox-storage.h" #include "index-sync-changes.h" +#include "mailbox-uidvalidity.h" #include "mbox-from.h" #include "mbox-file.h" #include "mbox-lock.h" @@ -1407,6 +1408,16 @@ } } +static uint32_t mbox_get_uidvalidity_next(struct mailbox_list *list) +{ + const char *path; + + path = mailbox_list_get_path(list, NULL, + MAILBOX_LIST_PATH_TYPE_CONTROL); + path = t_strconcat(path, "/"MBOX_UIDVALIDITY_FNAME, NULL); + return mailbox_uidvalidity_next(list, path); +} + static int mbox_sync_update_index_header(struct mbox_sync_context *sync_ctx) { struct mail_index_view *view; @@ -1462,7 +1473,7 @@ if (sync_ctx->base_uid_validity == 0) { sync_ctx->base_uid_validity = sync_ctx->hdr->uid_validity != 0 ? sync_ctx->hdr->uid_validity : - I_MAX((unsigned int)ioloop_time, 1); + mbox_get_uidvalidity_next(sync_ctx->mbox->box.list); } if (sync_ctx->base_uid_validity != sync_ctx->hdr->uid_validity) { mail_index_update_header(sync_ctx->t, From dovecot at dovecot.org Wed Apr 11 17:21:12 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 11 Apr 2012 17:21:12 +0300 Subject: dovecot-2.1: dict file: Fixed assert-crash with fcntl/flock lock... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/4fb683720a06 changeset: 14414:4fb683720a06 user: Timo Sirainen date: Wed Apr 11 17:21:01 2012 +0300 description: dict file: Fixed assert-crash with fcntl/flock lock method. diffstat: src/lib-dict/dict-file.c | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diffs (29 lines): diff -r 85966c47f172 -r 4fb683720a06 src/lib-dict/dict-file.c --- a/src/lib-dict/dict-file.c Wed Apr 11 15:02:53 2012 +0300 +++ b/src/lib-dict/dict-file.c Wed Apr 11 17:21:01 2012 +0300 @@ -422,20 +422,20 @@ static int file_dict_lock(struct file_dict *dict, struct file_lock **lock_r) { - int fd, ret; + int ret; if (file_dict_open_latest(dict) < 0) return -1; if (dict->fd == -1) { /* quota file doesn't exist yet, we need to create it */ - fd = open(dict->path, O_CREAT | O_RDWR, 0600); - if (fd == -1) { + dict->fd = open(dict->path, O_CREAT | O_RDWR, 0600); + if (dict->fd == -1) { i_error("creat(%s) failed: %m", dict->path); return -1; } - (void)fd_copy_parent_dir_permissions(dict->path, fd, dict->path); - (void)close(fd); + (void)fd_copy_parent_dir_permissions(dict->path, dict->fd, + dict->path); } do { From dovecot at dovecot.org Wed Apr 11 17:29:54 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 11 Apr 2012 17:29:54 +0300 Subject: dovecot-2.0: imap-login: Memory leak fix. Message-ID: details: http://hg.dovecot.org/dovecot-2.0/rev/67f1cef07427 changeset: 13089:67f1cef07427 user: Timo Sirainen date: Thu Mar 22 16:03:29 2012 +0200 description: imap-login: Memory leak fix. diffstat: src/login-common/client-common.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (11 lines): diff -r ee99143fd9df -r 67f1cef07427 src/login-common/client-common.c --- a/src/login-common/client-common.c Tue Apr 10 18:05:36 2012 +0300 +++ b/src/login-common/client-common.c Thu Mar 22 16:03:29 2012 +0200 @@ -204,6 +204,7 @@ i_free(client->proxy_master_user); i_free(client->virtual_user); i_free(client->auth_mech_name); + i_free(client->master_data_prefix); pool_unref(&client->pool); i_assert(clients_count > 0); From dovecot at dovecot.org Wed Apr 11 18:23:45 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 11 Apr 2012 18:23:45 +0300 Subject: dovecot-2.1: lib-storage: LIST with mailbox {} settings incorrec... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/9cc178c7afb3 changeset: 14415:9cc178c7afb3 user: Timo Sirainen date: Wed Apr 11 18:23:34 2012 +0300 description: lib-storage: LIST with mailbox {} settings incorrectly set subscribed-flags. diffstat: src/lib-storage/mailbox-list-iter.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diffs (11 lines): diff -r 4fb683720a06 -r 9cc178c7afb3 src/lib-storage/mailbox-list-iter.c --- a/src/lib-storage/mailbox-list-iter.c Wed Apr 11 17:21:01 2012 +0300 +++ b/src/lib-storage/mailbox-list-iter.c Wed Apr 11 18:23:34 2012 +0300 @@ -533,7 +533,6 @@ if ((ctx->flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) == 0) match2 = match; else { - info->flags |= MAILBOX_SUBSCRIBED; match2 = autocreate_box_match(&actx->all_ns_box_sets, ctx->list->ns, info->name, FALSE, &idx); From dovecot at dovecot.org Wed Apr 11 19:06:49 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 11 Apr 2012 19:06:49 +0300 Subject: dovecot-2.1: Memory leak fixes. Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/584bd77c38fd changeset: 14416:584bd77c38fd user: Timo Sirainen date: Wed Apr 11 19:06:44 2012 +0300 description: Memory leak fixes. diffstat: src/lib-storage/index/index-thread.c | 3 +++ src/login-common/ssl-proxy-openssl.c | 9 +++++---- src/plugins/quota/quota.c | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diffs (72 lines): diff -r 9cc178c7afb3 -r 584bd77c38fd src/lib-storage/index/index-thread.c --- a/src/lib-storage/index/index-thread.c Wed Apr 11 18:23:34 2012 +0300 +++ b/src/lib-storage/index/index-thread.c Wed Apr 11 19:06:44 2012 +0300 @@ -325,6 +325,7 @@ if (seq1 == 0) { /* nothing is missing */ mail_index_strmap_view_sync_commit(&ctx->strmap_sync); + mailbox_header_lookup_unref(&headers_ctx); return 0; } @@ -332,6 +333,8 @@ mail_search_build_add_seqset(search_args, seq1, seq2); search_ctx = mailbox_search_init(ctx->t, search_args, NULL, 0, headers_ctx); + mailbox_header_lookup_unref(&headers_ctx); + mail_search_args_unref(&search_args); while (mailbox_search_next(search_ctx, &mail)) { if (mail_thread_map_add_mail(ctx, mail) < 0) { diff -r 9cc178c7afb3 -r 584bd77c38fd src/login-common/ssl-proxy-openssl.c --- a/src/login-common/ssl-proxy-openssl.c Wed Apr 11 18:23:34 2012 +0300 +++ b/src/login-common/ssl-proxy-openssl.c Wed Apr 11 19:06:44 2012 +0300 @@ -942,7 +942,8 @@ } static STACK_OF(X509_NAME) * -ssl_proxy_ctx_init(SSL_CTX *ssl_ctx, const struct login_settings *set) +ssl_proxy_ctx_init(SSL_CTX *ssl_ctx, const struct login_settings *set, + bool load_xnames) { X509_STORE *store; STACK_OF(X509_NAME) *xnames = NULL; @@ -956,7 +957,7 @@ SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS); #endif - if (*set->ssl_ca != '\0') { + if (*set->ssl_ca != '\0' && load_xnames) { /* set trusted CA certs */ store = SSL_CTX_get_cert_store(ssl_ctx); xnames = load_ca(store, set->ssl_ca); @@ -1198,7 +1199,7 @@ ctx->ctx = ssl_ctx = SSL_CTX_new(SSLv23_server_method()); if (ssl_ctx == NULL) i_fatal("SSL_CTX_new() failed"); - xnames = ssl_proxy_ctx_init(ssl_ctx, set); + xnames = ssl_proxy_ctx_init(ssl_ctx, set, ctx->verify_client_cert); if (SSL_CTX_set_cipher_list(ssl_ctx, ctx->cipher_list) != 1) { i_fatal("Can't set cipher list to '%s': %s", @@ -1265,7 +1266,7 @@ if ((ssl_client_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) i_fatal("SSL_CTX_new() failed"); - xnames = ssl_proxy_ctx_init(ssl_client_ctx, set); + xnames = ssl_proxy_ctx_init(ssl_client_ctx, set, TRUE); ssl_proxy_ctx_verify_client(ssl_client_ctx, xnames); ssl_proxy_client_ctx_set_client_cert(ssl_client_ctx, set); diff -r 9cc178c7afb3 -r 584bd77c38fd src/plugins/quota/quota.c --- a/src/plugins/quota/quota.c Wed Apr 11 18:23:34 2012 +0300 +++ b/src/plugins/quota/quota.c Wed Apr 11 19:06:44 2012 +0300 @@ -723,7 +723,7 @@ return -1; warning = array_append_space(&root_set->warning_rules); - warning->command = i_strdup(p+1); + warning->command = p_strdup(root_set->set->pool, p+1); warning->rule = rule; warning->reverse = reverse; From dovecot at dovecot.org Thu Apr 12 10:42:11 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 12 Apr 2012 10:42:11 +0300 Subject: dovecot-2.1: login: Reverted memory leak fix, because it broke s... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/f80f18d0ffa3 changeset: 14417:f80f18d0ffa3 user: Timo Sirainen date: Thu Apr 12 10:41:44 2012 +0300 description: login: Reverted memory leak fix, because it broke some SSL setups? diffstat: src/login-common/ssl-proxy-openssl.c | 9 ++++----- 1 files changed, 4 insertions(+), 5 deletions(-) diffs (40 lines): diff -r 584bd77c38fd -r f80f18d0ffa3 src/login-common/ssl-proxy-openssl.c --- a/src/login-common/ssl-proxy-openssl.c Wed Apr 11 19:06:44 2012 +0300 +++ b/src/login-common/ssl-proxy-openssl.c Thu Apr 12 10:41:44 2012 +0300 @@ -942,8 +942,7 @@ } static STACK_OF(X509_NAME) * -ssl_proxy_ctx_init(SSL_CTX *ssl_ctx, const struct login_settings *set, - bool load_xnames) +ssl_proxy_ctx_init(SSL_CTX *ssl_ctx, const struct login_settings *set) { X509_STORE *store; STACK_OF(X509_NAME) *xnames = NULL; @@ -957,7 +956,7 @@ SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS); #endif - if (*set->ssl_ca != '\0' && load_xnames) { + if (*set->ssl_ca != '\0') { /* set trusted CA certs */ store = SSL_CTX_get_cert_store(ssl_ctx); xnames = load_ca(store, set->ssl_ca); @@ -1199,7 +1198,7 @@ ctx->ctx = ssl_ctx = SSL_CTX_new(SSLv23_server_method()); if (ssl_ctx == NULL) i_fatal("SSL_CTX_new() failed"); - xnames = ssl_proxy_ctx_init(ssl_ctx, set, ctx->verify_client_cert); + xnames = ssl_proxy_ctx_init(ssl_ctx, set); if (SSL_CTX_set_cipher_list(ssl_ctx, ctx->cipher_list) != 1) { i_fatal("Can't set cipher list to '%s': %s", @@ -1266,7 +1265,7 @@ if ((ssl_client_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) i_fatal("SSL_CTX_new() failed"); - xnames = ssl_proxy_ctx_init(ssl_client_ctx, set, TRUE); + xnames = ssl_proxy_ctx_init(ssl_client_ctx, set); ssl_proxy_ctx_verify_client(ssl_client_ctx, xnames); ssl_proxy_client_ctx_set_client_cert(ssl_client_ctx, set); From dovecot at dovecot.org Thu Apr 12 10:49:01 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 12 Apr 2012 10:49:01 +0300 Subject: dovecot-2.1: login: Another attempt at fixing SSL memory leak. Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/85ad4baedd43 changeset: 14418:85ad4baedd43 user: Timo Sirainen date: Thu Apr 12 10:48:55 2012 +0300 description: login: Another attempt at fixing SSL memory leak. diffstat: src/login-common/ssl-proxy-openssl.c | 30 +++++++++++++++++------------- 1 files changed, 17 insertions(+), 13 deletions(-) diffs (85 lines): diff -r f80f18d0ffa3 -r 85ad4baedd43 src/login-common/ssl-proxy-openssl.c --- a/src/login-common/ssl-proxy-openssl.c Thu Apr 12 10:41:44 2012 +0300 +++ b/src/login-common/ssl-proxy-openssl.c Thu Apr 12 10:48:55 2012 +0300 @@ -903,11 +903,11 @@ return strstr(cert, "PRIVATE KEY---") != NULL; } -static STACK_OF(X509_NAME) *load_ca(X509_STORE *store, const char *ca) +static void load_ca(X509_STORE *store, const char *ca, + STACK_OF(X509_NAME) **xnames_r) { /* mostly just copy&pasted from X509_load_cert_crl_file() */ STACK_OF(X509_INFO) *inf; - STACK_OF(X509_NAME) *xnames; X509_INFO *itmp; X509_NAME *xname; BIO *bio; @@ -921,28 +921,32 @@ i_fatal("Couldn't parse ssl_ca: %s", ssl_last_error()); BIO_free(bio); - xnames = sk_X509_NAME_new_null(); - if (xnames == NULL) - i_fatal("sk_X509_NAME_new_null() failed"); + if (xnames_r != NULL) { + *xnames_r = sk_X509_NAME_new_null(); + if (*xnames_r == NULL) + i_fatal_status(FATAL_OUTOFMEM, "sk_X509_NAME_new_null() failed"); + } for(i = 0; i < sk_X509_INFO_num(inf); i++) { itmp = sk_X509_INFO_value(inf, i); if(itmp->x509) { X509_STORE_add_cert(store, itmp->x509); xname = X509_get_subject_name(itmp->x509); - if (xname != NULL) + if (xname != NULL && xnames_r != NULL) { xname = X509_NAME_dup(xname); - if (xname != NULL) - sk_X509_NAME_push(xnames, xname); + if (xname == NULL) + i_fatal_status(FATAL_OUTOFMEM, "X509_NAME_dup() failed"); + sk_X509_NAME_push(*xnames_r, xname); + } } if(itmp->crl) X509_STORE_add_crl(store, itmp->crl); } sk_X509_INFO_pop_free(inf, X509_INFO_free); - return xnames; } static STACK_OF(X509_NAME) * -ssl_proxy_ctx_init(SSL_CTX *ssl_ctx, const struct login_settings *set) +ssl_proxy_ctx_init(SSL_CTX *ssl_ctx, const struct login_settings *set, + bool load_xnames) { X509_STORE *store; STACK_OF(X509_NAME) *xnames = NULL; @@ -959,7 +963,7 @@ if (*set->ssl_ca != '\0') { /* set trusted CA certs */ store = SSL_CTX_get_cert_store(ssl_ctx); - xnames = load_ca(store, set->ssl_ca); + load_ca(store, set->ssl_ca, load_xnames ? &xnames : NULL); } SSL_CTX_set_info_callback(ssl_ctx, ssl_info_callback); if (SSL_CTX_need_tmp_RSA(ssl_ctx)) @@ -1198,7 +1202,7 @@ ctx->ctx = ssl_ctx = SSL_CTX_new(SSLv23_server_method()); if (ssl_ctx == NULL) i_fatal("SSL_CTX_new() failed"); - xnames = ssl_proxy_ctx_init(ssl_ctx, set); + xnames = ssl_proxy_ctx_init(ssl_ctx, set, ctx->verify_client_cert); if (SSL_CTX_set_cipher_list(ssl_ctx, ctx->cipher_list) != 1) { i_fatal("Can't set cipher list to '%s': %s", @@ -1265,7 +1269,7 @@ if ((ssl_client_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) i_fatal("SSL_CTX_new() failed"); - xnames = ssl_proxy_ctx_init(ssl_client_ctx, set); + xnames = ssl_proxy_ctx_init(ssl_client_ctx, set, TRUE); ssl_proxy_ctx_verify_client(ssl_client_ctx, xnames); ssl_proxy_client_ctx_set_client_cert(ssl_client_ctx, set); From dovecot at dovecot.org Mon Apr 16 21:52:12 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 16 Apr 2012 21:52:12 +0300 Subject: dovecot-2.0: login: Fixed memory leak when reading SSL server ce... Message-ID: details: http://hg.dovecot.org/dovecot-2.0/rev/6299dfb73732 changeset: 13090:6299dfb73732 user: Timo Sirainen date: Mon Apr 16 21:51:58 2012 +0300 description: login: Fixed memory leak when reading SSL server certificate with some settings. diffstat: src/login-common/ssl-proxy-openssl.c | 30 +++++++++++++++++------------- 1 files changed, 17 insertions(+), 13 deletions(-) diffs (85 lines): diff -r 67f1cef07427 -r 6299dfb73732 src/login-common/ssl-proxy-openssl.c --- a/src/login-common/ssl-proxy-openssl.c Thu Mar 22 16:03:29 2012 +0200 +++ b/src/login-common/ssl-proxy-openssl.c Mon Apr 16 21:51:58 2012 +0300 @@ -967,11 +967,11 @@ return strstr(cert, "PRIVATE KEY---") != NULL; } -static STACK_OF(X509_NAME) *load_ca(X509_STORE *store, const char *ca) +static void load_ca(X509_STORE *store, const char *ca, + STACK_OF(X509_NAME) **xnames_r) { /* mostly just copy&pasted from X509_load_cert_crl_file() */ STACK_OF(X509_INFO) *inf; - STACK_OF(X509_NAME) *xnames; X509_INFO *itmp; X509_NAME *xname; BIO *bio; @@ -985,28 +985,32 @@ i_fatal("Couldn't parse ssl_ca: %s", ssl_last_error()); BIO_free(bio); - xnames = sk_X509_NAME_new_null(); - if (xnames == NULL) - i_fatal("sk_X509_NAME_new_null() failed"); + if (xnames_r != NULL) { + *xnames_r = sk_X509_NAME_new_null(); + if (*xnames_r == NULL) + i_fatal_status(FATAL_OUTOFMEM, "sk_X509_NAME_new_null() failed"); + } for(i = 0; i < sk_X509_INFO_num(inf); i++) { itmp = sk_X509_INFO_value(inf, i); if(itmp->x509) { X509_STORE_add_cert(store, itmp->x509); xname = X509_get_subject_name(itmp->x509); - if (xname != NULL) + if (xname != NULL && xnames_r != NULL) { xname = X509_NAME_dup(xname); - if (xname != NULL) - sk_X509_NAME_push(xnames, xname); + if (xname == NULL) + i_fatal_status(FATAL_OUTOFMEM, "X509_NAME_dup() failed"); + sk_X509_NAME_push(*xnames_r, xname); + } } if(itmp->crl) X509_STORE_add_crl(store, itmp->crl); } sk_X509_INFO_pop_free(inf, X509_INFO_free); - return xnames; } static STACK_OF(X509_NAME) * -ssl_proxy_ctx_init(SSL_CTX *ssl_ctx, const struct login_settings *set) +ssl_proxy_ctx_init(SSL_CTX *ssl_ctx, const struct login_settings *set, + bool load_xnames) { X509_STORE *store; STACK_OF(X509_NAME) *xnames = NULL; @@ -1021,7 +1025,7 @@ if (*set->ssl_ca != '\0') { /* set trusted CA certs */ store = SSL_CTX_get_cert_store(ssl_ctx); - xnames = load_ca(store, set->ssl_ca); + load_ca(store, set->ssl_ca, load_xnames ? &xnames : NULL); } SSL_CTX_set_info_callback(ssl_ctx, ssl_info_callback); if (SSL_CTX_need_tmp_RSA(ssl_ctx)) @@ -1208,7 +1212,7 @@ ctx->ctx = ssl_ctx = SSL_CTX_new(SSLv23_server_method()); if (ssl_ctx == NULL) i_fatal("SSL_CTX_new() failed"); - xnames = ssl_proxy_ctx_init(ssl_ctx, set); + xnames = ssl_proxy_ctx_init(ssl_ctx, set, ctx->verify_client_cert); if (SSL_CTX_set_cipher_list(ssl_ctx, ctx->cipher_list) != 1) { i_fatal("Can't set cipher list to '%s': %s", @@ -1274,7 +1278,7 @@ if ((ssl_client_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) i_fatal("SSL_CTX_new() failed"); - xnames = ssl_proxy_ctx_init(ssl_client_ctx, set); + xnames = ssl_proxy_ctx_init(ssl_client_ctx, set, TRUE); ssl_proxy_ctx_verify_client(ssl_client_ctx, xnames); ssl_proxy_client_ctx_set_client_cert(ssl_client_ctx, set); From dovecot at dovecot.org Mon Apr 16 22:05:54 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 16 Apr 2012 22:05:54 +0300 Subject: dovecot-2.1: login: Fixed per-IP ssl_ca setting inside local/rem... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/b60701dd4751 changeset: 14419:b60701dd4751 user: Timo Sirainen date: Mon Apr 16 22:05:47 2012 +0300 description: login: Fixed per-IP ssl_ca setting inside local/remote block. diffstat: src/login-common/ssl-proxy-openssl.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diffs (12 lines): diff -r 85ad4baedd43 -r b60701dd4751 src/login-common/ssl-proxy-openssl.c --- a/src/login-common/ssl-proxy-openssl.c Thu Apr 12 10:48:55 2012 +0300 +++ b/src/login-common/ssl-proxy-openssl.c Mon Apr 16 22:05:47 2012 +0300 @@ -139,6 +139,8 @@ return 1; if (strcmp(ctx1->key, ctx2->key) != 0) return 1; + if (null_strcmp(ctx1->ca, ctx2->ca) != 0) + return 1; if (null_strcmp(ctx1->cipher_list, ctx2->cipher_list) != 0) return 1; if (null_strcmp(ctx1->protocols, ctx2->protocols) != 0) From dovecot at dovecot.org Mon Apr 16 22:06:04 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 16 Apr 2012 22:06:04 +0300 Subject: dovecot-2.0: login: Fixed per-IP ssl_ca setting inside local/rem... Message-ID: details: http://hg.dovecot.org/dovecot-2.0/rev/459258e15ca7 changeset: 13091:459258e15ca7 user: Timo Sirainen date: Mon Apr 16 22:05:47 2012 +0300 description: login: Fixed per-IP ssl_ca setting inside local/remote block. diffstat: src/login-common/ssl-proxy-openssl.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diffs (12 lines): diff -r 6299dfb73732 -r 459258e15ca7 src/login-common/ssl-proxy-openssl.c --- a/src/login-common/ssl-proxy-openssl.c Mon Apr 16 21:51:58 2012 +0300 +++ b/src/login-common/ssl-proxy-openssl.c Mon Apr 16 22:05:47 2012 +0300 @@ -135,6 +135,8 @@ return 1; if (strcmp(ctx1->key, ctx2->key) != 0) return 1; + if (null_strcmp(ctx1->ca, ctx2->ca) != 0) + return 1; if (null_strcmp(ctx1->cipher_list, ctx2->cipher_list) != 0) return 1; From dovecot at dovecot.org Tue Apr 17 13:56:11 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 17 Apr 2012 13:56:11 +0300 Subject: dovecot-2.1: login: Log message change: Tried to use s/disabled/... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/d6376942d9a6 changeset: 14420:d6376942d9a6 user: Timo Sirainen date: Tue Apr 17 13:56:00 2012 +0300 description: login: Log message change: Tried to use s/disabled/disallowed/ plaintext auth diffstat: src/login-common/client-common.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r b60701dd4751 -r d6376942d9a6 src/login-common/client-common.c --- a/src/login-common/client-common.c Mon Apr 16 22:05:47 2012 +0300 +++ b/src/login-common/client-common.c Tue Apr 17 13:56:00 2012 +0300 @@ -616,7 +616,7 @@ /* some auth attempts without SSL/TLS */ if (client->auth_tried_disabled_plaintext) - return "(tried to use disabled plaintext auth)"; + return "(tried to use disallowed plaintext auth)"; if (client->set->auth_ssl_require_client_cert && client->ssl_proxy == NULL) return "(cert required, client didn't start TLS)"; From dovecot at dovecot.org Wed Apr 18 18:09:40 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 18 Apr 2012 18:09:40 +0300 Subject: dovecot-2.1: imapc: Added guid-forced feature to use SHA1(messag... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/16ed300484c9 changeset: 14421:16ed300484c9 user: Timo Sirainen date: Wed Apr 18 18:09:14 2012 +0300 description: imapc: Added guid-forced feature to use SHA1(message) as GUID. diffstat: src/lib-storage/index/imapc/imapc-mail.c | 48 ++++++++++++++++++++++++--- src/lib-storage/index/imapc/imapc-settings.c | 1 + src/lib-storage/index/imapc/imapc-settings.h | 3 +- 3 files changed, 45 insertions(+), 7 deletions(-) diffs (103 lines): diff -r d6376942d9a6 -r 16ed300484c9 src/lib-storage/index/imapc/imapc-mail.c --- a/src/lib-storage/index/imapc/imapc-mail.c Tue Apr 17 13:56:00 2012 +0300 +++ b/src/lib-storage/index/imapc/imapc-mail.c Wed Apr 18 18:09:14 2012 +0300 @@ -2,6 +2,8 @@ #include "lib.h" #include "str.h" +#include "hex-binary.h" +#include "sha1.h" #include "istream.h" #include "imap-envelope.h" #include "imapc-msgmap.h" @@ -307,6 +309,33 @@ buffer_free(&mail->body); } +static int imapc_mail_get_body_hash(struct index_mail *imail) +{ + struct istream *input; + const unsigned char *data; + size_t size; + uoff_t old_offset; + struct sha1_ctxt sha1_ctx; + unsigned char sha1_output[SHA1_RESULTLEN]; + const char *sha1_str; + + sha1_init(&sha1_ctx); + old_offset = imail->data.stream == NULL ? 0 : + imail->data.stream->v_offset; + if (mail_get_stream(&imail->mail.mail, NULL, NULL, &input) < 0) + return -1; + while (i_stream_read_data(input, &data, &size, 0) > 0) { + sha1_loop(&sha1_ctx, data, size); + i_stream_skip(input, size); + } + i_stream_seek(imail->data.stream, old_offset); + sha1_result(&sha1_ctx, sha1_output); + + sha1_str = binary_to_hex(sha1_output, sizeof(sha1_output)); + imail->data.guid = p_strdup(imail->data_pool, sha1_str); + return 0; +} + static int imapc_mail_get_guid(struct mail *_mail, const char **value_r) { struct index_mail *imail = (struct index_mail *)_mail; @@ -328,11 +357,17 @@ } /* GUID not in cache, fetch it */ - if (imapc_mail_fetch(_mail, MAIL_FETCH_GUID) < 0) - return -1; - if (imail->data.guid == NULL) { - (void)imapc_mail_failed(_mail, mbox->guid_fetch_field_name); - return -1; + if (mbox->guid_fetch_field_name != NULL) { + if (imapc_mail_fetch(_mail, MAIL_FETCH_GUID) < 0) + return -1; + if (imail->data.guid == NULL) { + (void)imapc_mail_failed(_mail, mbox->guid_fetch_field_name); + return -1; + } + } else { + /* use hash of message body as the GUID */ + if (imapc_mail_get_body_hash(imail) < 0) + return -1; } index_mail_cache_add_idx(imail, cache_idx, @@ -349,7 +384,8 @@ switch (field) { case MAIL_FETCH_GUID: - if (mbox->guid_fetch_field_name == NULL) { + if (!IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_GUID_FORCED) && + mbox->guid_fetch_field_name == NULL) { /* GUIDs not supported by server */ break; } diff -r d6376942d9a6 -r 16ed300484c9 src/lib-storage/index/imapc/imapc-settings.c --- a/src/lib-storage/index/imapc/imapc-settings.c Tue Apr 17 13:56:00 2012 +0300 +++ b/src/lib-storage/index/imapc/imapc-settings.c Wed Apr 18 18:09:14 2012 +0300 @@ -76,6 +76,7 @@ static const struct imapc_feature_list imapc_feature_list[] = { { "rfc822.size", IMAPC_FEATURE_RFC822_SIZE }, + { "guid-forced", IMAPC_FEATURE_GUID_FORCED }, { NULL, 0 } }; diff -r d6376942d9a6 -r 16ed300484c9 src/lib-storage/index/imapc/imapc-settings.h --- a/src/lib-storage/index/imapc/imapc-settings.h Tue Apr 17 13:56:00 2012 +0300 +++ b/src/lib-storage/index/imapc/imapc-settings.h Wed Apr 18 18:09:14 2012 +0300 @@ -3,7 +3,8 @@ /* */ enum imapc_features { - IMAPC_FEATURE_RFC822_SIZE = 0x01 + IMAPC_FEATURE_RFC822_SIZE = 0x01, + IMAPC_FEATURE_GUID_FORCED = 0x02 }; /* */ From dovecot at dovecot.org Wed Apr 18 18:33:12 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 18 Apr 2012 18:33:12 +0300 Subject: dovecot-2.1: imapc: Use SHA1 of message header for guid-forced i... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/ea7ca6330491 changeset: 14422:ea7ca6330491 user: Timo Sirainen date: Wed Apr 18 18:33:02 2012 +0300 description: imapc: Use SHA1 of message header for guid-forced instead of the entire body. diffstat: src/lib-storage/index/imapc/imapc-mail.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diffs (32 lines): diff -r 16ed300484c9 -r ea7ca6330491 src/lib-storage/index/imapc/imapc-mail.c --- a/src/lib-storage/index/imapc/imapc-mail.c Wed Apr 18 18:09:14 2012 +0300 +++ b/src/lib-storage/index/imapc/imapc-mail.c Wed Apr 18 18:33:02 2012 +0300 @@ -309,7 +309,7 @@ buffer_free(&mail->body); } -static int imapc_mail_get_body_hash(struct index_mail *imail) +static int imapc_mail_get_hdr_hash(struct index_mail *imail) { struct istream *input; const unsigned char *data; @@ -322,7 +322,7 @@ sha1_init(&sha1_ctx); old_offset = imail->data.stream == NULL ? 0 : imail->data.stream->v_offset; - if (mail_get_stream(&imail->mail.mail, NULL, NULL, &input) < 0) + if (mail_get_hdr_stream(&imail->mail.mail, NULL, &input) < 0) return -1; while (i_stream_read_data(input, &data, &size, 0) > 0) { sha1_loop(&sha1_ctx, data, size); @@ -365,8 +365,8 @@ return -1; } } else { - /* use hash of message body as the GUID */ - if (imapc_mail_get_body_hash(imail) < 0) + /* use hash of message headers as the GUID */ + if (imapc_mail_get_hdr_hash(imail) < 0) return -1; } From dovecot at dovecot.org Wed Apr 18 19:29:30 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 18 Apr 2012 19:29:30 +0300 Subject: dovecot-2.1: trash plugin fixes Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/51b40cffb628 changeset: 14423:51b40cffb628 user: Timo Sirainen date: Wed Apr 18 19:29:22 2012 +0300 description: trash plugin fixes diffstat: src/plugins/trash/trash-plugin.c | 16 +++++++--------- 1 files changed, 7 insertions(+), 9 deletions(-) diffs (43 lines): diff -r ea7ca6330491 -r 51b40cffb628 src/plugins/trash/trash-plugin.c --- a/src/plugins/trash/trash-plugin.c Wed Apr 18 18:33:02 2012 +0300 +++ b/src/plugins/trash/trash-plugin.c Wed Apr 18 19:29:22 2012 +0300 @@ -158,9 +158,10 @@ trash->mail = NULL; (void)mailbox_search_deinit(&trash->search_ctx); - if (size_expunged >= size_needed) + if (size_expunged >= size_needed) { (void)mailbox_transaction_commit(&trash->trans); - else { + (void)mailbox_sync(trash->box, 0); + } else { /* couldn't get enough space, don't expunge anything */ mailbox_transaction_rollback(&trash->trans); } @@ -175,14 +176,12 @@ (unsigned long long)size_needed, (unsigned long long)size_expunged); } - return FALSE; + return 0; } - ctx->bytes_used = ctx->bytes_used > (int64_t)size_expunged ? - ctx->bytes_used - size_expunged : 0; - ctx->count_used = ctx->count_used > (int64_t)expunged_count ? - ctx->count_used - expunged_count : 0; - return TRUE; + ctx->bytes_ceil += size_expunged; + ctx->count_ceil += expunged_count; + return 1; } static int @@ -214,7 +213,6 @@ if (ret <= 0) return 0; } - return 0; } From dovecot at dovecot.org Wed Apr 18 19:56:48 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 18 Apr 2012 19:56:48 +0300 Subject: dovecot-2.1: fts-solr: doveadm fts rescan now resets the last-in... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/d145ea6f7061 changeset: 14424:d145ea6f7061 user: Timo Sirainen date: Wed Apr 18 19:56:29 2012 +0300 description: fts-solr: doveadm fts rescan now resets the last-indexed-uid fields to allow reindexing. diffstat: src/plugins/fts-solr/fts-backend-solr.c | 30 +++++++++++++++++++++++++++++- 1 files changed, 29 insertions(+), 1 deletions(-) diffs (47 lines): diff -r 51b40cffb628 -r d145ea6f7061 src/plugins/fts-solr/fts-backend-solr.c --- a/src/plugins/fts-solr/fts-backend-solr.c Wed Apr 18 19:29:22 2012 +0300 +++ b/src/plugins/fts-solr/fts-backend-solr.c Wed Apr 18 19:56:29 2012 +0300 @@ -545,6 +545,34 @@ return 0; } +static int fts_backend_solr_rescan(struct fts_backend *backend) +{ + struct mailbox_list_iterate_context *iter; + const struct mailbox_info *info; + struct mailbox *box; + int ret = 0; + + /* FIXME: proper rescan needed. for now we'll just reset the + last-uids */ + iter = mailbox_list_iter_init(backend->ns->list, "*", + MAILBOX_LIST_ITER_NO_AUTO_BOXES); + while ((info = mailbox_list_iter_next(iter)) != NULL) { + if ((info->flags & + (MAILBOX_NONEXISTENT | MAILBOX_NOSELECT)) != 0) + continue; + + box = mailbox_alloc(info->ns->list, info->name, 0); + if (mailbox_open(box) == 0) { + if (fts_index_set_last_uid(box, 0) < 0) + ret = -1; + } + mailbox_free(&box); + } + if (mailbox_list_iter_deinit(&iter) < 0) + ret = -1; + return ret; +} + static int fts_backend_solr_optimize(struct fts_backend *backend ATTR_UNUSED) { return 0; @@ -850,7 +878,7 @@ fts_backend_solr_update_unset_build_key, fts_backend_solr_update_build_more, fts_backend_solr_refresh, - NULL, + fts_backend_solr_rescan, fts_backend_solr_optimize, fts_backend_default_can_lookup, fts_backend_solr_lookup, From dovecot at dovecot.org Wed Apr 18 20:09:36 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 18 Apr 2012 20:09:36 +0300 Subject: dovecot-2.1: auth: Changed auth-userdb socket's default user to ... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/bda92bf286a0 changeset: 14425:bda92bf286a0 user: Timo Sirainen date: Wed Apr 18 20:09:30 2012 +0300 description: auth: Changed auth-userdb socket's default user to $default_internal_user. This makes the defaults more usable for director setups. diffstat: src/auth/auth-settings.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r d145ea6f7061 -r bda92bf286a0 src/auth/auth-settings.c --- a/src/auth/auth-settings.c Wed Apr 18 19:56:29 2012 +0300 +++ b/src/auth/auth-settings.c Wed Apr 18 20:09:30 2012 +0300 @@ -19,7 +19,7 @@ { "login/login", 0666, "", "" }, { "auth-login", 0600, "$default_internal_user", "" }, { "auth-client", 0600, "", "" }, - { "auth-userdb", 0666, "", "" }, + { "auth-userdb", 0666, "$default_internal_user", "" }, { "auth-master", 0600, "", "" } }; static struct file_listener_settings *auth_unix_listeners[] = { From dovecot at dovecot.org Thu Apr 19 14:40:29 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 19 Apr 2012 14:40:29 +0300 Subject: dovecot-2.1: maildir_very_dirty_syncs=yes: Try harder to avoid r... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/ff07827db69a changeset: 14426:ff07827db69a user: Timo Sirainen date: Thu Apr 19 14:39:26 2012 +0300 description: maildir_very_dirty_syncs=yes: Try harder to avoid readdir()ing. diffstat: src/lib-storage/index/maildir/maildir-sync.c | 51 +++++++++++++++------------ src/lib-storage/index/maildir/maildir-sync.h | 1 + src/lib-storage/index/maildir/maildir-util.c | 11 ++++++ 3 files changed, 41 insertions(+), 22 deletions(-) diffs (108 lines): diff -r bda92bf286a0 -r ff07827db69a src/lib-storage/index/maildir/maildir-sync.c --- a/src/lib-storage/index/maildir/maildir-sync.c Wed Apr 18 20:09:30 2012 +0300 +++ b/src/lib-storage/index/maildir/maildir-sync.c Thu Apr 19 14:39:26 2012 +0300 @@ -993,6 +993,34 @@ return ret; } +int maildir_sync_refresh_flags_view(struct maildir_mailbox *mbox) +{ + struct mail_index_view_sync_ctx *sync_ctx; + bool delayed_expunges; + + (void)mail_index_refresh(mbox->box.index); + if (mbox->flags_view == NULL) + mbox->flags_view = mail_index_view_open(mbox->box.index); + + sync_ctx = mail_index_view_sync_begin(mbox->flags_view, + MAIL_INDEX_VIEW_SYNC_FLAG_FIX_INCONSISTENT); + if (mail_index_view_sync_commit(&sync_ctx, &delayed_expunges) < 0) { + mail_storage_set_index_error(&mbox->box); + return -1; + } + /* make sure the map stays in private memory */ + if (mbox->flags_view->map->refcount > 1) { + struct mail_index_map *map; + + map = mail_index_map_clone(mbox->flags_view->map); + mail_index_unmap(&mbox->flags_view->map); + mbox->flags_view->map = map; + } + mail_index_record_map_move_to_private(mbox->flags_view->map); + mail_index_map_move_to_memory(mbox->flags_view->map); + return 0; +} + struct mailbox_sync_context * maildir_storage_sync_init(struct mailbox *box, enum mailbox_sync_flags flags) { @@ -1025,29 +1053,8 @@ } if (mbox->storage->set->maildir_very_dirty_syncs) { - struct mail_index_view_sync_ctx *sync_ctx; - bool b; - - if (mbox->flags_view == NULL) { - mbox->flags_view = - mail_index_view_open(mbox->box.index); - } - sync_ctx = mail_index_view_sync_begin(mbox->flags_view, - MAIL_INDEX_VIEW_SYNC_FLAG_FIX_INCONSISTENT); - if (mail_index_view_sync_commit(&sync_ctx, &b) < 0) { - mail_storage_set_index_error(&mbox->box); + if (maildir_sync_refresh_flags_view(mbox) < 0) ret = -1; - } - /* make sure the map stays in private memory */ - if (mbox->flags_view->map->refcount > 1) { - struct mail_index_map *map; - - map = mail_index_map_clone(mbox->flags_view->map); - mail_index_unmap(&mbox->flags_view->map); - mbox->flags_view->map = map; - } - mail_index_record_map_move_to_private(mbox->flags_view->map); - mail_index_map_move_to_memory(mbox->flags_view->map); maildir_uidlist_set_all_nonsynced(mbox->uidlist); } mbox->synced = TRUE; diff -r bda92bf286a0 -r ff07827db69a src/lib-storage/index/maildir/maildir-sync.h --- a/src/lib-storage/index/maildir/maildir-sync.h Wed Apr 18 20:09:30 2012 +0300 +++ b/src/lib-storage/index/maildir/maildir-sync.h Thu Apr 19 14:39:26 2012 +0300 @@ -42,6 +42,7 @@ void maildir_sync_notify(struct maildir_sync_context *ctx); void maildir_sync_set_new_msgs_count(struct maildir_index_sync_context *ctx, unsigned int count); +int maildir_sync_refresh_flags_view(struct maildir_mailbox *mbox); int maildir_sync_lookup(struct maildir_mailbox *mbox, uint32_t uid, enum maildir_uidlist_rec_flag *flags_r, diff -r bda92bf286a0 -r ff07827db69a src/lib-storage/index/maildir/maildir-util.c --- a/src/lib-storage/index/maildir/maildir-util.c Wed Apr 18 20:09:30 2012 +0300 +++ b/src/lib-storage/index/maildir/maildir-util.c Thu Apr 19 14:39:26 2012 +0300 @@ -103,6 +103,12 @@ if (ret > 0 && (flags & MAILDIR_UIDLIST_REC_FLAG_NONSYNCED) != 0) { /* file was found. make sure we remember its latest name. */ maildir_uidlist_update_fname(mbox->uidlist, fname); + } else if (ret == 0 && + (flags & MAILDIR_UIDLIST_REC_FLAG_NONSYNCED) == 0) { + /* file wasn't found. mark this message nonsynced, so we can + retry the lookup by guessing the flags */ + maildir_uidlist_add_flags(mbox->uidlist, fname, + MAILDIR_UIDLIST_REC_FLAG_NONSYNCED); } return ret; } @@ -133,6 +139,11 @@ T_BEGIN { ret = maildir_file_do_try(mbox, uid, callback, context); } T_END; + if (ret == 0 && mbox->storage->set->maildir_very_dirty_syncs) T_BEGIN { + /* try guessing again with refreshed flags */ + if (maildir_sync_refresh_flags_view(mbox) == 0) + ret = maildir_file_do_try(mbox, uid, callback, context); + } T_END; for (i = 0; i < MAILDIR_RESYNC_RETRY_COUNT && ret == 0; i++) { /* file is either renamed or deleted. sync the maildir and see which one. if file appears to be renamed constantly, From dovecot at dovecot.org Thu Apr 19 18:16:07 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 19 Apr 2012 18:16:07 +0300 Subject: dovecot-2.1: lib-storage: Added mailbox_delete_empty(). Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/2d8bafd11569 changeset: 14427:2d8bafd11569 user: Timo Sirainen date: Thu Apr 19 18:15:37 2012 +0300 description: lib-storage: Added mailbox_delete_empty(). diffstat: src/lib-storage/index/index-storage.c | 6 ++++-- src/lib-storage/mail-storage-private.h | 2 ++ src/lib-storage/mail-storage.c | 12 ++++++++++++ src/lib-storage/mail-storage.h | 3 +++ 4 files changed, 21 insertions(+), 2 deletions(-) diffs (63 lines): diff -r ff07827db69a -r 2d8bafd11569 src/lib-storage/index/index-storage.c --- a/src/lib-storage/index/index-storage.c Thu Apr 19 14:39:26 2012 +0300 +++ b/src/lib-storage/index/index-storage.c Thu Apr 19 18:15:37 2012 +0300 @@ -535,8 +535,10 @@ no) finish deleting the mailbox */ - if (mailbox_expunge_all_mails(box) < 0) - return -1; + if (!box->deleting_must_be_empty) { + if (mailbox_expunge_all_mails(box) < 0) + return -1; + } if (mailbox_mark_index_deleted(box, TRUE) < 0) return -1; diff -r ff07827db69a -r 2d8bafd11569 src/lib-storage/mail-storage-private.h --- a/src/lib-storage/mail-storage-private.h Thu Apr 19 14:39:26 2012 +0300 +++ b/src/lib-storage/mail-storage-private.h Thu Apr 19 18:15:37 2012 +0300 @@ -265,6 +265,8 @@ unsigned int creating:1; /* Mailbox is being deleted */ unsigned int deleting:1; + /* Delete mailbox only if it's empty */ + unsigned int deleting_must_be_empty:1; /* Mailbox was already marked as deleted within this allocation. */ unsigned int marked_deleted:1; /* TRUE if this is an INBOX for this user */ diff -r ff07827db69a -r 2d8bafd11569 src/lib-storage/mail-storage.c --- a/src/lib-storage/mail-storage.c Thu Apr 19 14:39:26 2012 +0300 +++ b/src/lib-storage/mail-storage.c Thu Apr 19 18:15:37 2012 +0300 @@ -1106,6 +1106,18 @@ return ret; } +int mailbox_delete_empty(struct mailbox *box) +{ + int ret; + + /* FIXME: should be a parameter to delete(), but since it changes API + don't do it for now */ + box->deleting_must_be_empty = TRUE; + ret = mailbox_delete(box); + box->deleting_must_be_empty = FALSE; + return ret; +} + static bool mail_storages_rename_compatible(struct mail_storage *storage1, struct mail_storage *storage2, diff -r ff07827db69a -r 2d8bafd11569 src/lib-storage/mail-storage.h --- a/src/lib-storage/mail-storage.h Thu Apr 19 14:39:26 2012 +0300 +++ b/src/lib-storage/mail-storage.h Thu Apr 19 18:15:37 2012 +0300 @@ -417,6 +417,9 @@ int mailbox_update(struct mailbox *box, const struct mailbox_update *update); /* Delete mailbox (and its parent directory, if it has no siblings) */ int mailbox_delete(struct mailbox *box); +/* Delete mailbox, but only if it's empty. If it's not, fails with + MAIL_ERROR_EXISTS. */ +int mailbox_delete_empty(struct mailbox *box); /* Rename mailbox. Renaming across different mailbox lists is possible only between private namespaces and storages of the same type. If the rename fails, the error is set to src's storage. */ From dovecot at dovecot.org Thu Apr 19 18:16:07 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 19 Apr 2012 18:16:07 +0300 Subject: dovecot-2.1: doveadm expunge: Added -d parameter to delete mailb... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/782570f644f7 changeset: 14428:782570f644f7 user: Timo Sirainen date: Thu Apr 19 18:15:56 2012 +0300 description: doveadm expunge: Added -d parameter to delete mailbox if it's empty after expunging. diffstat: src/doveadm/doveadm-mail-expunge.c | 64 ++++++++++++++++++++++++++++++++----- src/doveadm/doveadm-mail-iter.c | 18 +++++++-- src/doveadm/doveadm-mail-iter.h | 2 + 3 files changed, 70 insertions(+), 14 deletions(-) diffs (161 lines): diff -r 2d8bafd11569 -r 782570f644f7 src/doveadm/doveadm-mail-expunge.c --- a/src/doveadm/doveadm-mail-expunge.c Thu Apr 19 18:15:37 2012 +0300 +++ b/src/doveadm/doveadm-mail-expunge.c Thu Apr 19 18:15:56 2012 +0300 @@ -9,16 +9,24 @@ #include "doveadm-mail-iter.h" #include "doveadm-mail.h" +struct expunge_cmd_context { + struct doveadm_mail_cmd_context ctx; + bool delete_empty_mailbox; +}; + static int -cmd_expunge_box(struct doveadm_mail_cmd_context *ctx, +cmd_expunge_box(struct doveadm_mail_cmd_context *_ctx, const struct mailbox_info *info, struct mail_search_args *search_args) { + struct expunge_cmd_context *ctx = (struct expunge_cmd_context *)_ctx; struct doveadm_mail_iter *iter; + struct mailbox *box; struct mailbox_transaction_context *trans; struct mail *mail; + enum mail_error error; - if (doveadm_mail_iter_init(ctx, info, search_args, 0, NULL, + if (doveadm_mail_iter_init(_ctx, info, search_args, 0, NULL, &trans, &iter) < 0) return -1; @@ -29,7 +37,29 @@ } mail_expunge(mail); } - return doveadm_mail_iter_deinit_sync(&iter); + + if (doveadm_mail_iter_deinit_keep_box(&iter, &box) < 0) { + mailbox_free(&box); + return -1; + } + if (mailbox_sync(box, 0) < 0) { + doveadm_mail_failed_mailbox(_ctx, box); + mailbox_free(&box); + return -1; + } + + if (ctx->delete_empty_mailbox) { + if (mailbox_delete_empty(box) < 0) { + (void)mailbox_get_last_error(box, &error); + if (error != MAIL_ERROR_EXISTS) { + doveadm_mail_failed_mailbox(_ctx, box); + mailbox_free(&box); + return -1; + } + } + } + mailbox_free(&box); + return 0; } static bool @@ -208,16 +238,32 @@ expunge_search_args_check(ctx->search_args, "expunge"); } +static bool cmd_expunge_parse_arg(struct doveadm_mail_cmd_context *_ctx, int c) +{ + struct expunge_cmd_context *ctx = (struct expunge_cmd_context *)_ctx; + + switch (c) { + case 'd': + ctx->delete_empty_mailbox = TRUE; + break; + default: + return FALSE; + } + return TRUE; +} + static struct doveadm_mail_cmd_context *cmd_expunge_alloc(void) { - struct doveadm_mail_cmd_context *ctx; + struct expunge_cmd_context *ctx; - ctx = doveadm_mail_cmd_alloc(struct doveadm_mail_cmd_context); - ctx->v.init = cmd_expunge_init; - ctx->v.run = cmd_expunge_run; - return ctx; + ctx = doveadm_mail_cmd_alloc(struct expunge_cmd_context); + ctx->ctx.getopt_args = "d"; + ctx->ctx.v.parse_arg = cmd_expunge_parse_arg; + ctx->ctx.v.init = cmd_expunge_init; + ctx->ctx.v.run = cmd_expunge_run; + return &ctx->ctx; } struct doveadm_mail_cmd cmd_expunge = { - cmd_expunge_alloc, "expunge", "" + cmd_expunge_alloc, "expunge", "[-d] " }; diff -r 2d8bafd11569 -r 782570f644f7 src/doveadm/doveadm-mail-iter.c --- a/src/doveadm/doveadm-mail-iter.c Thu Apr 19 18:15:37 2012 +0300 +++ b/src/doveadm/doveadm-mail-iter.c Thu Apr 19 18:15:56 2012 +0300 @@ -83,7 +83,7 @@ static int doveadm_mail_iter_deinit_full(struct doveadm_mail_iter **_iter, - bool sync, bool commit) + bool sync, bool commit, bool keep_box) { struct doveadm_mail_iter *iter = *_iter; int ret; @@ -95,24 +95,32 @@ ret = mailbox_sync(iter->box, 0); if (ret < 0) doveadm_mail_failed_mailbox(iter->ctx, iter->box); - mailbox_free(&iter->box); + if (!keep_box) + mailbox_free(&iter->box); i_free(iter); return ret; } int doveadm_mail_iter_deinit(struct doveadm_mail_iter **_iter) { - return doveadm_mail_iter_deinit_full(_iter, FALSE, TRUE); + return doveadm_mail_iter_deinit_full(_iter, FALSE, TRUE, FALSE); } int doveadm_mail_iter_deinit_sync(struct doveadm_mail_iter **_iter) { - return doveadm_mail_iter_deinit_full(_iter, TRUE, TRUE); + return doveadm_mail_iter_deinit_full(_iter, TRUE, TRUE, FALSE); +} + +int doveadm_mail_iter_deinit_keep_box(struct doveadm_mail_iter **iter, + struct mailbox **box_r) +{ + *box_r = (*iter)->box; + return doveadm_mail_iter_deinit_full(iter, FALSE, TRUE, TRUE); } void doveadm_mail_iter_deinit_rollback(struct doveadm_mail_iter **_iter) { - (void)doveadm_mail_iter_deinit_full(_iter, FALSE, FALSE); + (void)doveadm_mail_iter_deinit_full(_iter, FALSE, FALSE, FALSE); } bool doveadm_mail_iter_next(struct doveadm_mail_iter *iter, diff -r 2d8bafd11569 -r 782570f644f7 src/doveadm/doveadm-mail-iter.h --- a/src/doveadm/doveadm-mail-iter.h Thu Apr 19 18:15:37 2012 +0300 +++ b/src/doveadm/doveadm-mail-iter.h Thu Apr 19 18:15:56 2012 +0300 @@ -13,6 +13,8 @@ struct doveadm_mail_iter **iter_r); int doveadm_mail_iter_deinit(struct doveadm_mail_iter **iter); int doveadm_mail_iter_deinit_sync(struct doveadm_mail_iter **iter); +int doveadm_mail_iter_deinit_keep_box(struct doveadm_mail_iter **iter, + struct mailbox **box_r); void doveadm_mail_iter_deinit_rollback(struct doveadm_mail_iter **iter); bool doveadm_mail_iter_next(struct doveadm_mail_iter *iter, From dovecot at dovecot.org Thu Apr 19 18:22:50 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 19 Apr 2012 18:22:50 +0300 Subject: dovecot-2.1: LMTP: Don't add Return-Path: header when proxying. Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/85b3975c9008 changeset: 14429:85b3975c9008 user: Timo Sirainen date: Thu Apr 19 18:22:39 2012 +0300 description: LMTP: Don't add Return-Path: header when proxying. The backend also adds it and we don't want duplicates. diffstat: src/lmtp/commands.c | 13 ++++++++++--- 1 files changed, 10 insertions(+), 3 deletions(-) diffs (30 lines): diff -r 782570f644f7 -r 85b3975c9008 src/lmtp/commands.c --- a/src/lmtp/commands.c Thu Apr 19 18:15:56 2012 +0300 +++ b/src/lmtp/commands.c Thu Apr 19 18:22:39 2012 +0300 @@ -416,6 +416,9 @@ } if (client->proxy != NULL) { + /* NOTE: if this restriction is ever removed, we'll also need + to send different message bodies to local and proxy + (with and without Return-Path: header) */ client_send_line(client, "451 4.3.0 <%s> " "Can't handle mixed proxy/non-proxy destinations", address); @@ -742,9 +745,13 @@ rcpt_to = rcpt->address; } - str_printfa(str, "Return-Path: <%s>\r\n", client->state.mail_from); - if (rcpt_to != NULL) - str_printfa(str, "Delivered-To: <%s>\r\n", rcpt_to); + /* don't set Return-Path when proxying so it won't get added twice */ + if (array_count(&client->state.rcpt_to) > 0) { + str_printfa(str, "Return-Path: <%s>\r\n", + client->state.mail_from); + if (rcpt_to != NULL) + str_printfa(str, "Delivered-To: <%s>\r\n", rcpt_to); + } str_printfa(str, "Received: from %s", client->lhlo); if ((host = net_ip2addr(&client->remote_ip)) != NULL) From dovecot at dovecot.org Thu Apr 19 18:59:38 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 19 Apr 2012 18:59:38 +0300 Subject: dovecot-2.1: raw storage: Name autocreated namespace as "raw-sto... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/90d7364b8c9d changeset: 14430:90d7364b8c9d user: Timo Sirainen date: Thu Apr 19 18:59:33 2012 +0300 description: raw storage: Name autocreated namespace as "raw-storage". diffstat: src/lib-storage/index/raw/raw-storage.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (11 lines): diff -r 85b3975c9008 -r 90d7364b8c9d src/lib-storage/index/raw/raw-storage.c --- a/src/lib-storage/index/raw/raw-storage.c Thu Apr 19 18:22:39 2012 +0300 +++ b/src/lib-storage/index/raw/raw-storage.c Thu Apr 19 18:59:33 2012 +0300 @@ -28,6 +28,7 @@ i_fatal("Raw user initialization failed: %s", error); ns_set = p_new(user->pool, struct mail_namespace_settings, 1); + ns_set->name = "raw-storage"; ns_set->location = ":LAYOUT=none"; ns_set->separator = "/"; From dovecot at dovecot.org Thu Apr 19 20:29:41 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 19 Apr 2012 20:29:41 +0300 Subject: dovecot-2.1: director: Increased timeouts. Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/110673e82868 changeset: 14431:110673e82868 user: Timo Sirainen date: Thu Apr 19 20:29:25 2012 +0300 description: director: Increased timeouts. diffstat: src/director/director-connection.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (18 lines): diff -r 90d7364b8c9d -r 110673e82868 src/director/director-connection.c --- a/src/director/director-connection.c Thu Apr 19 18:59:33 2012 +0300 +++ b/src/director/director-connection.c Thu Apr 19 20:29:25 2012 +0300 @@ -51,12 +51,12 @@ #define OUTBUF_FLUSH_THRESHOLD (1024*128) /* Max idling time before "ME" command must have been received, or we'll disconnect. */ -#define DIRECTOR_CONNECTION_ME_TIMEOUT_MSECS (2*1000) +#define DIRECTOR_CONNECTION_ME_TIMEOUT_MSECS (10*1000) /* Max idling time before "DONE" command must have been received, or we'll disconnect. */ #define DIRECTOR_CONNECTION_DONE_TIMEOUT_MSECS (30*1000) /* How long to wait for PONG for an idling connection */ -#define DIRECTOR_CONNECTION_PING_IDLE_TIMEOUT_MSECS (2*1000) +#define DIRECTOR_CONNECTION_PING_IDLE_TIMEOUT_MSECS (10*1000) /* Maximum time to wait for PONG reply */ #define DIRECTOR_CONNECTION_PONG_TIMEOUT_MSECS (60*1000) /* How long to wait to send PING when connection is idle */ From dovecot at dovecot.org Thu Apr 19 21:52:06 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 19 Apr 2012 21:52:06 +0300 Subject: dovecot-2.1: director: Optimized adding users to linked list dur... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/0b4295b48941 changeset: 14432:0b4295b48941 user: Timo Sirainen date: Thu Apr 19 21:51:48 2012 +0300 description: director: Optimized adding users to linked list during handshake. diffstat: src/director/Makefile.am | 20 ++++++- src/director/director-connection.c | 4 +- src/director/director-request.c | 2 +- src/director/director.c | 2 +- src/director/test-user-directory.c | 104 +++++++++++++++++++++++++++++++++++++ src/director/user-directory.c | 83 ++++++++++++++++++++++++---- src/director/user-directory.h | 3 +- 7 files changed, 199 insertions(+), 19 deletions(-) diffs (truncated from 327 to 300 lines): diff -r 110673e82868 -r 0b4295b48941 src/director/Makefile.am --- a/src/director/Makefile.am Thu Apr 19 20:29:25 2012 +0300 +++ b/src/director/Makefile.am Thu Apr 19 21:51:48 2012 +0300 @@ -4,6 +4,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/lib \ + -I$(top_srcdir)/src/lib-test \ -I$(top_srcdir)/src/lib-auth \ -I$(top_srcdir)/src/lib-imap \ -I$(top_srcdir)/src/lib-settings \ @@ -40,10 +41,27 @@ notify-connection.h \ user-directory.h -noinst_PROGRAMS = director-test +noinst_PROGRAMS = director-test $(test_programs) director_test_LDADD = $(LIBDOVECOT) director_test_DEPENDENCIES = $(LIBDOVECOT_DEPS) director_test_SOURCES = \ director-test.c + +test_programs = \ + test-user-directory + +test_libs = \ + ../lib-test/libtest.la \ + ../lib/liblib.la + +test_user_directory_SOURCES = test-user-directory.c +test_user_directory_LDADD = user-directory.o $(test_libs) +test_user_directory_DEPENDENCIES = user-directory.o $(test_libs) + +check: check-am check-test +check-test: all-am + for bin in $(test_programs); do \ + if ! $(RUN_TEST) ./$$bin; then exit 1; fi; \ + done diff -r 110673e82868 -r 0b4295b48941 src/director/director-connection.c --- a/src/director/director-connection.c Thu Apr 19 20:29:25 2012 +0300 +++ b/src/director/director-connection.c Thu Apr 19 21:51:48 2012 +0300 @@ -540,7 +540,7 @@ } if (director_user_refresh(conn, username_hash, - host, ioloop_time, FALSE, &user)) { + host, (time_t)-1, FALSE, &user)) { i_assert(!user->weak); director_update_user(conn->dir, conn->host, user); } @@ -674,7 +674,7 @@ } if (director_user_refresh(conn, username_hash, - host, ioloop_time, weak, &user)) { + host, (time_t)-1, weak, &user)) { if (!user->weak) director_update_user(conn->dir, src_host, user); else { diff -r 110673e82868 -r 0b4295b48941 src/director/director-request.c --- a/src/director/director-request.c Thu Apr 19 20:29:25 2012 +0300 +++ b/src/director/director-request.c Thu Apr 19 21:51:48 2012 +0300 @@ -225,7 +225,7 @@ return FALSE; } user = user_directory_add(dir->users, request->username_hash, - host, ioloop_time); + host, (time_t)-1); } i_assert(!user->weak); diff -r 110673e82868 -r 0b4295b48941 src/director/director.c --- a/src/director/director.c Thu Apr 19 20:29:25 2012 +0300 +++ b/src/director/director.c Thu Apr 19 21:51:48 2012 +0300 @@ -582,7 +582,7 @@ user = user_directory_lookup(dir->users, username_hash); if (user == NULL) { user = user_directory_add(dir->users, username_hash, - host, ioloop_time); + host, (time_t)-1); } else { if (user->host == host) { /* user is already in this host */ diff -r 110673e82868 -r 0b4295b48941 src/director/test-user-directory.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/director/test-user-directory.c Thu Apr 19 21:51:48 2012 +0300 @@ -0,0 +1,104 @@ +/* Copyright (c) 2012 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "ioloop.h" +#include "mail-user-hash.h" +#include "mail-host.h" +#include "user-directory.h" +#include "test-common.h" + +#include + +#define USER_DIR_TIMEOUT 1000000 + +unsigned int mail_user_hash(const char *username ATTR_UNUSED, + const char *format ATTR_UNUSED) { return 0; } + +static void +verify_user_directory(struct user_directory *dir, unsigned int user_count) +{ + struct user_directory_iter *iter; + struct user *user, *prev = NULL; + unsigned int prev_stamp = 0, iter_count = 0; + + iter = user_directory_iter_init(dir); + while ((user = user_directory_iter_next(iter)) != NULL) { + test_assert(prev_stamp <= user->timestamp); + test_assert(user->prev == prev); + test_assert(prev == NULL || user->prev->next == user); + + iter_count++; + prev = user; + } + test_assert(prev == NULL || prev->next == NULL); + user_directory_iter_deinit(&iter); + test_assert(iter_count == user_count); +} + +static void test_user_directory_ascending(void) +{ + const unsigned int count = 100000; + struct user_directory *dir; + struct mail_host *host = t_new(struct mail_host, 1); + unsigned int i; + + test_begin("user directory ascending"); + dir = user_directory_init(USER_DIR_TIMEOUT, "%u"); + user_directory_add(dir, 1, host, ioloop_time + count+1); + + for (i = 0; i < count; i++) + user_directory_add(dir, i+2, host, ioloop_time + i); + verify_user_directory(dir, count+1); + user_directory_deinit(&dir); + test_end(); +} + +static void test_user_directory_descending(void) +{ + const unsigned int count = 1000; + struct user_directory *dir; + struct mail_host *host = t_new(struct mail_host, 1); + unsigned int i; + + test_begin("user directory descending"); + dir = user_directory_init(USER_DIR_TIMEOUT, "%u"); + + for (i = 0; i < count; i++) + user_directory_add(dir, i+1, host, ioloop_time - i); + verify_user_directory(dir, count); + user_directory_deinit(&dir); + test_end(); +} + +static void test_user_directory_random(void) +{ + struct user_directory *dir; + struct mail_host *host = t_new(struct mail_host, 1); + time_t timestamp; + unsigned int i, count = 10000 + rand()%10000; + + test_begin("user directory random"); + dir = user_directory_init(USER_DIR_TIMEOUT, "%u"); + for (i = 0; i < count; i++) { + if (rand() % 10 == 0) + timestamp = (time_t)-1; + else + timestamp = ioloop_time-rand()%100; + user_directory_add(dir, i+1, host, timestamp); + } + verify_user_directory(dir, count); + user_directory_deinit(&dir); + test_end(); +} + +int main(void) +{ + static void (*test_functions[])(void) = { + test_user_directory_ascending, + test_user_directory_descending, + test_user_directory_random, + NULL + }; + ioloop_time = 1234567890; + return test_run(test_functions); +} diff -r 110673e82868 -r 0b4295b48941 src/director/user-directory.c --- a/src/director/user-directory.c Thu Apr 19 20:29:25 2012 +0300 +++ b/src/director/user-directory.c Thu Apr 19 21:51:48 2012 +0300 @@ -24,6 +24,7 @@ struct hash_table *hash; /* sorted by time */ struct user *head, *tail; + struct user *prev_insert_pos; ARRAY_DEFINE(iters, struct user_directory_iter *); @@ -42,6 +43,9 @@ if ((*iterp)->pos == user) (*iterp)->pos = user->next; } + + if (dir->prev_insert_pos == user) + dir->prev_insert_pos = user->next; } static void user_free(struct user_directory *dir, struct user *user) @@ -79,11 +83,61 @@ return hash_table_lookup(dir->hash, POINTER_CAST(username_hash)); } +static void +user_directory_insert_backwards(struct user_directory *dir, + struct user *pos, struct user *user) +{ + for (; pos != NULL; pos = pos->prev) { + if ((time_t)pos->timestamp <= user->timestamp) + break; + } + if (pos == NULL) + DLLIST2_PREPEND(&dir->head, &dir->tail, user); + else { + user->prev = pos; + user->next = pos->next; + user->prev->next = user; + if (user->next != NULL) + user->next->prev = user; + else + dir->tail = user; + } +} + +static void +user_directory_insert_forwards(struct user_directory *dir, + struct user *pos, struct user *user) +{ + for (; pos != NULL; pos = pos->next) { + if ((time_t)pos->timestamp >= user->timestamp) + break; + } + if (pos == NULL) + DLLIST2_APPEND(&dir->head, &dir->tail, user); + else { + user->prev = pos->prev; + user->next = pos; + if (user->prev != NULL) + user->prev->next = user; + else + dir->head = user; + user->next->prev = user; + } +} + struct user * user_directory_add(struct user_directory *dir, unsigned int username_hash, struct mail_host *host, time_t timestamp) { - struct user *user, *pos; + struct user *user; + + if (timestamp == (time_t)-1) { + /* make sure we add it at the end */ + timestamp = ioloop_time; + if (dir->tail != NULL && + timestamp < (time_t)dir->tail->timestamp) + timestamp = (time_t)dir->tail->timestamp; + } user = i_new(struct user, 1); user->username_hash = username_hash; @@ -94,21 +148,24 @@ if (dir->tail == NULL || (time_t)dir->tail->timestamp <= timestamp) DLLIST2_APPEND(&dir->head, &dir->tail, user); else { - /* need to insert to correct position */ - for (pos = dir->tail; pos != NULL; pos = pos->prev) { - if ((time_t)pos->timestamp <= timestamp) - break; - } - if (pos == NULL) - DLLIST2_PREPEND(&dir->head, &dir->tail, user); - else { - user->prev = pos; - user->next = pos->next; - user->prev->next = user; - user->next->prev = user; + /* need to insert to correct position. we should get here + only when handshaking. the handshaking USER requests should + come sorted by timestamp. so keep track of the previous + insert position, the next USER should be inserted after + it. */ + if (dir->prev_insert_pos == NULL) { + /* find the position starting from tail */ From dovecot at dovecot.org Thu Apr 19 22:17:45 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 19 Apr 2012 22:17:45 +0300 Subject: dovecot-2.1: director: Never set user's timestamp higher than ou... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/9104a9074a5a changeset: 14433:9104a9074a5a user: Timo Sirainen date: Thu Apr 19 22:17:34 2012 +0300 description: director: Never set user's timestamp higher than our ioloop_time. diffstat: src/director/user-directory.c | 9 +++++---- 1 files changed, 5 insertions(+), 4 deletions(-) diffs (20 lines): diff -r 0b4295b48941 -r 9104a9074a5a src/director/user-directory.c --- a/src/director/user-directory.c Thu Apr 19 21:51:48 2012 +0300 +++ b/src/director/user-directory.c Thu Apr 19 22:17:34 2012 +0300 @@ -132,11 +132,12 @@ struct user *user; if (timestamp == (time_t)-1) { - /* make sure we add it at the end */ + /* add it at the end */ timestamp = ioloop_time; - if (dir->tail != NULL && - timestamp < (time_t)dir->tail->timestamp) - timestamp = (time_t)dir->tail->timestamp; + } else { + /* make sure we don't add timestamps higher than ioloop time */ + if (timestamp > ioloop_time) + timestamp = ioloop_time; } user = i_new(struct user, 1); From dovecot at dovecot.org Thu Apr 19 23:07:06 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 19 Apr 2012 23:07:06 +0300 Subject: dovecot-2.1: Added t_strsplit_tab() Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/7eb9688c266f changeset: 14434:7eb9688c266f user: Timo Sirainen date: Thu Apr 19 23:00:16 2012 +0300 description: Added t_strsplit_tab() diffstat: src/lib/strfuncs.c | 41 ++++++++++++++++++++++++++++++++++++ src/lib/strfuncs.h | 2 + src/lib/test-strfuncs.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+), 0 deletions(-) diffs (136 lines): diff -r 9104a9074a5a -r 7eb9688c266f src/lib/strfuncs.c --- a/src/lib/strfuncs.c Thu Apr 19 22:17:34 2012 +0300 +++ b/src/lib/strfuncs.c Thu Apr 19 23:00:16 2012 +0300 @@ -463,6 +463,47 @@ return split_str(pool, data, separators, TRUE); } +const char **t_strsplit_tab(const char *data) +{ + const char **array; + char *dest; + unsigned int i, array_idx, array_size, dest_size; + + if (*data == '\0') + return t_new(const char *, 1); + + array_size = 1; + dest_size = 128; + dest = t_buffer_get(dest_size+1); + for (i = 0; data[i] != '\0'; i++) { + if (i >= dest_size) { + dest_size = nearest_power(dest_size+1); + dest = t_buffer_reget(dest, dest_size+1); + } + if (data[i] != '\t') + dest[i] = data[i]; + else { + dest[i] = '\0'; + array_size++; + } + } + i_assert(i <= dest_size); + dest[i] = '\0'; + t_buffer_alloc(i+1); + dest_size = i; + + array = t_new(const char *, array_size + 1); + array[0] = dest; array_idx = 1; + + for (i = 0; i < dest_size; i++) { + if (dest[i] == '\0') + array[array_idx++] = dest+i+1; + } + i_assert(array_idx == array_size); + array[array_idx] = NULL; + return array; +} + void p_strsplit_free(pool_t pool, char **arr) { p_free(pool, arr[0]); diff -r 9104a9074a5a -r 7eb9688c266f src/lib/strfuncs.h --- a/src/lib/strfuncs.h Thu Apr 19 22:17:34 2012 +0300 +++ b/src/lib/strfuncs.h Thu Apr 19 23:00:16 2012 +0300 @@ -66,6 +66,8 @@ const char **t_strsplit_spaces(const char *data, const char *separators) ATTR_MALLOC; void p_strsplit_free(pool_t pool, char **arr); +/* Optimized version of t_strsplit(data, "\t") */ +const char **t_strsplit_tab(const char *data); const char *dec2str(uintmax_t number); diff -r 9104a9074a5a -r 7eb9688c266f src/lib/test-strfuncs.c --- a/src/lib/test-strfuncs.c Thu Apr 19 22:17:34 2012 +0300 +++ b/src/lib/test-strfuncs.c Thu Apr 19 23:00:16 2012 +0300 @@ -2,6 +2,8 @@ #include "test-lib.h" +#include + static void test_p_strarray_dup(void) { const char *input[][3] = { @@ -27,7 +29,60 @@ test_end(); } +static void strsplit_verify(const char *str) +{ + T_BEGIN { + const char **s1, **s2; + unsigned int i; + + s1 = t_strsplit_tab(str); + s2 = t_strsplit(str, "\t"); + for (i = 0; s1[i] != NULL; i++) { + test_assert(s2[i] != NULL); + test_assert(strcmp(s1[i], s2[i]) == 0); + } + test_assert(s2[i] == NULL); + } T_END; +} + +static void test_t_strsplit_tab(void) +{ + char buf[4096]; + unsigned int i, j, max; + + test_begin("t_strsplit_tab"); + strsplit_verify(""); + strsplit_verify("\t"); + strsplit_verify("\t\t"); + strsplit_verify("foo"); + strsplit_verify("foo\tbar"); + strsplit_verify("foo\tbar\tbaz"); + strsplit_verify("foo\t\tbaz"); + buf[sizeof(buf)-1] = '\0'; + for (i = 0; i < sizeof(buf)-1; i++) + buf[i] = '\t'; + strsplit_verify(buf); + for (j = 0; j < 256; j++) { + memset(buf, '\t', j); + buf[j+1] = '\0'; + strsplit_verify(buf); + } + for (j = 0; j < 100; j++) { + max = (rand() % sizeof(buf)) + 1; + buf[--max] = '\0'; + for (i = 0; i < max; i++) { + if (rand() % 10 == 0) + buf[i] = '\t'; + else + buf[i] = 'x'; + } + strsplit_verify(buf); + } + test_end(); +} + void test_strfuncs(void) { test_p_strarray_dup(); + test_t_strsplit_tab(); } From dovecot at dovecot.org Thu Apr 19 23:07:07 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 19 Apr 2012 23:07:07 +0300 Subject: dovecot-2.1: Use t_strsplit_tab() wherever possible Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/fc8031c5e691 changeset: 14435:fc8031c5e691 user: Timo Sirainen date: Thu Apr 19 23:06:55 2012 +0300 description: Use t_strsplit_tab() wherever possible diffstat: src/anvil/anvil-connection.c | 2 +- src/auth/auth-master-connection.c | 6 +++--- src/auth/auth-request-handler.c | 4 ++-- src/auth/auth-stream.c | 2 +- src/auth/auth-worker-client.c | 2 +- src/auth/db-checkpassword.c | 2 +- src/auth/passdb-blocking.c | 2 +- src/auth/passdb-cache.c | 4 ++-- src/config/config-connection.c | 2 +- src/dict/dict-commands.c | 8 ++++---- src/director/director-connection.c | 2 +- src/director/director-test.c | 2 +- src/director/doveadm-connection.c | 4 ++-- src/director/login-connection.c | 2 +- src/doveadm/doveadm-director.c | 10 +++++----- src/doveadm/doveadm-penalty.c | 2 +- src/doveadm/doveadm-proxy.c | 2 +- src/doveadm/doveadm-who.c | 2 +- src/ipc/ipc-connection.c | 2 +- src/lib-auth/auth-master.c | 4 ++-- src/lib-auth/auth-server-connection.c | 2 +- src/lib-master/master-login-auth.c | 4 ++-- src/lib-master/master-login.c | 2 +- src/lib-master/master-service-settings.c | 2 +- src/login-common/login-proxy.c | 2 +- src/util/script-login.c | 2 +- 26 files changed, 40 insertions(+), 40 deletions(-) diffs (truncated from 438 to 300 lines): diff -r 7eb9688c266f -r fc8031c5e691 src/anvil/anvil-connection.c --- a/src/anvil/anvil-connection.c Thu Apr 19 23:00:16 2012 +0300 +++ b/src/anvil/anvil-connection.c Thu Apr 19 23:06:55 2012 +0300 @@ -40,7 +40,7 @@ const char *line; line = i_stream_next_line(conn->input); - return line == NULL ? NULL : t_strsplit(line, "\t"); + return line == NULL ? NULL : t_strsplit_tab(line); } static int diff -r 7eb9688c266f -r fc8031c5e691 src/auth/auth-master-connection.c --- a/src/auth/auth-master-connection.c Thu Apr 19 23:00:16 2012 +0300 +++ b/src/auth/auth-master-connection.c Thu Apr 19 23:06:55 2012 +0300 @@ -100,7 +100,7 @@ buffer_t buf; /* */ - list = t_strsplit(args, "\t"); + list = t_strsplit_tab(args); if (str_array_length(list) < 4 || str_to_uint(list[0], &id) < 0 || str_to_uint(list[1], &client_pid) < 0 || @@ -146,7 +146,7 @@ unsigned int id; /* [] */ - list = t_strsplit(args, "\t"); + list = t_strsplit_tab(args); if (list[0] == NULL || list[1] == NULL || str_to_uint(list[0], &id) < 0) { i_error("BUG: Master sent broken %s", cmd); @@ -485,7 +485,7 @@ unsigned int id; /* [] */ - list = t_strsplit(args, "\t"); + list = t_strsplit_tab(args); if (list[0] == NULL || str_to_uint(list[0], &id) < 0) { i_error("BUG: Master sent broken LIST"); return -1; diff -r 7eb9688c266f -r fc8031c5e691 src/auth/auth-request-handler.c --- a/src/auth/auth-request-handler.c Thu Apr 19 23:00:16 2012 +0300 +++ b/src/auth/auth-request-handler.c Thu Apr 19 23:06:55 2012 +0300 @@ -170,7 +170,7 @@ } } - fields = t_strsplit(extra_fields, "\t"); + fields = t_strsplit_tab(extra_fields); for (src = 0; fields[src] != NULL; src++) { if (strncmp(fields[src], "userdb_", 7) != 0) { if (!seen_pass && strncmp(fields[src], "pass=", 5) == 0) @@ -439,7 +439,7 @@ i_assert(!handler->destroyed); /* [...] */ - list = t_strsplit(args, "\t"); + list = t_strsplit_tab(args); if (list[0] == NULL || list[1] == NULL || str_to_uint(list[0], &id) < 0) { i_error("BUG: Authentication client %u " diff -r 7eb9688c266f -r fc8031c5e691 src/auth/auth-stream.c --- a/src/auth/auth-stream.c Thu Apr 19 23:00:16 2012 +0300 +++ b/src/auth/auth-stream.c Thu Apr 19 23:06:55 2012 +0300 @@ -140,7 +140,7 @@ const char *const *auth_stream_split(struct auth_stream_reply *reply) { - return t_strsplit(str_c(reply->str), "\t"); + return t_strsplit_tab(str_c(reply->str)); } string_t *auth_stream_reply_get_str(struct auth_stream_reply *reply) diff -r 7eb9688c266f -r fc8031c5e691 src/auth/auth-worker-client.c --- a/src/auth/auth-worker-client.c Thu Apr 19 23:00:16 2012 +0300 +++ b/src/auth/auth-worker-client.c Thu Apr 19 23:06:55 2012 +0300 @@ -547,7 +547,7 @@ unsigned int id; bool ret = FALSE; - args = t_strsplit(line, "\t"); + args = t_strsplit_tab(line); if (args[0] == NULL || args[1] == NULL || args[2] == NULL || str_to_uint(args[0], &id) < 0) { i_error("BUG: Invalid input: %s", line); diff -r 7eb9688c266f -r fc8031c5e691 src/auth/db-checkpassword.c --- a/src/auth/db-checkpassword.c Thu Apr 19 23:00:16 2012 +0300 +++ b/src/auth/db-checkpassword.c Thu Apr 19 23:06:55 2012 +0300 @@ -54,7 +54,7 @@ const char *const *tmp; const char *key, *p; - for (tmp = t_strsplit(extra_fields, "\t"); *tmp != NULL; tmp++) { + for (tmp = t_strsplit_tab(extra_fields); *tmp != NULL; tmp++) { key = t_str_ucase(t_strcut(*tmp, '=')); p = strchr(*tmp, '='); if (p == NULL) diff -r 7eb9688c266f -r fc8031c5e691 src/auth/passdb-blocking.c --- a/src/auth/passdb-blocking.c Thu Apr 19 23:00:16 2012 +0300 +++ b/src/auth/passdb-blocking.c Thu Apr 19 23:06:55 2012 +0300 @@ -30,7 +30,7 @@ enum passdb_result ret; const char *const *args; - args = t_strsplit(reply, "\t"); + args = t_strsplit_tab(reply); if (strcmp(*args, "OK") == 0 && args[1] != NULL && args[2] != NULL) { /* OK \t user \t password [\t extra] */ diff -r 7eb9688c266f -r fc8031c5e691 src/auth/passdb-cache.c --- a/src/auth/passdb-cache.c Thu Apr 19 23:00:16 2012 +0300 +++ b/src/auth/passdb-cache.c Thu Apr 19 23:06:55 2012 +0300 @@ -53,7 +53,7 @@ return TRUE; } - list = t_strsplit(value, "\t"); + list = t_strsplit_tab(value); cached_pw = list[0]; if (*cached_pw == '\0') { @@ -117,7 +117,7 @@ return TRUE; } - list = t_strsplit(value, "\t"); + list = t_strsplit_tab(value); auth_request_set_fields(request, list + 1, NULL); *result_r = PASSDB_RESULT_OK; diff -r 7eb9688c266f -r fc8031c5e691 src/config/config-connection.c --- a/src/config/config-connection.c Thu Apr 19 23:00:16 2012 +0300 +++ b/src/config/config-connection.c Thu Apr 19 23:06:55 2012 +0300 @@ -42,7 +42,7 @@ if (line == NULL) return NULL; - return t_strsplit(line, "\t"); + return t_strsplit_tab(line); } static void diff -r 7eb9688c266f -r fc8031c5e691 src/dict/dict-commands.c --- a/src/dict/dict-commands.c Thu Apr 19 23:00:16 2012 +0300 +++ b/src/dict/dict-commands.c Thu Apr 19 23:06:55 2012 +0300 @@ -90,7 +90,7 @@ return -1; } - args = t_strsplit(line, "\t"); + args = t_strsplit_tab(line); if (str_array_length(args) < 2 || str_to_uint(args[0], &flags) < 0) { i_error("dict client: ITERATE: broken input"); @@ -272,7 +272,7 @@ const char *const *args; /* */ - args = t_strsplit(line, "\t"); + args = t_strsplit_tab(line); if (str_array_length(args) != 3) { i_error("dict client: SET: broken input"); return -1; @@ -291,7 +291,7 @@ const char *const *args; /* */ - args = t_strsplit(line, "\t"); + args = t_strsplit_tab(line); if (str_array_length(args) != 2) { i_error("dict client: UNSET: broken input"); return -1; @@ -311,7 +311,7 @@ long long diff; /* */ - args = t_strsplit(line, "\t"); + args = t_strsplit_tab(line); if (str_array_length(args) != 3 || str_to_llong(args[2], &diff) < 0) { i_error("dict client: ATOMIC_INC: broken input"); diff -r 7eb9688c266f -r fc8031c5e691 src/director/director-connection.c --- a/src/director/director-connection.c Thu Apr 19 23:00:16 2012 +0300 +++ b/src/director/director-connection.c Thu Apr 19 23:06:55 2012 +0300 @@ -1169,7 +1169,7 @@ const char *cmd, *const *args; bool ret; - args = t_strsplit(line, "\t"); + args = t_strsplit_tab(line); cmd = args[0]; args++; if (cmd == NULL) { i_error("director(%s): Received empty line", conn->name); diff -r 7eb9688c266f -r fc8031c5e691 src/director/director-test.c --- a/src/director/director-test.c Thu Apr 19 23:00:16 2012 +0300 +++ b/src/director/director-test.c Thu Apr 19 23:06:55 2012 +0300 @@ -492,7 +492,7 @@ break; /* ip vhost-count user-count */ T_BEGIN { - const char *const *args = t_strsplit(line, "\t"); + const char *const *args = t_strsplit_tab(line); struct host *host; host = i_new(struct host, 1); diff -r 7eb9688c266f -r fc8031c5e691 src/director/doveadm-connection.c --- a/src/director/doveadm-connection.c Thu Apr 19 23:00:16 2012 +0300 +++ b/src/director/doveadm-connection.c Thu Apr 19 23:06:55 2012 +0300 @@ -137,7 +137,7 @@ struct ip_addr ip; unsigned int vhost_count = -1U; - args = t_strsplit(line, "\t"); + args = t_strsplit_tab(line); if (args[0] == NULL || net_addr2ip(args[0], &ip) < 0 || (args[1] != NULL && str_to_uint(args[1], &vhost_count) < 0)) { @@ -300,7 +300,7 @@ struct mail_host *host; struct ip_addr ip; - args = t_strsplit(line, "\t"); + args = t_strsplit_tab(line); if (args[0] == NULL || args[1] == NULL || net_addr2ip(args[1], &ip) < 0) { i_error("doveadm sent invalid USER-MOVE parameters: %s", line); diff -r 7eb9688c266f -r fc8031c5e691 src/director/login-connection.c --- a/src/director/login-connection.c Thu Apr 19 23:00:16 2012 +0300 +++ b/src/director/login-connection.c Thu Apr 19 23:06:55 2012 +0300 @@ -121,7 +121,7 @@ } /* OK [] */ - args = t_strsplit(line_params, "\t"); + args = t_strsplit_tab(line_params); if (*args != NULL) { /* we should always get here, but in case we don't just forward as-is and let login process handle the error. */ diff -r 7eb9688c266f -r fc8031c5e691 src/doveadm/doveadm-director.c --- a/src/doveadm/doveadm-director.c Thu Apr 19 23:00:16 2012 +0300 +++ b/src/doveadm/doveadm-director.c Thu Apr 19 23:06:55 2012 +0300 @@ -120,7 +120,7 @@ return; } - args = t_strsplit(line, "\t"); + args = t_strsplit_tab(line); if (str_array_length(args) != 4 || str_to_uint(args[1], &expires) < 0) { i_error("Invalid reply from director"); @@ -162,7 +162,7 @@ if (*line == '\0') break; T_BEGIN { - args = t_strsplit(line, "\t"); + args = t_strsplit_tab(line); if (str_array_length(args) >= 3) { doveadm_print(args[0]); doveadm_print(args[1]); @@ -315,7 +315,7 @@ if (*line == '\0') break; T_BEGIN { - args = t_strsplit(line, "\t"); + args = t_strsplit_tab(line); if (str_array_length(args) < 3 || str_to_uint(args[0], &user_hash) < 0 || str_to_uint(args[1], &expires) < 0 || @@ -559,7 +559,7 @@ if (*line == '\0') break; T_BEGIN { - args = t_strsplit(line, "\t"); + args = t_strsplit_tab(line); if (str_array_length(args) >= 2) { director_dump_cmd(ctx, "add", "%s %s", args[0], args[1]); @@ -599,7 +599,7 @@ if (*line == '\0') break; T_BEGIN { - args = t_strsplit(line, "\t"); + args = t_strsplit_tab(line); if (str_array_length(args) >= 4 && str_to_ulong(args[3], &l) == 0) { doveadm_print(args[0]); diff -r 7eb9688c266f -r fc8031c5e691 src/doveadm/doveadm-penalty.c --- a/src/doveadm/doveadm-penalty.c Thu Apr 19 23:00:16 2012 +0300 +++ b/src/doveadm/doveadm-penalty.c Thu Apr 19 23:06:55 2012 +0300 @@ -27,7 +27,7 @@ static void penalty_parse_line(const char *line, struct penalty_line *line_r) { - const char *const *args = t_strsplit(line, "\t"); + const char *const *args = t_strsplit_tab(line); const char *ident = args[0]; const char *penalty_str = args[1]; const char *last_penalty_str = args[2]; From dovecot at dovecot.org Thu Apr 19 23:42:13 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 19 Apr 2012 23:42:13 +0300 Subject: dovecot-2.1: director: Decreased timeout for resending lost SYNC... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/3acc1451ab56 changeset: 14436:3acc1451ab56 user: Timo Sirainen date: Thu Apr 19 23:34:41 2012 +0300 description: director: Decreased timeout for resending lost SYNC request. diffstat: src/director/director.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r fc8031c5e691 -r 3acc1451ab56 src/director/director.c --- a/src/director/director.c Thu Apr 19 23:06:55 2012 +0300 +++ b/src/director/director.c Thu Apr 19 23:34:41 2012 +0300 @@ -17,7 +17,7 @@ #define DIRECTOR_RECONNECT_TIMEOUT_MSECS (30*1000) #define DIRECTOR_USER_MOVE_TIMEOUT_MSECS (30*1000) #define DIRECTOR_USER_MOVE_FINISH_DELAY_MSECS (2*1000) -#define DIRECTOR_SYNC_TIMEOUT_MSECS (15*1000) +#define DIRECTOR_SYNC_TIMEOUT_MSECS (5*1000) static bool director_is_self_ip_set(struct director *dir) { From dovecot at dovecot.org Thu Apr 19 23:42:13 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 19 Apr 2012 23:42:13 +0300 Subject: dovecot-2.1: timeout_reset(): Don't use cached ioloop_timeval. Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/266521d59e2c changeset: 14437:266521d59e2c user: Timo Sirainen date: Thu Apr 19 23:41:59 2012 +0300 description: timeout_reset(): Don't use cached ioloop_timeval. Timeouts are sometimes reset after a long running callback. In those cases a cached timeval may be too far behind. diffstat: src/lib/ioloop.c | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diffs (13 lines): diff -r 3acc1451ab56 -r 266521d59e2c src/lib/ioloop.c --- a/src/lib/ioloop.c Thu Apr 19 23:34:41 2012 +0300 +++ b/src/lib/ioloop.c Thu Apr 19 23:41:59 2012 +0300 @@ -206,8 +206,7 @@ void timeout_reset(struct timeout *timeout) { - timeout_reset_timeval(timeout, timeout->ioloop->running ? NULL : - &ioloop_timeval); + timeout_reset_timeval(timeout, NULL); } static int timeout_get_wait_time(struct timeout *timeout, struct timeval *tv_r, From dovecot at dovecot.org Thu Apr 19 23:45:36 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 19 Apr 2012 23:45:36 +0300 Subject: dovecot-2.1: director: Don't delay reading input from remote con... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/25c941423e42 changeset: 14438:25c941423e42 user: Timo Sirainen date: Thu Apr 19 23:45:31 2012 +0300 description: director: Don't delay reading input from remote connection during handshake. diffstat: src/director/director-connection.c | 4 +--- 1 files changed, 1 insertions(+), 3 deletions(-) diffs (21 lines): diff -r 266521d59e2c -r 25c941423e42 src/director/director-connection.c --- a/src/director/director-connection.c Thu Apr 19 23:41:59 2012 +0300 +++ b/src/director/director-connection.c Thu Apr 19 23:45:31 2012 +0300 @@ -1282,9 +1282,6 @@ user_directory_iter_deinit(&conn->user_iter); director_connection_send(conn, "DONE\n"); - i_assert(conn->io == NULL); - conn->io = io_add(conn->fd, IO_READ, director_connection_input, conn); - ret = o_stream_flush(conn->output); timeout_reset(conn->to_ping); return ret; @@ -1365,6 +1362,7 @@ director_connection_output, conn); io_remove(&conn->io); + conn->io = io_add(conn->fd, IO_READ, director_connection_input, conn); o_stream_cork(conn->output); director_connection_send_handshake(conn); From dovecot at dovecot.org Thu Apr 19 23:51:51 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 19 Apr 2012 23:51:51 +0300 Subject: dovecot-2.1: director: Reverted previous change, it didn't work ... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/9ef4dee0792f changeset: 14439:9ef4dee0792f user: Timo Sirainen date: Thu Apr 19 23:51:46 2012 +0300 description: director: Reverted previous change, it didn't work properly. diffstat: src/director/director-connection.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diffs (21 lines): diff -r 25c941423e42 -r 9ef4dee0792f src/director/director-connection.c --- a/src/director/director-connection.c Thu Apr 19 23:45:31 2012 +0300 +++ b/src/director/director-connection.c Thu Apr 19 23:51:46 2012 +0300 @@ -1282,6 +1282,9 @@ user_directory_iter_deinit(&conn->user_iter); director_connection_send(conn, "DONE\n"); + i_assert(conn->io == NULL); + conn->io = io_add(conn->fd, IO_READ, director_connection_input, conn); + ret = o_stream_flush(conn->output); timeout_reset(conn->to_ping); return ret; @@ -1362,7 +1365,6 @@ director_connection_output, conn); io_remove(&conn->io); - conn->io = io_add(conn->fd, IO_READ, director_connection_input, conn); o_stream_cork(conn->output); director_connection_send_handshake(conn); From dovecot at dovecot.org Fri Apr 20 00:03:53 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 20 Apr 2012 00:03:53 +0300 Subject: dovecot-2.1: director: Improved error message Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/8245a97bf36c changeset: 14440:8245a97bf36c user: Timo Sirainen date: Fri Apr 20 00:03:47 2012 +0300 description: director: Improved error message diffstat: src/director/director-connection.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diffs (13 lines): diff -r 9ef4dee0792f -r 8245a97bf36c src/director/director-connection.c --- a/src/director/director-connection.c Thu Apr 19 23:51:46 2012 +0300 +++ b/src/director/director-connection.c Fri Apr 20 00:03:47 2012 +0300 @@ -134,6 +134,9 @@ if (!conn->connected) { i_error("director(%s): Connect timed out (%u secs)", conn->name, secs); + } else if (conn->io == NULL) { + i_error("director(%s): Sending handshake (%u secs)", + conn->name, secs); } else if (!conn->me_received) { i_error("director(%s): Handshaking ME timed out (%u secs)", conn->name, secs); From dovecot at dovecot.org Fri Apr 20 00:14:11 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 20 Apr 2012 00:14:11 +0300 Subject: dovecot-2.1: director: Increased timeout for sending USER data i... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/ea5b949a623b changeset: 14441:ea5b949a623b user: Timo Sirainen date: Fri Apr 20 00:13:55 2012 +0300 description: director: Increased timeout for sending USER data in handshake. diffstat: src/director/director-connection.c | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-) diffs (24 lines): diff -r 8245a97bf36c -r ea5b949a623b src/director/director-connection.c --- a/src/director/director-connection.c Fri Apr 20 00:03:47 2012 +0300 +++ b/src/director/director-connection.c Fri Apr 20 00:13:55 2012 +0300 @@ -52,6 +52,10 @@ /* Max idling time before "ME" command must have been received, or we'll disconnect. */ #define DIRECTOR_CONNECTION_ME_TIMEOUT_MSECS (10*1000) +/* Max time to wait for USERs in handshake to be sent. With a lot of users the + kernel may quickly eat up everything we send, while the receiver is busy + parsing the data. */ +#define DIRECTOR_CONNECTION_SEND_USERS_TIMEOUT_MSECS (120*1000) /* Max idling time before "DONE" command must have been received, or we'll disconnect. */ #define DIRECTOR_CONNECTION_DONE_TIMEOUT_MSECS (30*1000) @@ -1368,6 +1372,9 @@ director_connection_output, conn); io_remove(&conn->io); + timeout_remove(&conn->to_ping); + conn->to_ping = timeout_add(DIRECTOR_CONNECTION_SEND_USERS_TIMEOUT_MSECS, + director_connection_init_timeout, conn); o_stream_cork(conn->output); director_connection_send_handshake(conn); From dovecot at dovecot.org Fri Apr 20 00:32:46 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 20 Apr 2012 00:32:46 +0300 Subject: dovecot-2.1: director: Improved debug handshake message. Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/ee169584bc44 changeset: 14442:ee169584bc44 user: Timo Sirainen date: Fri Apr 20 00:32:34 2012 +0300 description: director: Improved debug handshake message. diffstat: src/director/director-connection.c | 10 ++++++++-- 1 files changed, 8 insertions(+), 2 deletions(-) diffs (20 lines): diff -r ea5b949a623b -r ee169584bc44 src/director/director-connection.c --- a/src/director/director-connection.c Fri Apr 20 00:13:55 2012 +0300 +++ b/src/director/director-connection.c Fri Apr 20 00:32:34 2012 +0300 @@ -866,8 +866,14 @@ { struct director *dir = conn->dir; - if (dir->debug) - i_debug("Handshaked to %s", conn->host->name); + if (dir->debug) { + unsigned int secs = time(NULL)-conn->created; + + i_debug("director(%s): Handshake took %u secs, " + "bytes in=%"PRIuUOFF_T" out=%"PRIuUOFF_T, + conn->name, secs, conn->input->v_offset, + conn->output->offset); + } /* the host is up now, make sure we can connect to it immediately if needed */ From dovecot at dovecot.org Fri Apr 20 00:33:17 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 20 Apr 2012 00:33:17 +0300 Subject: dovecot-2.1: director: Fixed protocol error detection/handling. Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/293ada796ae6 changeset: 14443:293ada796ae6 user: Timo Sirainen date: Fri Apr 20 00:33:13 2012 +0300 description: director: Fixed protocol error detection/handling. diffstat: src/director/director-connection.c | 30 +++++++++++++----------------- 1 files changed, 13 insertions(+), 17 deletions(-) diffs (86 lines): diff -r ee169584bc44 -r 293ada796ae6 src/director/director-connection.c --- a/src/director/director-connection.c Fri Apr 20 00:32:34 2012 +0300 +++ b/src/director/director-connection.c Fri Apr 20 00:33:13 2012 +0300 @@ -117,7 +117,7 @@ }; static void director_connection_disconnected(struct director_connection **conn); -static void director_connection_protocol_error(struct director_connection **conn); +static void director_connection_reconnect(struct director_connection **conn); static void ATTR_FORMAT(2, 3) director_cmd_error(struct director_connection *conn, const char *fmt, ...) @@ -128,6 +128,8 @@ i_error("director(%s): Command %s: %s (input: %s)", conn->name, conn->cur_cmd, t_strdup_vprintf(fmt, args), conn->cur_line); va_end(args); + + conn->host->last_protocol_failure = ioloop_time; } static void @@ -1133,10 +1135,8 @@ if (ret < 0) { /* invalid commands during handshake, we probably don't want to reconnect here */ - if (conn->dir->debug) { - i_debug("director(%s): Handshaking failed", - conn->host->name); - } + i_error("director(%s): Handshaking failed", + conn->name); return FALSE; } /* allow also other commands during handshake */ @@ -1185,7 +1185,7 @@ args = t_strsplit_tab(line); cmd = args[0]; args++; if (cmd == NULL) { - i_error("director(%s): Received empty line", conn->name); + director_cmd_error(conn, "Received empty line"); return FALSE; } @@ -1215,9 +1215,9 @@ return; case -2: /* buffer full */ - i_error("BUG: Director %s sent us more than %d bytes", - conn->name, MAX_INBUF_SIZE); - director_connection_protocol_error(&conn); + director_cmd_error(conn, "Director sent us more than %d bytes", + MAX_INBUF_SIZE); + director_connection_reconnect(&conn); return; } @@ -1228,11 +1228,9 @@ } T_END; if (!ret) { - if (dir->debug) { - i_debug("director(%s): Invalid input, disconnecting", - conn->name); - } - director_connection_protocol_error(&conn); + i_error("director(%s): Invalid input, disconnecting", + conn->name); + director_connection_reconnect(&conn); break; } } @@ -1480,13 +1478,11 @@ director_connect(dir); } -void director_connection_protocol_error(struct director_connection **_conn) +void director_connection_reconnect(struct director_connection **_conn) { struct director_connection *conn = *_conn; struct director *dir = conn->dir; - conn->host->last_protocol_failure = ioloop_time; - director_connection_deinit(_conn); if (dir->right == NULL) director_connect(dir); From dovecot at dovecot.org Fri Apr 20 00:42:40 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 20 Apr 2012 00:42:40 +0300 Subject: dovecot-2.1: director: Make sure handshaking doesn't get stuck s... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/d9f33d78fa3d changeset: 14444:d9f33d78fa3d user: Timo Sirainen date: Fri Apr 20 00:42:10 2012 +0300 description: director: Make sure handshaking doesn't get stuck sending USERs. diffstat: src/director/director-connection.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diffs (12 lines): diff -r 293ada796ae6 -r d9f33d78fa3d src/director/director-connection.c --- a/src/director/director-connection.c Fri Apr 20 00:33:13 2012 +0300 +++ b/src/director/director-connection.c Fri Apr 20 00:42:10 2012 +0300 @@ -1312,6 +1312,8 @@ o_stream_uncork(conn->output); if (ret < 0) director_connection_disconnected(&conn); + else + o_stream_set_flush_pending(conn->output, TRUE); return ret; } return o_stream_flush(conn->output); From dovecot at dovecot.org Fri Apr 20 00:49:39 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 20 Apr 2012 00:49:39 +0300 Subject: dovecot-2.1: director: Another fix for stuck handshake. Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/ce4e1bf7262d changeset: 14445:ce4e1bf7262d user: Timo Sirainen date: Fri Apr 20 00:49:29 2012 +0300 description: director: Another fix for stuck handshake. diffstat: src/director/director-connection.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diffs (13 lines): diff -r d9f33d78fa3d -r ce4e1bf7262d src/director/director-connection.c --- a/src/director/director-connection.c Fri Apr 20 00:42:10 2012 +0300 +++ b/src/director/director-connection.c Fri Apr 20 00:49:29 2012 +0300 @@ -1389,7 +1389,8 @@ director_connection_send(conn, str_c(str)); conn->user_iter = user_directory_iter_init(dir->users); - (void)director_connection_send_users(conn); + if (director_connection_send_users(conn) == 0) + o_stream_set_flush_pending(conn->output, TRUE); o_stream_uncork(conn->output); } From dovecot at dovecot.org Fri Apr 20 00:59:10 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 20 Apr 2012 00:59:10 +0300 Subject: dovecot-2.1: director: Removed unnecessary error messages. Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/0c3c4d098842 changeset: 14446:0c3c4d098842 user: Timo Sirainen date: Fri Apr 20 00:59:01 2012 +0300 description: director: Removed unnecessary error messages. diffstat: src/director/director-connection.c | 4 ---- 1 files changed, 0 insertions(+), 4 deletions(-) diffs (21 lines): diff -r ce4e1bf7262d -r 0c3c4d098842 src/director/director-connection.c --- a/src/director/director-connection.c Fri Apr 20 00:49:29 2012 +0300 +++ b/src/director/director-connection.c Fri Apr 20 00:59:01 2012 +0300 @@ -1135,8 +1135,6 @@ if (ret < 0) { /* invalid commands during handshake, we probably don't want to reconnect here */ - i_error("director(%s): Handshaking failed", - conn->name); return FALSE; } /* allow also other commands during handshake */ @@ -1228,8 +1226,6 @@ } T_END; if (!ret) { - i_error("director(%s): Invalid input, disconnecting", - conn->name); director_connection_reconnect(&conn); break; } From dovecot at dovecot.org Fri Apr 20 01:15:00 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 20 Apr 2012 01:15:00 +0300 Subject: dovecot-2.1: director: USER sending timeout was higher than it n... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/10f5456704a7 changeset: 14447:10f5456704a7 user: Timo Sirainen date: Fri Apr 20 01:14:41 2012 +0300 description: director: USER sending timeout was higher than it needed to be. The problem was USER sending getting stuck, not the timeout itself.. diffstat: src/director/director-connection.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 0c3c4d098842 -r 10f5456704a7 src/director/director-connection.c --- a/src/director/director-connection.c Fri Apr 20 00:59:01 2012 +0300 +++ b/src/director/director-connection.c Fri Apr 20 01:14:41 2012 +0300 @@ -55,7 +55,7 @@ /* Max time to wait for USERs in handshake to be sent. With a lot of users the kernel may quickly eat up everything we send, while the receiver is busy parsing the data. */ -#define DIRECTOR_CONNECTION_SEND_USERS_TIMEOUT_MSECS (120*1000) +#define DIRECTOR_CONNECTION_SEND_USERS_TIMEOUT_MSECS (30*1000) /* Max idling time before "DONE" command must have been received, or we'll disconnect. */ #define DIRECTOR_CONNECTION_DONE_TIMEOUT_MSECS (30*1000) From dovecot at dovecot.org Fri Apr 20 01:32:07 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 20 Apr 2012 01:32:07 +0300 Subject: dovecot-2.1: director: Adding 25c941423e42 patch yet again, now ... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/25ca6b6d754a changeset: 14448:25ca6b6d754a user: Timo Sirainen date: Fri Apr 20 01:32:01 2012 +0300 description: director: Adding 25c941423e42 patch yet again, now it seems to work right. And also fixes detection of outgoing connections that die during handshake sending. diffstat: src/director/director-connection.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diffs (12 lines): diff -r 10f5456704a7 -r 25ca6b6d754a src/director/director-connection.c --- a/src/director/director-connection.c Fri Apr 20 01:14:41 2012 +0300 +++ b/src/director/director-connection.c Fri Apr 20 01:32:01 2012 +0300 @@ -1374,6 +1374,8 @@ director_connection_output, conn); io_remove(&conn->io); + conn->io = io_add(conn->fd, IO_READ, director_connection_input, conn); + timeout_remove(&conn->to_ping); conn->to_ping = timeout_add(DIRECTOR_CONNECTION_SEND_USERS_TIMEOUT_MSECS, director_connection_init_timeout, conn); From dovecot at dovecot.org Fri Apr 20 01:35:11 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 20 Apr 2012 01:35:11 +0300 Subject: dovecot-2.1: director: And crashfix for previous change.. Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/5d169948b59d changeset: 14449:5d169948b59d user: Timo Sirainen date: Fri Apr 20 01:35:06 2012 +0300 description: director: And crashfix for previous change.. diffstat: src/director/director-connection.c | 3 --- 1 files changed, 0 insertions(+), 3 deletions(-) diffs (13 lines): diff -r 25ca6b6d754a -r 5d169948b59d src/director/director-connection.c --- a/src/director/director-connection.c Fri Apr 20 01:32:01 2012 +0300 +++ b/src/director/director-connection.c Fri Apr 20 01:35:06 2012 +0300 @@ -1289,9 +1289,6 @@ user_directory_iter_deinit(&conn->user_iter); director_connection_send(conn, "DONE\n"); - i_assert(conn->io == NULL); - conn->io = io_add(conn->fd, IO_READ, director_connection_input, conn); - ret = o_stream_flush(conn->output); timeout_reset(conn->to_ping); return ret; From dovecot at dovecot.org Fri Apr 20 11:22:48 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 20 Apr 2012 11:22:48 +0300 Subject: dovecot-2.1: director: Minor error message fix Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/58286c1e272d changeset: 14450:58286c1e272d user: Timo Sirainen date: Fri Apr 20 11:09:36 2012 +0300 description: director: Minor error message fix diffstat: src/director/director-connection.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 5d169948b59d -r 58286c1e272d src/director/director-connection.c --- a/src/director/director-connection.c Fri Apr 20 01:35:06 2012 +0300 +++ b/src/director/director-connection.c Fri Apr 20 11:09:36 2012 +0300 @@ -455,7 +455,7 @@ } if (user->to_move != NULL) str_append(str, ",moving"); - if (user->kill_state == USER_KILL_STATE_NONE) + if (user->kill_state != USER_KILL_STATE_NONE) str_printfa(str, ",kill_state=%d", user->kill_state); str_append_c(str, ')'); i_error("%s", str_c(str)); From dovecot at dovecot.org Fri Apr 20 11:22:48 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 20 Apr 2012 11:22:48 +0300 Subject: dovecot-2.1: director: Removed special (time_t)-1 code, it's not... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/45be27ff3414 changeset: 14451:45be27ff3414 user: Timo Sirainen date: Fri Apr 20 11:22:26 2012 +0300 description: director: Removed special (time_t)-1 code, it's not actually needed. Also this fixes a user refreshing issue. diffstat: src/director/director-connection.c | 4 ++-- src/director/director-request.c | 2 +- src/director/director.c | 2 +- src/director/test-user-directory.c | 2 +- src/director/user-directory.c | 9 ++------- src/director/user-directory.h | 3 +-- 6 files changed, 8 insertions(+), 14 deletions(-) diffs (90 lines): diff -r 58286c1e272d -r 45be27ff3414 src/director/director-connection.c --- a/src/director/director-connection.c Fri Apr 20 11:09:36 2012 +0300 +++ b/src/director/director-connection.c Fri Apr 20 11:22:26 2012 +0300 @@ -549,7 +549,7 @@ } if (director_user_refresh(conn, username_hash, - host, (time_t)-1, FALSE, &user)) { + host, ioloop_time, FALSE, &user)) { i_assert(!user->weak); director_update_user(conn->dir, conn->host, user); } @@ -683,7 +683,7 @@ } if (director_user_refresh(conn, username_hash, - host, (time_t)-1, weak, &user)) { + host, ioloop_time, weak, &user)) { if (!user->weak) director_update_user(conn->dir, src_host, user); else { diff -r 58286c1e272d -r 45be27ff3414 src/director/director-request.c --- a/src/director/director-request.c Fri Apr 20 11:09:36 2012 +0300 +++ b/src/director/director-request.c Fri Apr 20 11:22:26 2012 +0300 @@ -225,7 +225,7 @@ return FALSE; } user = user_directory_add(dir->users, request->username_hash, - host, (time_t)-1); + host, ioloop_time); } i_assert(!user->weak); diff -r 58286c1e272d -r 45be27ff3414 src/director/director.c --- a/src/director/director.c Fri Apr 20 11:09:36 2012 +0300 +++ b/src/director/director.c Fri Apr 20 11:22:26 2012 +0300 @@ -582,7 +582,7 @@ user = user_directory_lookup(dir->users, username_hash); if (user == NULL) { user = user_directory_add(dir->users, username_hash, - host, (time_t)-1); + host, ioloop_time); } else { if (user->host == host) { /* user is already in this host */ diff -r 58286c1e272d -r 45be27ff3414 src/director/test-user-directory.c --- a/src/director/test-user-directory.c Fri Apr 20 11:09:36 2012 +0300 +++ b/src/director/test-user-directory.c Fri Apr 20 11:22:26 2012 +0300 @@ -81,7 +81,7 @@ dir = user_directory_init(USER_DIR_TIMEOUT, "%u"); for (i = 0; i < count; i++) { if (rand() % 10 == 0) - timestamp = (time_t)-1; + timestamp = ioloop_time; else timestamp = ioloop_time-rand()%100; user_directory_add(dir, i+1, host, timestamp); diff -r 58286c1e272d -r 45be27ff3414 src/director/user-directory.c --- a/src/director/user-directory.c Fri Apr 20 11:09:36 2012 +0300 +++ b/src/director/user-directory.c Fri Apr 20 11:22:26 2012 +0300 @@ -131,14 +131,9 @@ { struct user *user; - if (timestamp == (time_t)-1) { - /* add it at the end */ + /* make sure we don't add timestamps higher than ioloop time */ + if (timestamp > ioloop_time) timestamp = ioloop_time; - } else { - /* make sure we don't add timestamps higher than ioloop time */ - if (timestamp > ioloop_time) - timestamp = ioloop_time; - } user = i_new(struct user, 1); user->username_hash = username_hash; diff -r 58286c1e272d -r 45be27ff3414 src/director/user-directory.h --- a/src/director/user-directory.h Fri Apr 20 11:09:36 2012 +0300 +++ b/src/director/user-directory.h Fri Apr 20 11:22:26 2012 +0300 @@ -54,8 +54,7 @@ /* Look up username from directory. Returns NULL if not found. */ struct user *user_directory_lookup(struct user_directory *dir, unsigned int username_hash); -/* Add a user to directory and return it. If timestamp is (time_t)-1, - the current time is used. */ +/* Add a user to directory and return it. */ struct user * user_directory_add(struct user_directory *dir, unsigned int username_hash, struct mail_host *host, time_t timestamp); From dovecot at dovecot.org Fri Apr 20 15:05:12 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 20 Apr 2012 15:05:12 +0300 Subject: dovecot-2.1: director: When another director reconnects, reset i... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/798b5e1609e5 changeset: 14452:798b5e1609e5 user: Timo Sirainen date: Fri Apr 20 15:04:58 2012 +0300 description: director: When another director reconnects, reset its "last received seq". This fixes some problems where HOST updates and others were thought as already being received after the originating director was restarted. diffstat: src/director/director-connection.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diffs (12 lines): diff -r 45be27ff3414 -r 798b5e1609e5 src/director/director-connection.c --- a/src/director/director-connection.c Fri Apr 20 11:22:26 2012 +0300 +++ b/src/director/director-connection.c Fri Apr 20 15:04:58 2012 +0300 @@ -571,6 +571,8 @@ /* already have this. just reset its last_network_failure timestamp, since it might be up now. */ host->last_network_failure = 0; + /* it also may have been restarted, so reset last_seq */ + host->last_seq = 0; return TRUE; } From dovecot at dovecot.org Fri Apr 20 15:26:56 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 20 Apr 2012 15:26:56 +0300 Subject: dovecot-2.1: layout=fs: Don't assume '/' hierarchy separator whe... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/a41f64348d0d changeset: 14453:a41f64348d0d user: Timo Sirainen date: Fri Apr 20 15:18:14 2012 +0300 description: layout=fs: Don't assume '/' hierarchy separator when finding mailbox roots. diffstat: src/lib-storage/list/mailbox-list-fs-iter.c | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diffs (24 lines): diff -r 798b5e1609e5 -r a41f64348d0d src/lib-storage/list/mailbox-list-fs-iter.c --- a/src/lib-storage/list/mailbox-list-fs-iter.c Fri Apr 20 15:04:58 2012 +0300 +++ b/src/lib-storage/list/mailbox-list-fs-iter.c Fri Apr 20 15:18:14 2012 +0300 @@ -373,6 +373,7 @@ { bool full_fs_access = ctx->ctx.list->mail_set->mail_full_filesystem_access; + char ns_sep = mail_namespace_get_sep(ctx->ctx.list->ns); const char *const *patterns, *pattern, *const *parentp, *const *childp; const char *p, *last, *root; unsigned int i, parentlen; @@ -387,10 +388,10 @@ for (p = last = pattern; *p != '\0'; p++) { if (*p == '%' || *p == '*') break; - if (*p == '/') + if (*p == ns_sep) last = p; } - if (p == last+1 && *pattern == '/') + if (p == last+1 && *pattern == ns_sep) root = "/"; else { root = mailbox_list_get_storage_name(ctx->ctx.list, From dovecot at dovecot.org Fri Apr 20 15:26:56 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 20 Apr 2012 15:26:56 +0300 Subject: dovecot-2.1: layout=fs: Fixed listing mailboxes with prefix=INBOX/ Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/8d0b71fb3e49 changeset: 14454:8d0b71fb3e49 user: Timo Sirainen date: Fri Apr 20 15:26:43 2012 +0300 description: layout=fs: Fixed listing mailboxes with prefix=INBOX/ diffstat: src/lib-storage/list/mailbox-list-fs-iter.c | 18 ++++++++++++++---- 1 files changed, 14 insertions(+), 4 deletions(-) diffs (41 lines): diff -r a41f64348d0d -r 8d0b71fb3e49 src/lib-storage/list/mailbox-list-fs-iter.c --- a/src/lib-storage/list/mailbox-list-fs-iter.c Fri Apr 20 15:18:14 2012 +0300 +++ b/src/lib-storage/list/mailbox-list-fs-iter.c Fri Apr 20 15:26:43 2012 +0300 @@ -371,11 +371,12 @@ static void fs_list_get_roots(struct fs_list_iterate_context *ctx) { + struct mail_namespace *ns = ctx->ctx.list->ns; + char ns_sep = mail_namespace_get_sep(ns); bool full_fs_access = ctx->ctx.list->mail_set->mail_full_filesystem_access; - char ns_sep = mail_namespace_get_sep(ctx->ctx.list->ns); const char *const *patterns, *pattern, *const *parentp, *const *childp; - const char *p, *last, *root; + const char *p, *last, *root, *prefix_vname; unsigned int i, parentlen; i_assert(*ctx->valid_patterns != NULL); @@ -391,11 +392,20 @@ if (*p == ns_sep) last = p; } + prefix_vname = t_strdup_until(pattern, last); + if (p == last+1 && *pattern == ns_sep) root = "/"; - else { + else if ((ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0 && + strcasecmp(prefix_vname, "INBOX") == 0 && + strncasecmp(ns->prefix, pattern, ns->prefix_len) == 0) { + /* special case: Namespace prefix is INBOX/ and + we just want to see its contents (not the + INBOX's children). */ + root = ""; + } else { root = mailbox_list_get_storage_name(ctx->ctx.list, - t_strdup_until(pattern, last)); + prefix_vname); } if (*root == '/') { From dovecot at dovecot.org Fri Apr 20 19:13:13 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 20 Apr 2012 19:13:13 +0300 Subject: dovecot-2.1: director: Director ring needs to be set unsynced im... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/a5b7dda1db6d changeset: 14455:a5b7dda1db6d user: Timo Sirainen date: Fri Apr 20 19:03:26 2012 +0300 description: director: Director ring needs to be set unsynced immediately even when sycning is frozen. diffstat: src/director/director.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diffs (25 lines): diff -r 8d0b71fb3e49 -r a5b7dda1db6d src/director/director.c --- a/src/director/director.c Fri Apr 20 15:26:43 2012 +0300 +++ b/src/director/director.c Fri Apr 20 19:03:26 2012 +0300 @@ -323,6 +323,10 @@ static void director_sync(struct director *dir) { + /* we're synced again when we receive this SYNC back */ + dir->sync_seq++; + director_set_ring_unsynced(dir); + if (dir->sync_frozen) { dir->sync_pending = TRUE; return; @@ -333,10 +337,6 @@ return; } - /* we're synced again when we receive this SYNC back */ - dir->sync_seq++; - director_set_ring_unsynced(dir); - if (dir->debug) { i_debug("Ring is desynced (seq=%u, sending SYNC to %s)", dir->sync_seq, dir->right == NULL ? "(nowhere)" : From dovecot at dovecot.org Fri Apr 20 19:13:13 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 20 Apr 2012 19:13:13 +0300 Subject: dovecot-2.1: director: Try harder to connect to ring before thin... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/f880cf0efa0a changeset: 14456:f880cf0efa0a user: Timo Sirainen date: Fri Apr 20 19:05:38 2012 +0300 description: director: Try harder to connect to ring before thinking we're alone. diffstat: src/director/director.c | 80 +++++++++++++++++++++++++++++++++--------------- src/director/director.h | 2 + 2 files changed, 56 insertions(+), 26 deletions(-) diffs (127 lines): diff -r a5b7dda1db6d -r f880cf0efa0a src/director/director.c --- a/src/director/director.c Fri Apr 20 19:03:26 2012 +0300 +++ b/src/director/director.c Fri Apr 20 19:05:38 2012 +0300 @@ -18,6 +18,8 @@ #define DIRECTOR_USER_MOVE_TIMEOUT_MSECS (30*1000) #define DIRECTOR_USER_MOVE_FINISH_DELAY_MSECS (2*1000) #define DIRECTOR_SYNC_TIMEOUT_MSECS (5*1000) +#define DIRECTOR_RING_MIN_WAIT_SECS 20 +#define DIRECTOR_QUICK_RECONNECT_TIMEOUT_MSECS 1000 static bool director_is_self_ip_set(struct director *dir) { @@ -138,6 +140,30 @@ return hosts[(self_idx + 1) % count]; } +static bool director_wait_for_others(struct director *dir) +{ + struct director_host *const *hostp; + + /* don't assume we're alone until we've attempted to connect + to others for a while */ + if (dir->ring_first_alone != 0 && + ioloop_time - dir->ring_first_alone > DIRECTOR_RING_MIN_WAIT_SECS) + return FALSE; + + if (dir->ring_first_alone == 0) + dir->ring_first_alone = ioloop_time; + /* reset all failures and try again */ + array_foreach(&dir->dir_hosts, hostp) { + (*hostp)->last_network_failure = 0; + (*hostp)->last_protocol_failure = 0; + } + if (dir->to_reconnect != NULL) + timeout_remove(&dir->to_reconnect); + dir->to_reconnect = timeout_add(DIRECTOR_QUICK_RECONNECT_TIMEOUT_MSECS, + director_connect, dir); + return TRUE; +} + void director_connect(struct director *dir) { struct director_host *const *hosts; @@ -163,26 +189,30 @@ continue; } - if (director_connect_host(dir, hosts[idx]) == 0) - break; + if (director_connect_host(dir, hosts[idx]) == 0) { + /* success */ + return; + } } - if (i == count) { - /* we're the only one */ - if (dir->debug) { - i_debug("director: Couldn't connect to right side, " - "we must be the only director left"); - } - if (dir->left != NULL) { - /* since we couldn't connect to it, - it must have failed recently */ - director_connection_deinit(&dir->left); - } - dir->ring_min_version = DIRECTOR_VERSION_MINOR; - if (!dir->ring_handshaked) - director_set_ring_handshaked(dir); - else - director_set_ring_synced(dir); + + if (count > 1 && director_wait_for_others(dir)) + return; + + /* we're the only one */ + if (count > 1) { + i_warning("director: Couldn't connect to right side, " + "we must be the only director left"); } + if (dir->left != NULL) { + /* since we couldn't connect to it, + it must have failed recently */ + director_connection_deinit(&dir->left); + } + dir->ring_min_version = DIRECTOR_VERSION_MINOR; + if (!dir->ring_handshaked) + director_set_ring_handshaked(dir); + else + director_set_ring_synced(dir); } void director_set_ring_handshaked(struct director *dir) @@ -238,16 +268,14 @@ host = dir->right == NULL ? NULL : director_connection_get_host(dir->right); + + if (dir->to_reconnect != NULL) + timeout_remove(&dir->to_reconnect); if (host != director_get_preferred_right_host(dir)) { /* try to reconnect to preferred host later */ - if (dir->to_reconnect == NULL) { - dir->to_reconnect = - timeout_add(DIRECTOR_RECONNECT_TIMEOUT_MSECS, - director_reconnect_timeout, dir); - } - } else { - if (dir->to_reconnect != NULL) - timeout_remove(&dir->to_reconnect); + dir->to_reconnect = + timeout_add(DIRECTOR_RECONNECT_TIMEOUT_MSECS, + director_reconnect_timeout, dir); } if (dir->left != NULL) diff -r a5b7dda1db6d -r f880cf0efa0a src/director/director.h --- a/src/director/director.h Fri Apr 20 19:03:26 2012 +0300 +++ b/src/director/director.h Fri Apr 20 19:05:38 2012 +0300 @@ -65,6 +65,8 @@ unsigned int ring_min_version; time_t ring_last_sync_time; + time_t ring_first_alone; + /* director ring handshaking is complete. director can start serving clients. */ unsigned int ring_handshaked:1; From dovecot at dovecot.org Fri Apr 20 19:13:13 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 20 Apr 2012 19:13:13 +0300 Subject: dovecot-2.1: director: Forward DIRECTOR commands to other connec... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/1856e9085f94 changeset: 14457:1856e9085f94 user: Timo Sirainen date: Fri Apr 20 19:08:25 2012 +0300 description: director: Forward DIRECTOR commands to other connected directors. They can use it to realize that the director was restarted and its sequences start from 1. diffstat: src/director/director-connection.c | 29 +++++++++++++++++++++-------- 1 files changed, 21 insertions(+), 8 deletions(-) diffs (49 lines): diff -r f880cf0efa0a -r 1856e9085f94 src/director/director-connection.c --- a/src/director/director-connection.c Fri Apr 20 19:05:38 2012 +0300 +++ b/src/director/director-connection.c Fri Apr 20 19:08:25 2012 +0300 @@ -562,24 +562,37 @@ struct director_host *host; struct ip_addr ip; unsigned int port; + bool forward = FALSE; if (!director_args_parse_ip_port(conn, args, &ip, &port)) return FALSE; host = director_host_lookup(conn->dir, &ip, port); if (host != NULL) { + if (host == conn->dir->self_host) { + /* ignore updates to ourself */ + return TRUE; + } + /* already have this. just reset its last_network_failure timestamp, since it might be up now. */ host->last_network_failure = 0; - /* it also may have been restarted, so reset last_seq */ - host->last_seq = 0; - return TRUE; + if (host->last_seq != 0) { + /* it also may have been restarted, reset last_seq */ + host->last_seq = 0; + forward = TRUE; + } + } else { + /* save the director and forward it */ + director_host_add(conn->dir, &ip, port); + forward = TRUE; } - - /* save the director and forward it */ - director_host_add(conn->dir, &ip, port); - director_update_send(conn->dir, director_connection_get_host(conn), - t_strdup_printf("DIRECTOR\t%s\t%u\n", net_ip2addr(&ip), port)); + if (forward) { + director_update_send(conn->dir, + director_connection_get_host(conn), + t_strdup_printf("DIRECTOR\t%s\t%u\n", + net_ip2addr(&ip), port)); + } return TRUE; } From dovecot at dovecot.org Fri Apr 20 19:13:13 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 20 Apr 2012 19:13:13 +0300 Subject: dovecot-2.1: director: Delay disconnecting director after sendin... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/d27b743c9921 changeset: 14458:d27b743c9921 user: Timo Sirainen date: Fri Apr 20 19:09:55 2012 +0300 description: director: Delay disconnecting director after sending CONNECT command. The director may not otherwise read the CONNECT. diffstat: src/director/director-connection.c | 47 +++++++++++++++++++++++++------------ 1 files changed, 32 insertions(+), 15 deletions(-) diffs (143 lines): diff -r 1856e9085f94 -r d27b743c9921 src/director/director-connection.c --- a/src/director/director-connection.c Fri Apr 20 19:08:25 2012 +0300 +++ b/src/director/director-connection.c Fri Apr 20 19:09:55 2012 +0300 @@ -70,6 +70,7 @@ /* If outgoing director connection exists for less than this many seconds, mark the host as failed so we won't try to reconnect to it immediately */ #define DIRECTOR_SUCCESS_MIN_CONNECT_SECS 40 +#define DIRECTOR_WAIT_DISCONNECT_MSECS 10 #if DIRECTOR_CONNECTION_DONE_TIMEOUT_MSECS <= DIRECTOR_CONNECTION_PING_TIMEOUT_MSECS # error DIRECTOR_CONNECTION_DONE_TIMEOUT_MSECS is too low @@ -96,7 +97,7 @@ struct io *io; struct istream *input; struct ostream *output; - struct timeout *to, *to_ping, *to_pong; + struct timeout *to_disconnect, *to_ping, *to_pong; struct user_directory_iter *user_iter; @@ -166,16 +167,28 @@ conn->to_ping = timeout_add(msecs, director_connection_ping, conn); } +static void director_connection_wait_timeout(struct director_connection *conn) +{ + director_connection_deinit(&conn); +} + static void director_connection_send_connect(struct director_connection *conn, struct director_host *host) { const char *connect_str; + if (conn->to_disconnect != NULL) + return; + connect_str = t_strdup_printf("CONNECT\t%s\t%u\n", net_ip2addr(&host->ip), host->port); director_connection_send(conn, connect_str); (void)o_stream_flush(conn->output); o_stream_uncork(conn->output); + + conn->to_disconnect = + timeout_add(DIRECTOR_WAIT_DISCONNECT_MSECS, + director_connection_wait_timeout, conn); } static void director_connection_assigned(struct director_connection *conn) @@ -226,7 +239,7 @@ "us, should use %s instead", conn->name, dir->left->host->name); director_connection_send_connect(conn, dir->left->host); - return FALSE; + return TRUE; } else { /* this new connection is the correct one, but wait until the old connection gets disconnected before using this one. @@ -249,7 +262,8 @@ array_foreach(&dir->connections, connp) { conn = *connp; - if (conn->in && conn->handshake_received && conn != dir->left) { + if (conn->in && conn->handshake_received && + conn->to_disconnect == NULL && conn != dir->left) { /* either use this or disconnect it */ if (!director_connection_assign_left(conn)) { /* we don't want this */ @@ -266,7 +280,7 @@ struct director_connection *const *connp; array_foreach(&dir->connections, connp) { - if (!(*connp)->in) + if (!(*connp)->in && (*connp)->to_disconnect == NULL) return TRUE; } return FALSE; @@ -1104,15 +1118,13 @@ conn = *connp; if (conn->in && conn != dir->left && conn->me_received && + conn->to_disconnect == NULL && director_host_cmp_to_self(dir->left->host, conn->host, dir->self_host) < 0) { i_warning("Director connection %s tried to connect to " "us, should use %s instead", conn->name, dir->left->host->name); director_connection_send_connect(conn, dir->left->host); - director_connection_deinit(&conn); - director_disconnect_wrong_lefts(dir); - return; } } } @@ -1234,6 +1246,17 @@ return; } + if (conn->to_disconnect != NULL) { + /* just read everything the remote sends, and wait for it + to disconnect. we mainly just want the remote to read the + CONNECT we sent it. */ + size_t size; + + (void)i_stream_get_data(conn->input, &size); + i_stream_skip(conn->input, size); + return; + } + director_sync_freeze(dir); while ((line = i_stream_next_line(conn->input)) != NULL) { T_BEGIN { @@ -1451,8 +1474,8 @@ if (conn->user_iter != NULL) user_directory_iter_deinit(&conn->user_iter); - if (conn->to != NULL) - timeout_remove(&conn->to); + if (conn->to_disconnect != NULL) + timeout_remove(&conn->to_disconnect); if (conn->to_pong != NULL) timeout_remove(&conn->to_pong); timeout_remove(&conn->to_ping); @@ -1501,11 +1524,6 @@ director_connect(dir); } -static void director_connection_timeout(struct director_connection *conn) -{ - director_connection_disconnected(&conn); -} - void director_connection_send(struct director_connection *conn, const char *data) { @@ -1524,7 +1542,6 @@ "disconnecting", conn->name); } o_stream_close(conn->output); - conn->to = timeout_add(0, director_connection_timeout, conn); } } From dovecot at dovecot.org Fri Apr 20 22:27:12 2012 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 20 Apr 2012 22:27:12 +0300 Subject: dovecot-2.1: imapc: Added imapc_list_prefix setting to limit wha... Message-ID: details: http://hg.dovecot.org/dovecot-2.1/rev/03f44d61d582 changeset: 14459:03f44d61d582 user: Timo Sirainen date: Fri Apr 20 22:27:01 2012 +0300 description: imapc: Added imapc_list_prefix setting to limit what mailboxes are accessed. diffstat: src/lib-storage/index/imapc/imapc-list.c | 49 +++++++++++++++++++++++++-- src/lib-storage/index/imapc/imapc-settings.c | 2 + src/lib-storage/index/imapc/imapc-settings.h | 1 + 3 files changed, 47 insertions(+), 5 deletions(-) diffs (124 lines): diff -r d27b743c9921 -r 03f44d61d582 src/lib-storage/index/imapc/imapc-list.c --- a/src/lib-storage/index/imapc/imapc-list.c Fri Apr 20 19:09:55 2012 +0300 +++ b/src/lib-storage/index/imapc/imapc-list.c Fri Apr 20 22:27:01 2012 +0300 @@ -92,7 +92,7 @@ T_BEGIN { const char *vname = - mailbox_list_default_get_vname(&list->list, name); + mailbox_list_get_vname(&list->list, name); if ((info_flags & MAILBOX_NONEXISTENT) != 0) node = mailbox_tree_lookup(tree, vname); @@ -191,6 +191,37 @@ return list->sep; } +static const char * +imapc_list_get_storage_name(struct mailbox_list *_list, const char *vname) +{ + struct imapc_mailbox_list *list = (struct imapc_mailbox_list *)_list; + const char *prefix = list->storage->set->imapc_list_prefix; + const char *storage_name; + + storage_name = mailbox_list_default_get_storage_name(_list, vname); + if (*prefix != '\0') { + storage_name = t_strdup_printf("%s%c%s", prefix, list->sep, + storage_name); + } + return storage_name; +} + +static const char * +imapc_list_get_vname(struct mailbox_list *_list, const char *storage_name) +{ + struct imapc_mailbox_list *list = (struct imapc_mailbox_list *)_list; + const char *prefix = list->storage->set->imapc_list_prefix; + unsigned int prefix_len; + + if (*prefix != '\0') { + prefix_len = strlen(prefix); + i_assert(strncmp(prefix, storage_name, prefix_len) == 0 && + storage_name[prefix_len] == list->sep); + storage_name += prefix_len+1; + } + return mailbox_list_default_get_vname(_list, storage_name); +} + static struct mailbox_list *imapc_list_get_fs(struct imapc_mailbox_list *list) { struct mailbox_list_settings list_set; @@ -313,14 +344,22 @@ { struct imapc_command *cmd; struct imapc_simple_context ctx; + const char *pattern; i_assert(list->sep != '\0'); if (list->refreshed_mailboxes) return 0; + if (*list->storage->set->imapc_list_prefix == '\0') + pattern = "*"; + else { + pattern = t_strdup_printf("%s%c*", + list->storage->set->imapc_list_prefix, list->sep); + } + cmd = imapc_list_simple_context_init(&ctx, list); - imapc_command_send(cmd, "LIST \"\" *"); + imapc_command_sendf(cmd, "LIST \"\" %s", pattern); mailbox_tree_deinit(&list->mailboxes); list->mailboxes = mailbox_tree_init(list->sep); @@ -611,7 +650,7 @@ i_assert(list->sep != '\0'); - vname = mailbox_list_default_get_vname(_list, name); + vname = mailbox_list_get_vname(_list, name); if (!list->refreshed_mailboxes) { node = mailbox_tree_lookup(list->mailboxes, vname); if (node != NULL) @@ -646,8 +685,8 @@ imapc_is_valid_existing_name, imapc_is_valid_create_name, imapc_list_get_hierarchy_sep, - mailbox_list_default_get_vname, - mailbox_list_default_get_storage_name, + imapc_list_get_vname, + imapc_list_get_storage_name, imapc_list_get_path, imapc_list_get_temp_prefix, imapc_list_join_refpattern, diff -r d27b743c9921 -r 03f44d61d582 src/lib-storage/index/imapc/imapc-settings.c --- a/src/lib-storage/index/imapc/imapc-settings.c Fri Apr 20 19:09:55 2012 +0300 +++ b/src/lib-storage/index/imapc/imapc-settings.c Fri Apr 20 22:27:01 2012 +0300 @@ -27,6 +27,7 @@ DEF(SET_STR, imapc_features), DEF(SET_STR, imapc_rawlog_dir), + DEF(SET_STR, imapc_list_prefix), DEF(SET_STR, ssl_crypto_device), SETTING_DEFINE_LIST_END @@ -46,6 +47,7 @@ .imapc_features = "", .imapc_rawlog_dir = "", + .imapc_list_prefix = "", .ssl_crypto_device = "" }; diff -r d27b743c9921 -r 03f44d61d582 src/lib-storage/index/imapc/imapc-settings.h --- a/src/lib-storage/index/imapc/imapc-settings.h Fri Apr 20 19:09:55 2012 +0300 +++ b/src/lib-storage/index/imapc/imapc-settings.h Fri Apr 20 22:27:01 2012 +0300 @@ -22,6 +22,7 @@ const char *imapc_features; const char *imapc_rawlog_dir; + const char *imapc_list_prefix; const char *ssl_crypto_device; enum imapc_features parsed_features; From pigeonhole at rename-it.nl Sun Apr 22 12:30:37 2012 From: pigeonhole at rename-it.nl (pigeonhole at rename-it.nl) Date: Sun, 22 Apr 2012 11:30:37 +0200 Subject: dovecot-2.1-pigeonhole: Added support for retrieving Sieve scrip... Message-ID: details: http://hg.rename-it.nl/dovecot-2.1-pigeonhole/rev/f7ea71241032 changeset: 1611:f7ea71241032 user: Stephan Bosch date: Sun Apr 22 11:30:28 2012 +0200 description: Added support for retrieving Sieve scripts from dict lookup. - Built generic interface for alternative script sources. - Implemented dict script location. NOTE: ManageSieve will not work with this yet, nor will sieve_before/sieve_after. diffstat: INSTALL | 75 +- TODO | 16 +- doc/script-location-dict.txt | 88 + src/lib-sieve-tool/sieve-tool.c | 15 +- src/lib-sieve/Makefile.am | 3 + src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c | 6 +- src/lib-sieve/plugins/environment/ext-environment-common.c | 12 +- src/lib-sieve/plugins/environment/sieve-ext-environment.h | 3 +- src/lib-sieve/plugins/include/cmd-include.c | 19 +- src/lib-sieve/plugins/include/ext-include-binary.c | 53 +- src/lib-sieve/plugins/include/ext-include-common.c | 22 +- src/lib-sieve/plugins/include/ext-include-common.h | 2 +- src/lib-sieve/plugins/notify/cmd-notify.c | 2 +- src/lib-sieve/plugins/vacation/cmd-vacation.c | 2 +- src/lib-sieve/sieve-actions.c | 15 +- src/lib-sieve/sieve-binary-file.c | 29 +- src/lib-sieve/sieve-binary.c | 51 +- src/lib-sieve/sieve-binary.h | 18 +- src/lib-sieve/sieve-common.h | 13 +- src/lib-sieve/sieve-message.c | 5 +- src/lib-sieve/sieve-message.h | 3 +- src/lib-sieve/sieve-script-dict.c | 283 +++++ src/lib-sieve/sieve-script-file.c | 397 +++++++ src/lib-sieve/sieve-script-file.h | 31 + src/lib-sieve/sieve-script-private.h | 89 +- src/lib-sieve/sieve-script.c | 629 +++++++----- src/lib-sieve/sieve-script.h | 59 +- src/lib-sieve/sieve-settings.h | 15 +- src/lib-sieve/sieve-types.h | 37 +- src/lib-sieve/sieve.c | 91 +- src/lib-sieve/sieve.h | 37 +- src/lib-sievestorage/sieve-storage-list.c | 5 + src/lib-sievestorage/sieve-storage-quota.c | 5 + src/lib-sievestorage/sieve-storage-save.c | 1 + src/lib-sievestorage/sieve-storage-script.c | 40 +- src/lib-sievestorage/sieve-storage.c | 35 + src/managesieve/cmd-getscript.c | 23 +- src/managesieve/managesieve-capabilities.c | 16 +- src/managesieve/managesieve-client.c | 37 +- src/plugins/lda-sieve/lda-sieve-plugin.c | 673 ++++++------ src/sieve-tools/sieve-filter.c | 7 +- src/sieve-tools/sieve-test.c | 23 +- src/sieve-tools/sievec.c | 5 +- src/testsuite/testsuite-binary.c | 11 +- src/testsuite/testsuite-script.c | 9 +- src/testsuite/testsuite-smtp.c | 4 +- src/testsuite/testsuite-smtp.h | 6 +- src/testsuite/testsuite.c | 2 - tests/extensions/environment/basic.svtest | 2 +- 49 files changed, 2086 insertions(+), 938 deletions(-) diffs (truncated from 4714 to 300 lines): diff -r a88c63b2d0b0 -r f7ea71241032 INSTALL --- a/INSTALL Mon Mar 26 21:07:14 2012 +0200 +++ b/INSTALL Sun Apr 22 11:30:28 2012 +0200 @@ -85,23 +85,21 @@ plugin section of the config file (default values are shown if applicable): sieve = ~/.dovecot.sieve - The path to the user's main active script. + The location of the user's main active script. sieve_default = - The path to the default personal sieve script file, which gets executed ONLY - if user's private Sieve script does no exist, e.g. - /var/lib/dovecot/default.sieve. This is usually a global script, so sure to - pre-compile this script manually using the sievec command line tool, as - explained in the README file. - - sieve_global_path = - This is the DEPRECATED former name of the sieve_default setting. + The location of the default personal sieve script file, which gets executed + ONLY if user's private Sieve script does no exist, e.g. + /var/lib/dovecot/default.sieve. This is usually a global script, so be sure + to pre-compile this script manually using the sievec command line tool, as + explained in the README file. This setting used to be called + `sieve_global_path', but that name is now deprecated. sieve_global_dir = - Directory for :global include scripts for the Sieve include extension. + Location for :global include scripts for the Sieve include extension. - sieve_dir = ~/ - Directory for :personal include scripts for the Sieve include extension. + sieve_dir = ~/sieve + Location for :personal include scripts for the Sieve include extension. sieve_extensions = Which Sieve language extensions are available to users. By default, all @@ -131,6 +129,12 @@ (wiki2.dovecot.org) or the pigeonhole website (http://pigeonhole.dovecot.org) for available plugins. + sieve_user_log = + The path to the file where the user log file is written. If not configured, a + default location is used. If the main user's personal Sieve (as configured + with sieve=) is a file, the logfile is set to .log by default. If + it is not a file, the default user log file is ~/.dovecot.sieve.log. + recipient_delimiter = + The separator that is expected between the :user and :detail address parts introduced by the subaddress extension. This may also be a sequence of @@ -176,7 +180,48 @@ The maximum number of redirect actions that can be performed during a single script execution. If set to 0, no redirect actions are allowed. -Sieve Interpreter - Per-user Sieve script location +Sieve Interpreter - Script Locations +------------------------------------ + +The location of Sieve scripts is not limited to the file system. The Sieve +interpreter can be extended to retrieve Sieve scripts from other sources as +well, such as a database. Currently, all settings that are used to obtain the +location of a single Sieve script, such as sieve=, sieve_default=, sieve_dir= +and sieve_global_dir= accept the following extended syntax: + +location = [:]path[;