From dovecot at dovecot.org Fri Aug 1 14:19:53 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 01 Aug 2014 14:19:53 +0000 Subject: dovecot-2.2: imap-urlauth: Error message typofix. Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/417a984e91f3 changeset: 17674:417a984e91f3 user: Timo Sirainen date: Fri Aug 01 17:17:53 2014 +0300 description: imap-urlauth: Error message typofix. Patch by Jelmer Vernooij diffstat: src/imap-urlauth/imap-urlauth-worker.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 9e769da78c9a -r 417a984e91f3 src/imap-urlauth/imap-urlauth-worker.c --- a/src/imap-urlauth/imap-urlauth-worker.c Thu Jul 31 15:58:18 2014 +0300 +++ b/src/imap-urlauth/imap-urlauth-worker.c Fri Aug 01 17:17:53 2014 +0300 @@ -478,7 +478,7 @@ } if (client_run_url(client) < 0) { client_abort(client, - "Session aborted: Fatal failure while transfering URL"); + "Session aborted: Fatal failure while transferring URL"); return 0; } } From dovecot at dovecot.org Mon Aug 4 12:08:05 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 04 Aug 2014 12:08:05 +0000 Subject: dovecot-2.2: expire plugin: Fixed crash at deinit if expire_dict... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/cac32684b3d6 changeset: 17675:cac32684b3d6 user: Timo Sirainen date: Mon Aug 04 14:05:51 2014 +0200 description: expire plugin: Fixed crash at deinit if expire_dict initialization failed. diffstat: src/plugins/expire/expire-plugin.c | 40 ++++++++++++++++++++----------------- 1 files changed, 22 insertions(+), 18 deletions(-) diffs (60 lines): diff -r 417a984e91f3 -r cac32684b3d6 src/plugins/expire/expire-plugin.c --- a/src/plugins/expire/expire-plugin.c Fri Aug 01 17:17:53 2014 +0300 +++ b/src/plugins/expire/expire-plugin.c Mon Aug 04 14:05:51 2014 +0200 @@ -325,34 +325,38 @@ static void expire_mail_namespaces_created(struct mail_namespace *ns) { struct mail_user *user = ns->user; + struct mail_user_vfuncs *v = user->vlast; struct expire_mail_user *euser; + struct dict *db; const char *dict_uri, *error; dict_uri = mail_user_plugin_getenv(user, "expire_dict"); if (mail_user_plugin_getenv(user, "expire") == NULL) { if (user->mail_debug) i_debug("expire: No expire setting - plugin disabled"); - } else if (dict_uri == NULL) { + return; + } + if (dict_uri == NULL) { i_error("expire plugin: expire_dict setting missing"); - } else { - struct mail_user_vfuncs *v = user->vlast; + return; + } - euser = p_new(user->pool, struct expire_mail_user, 1); - euser->module_ctx.super = *v; - user->vlast = &euser->module_ctx.super; - v->deinit = expire_mail_user_deinit; + /* we're using only shared dictionary, the username doesn't matter. */ + if (dict_init(dict_uri, DICT_DATA_TYPE_UINT32, "", + user->set->base_dir, &db, &error) < 0) { + i_error("expire plugin: dict_init(%s) failed: %s", + dict_uri, error); + return; + } - euser->set = expire_set_init(expire_get_patterns(user)); - /* we're using only shared dictionary, the username - doesn't matter. */ - if (dict_init(dict_uri, DICT_DATA_TYPE_UINT32, "", - user->set->base_dir, &euser->db, &error) < 0) { - i_error("expire plugin: dict_init(%s) failed: %s", - dict_uri, error); - } else { - MODULE_CONTEXT_SET(user, expire_mail_user_module, euser); - } - } + euser = p_new(user->pool, struct expire_mail_user, 1); + euser->module_ctx.super = *v; + user->vlast = &euser->module_ctx.super; + v->deinit = expire_mail_user_deinit; + + euser->db = db; + euser->set = expire_set_init(expire_get_patterns(user)); + MODULE_CONTEXT_SET(user, expire_mail_user_module, euser); } static struct mail_storage_hooks expire_mail_storage_hooks = { From pigeonhole at rename-it.nl Tue Aug 5 01:47:50 2014 From: pigeonhole at rename-it.nl (pigeonhole at rename-it.nl) Date: Tue, 05 Aug 2014 03:47:50 +0200 Subject: dovecot-2.2-pigeonhole: lib-sieve: file storage: Fixed segfault ... Message-ID: details: http://hg.rename-it.nl/dovecot-2.2-pigeonhole/rev/35ff96d4c61b changeset: 1905:35ff96d4c61b user: Stephan Bosch date: Tue Aug 05 03:47:36 2014 +0200 description: lib-sieve: file storage: Fixed segfault bug in script sequence code. diffstat: src/lib-sieve/storage/file/sieve-file-script-sequence.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 2db02e11cd5e -r 35ff96d4c61b src/lib-sieve/storage/file/sieve-file-script-sequence.c --- a/src/lib-sieve/storage/file/sieve-file-script-sequence.c Thu Jul 31 02:17:50 2014 +0200 +++ b/src/lib-sieve/storage/file/sieve-file-script-sequence.c Tue Aug 05 03:47:36 2014 +0200 @@ -239,6 +239,7 @@ struct sieve_file_script_sequence *fseq = (struct sieve_file_script_sequence *)seq; - array_free(&fseq->script_files); + if ( array_is_created(&fseq->script_files) ) + array_free(&fseq->script_files); pool_unref(&fseq->pool); } From pigeonhole at rename-it.nl Tue Aug 5 01:56:03 2014 From: pigeonhole at rename-it.nl (pigeonhole at rename-it.nl) Date: Tue, 05 Aug 2014 03:56:03 +0200 Subject: dovecot-2.2-pigeonhole: lib-sieve: file storage: Fixed assert fa... Message-ID: details: http://hg.rename-it.nl/dovecot-2.2-pigeonhole/rev/860c4e547490 changeset: 1906:860c4e547490 user: Stephan Bosch date: Tue Aug 05 03:55:56 2014 +0200 description: lib-sieve: file storage: Fixed assert failure in script sequence code. Single script was only initialized and not actually opened. diffstat: src/lib-sieve/storage/file/sieve-file-script-sequence.c | 2 +- src/lib-sieve/storage/file/sieve-file-script.c | 19 +++++++++++++++++ src/lib-sieve/storage/file/sieve-file-storage.h | 2 + 3 files changed, 22 insertions(+), 1 deletions(-) diffs (53 lines): diff -r 35ff96d4c61b -r 860c4e547490 src/lib-sieve/storage/file/sieve-file-script-sequence.c --- a/src/lib-sieve/storage/file/sieve-file-script-sequence.c Tue Aug 05 03:47:36 2014 +0200 +++ b/src/lib-sieve/storage/file/sieve-file-script-sequence.c Tue Aug 05 03:55:56 2014 +0200 @@ -210,7 +210,7 @@ fscript = NULL; if ( fseq->storage_is_file ) { if ( fseq->index++ < 1 ) - fscript = sieve_file_script_init_from_name(fstorage, NULL); + fscript = sieve_file_script_open_from_name(fstorage, NULL); } else { files = array_get(&fseq->script_files, &count); diff -r 35ff96d4c61b -r 860c4e547490 src/lib-sieve/storage/file/sieve-file-script.c --- a/src/lib-sieve/storage/file/sieve-file-script.c Tue Aug 05 03:47:36 2014 +0200 +++ b/src/lib-sieve/storage/file/sieve-file-script.c Tue Aug 05 03:55:56 2014 +0200 @@ -161,6 +161,25 @@ return fscript; } +struct sieve_file_script *sieve_file_script_open_from_name +(struct sieve_file_storage *fstorage, const char *name) +{ + struct sieve_file_script *fscript; + enum sieve_error error; + + fscript = sieve_file_script_init_from_name(fstorage, name); + if ( fscript == NULL ) + return NULL; + + if ( sieve_script_open(&fscript->script, &error) < 0 ) { + struct sieve_script *script = &fscript->script; + sieve_script_unref(&script); + return NULL; + } + + return fscript; +} + struct sieve_file_script *sieve_file_script_init_from_path (struct sieve_file_storage *fstorage, const char *path, const char *scriptname, enum sieve_error *error_r) diff -r 35ff96d4c61b -r 860c4e547490 src/lib-sieve/storage/file/sieve-file-storage.h --- a/src/lib-sieve/storage/file/sieve-file-storage.h Tue Aug 05 03:47:36 2014 +0200 +++ b/src/lib-sieve/storage/file/sieve-file-storage.h Tue Aug 05 03:55:56 2014 +0200 @@ -145,6 +145,8 @@ const char *scriptname); struct sieve_file_script *sieve_file_script_init_from_name (struct sieve_file_storage *fstorage, const char *name); +struct sieve_file_script *sieve_file_script_open_from_name + (struct sieve_file_storage *fstorage, const char *name); struct sieve_file_script *sieve_file_script_init_from_path (struct sieve_file_storage *fstorage, const char *path, From dovecot at dovecot.org Tue Aug 5 14:09:49 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 05 Aug 2014 14:09:49 +0000 Subject: dovecot-2.2: lib-http server: Removed "bool close" parameters in... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/898d4cce2aa9 changeset: 17676:898d4cce2aa9 user: Timo Sirainen date: Tue Aug 05 16:07:25 2014 +0200 description: lib-http server: Removed "bool close" parameters in favor of _close() functions. Most callers don't want to close the connection so it's an extra parameter usually. Also it's difficult to remember what the TRUE/FALSE means so it's easy to cause bugs by copy&pasting the code. http_server_request_fail() will also now forcibly close the connection if conn->input_broken is set. diffstat: src/lib-http/http-server-connection.c | 25 ++++++++++++------------- src/lib-http/http-server-request.c | 20 ++++++++++++++++++-- src/lib-http/http-server-response.c | 13 ++++++++++--- src/lib-http/http-server.h | 11 +++++++++-- 4 files changed, 49 insertions(+), 20 deletions(-) diffs (174 lines): diff -r cac32684b3d6 -r 898d4cce2aa9 src/lib-http/http-server-connection.c --- a/src/lib-http/http-server-connection.c Mon Aug 04 14:05:51 2014 +0200 +++ b/src/lib-http/http-server-connection.c Tue Aug 05 16:07:25 2014 +0200 @@ -206,13 +206,13 @@ conn->input_broken = TRUE; http_server_connection_client_error(conn, "Client sent excessively large request"); - http_server_request_fail(req, 413, "Payload Too Large", TRUE); + http_server_request_fail_close(req, 413, "Payload Too Large"); return; case EIO: conn->input_broken = TRUE; http_server_connection_client_error(conn, "Client sent invalid request payload"); - http_server_request_fail(req, 400, "Bad Request", conn->input_broken); + http_server_request_fail_close(req, 400, "Bad Request"); return; default: break; @@ -243,11 +243,11 @@ /* CONNECT method */ if (strcmp(req->req.method, "CONNECT") == 0) { if (conn->callbacks->handle_connect_request == NULL) { - http_server_request_fail(req, 505, "Not Implemented", FALSE); + http_server_request_fail(req, 505, "Not Implemented"); return; } if (req->req.target.format != HTTP_REQUEST_TARGET_FORMAT_AUTHORITY) { - http_server_request_fail(req, 400, "Bad Request", FALSE); + http_server_request_fail(req, 400, "Bad Request"); return; } conn->callbacks->handle_connect_request @@ -256,7 +256,7 @@ /* other methods */ } else { if (conn->callbacks->handle_request == NULL) { - http_server_request_fail(req, 505, "Not Implemented", FALSE); + http_server_request_fail(req, 505, "Not Implemented"); return; } else { conn->callbacks->handle_request(conn->context, req); @@ -273,7 +273,7 @@ i_assert(conn->incoming_payload == NULL); if (req->req.version_major != 1) { - http_server_request_fail(req, 505, "HTTP Version Not Supported", FALSE); + http_server_request_fail(req, 505, "HTTP Version Not Supported"); return TRUE; } @@ -492,24 +492,23 @@ case HTTP_REQUEST_PARSE_ERROR_BROKEN_REQUEST: conn->input_broken = TRUE; case HTTP_REQUEST_PARSE_ERROR_BAD_REQUEST: - http_server_request_fail(req, 400, "Bad Request", conn->input_broken); + http_server_request_fail(req, 400, "Bad Request"); break; - case HTTP_REQUEST_PARSE_ERROR_METHOD_TOO_LONG: + case HTTP_REQUEST_PARSE_ERROR_METHOD_TOO_LONG: conn->input_broken = TRUE; case HTTP_REQUEST_PARSE_ERROR_NOT_IMPLEMENTED: - http_server_request_fail(req, - 501, "Not Implemented", conn->input_broken); + http_server_request_fail(req, 501, "Not Implemented"); break; case HTTP_REQUEST_PARSE_ERROR_TARGET_TOO_LONG: - http_server_request_fail(req, 414, "URI Too Long", TRUE); conn->input_broken = TRUE; + http_server_request_fail_close(req, 414, "URI Too Long"); break; case HTTP_REQUEST_PARSE_ERROR_EXPECTATION_FAILED: - http_server_request_fail(req, 417, "Expectation Failed", FALSE); + http_server_request_fail(req, 417, "Expectation Failed"); break; case HTTP_REQUEST_PARSE_ERROR_PAYLOAD_TOO_LARGE: - http_server_request_fail(req, 413, "Payload Too Large", TRUE); conn->input_broken = TRUE; + http_server_request_fail_close(req, 413, "Payload Too Large"); break; return; default: diff -r cac32684b3d6 -r 898d4cce2aa9 src/lib-http/http-server-request.c --- a/src/lib-http/http-server-request.c Mon Aug 04 14:05:51 2014 +0200 +++ b/src/lib-http/http-server-request.c Tue Aug 05 16:07:25 2014 +0200 @@ -174,7 +174,8 @@ http_server_connection_send_responses(conn); } -void http_server_request_fail(struct http_server_request *req, +static void +http_server_request_fail_full(struct http_server_request *req, unsigned int status, const char *reason, bool close) { struct http_server_response *resp; @@ -185,6 +186,21 @@ reason = t_strconcat(reason, "\r\n", NULL); http_server_response_set_payload_data (resp, (const unsigned char *)reason, strlen(reason)); - http_server_response_submit(resp, close); + if (close) + http_server_response_submit_close(resp); + else + http_server_response_submit(resp); } +void http_server_request_fail(struct http_server_request *req, + unsigned int status, const char *reason) +{ + http_server_request_fail_full(req, status, reason, + req->conn->input_broken); +} + +void http_server_request_fail_close(struct http_server_request *req, + unsigned int status, const char *reason) +{ + http_server_request_fail_full(req, status, reason, TRUE); +} diff -r cac32684b3d6 -r 898d4cce2aa9 src/lib-http/http-server-response.c --- a/src/lib-http/http-server-response.c Mon Aug 04 14:05:51 2014 +0200 +++ b/src/lib-http/http-server-response.c Tue Aug 05 16:07:25 2014 +0200 @@ -142,13 +142,20 @@ http_server_request_submit_response(resp->request); } -void http_server_response_submit(struct http_server_response *resp, - bool close) +void http_server_response_submit(struct http_server_response *resp) { i_assert(!resp->submitted); http_server_response_debug(resp, "Submitted"); - http_server_response_do_submit(resp, close); + http_server_response_do_submit(resp, FALSE); +} + +void http_server_response_submit_close(struct http_server_response *resp) +{ + i_assert(!resp->submitted); + http_server_response_debug(resp, "Submitted"); + + http_server_response_do_submit(resp, TRUE); } void http_server_response_submit_tunnel(struct http_server_response *resp, diff -r cac32684b3d6 -r 898d4cce2aa9 src/lib-http/http-server.h --- a/src/lib-http/http-server.h Mon Aug 04 14:05:51 2014 +0200 +++ b/src/lib-http/http-server.h Tue Aug 05 16:07:25 2014 +0200 @@ -65,8 +65,13 @@ const struct http_request * http_server_request_get(struct http_server_request *req); pool_t http_server_request_get_pool(struct http_server_request *req); +/* Send a failure response to the request with given status/reason. */ void http_server_request_fail(struct http_server_request *req, - unsigned int status, const char *reason, bool close); + unsigned int status, const char *reason); +/* Send a failure response to the request with given status/reason + and close the connection. */ +void http_server_request_fail_close(struct http_server_request *req, + unsigned int status, const char *reason); /* Call the specified callback when HTTP request is destroyed. */ void http_server_request_set_destroy_callback(struct http_server_request *req, @@ -84,7 +89,9 @@ struct istream *input); void http_server_response_set_payload_data(struct http_server_response *resp, const unsigned char *data, size_t size); -void http_server_response_submit(struct http_server_response *resp, bool close); +void http_server_response_submit(struct http_server_response *resp); +/* Submit response and close the connection. */ +void http_server_response_submit_close(struct http_server_response *resp); void http_server_response_submit_tunnel(struct http_server_response *resp, http_server_tunnel_callback_t callback, void *context); From dovecot at dovecot.org Tue Aug 5 14:11:39 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 05 Aug 2014 14:11:39 +0000 Subject: dovecot-2.2: lib-http server: Removed extra "return;" that was n... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/8bb726d6c5db changeset: 17677:8bb726d6c5db user: Timo Sirainen date: Tue Aug 05 16:09:44 2014 +0200 description: lib-http server: Removed extra "return;" that was never called. diffstat: src/lib-http/http-server-connection.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diffs (11 lines): diff -r 898d4cce2aa9 -r 8bb726d6c5db src/lib-http/http-server-connection.c --- a/src/lib-http/http-server-connection.c Tue Aug 05 16:07:25 2014 +0200 +++ b/src/lib-http/http-server-connection.c Tue Aug 05 16:09:44 2014 +0200 @@ -510,7 +510,6 @@ conn->input_broken = TRUE; http_server_request_fail_close(req, 413, "Payload Too Large"); break; - return; default: i_unreached(); } From dovecot at dovecot.org Tue Aug 5 14:24:43 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 05 Aug 2014 14:24:43 +0000 Subject: dovecot-2.2: lib-http server: Added http_server_request_get_resp... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/c9151da3a9b3 changeset: 17678:c9151da3a9b3 user: Timo Sirainen date: Tue Aug 05 16:22:43 2014 +0200 description: lib-http server: Added http_server_request_get_response() Also make sure that only a single response can be created for a request. diffstat: src/lib-http/http-server-request.c | 6 ++++++ src/lib-http/http-server-response.c | 2 ++ src/lib-http/http-server.h | 6 ++++++ 3 files changed, 14 insertions(+), 0 deletions(-) diffs (51 lines): diff -r 8bb726d6c5db -r c9151da3a9b3 src/lib-http/http-server-request.c --- a/src/lib-http/http-server-request.c Tue Aug 05 16:09:44 2014 +0200 +++ b/src/lib-http/http-server-request.c Tue Aug 05 16:22:43 2014 +0200 @@ -93,6 +93,12 @@ return req->pool; } +struct http_server_response * +http_server_request_get_response(struct http_server_request *req) +{ + return req->response; +} + void http_server_request_halt_payload(struct http_server_request *req) { i_assert(req->state <= HTTP_SERVER_REQUEST_STATE_QUEUED); diff -r 8bb726d6c5db -r c9151da3a9b3 src/lib-http/http-server-response.c --- a/src/lib-http/http-server-response.c Tue Aug 05 16:09:44 2014 +0200 +++ b/src/lib-http/http-server-response.c Tue Aug 05 16:22:43 2014 +0200 @@ -41,6 +41,8 @@ { struct http_server_response *resp; + i_assert(req->response == NULL); + resp = req->response = p_new(req->pool, struct http_server_response, 1); resp->request = req; resp->status = status; diff -r 8bb726d6c5db -r c9151da3a9b3 src/lib-http/http-server.h --- a/src/lib-http/http-server.h Tue Aug 05 16:09:44 2014 +0200 +++ b/src/lib-http/http-server.h Tue Aug 05 16:22:43 2014 +0200 @@ -65,6 +65,10 @@ const struct http_request * http_server_request_get(struct http_server_request *req); pool_t http_server_request_get_pool(struct http_server_request *req); +/* Returns the response created for the request with + http_server_response_create(), or NULL if none. */ +struct http_server_response * +http_server_request_get_response(struct http_server_request *req); /* Send a failure response to the request with given status/reason. */ void http_server_request_fail(struct http_server_request *req, unsigned int status, const char *reason); @@ -78,6 +82,8 @@ void (*callback)(void *), void *context); +/* Start creating the response for the request. This function can be called + only once for each request. */ struct http_server_response * http_server_response_create(struct http_server_request *req, unsigned int status, const char *reason); From dovecot at dovecot.org Tue Aug 5 14:30:10 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 05 Aug 2014 14:30:10 +0000 Subject: dovecot-2.2: lib-http server: Create a new data stack frame for ... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/7e084d643e59 changeset: 17679:7e084d643e59 user: Timo Sirainen date: Tue Aug 05 16:28:15 2014 +0200 description: lib-http server: Create a new data stack frame for all the callbacks. diffstat: src/lib-http/http-server-connection.c | 10 +++++++--- 1 files changed, 7 insertions(+), 3 deletions(-) diffs (36 lines): diff -r c9151da3a9b3 -r 7e084d643e59 src/lib-http/http-server-connection.c --- a/src/lib-http/http-server-connection.c Tue Aug 05 16:22:43 2014 +0200 +++ b/src/lib-http/http-server-connection.c Tue Aug 05 16:28:15 2014 +0200 @@ -367,6 +367,7 @@ struct http_server_request *req, *pending_request; enum http_request_parse_error error_code; const char *error; + bool cont; int ret; i_assert(!conn->input_broken && conn->incoming_payload == NULL); @@ -431,7 +432,10 @@ /* handle request req may be destroyed after this, so don't refer to it if ret > 0 */ http_server_request_ref(req); - if (!http_server_connection_handle_request(conn, req)) { + T_BEGIN { + cont = http_server_connection_handle_request(conn, req); + } T_END; + if (!cont) { http_server_request_unref(&req); return; } @@ -828,10 +832,10 @@ connection_deinit(&conn->conn); if (conn->callbacks != NULL && - conn->callbacks->connection_destroy != NULL) { + conn->callbacks->connection_destroy != NULL) T_BEGIN { conn->callbacks->connection_destroy (conn->context, conn->disconnect_reason); - } + } T_END; i_free(conn->disconnect_reason); i_free(conn); From dovecot at dovecot.org Tue Aug 5 15:45:36 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 05 Aug 2014 15:45:36 +0000 Subject: dovecot-2.2: lib-http server: Made http_server_request_[un]ref()... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/beaee1a2ad61 changeset: 17680:beaee1a2ad61 user: Timo Sirainen date: Tue Aug 05 17:37:25 2014 +0200 description: lib-http server: Made http_server_request_[un]ref() public. Also http_server_request_unref() now returns if this was the last reference or not. diffstat: src/lib-http/http-server-private.h | 2 -- src/lib-http/http-server-request.c | 5 +++-- src/lib-http/http-server.h | 6 ++++++ 3 files changed, 9 insertions(+), 4 deletions(-) diffs (56 lines): diff -r 7e084d643e59 -r beaee1a2ad61 src/lib-http/http-server-private.h --- a/src/lib-http/http-server-private.h Tue Aug 05 16:28:15 2014 +0200 +++ b/src/lib-http/http-server-private.h Tue Aug 05 17:37:25 2014 +0200 @@ -156,8 +156,6 @@ struct http_server_request * http_server_request_new(struct http_server_connection *conn); -void http_server_request_ref(struct http_server_request *req); -void http_server_request_unref(struct http_server_request **_req); void http_server_request_abort(struct http_server_request **_req); void http_server_request_halt_payload(struct http_server_request *req); diff -r 7e084d643e59 -r beaee1a2ad61 src/lib-http/http-server-request.c --- a/src/lib-http/http-server-request.c Tue Aug 05 16:28:15 2014 +0200 +++ b/src/lib-http/http-server-request.c Tue Aug 05 17:37:25 2014 +0200 @@ -28,14 +28,14 @@ req->refcount++; } -void http_server_request_unref(struct http_server_request **_req) +bool http_server_request_unref(struct http_server_request **_req) { struct http_server_request *req = *_req; struct http_server_connection *conn = req->conn; i_assert(req->refcount > 0); if (--req->refcount > 0) - return; + return TRUE; if (req->state < HTTP_SERVER_REQUEST_STATE_FINISHED) { req->state = HTTP_SERVER_REQUEST_STATE_ABORTED; @@ -52,6 +52,7 @@ http_server_response_free(req->response); pool_unref(&req->pool); *_req = NULL; + return FALSE; } void http_server_request_set_destroy_callback(struct http_server_request *req, diff -r 7e084d643e59 -r beaee1a2ad61 src/lib-http/http-server.h --- a/src/lib-http/http-server.h Tue Aug 05 16:28:15 2014 +0200 +++ b/src/lib-http/http-server.h Tue Aug 05 17:37:25 2014 +0200 @@ -82,6 +82,12 @@ void (*callback)(void *), void *context); +/* Reference a server request */ +void http_server_request_ref(struct http_server_request *req); +/* Unreference a server request. Returns TRUE if there are still more + references, FALSE if not. */ +bool http_server_request_unref(struct http_server_request **_req); + /* Start creating the response for the request. This function can be called only once for each request. */ struct http_server_response * From dovecot at dovecot.org Tue Aug 5 15:45:37 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 05 Aug 2014 15:45:37 +0000 Subject: dovecot-2.2: lib-http server: Require handle_request() to either... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/6785b41831d3 changeset: 17681:6785b41831d3 user: Timo Sirainen date: Tue Aug 05 17:43:31 2014 +0200 description: lib-http server: Require handle_request() to either send a response or reference the request. This should make it more difficult to accidentally forget to send a response and cause a hang. Currently this assert-crashes, although it would have been possible to make it return some internal error instead also. diffstat: src/lib-http/http-server-connection.c | 5 +++++ src/lib-http/http-server.h | 4 ++++ 2 files changed, 9 insertions(+), 0 deletions(-) diffs (30 lines): diff -r beaee1a2ad61 -r 6785b41831d3 src/lib-http/http-server-connection.c --- a/src/lib-http/http-server-connection.c Tue Aug 05 17:37:25 2014 +0200 +++ b/src/lib-http/http-server-connection.c Tue Aug 05 17:43:31 2014 +0200 @@ -259,7 +259,12 @@ http_server_request_fail(req, 505, "Not Implemented"); return; } else { + unsigned int old_refcount = req->refcount; + conn->callbacks->handle_request(conn->context, req); + i_assert((req->response != NULL && + req->response->submitted) || + req->refcount > old_refcount); } } } diff -r beaee1a2ad61 -r 6785b41831d3 src/lib-http/http-server.h --- a/src/lib-http/http-server.h Tue Aug 05 17:37:25 2014 +0200 +++ b/src/lib-http/http-server.h Tue Aug 05 17:43:31 2014 +0200 @@ -38,6 +38,10 @@ }; struct http_server_callbacks { + /* Reference the server request. Before returning you must either send + a response to the request or reference the request with + http_server_request_ref() and unreference it later after sending + the response. */ void (*handle_request)(void *context, struct http_server_request *req); void (*handle_connect_request)(void *context, struct http_server_request *req, struct http_url *target); From pigeonhole at rename-it.nl Tue Aug 5 16:25:21 2014 From: pigeonhole at rename-it.nl (pigeonhole at rename-it.nl) Date: Tue, 05 Aug 2014 18:25:21 +0200 Subject: dovecot-2.2-pigeonhole: lib-sieve: editheader extension: Fixed s... Message-ID: details: http://hg.rename-it.nl/dovecot-2.2-pigeonhole/rev/1e388884d31c changeset: 1907:1e388884d31c user: Stephan Bosch date: Tue Aug 05 18:25:12 2014 +0200 description: lib-sieve: editheader extension: Fixed several problems in deleteheader command. diffstat: src/lib-sieve/plugins/editheader/cmd-deleteheader.c | 6 +- src/lib-sieve/util/edit-mail.c | 36 +++-- tests/extensions/editheader/deleteheader.svtest | 131 +++++++++++++++++++- 3 files changed, 154 insertions(+), 19 deletions(-) diffs (250 lines): diff -r 860c4e547490 -r 1e388884d31c src/lib-sieve/plugins/editheader/cmd-deleteheader.c --- a/src/lib-sieve/plugins/editheader/cmd-deleteheader.c Tue Aug 05 03:55:56 2014 +0200 +++ b/src/lib-sieve/plugins/editheader/cmd-deleteheader.c Tue Aug 05 18:25:12 2014 +0200 @@ -472,7 +472,7 @@ mctx = sieve_match_begin(renv, &mcht, &cmp); /* Match */ - do { + for (;;) { pos++; /* Check index if any */ @@ -496,7 +496,9 @@ } } - } while ( edit_mail_headers_iterate_next(edhiter) ); + if ( !edit_mail_headers_iterate_next(edhiter) ) + break; + } /* Finish match */ mret = sieve_match_end(&mctx, &ret); diff -r 860c4e547490 -r 1e388884d31c src/lib-sieve/util/edit-mail.c --- a/src/lib-sieve/util/edit-mail.c Tue Aug 05 03:55:56 2014 +0200 +++ b/src/lib-sieve/util/edit-mail.c Tue Aug 05 18:25:12 2014 +0200 @@ -1115,6 +1115,7 @@ { struct edit_mail_header_iter *edhiter; struct _header_index *header_idx = NULL; + struct _header_field_index *current = NULL; /* Make sure headers are parsed */ if ( edit_mail_headers_parse(edmail) <= 0 ) { @@ -1124,22 +1125,26 @@ header_idx = edit_mail_header_find(edmail, field_name); + if ( field_name != NULL && header_idx == NULL ) { + current = NULL; + } else if ( !reverse ) { + current = + ( header_idx != NULL ? header_idx->first : edmail->header_fields_head ); + } else { + current = + ( header_idx != NULL ? header_idx->last : edmail->header_fields_tail ); + if ( current->header == NULL ) + current = current->prev; + } + + if ( current == NULL ) + return 0; + edhiter = i_new(struct edit_mail_header_iter, 1); edhiter->mail = edmail; edhiter->header = header_idx; edhiter->reverse = reverse; - - if ( field_name != NULL && header_idx == NULL ) { - edhiter->current = NULL; - } else if ( !reverse ) { - edhiter->current = - ( header_idx != NULL ? header_idx->first : edmail->header_fields_head ); - } else { - edhiter->current = - ( header_idx != NULL ? header_idx->last : edmail->header_fields_tail ); - if ( edhiter->current->header == NULL ) - edhiter->current = edhiter->current->prev; - } + edhiter->current = current; *edhiter_r = edhiter; return 1; @@ -1171,9 +1176,12 @@ bool edit_mail_headers_iterate_next (struct edit_mail_header_iter *edhiter) { + if ( edhiter->current == NULL ) + return FALSE; + do { - edhiter->current = - ( !edhiter->reverse ? edhiter->current->next : edhiter->current->next ); + edhiter->current = + ( !edhiter->reverse ? edhiter->current->next : edhiter->current->prev ); } while ( edhiter->current != NULL && edhiter->current->header != NULL && edhiter->header != NULL && edhiter->current->header != edhiter->header ); diff -r 860c4e547490 -r 1e388884d31c tests/extensions/editheader/deleteheader.svtest --- a/tests/extensions/editheader/deleteheader.svtest Tue Aug 05 03:55:56 2014 +0200 +++ b/tests/extensions/editheader/deleteheader.svtest Tue Aug 05 18:25:12 2014 +0200 @@ -99,6 +99,82 @@ } } +test_set "message" "${message}"; +test "Deleteheader - nonexistent (match)" { + if size :over 288 { + test_fail "original message is longer than 288 bytes?!"; + } + + if size :under 288 { + test_fail "original message is shorter than 288 bytes?!"; + } + + deleteheader :matches "X-Z" "*frop*"; + + if size :under 288 { + test_fail "message is shorter than original"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained"; + } + + if not header :is "X-B" "omdat dit anders" { + test_fail "original X-B header not retained"; + } + + if not header :is "X-C" "niet via e-mail versturen" { + test_fail "original X-C header not retained"; + } + + redirect "frop at example.com"; + fileinto :create "folder1b"; + + if not test_result_execute { + test_fail "failed to execute result"; + } + + if not test_message :folder "folder1b" 0 { + test_fail "message not stored"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained in stored mail"; + } + + if not header :is "X-B" "omdat dit anders" { + test_fail "original X-B header not retained in stored mail"; + } + + if not header :is "X-C" "niet via e-mail versturen" { + test_fail "original X-C header not retained in stored mail"; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in stored mail"; + } + + if not test_message :smtp 0 { + test_fail "message not redirected"; + } + + if not header :is "subject" "Frop!" { + test_fail "original subject header not retained in redirected mail"; + } + + if not header :is "X-B" "omdat dit anders" { + test_fail "original X-B header not retained in redirected mail"; + } + + if not header :is "X-C" "niet via e-mail versturen" { + test_fail "original X-C header not retained in redirected mail"; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in redirected mail"; + } +} + test_result_reset; test_set "message" "${message}"; test "Deleteheader - one" { @@ -867,9 +943,7 @@ * */ -test_result_reset; - -test_set "message" text: +set "message2" text: X-A: Long folded header to test removal of folded headers from a message. This is the top header. X-B: First intermittent unfolded header @@ -884,6 +958,8 @@ . ; +test_result_reset; +test_set "message" "${message2}"; test "Deleteheader - folded" { deleteheader "X-A"; @@ -930,6 +1006,55 @@ } } +test_result_reset; +test_set "message" "${message2}"; +test "Deleteheader - folded (match)" { + deleteheader :matches "X-A" "*header*"; + + if exists "X-A" { + test_fail "original X-A (1) header not deleted"; + } + + if not header :is "X-B" "First intermittent unfolded header" { + test_fail "original X-B (2) header not retained"; + } + + if not header :is "X-B" "Second intermittent unfolded header" { + test_fail "original X-B (2) header not retained"; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in redirected mail"; + } + + redirect "frop at example.com"; + + if not test_result_execute { + test_fail "failed to execute result"; + } + + if not test_message :smtp 0 { + test_fail "message not redirected"; + } + + if exists "X-A" { + test_fail "original X-A (1) header not deleted in redirected mail"; + } + + if not header :is "X-B" "First intermittent unfolded header" { + test_fail "original X-B (2) header not retained in redirected mail"; + } + + if not header :is "X-B" "Second intermittent unfolded header" { + test_fail "original X-B (2) header not retained in redirected mail"; + } + + if not body :matches "Frop!*" { + test_fail "body not retained in redirected mail"; + } +} + + /* * TEST: Ignoring whitespace */ From dovecot at dovecot.org Tue Aug 5 18:25:32 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 05 Aug 2014 18:25:32 +0000 Subject: dovecot-2.2: lib-http: server: Fixed server waiting for payload ... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/72db5dc3d402 changeset: 17682:72db5dc3d402 user: Stephan Bosch date: Tue Aug 05 20:23:32 2014 +0200 description: lib-http: server: Fixed server waiting for payload of already failed request. diffstat: src/lib-http/http-server-private.h | 3 ++- src/lib-http/http-server-request.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletions(-) diffs (32 lines): diff -r 6785b41831d3 -r 72db5dc3d402 src/lib-http/http-server-private.h --- a/src/lib-http/http-server-private.h Tue Aug 05 17:43:31 2014 +0200 +++ b/src/lib-http/http-server-private.h Tue Aug 05 20:23:32 2014 +0200 @@ -82,6 +82,7 @@ unsigned int payload_halted:1; unsigned int sent_100_continue:1; + unsigned int failed:1; }; struct http_server_connection { @@ -175,7 +176,7 @@ static inline bool http_server_request_is_complete(struct http_server_request *req) { - return (req->conn->input_broken || + return (req->failed || req->conn->input_broken || (req->next != NULL && !http_server_request_is_new(req->next)) || !http_server_connection_pending_payload(req->conn)); } diff -r 6785b41831d3 -r 72db5dc3d402 src/lib-http/http-server-request.c --- a/src/lib-http/http-server-request.c Tue Aug 05 17:43:31 2014 +0200 +++ b/src/lib-http/http-server-request.c Tue Aug 05 20:23:32 2014 +0200 @@ -187,6 +187,8 @@ { struct http_server_response *resp; + req->failed = TRUE; + resp = http_server_response_create(req, status, reason); http_server_response_add_header (resp, "Content-Type", "text/plain; charset=utf-8"); From dovecot at dovecot.org Wed Aug 6 13:41:37 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 06 Aug 2014 13:41:37 +0000 Subject: dovecot-2.2: auth: passdb static assumed that missing "password"... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/0fe379f28af9 changeset: 17683:0fe379f28af9 user: Timo Sirainen date: Wed Aug 06 16:39:27 2014 +0300 description: auth: passdb static assumed that missing "password" field meant empty password Missing password should be an error unless nopassword is set. If an empty password is wanted then "password=" can be used. diffstat: src/auth/passdb-static.c | 25 ++++++++++++++++++------- 1 files changed, 18 insertions(+), 7 deletions(-) diffs (64 lines): diff -r 72db5dc3d402 -r 0fe379f28af9 src/auth/passdb-static.c --- a/src/auth/passdb-static.c Tue Aug 05 20:23:32 2014 +0200 +++ b/src/auth/passdb-static.c Wed Aug 06 16:39:27 2014 +0300 @@ -13,7 +13,7 @@ const char *static_password_tmpl; }; -static void +static enum passdb_result static_save_fields(struct auth_request *request, const char **password_r) { struct static_passdb_module *module = @@ -24,23 +24,33 @@ auth_request_log_debug(request, AUTH_SUBSYS_DB, "lookup"); passdb_template_export(module->tmpl, request); - if (module->static_password_tmpl == NULL) - *password_r = ""; - else { + if (module->static_password_tmpl != NULL) { table = auth_request_get_var_expand_table(request, NULL); var_expand(str, module->static_password_tmpl, table); *password_r = str_c(str); + } else if (auth_fields_exists(request->extra_fields, "nopassword")) { + *password_r = ""; + } else { + auth_request_log_info(request, AUTH_SUBSYS_DB, + "No password returned (and no nopassword)"); + return PASSDB_RESULT_PASSWORD_MISMATCH; } + return PASSDB_RESULT_OK; } static void static_verify_plain(struct auth_request *request, const char *password, verify_plain_callback_t *callback) { + enum passdb_result result; const char *static_password; int ret; - static_save_fields(request, &static_password); + result = static_save_fields(request, &static_password); + if (result != PASSDB_RESULT_OK) { + callback(result, request); + return; + } ret = auth_request_password_verify(request, password, static_password, STATIC_PASS_SCHEME, AUTH_SUBSYS_DB); @@ -56,10 +66,11 @@ static_lookup_credentials(struct auth_request *request, lookup_credentials_callback_t *callback) { + enum passdb_result result; const char *static_password; - static_save_fields(request, &static_password); - passdb_handle_credentials(PASSDB_RESULT_OK, static_password, + result = static_save_fields(request, &static_password); + passdb_handle_credentials(result, static_password, STATIC_PASS_SCHEME, callback, request); } From dovecot at dovecot.org Fri Aug 8 10:34:07 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 08 Aug 2014 10:34:07 +0000 Subject: dovecot-2.2: virtual: Make sure modseqs are always enabled for b... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/d733aecb00d5 changeset: 17684:d733aecb00d5 user: Timo Sirainen date: Fri Aug 08 13:32:08 2014 +0300 description: virtual: Make sure modseqs are always enabled for backend mailboxes. mailbox_get_status() wasn't adding a missing highestmodseq otherwise to the mailbox list index. diffstat: src/plugins/virtual/virtual-storage.c | 3 +++ src/plugins/virtual/virtual-sync.c | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diffs (26 lines): diff -r 0fe379f28af9 -r d733aecb00d5 src/plugins/virtual/virtual-storage.c --- a/src/plugins/virtual/virtual-storage.c Wed Aug 06 16:39:27 2014 +0300 +++ b/src/plugins/virtual/virtual-storage.c Fri Aug 08 13:32:08 2014 +0300 @@ -199,6 +199,9 @@ i_array_init(&bbox->uids, 64); i_array_init(&bbox->sync_pending_removes, 64); + /* we use modseqs for being able to check quickly if backend mailboxes + have changed. make sure the backend has them enabled. */ + mailbox_enable(bbox->box, MAILBOX_FEATURE_CONDSTORE); return 1; } diff -r 0fe379f28af9 -r d733aecb00d5 src/plugins/virtual/virtual-sync.c --- a/src/plugins/virtual/virtual-sync.c Wed Aug 06 16:39:27 2014 +0300 +++ b/src/plugins/virtual/virtual-sync.c Fri Aug 08 13:32:08 2014 +0300 @@ -1085,9 +1085,6 @@ } if (mailbox_sync(bbox->box, sync_flags) < 0) return -1; - /* we use modseqs for speeding up initial search result - build. make sure the backend has them enabled. */ - mail_index_modseq_enable(bbox->box->index); } virtual_backend_box_sync_mail_set(bbox); From dovecot at dovecot.org Fri Aug 8 10:48:05 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 08 Aug 2014 10:48:05 +0000 Subject: dovecot-2.2: lib-storage: mailbox_get_*status(STATUS_HIGHESTMODS... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/48506e8e1c7a changeset: 17685:48506e8e1c7a user: Timo Sirainen date: Fri Aug 08 13:46:05 2014 +0300 description: lib-storage: mailbox_get_*status(STATUS_HIGHESTMODSEQ) now enables CONDSTORE feature. This makes sure that the highestmodseq is added to the mailbox list index if not already there. diffstat: src/lib-storage/mail-storage.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diffs (22 lines): diff -r d733aecb00d5 -r 48506e8e1c7a src/lib-storage/mail-storage.c --- a/src/lib-storage/mail-storage.c Fri Aug 08 13:32:08 2014 +0300 +++ b/src/lib-storage/mail-storage.c Fri Aug 08 13:46:05 2014 +0300 @@ -1523,6 +1523,9 @@ mailbox_get_status_set_defaults(box, status_r); if (mailbox_verify_existing_name(box) < 0) return -1; + + if ((items & STATUS_HIGHESTMODSEQ) != 0) + mailbox_enable(box, MAILBOX_FEATURE_CONDSTORE); if (box->v.get_status(box, items, status_r) < 0) return -1; i_assert(status_r->have_guids || !status_r->have_save_guids); @@ -1537,6 +1540,8 @@ i_assert((items & MAILBOX_STATUS_FAILING_ITEMS) == 0); mailbox_get_status_set_defaults(box, status_r); + if ((items & STATUS_HIGHESTMODSEQ) != 0) + mailbox_enable(box, MAILBOX_FEATURE_CONDSTORE); if (box->v.get_status(box, items, status_r) < 0) i_unreached(); } From dovecot at dovecot.org Fri Aug 8 11:56:52 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 08 Aug 2014 11:56:52 +0000 Subject: dovecot-2.2: virtual: Make sure virtual mailbox doesn't try to a... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/056dfefd81b9 changeset: 17686:056dfefd81b9 user: Timo Sirainen date: Fri Aug 08 14:54:20 2014 +0300 description: virtual: Make sure virtual mailbox doesn't try to access itself as a backend mailbox. diffstat: src/plugins/virtual/virtual-config.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diffs (25 lines): diff -r 48506e8e1c7a -r 056dfefd81b9 src/plugins/virtual/virtual-config.c --- a/src/plugins/virtual/virtual-config.c Fri Aug 08 13:46:05 2014 +0300 +++ b/src/plugins/virtual/virtual-config.c Fri Aug 08 14:54:20 2014 +0300 @@ -171,6 +171,10 @@ bbox->name++; ctx->mbox->save_bbox = bbox; } + if (strcmp(bbox->name, ctx->mbox->box.vname) == 0) { + *error_r = "Virtual mailbox can't point to itself"; + return -1; + } ctx->have_mailbox_defines = TRUE; array_append(&ctx->mbox->backend_boxes, &bbox, 1); return 0; @@ -324,6 +328,10 @@ directories) */ if ((info->flags & MAILBOX_NOSELECT) != 0) continue; + if (strcmp(info->vname, ctx->mbox->box.vname) == 0) { + /* don't allow virtual folder to point to itself */ + continue; + } if (virtual_config_match(info, &wildcard_boxes, &i) && !virtual_config_match(info, &neg_boxes, &j) && From dovecot at dovecot.org Fri Aug 8 11:56:53 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 08 Aug 2014 11:56:53 +0000 Subject: dovecot-2.2: virtual: Allow "*" to match inbox=yes namespace if ... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/4db555d87a54 changeset: 17687:4db555d87a54 user: Timo Sirainen date: Fri Aug 08 14:54:46 2014 +0300 description: virtual: Allow "*" to match inbox=yes namespace if there's otherwise no prefix="" namespace. diffstat: src/plugins/virtual/virtual-config.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diffs (18 lines): diff -r 056dfefd81b9 -r 4db555d87a54 src/plugins/virtual/virtual-config.c --- a/src/plugins/virtual/virtual-config.c Fri Aug 08 14:54:20 2014 +0300 +++ b/src/plugins/virtual/virtual-config.c Fri Aug 08 14:54:46 2014 +0300 @@ -263,6 +263,14 @@ (config_ns->flags & NAMESPACE_FLAG_AUTOCREATED) == 0 && (iter_ns->flags & NAMESPACE_FLAG_AUTOCREATED) != 0) return TRUE; + if ((iter_ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0 && + (config_ns->flags & NAMESPACE_FLAG_AUTOCREATED) != 0 && + config_ns->prefix_len == 0) { + /* prefix="" namespace was autocreated, so e.g. "*" would match + only that empty namespace. but we want "*" to also match + the inbox=yes namespace, so check it here separately. */ + return TRUE; + } return FALSE; } From dovecot at dovecot.org Fri Aug 8 12:17:09 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 08 Aug 2014 12:17:09 +0000 Subject: dovecot-2.2: doveadm search: If mailbox GUID lookup fails, print... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/f206042d6286 changeset: 17688:f206042d6286 user: Timo Sirainen date: Fri Aug 08 15:15:03 2014 +0300 description: doveadm search: If mailbox GUID lookup fails, print an error. diffstat: src/doveadm/doveadm-mail-search.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diffs (13 lines): diff -r 4db555d87a54 -r f206042d6286 src/doveadm/doveadm-mail-search.c --- a/src/doveadm/doveadm-mail-search.c Fri Aug 08 14:54:46 2014 +0300 +++ b/src/doveadm/doveadm-mail-search.c Fri Aug 08 15:15:03 2014 +0300 @@ -26,6 +26,9 @@ box = doveadm_mail_iter_get_mailbox(iter); if (mailbox_get_metadata(box, MAILBOX_METADATA_GUID, &metadata) < 0) { + i_error("Couldn't get mailbox '%s' GUID: %s", + mailbox_get_vname(box), + mailbox_get_last_error(box, NULL)); ret = -1; doveadm_mail_failed_mailbox(ctx, box); } else { From dovecot at dovecot.org Fri Aug 8 13:22:39 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 08 Aug 2014 13:22:39 +0000 Subject: dovecot-2.2: fts: Added fts_no_autofuzzy setting to require exac... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/cdf4edcc6256 changeset: 17689:cdf4edcc6256 user: Timo Sirainen date: Fri Aug 08 16:20:31 2014 +0300 description: fts: Added fts_no_autofuzzy setting to require exact matches for found results. This is done by using the FTS search results as only filters on which the regular non-FTS search is done. diffstat: src/plugins/fts-lucene/fts-backend-lucene.c | 11 ++++--- src/plugins/fts-lucene/lucene-wrapper.cc | 40 ++++++++++++++++++---------- src/plugins/fts-lucene/lucene-wrapper.h | 6 ++- src/plugins/fts-solr/fts-backend-solr-old.c | 21 +++++++++++--- src/plugins/fts-solr/fts-backend-solr.c | 22 +++++++++++---- src/plugins/fts-squat/fts-backend-squat.c | 4 ++- src/plugins/fts/fts-api-private.h | 5 ++- src/plugins/fts/fts-api.c | 12 +++++--- src/plugins/fts/fts-api.h | 16 ++++++++-- src/plugins/fts/fts-search.c | 8 ++++- src/plugins/fts/fts-storage.c | 3 ++ src/plugins/fts/fts-storage.h | 1 + 12 files changed, 103 insertions(+), 46 deletions(-) diffs (truncated from 524 to 300 lines): diff -r f206042d6286 -r cdf4edcc6256 src/plugins/fts-lucene/fts-backend-lucene.c --- a/src/plugins/fts-lucene/fts-backend-lucene.c Fri Aug 08 15:15:03 2014 +0300 +++ b/src/plugins/fts-lucene/fts-backend-lucene.c Fri Aug 08 16:20:31 2014 +0300 @@ -481,7 +481,8 @@ static int fts_backend_lucene_lookup(struct fts_backend *_backend, struct mailbox *box, - struct mail_search_arg *args, bool and_args, + struct mail_search_arg *args, + enum fts_lookup_flags flags, struct fts_result *result) { struct lucene_fts_backend *backend = @@ -493,8 +494,7 @@ if (fts_backend_select(backend, box) < 0) return -1; T_BEGIN { - ret = lucene_index_lookup(backend->index, args, and_args, - result); + ret = lucene_index_lookup(backend->index, args, flags, result); } T_END; return ret; } @@ -550,7 +550,8 @@ static int fts_backend_lucene_lookup_multi(struct fts_backend *_backend, struct mailbox *const boxes[], - struct mail_search_arg *args, bool and_args, + struct mail_search_arg *args, + enum fts_lookup_flags flags, struct fts_multi_result *result) { struct lucene_fts_backend *backend = @@ -566,7 +567,7 @@ ret = mailboxes_get_guids(boxes, guids, result); if (ret == 0) { ret = lucene_index_lookup_multi(backend->index, - guids, args, and_args, + guids, args, flags, result); } hash_table_destroy(&guids); diff -r f206042d6286 -r cdf4edcc6256 src/plugins/fts-lucene/lucene-wrapper.cc --- a/src/plugins/fts-lucene/lucene-wrapper.cc Fri Aug 08 15:15:03 2014 +0300 +++ b/src/plugins/fts-lucene/lucene-wrapper.cc Fri Aug 08 16:20:31 2014 +0300 @@ -1127,8 +1127,10 @@ static bool lucene_add_definite_query(struct lucene_index *index, ARRAY_TYPE(lucene_query) &queries, - struct mail_search_arg *arg, bool and_args) + struct mail_search_arg *arg, + enum fts_lookup_flags flags) { + bool and_args = (flags & FTS_LOOKUP_FLAG_AND_ARGS) != 0; Query *q; if (arg->match_not && !and_args) { @@ -1191,8 +1193,10 @@ static bool lucene_add_maybe_query(struct lucene_index *index, ARRAY_TYPE(lucene_query) &queries, - struct mail_search_arg *arg, bool and_args) + struct mail_search_arg *arg, + enum fts_lookup_flags flags) { + bool and_args = (flags & FTS_LOOKUP_FLAG_AND_ARGS) != 0; Query *q = NULL; if (arg->match_not) { @@ -1236,7 +1240,6 @@ else lq->occur = BooleanClause::MUST_NOT; return true; - return true; } static bool queries_have_non_must_nots(ARRAY_TYPE(lucene_query) &queries) @@ -1319,7 +1322,8 @@ } int lucene_index_lookup(struct lucene_index *index, - struct mail_search_arg *args, bool and_args, + struct mail_search_arg *args, + enum fts_lookup_flags flags, struct fts_result *result) { struct mail_search_arg *arg; @@ -1332,15 +1336,18 @@ bool have_definites = false; for (arg = args; arg != NULL; arg = arg->next) { - if (lucene_add_definite_query(index, def_queries, arg, and_args)) { + if (lucene_add_definite_query(index, def_queries, arg, flags)) { arg->match_always = true; have_definites = true; } } if (have_definites) { + ARRAY_TYPE(seq_range) *uids_arr = + (flags & FTS_LOOKUP_FLAG_NO_AUTO_FUZZY) == 0 ? + &result->definite_uids : &result->maybe_uids; if (lucene_index_search(index, def_queries, result, - &result->definite_uids) < 0) + uids_arr) < 0) return -1; } @@ -1356,7 +1363,7 @@ bool have_maybies = false; for (arg = args; arg != NULL; arg = arg->next) { - if (lucene_add_maybe_query(index, maybe_queries, arg, and_args)) { + if (lucene_add_maybe_query(index, maybe_queries, arg, flags)) { arg->match_always = true; have_maybies = true; } @@ -1374,6 +1381,7 @@ lucene_index_search_multi(struct lucene_index *index, HASH_TABLE_TYPE(wguid_result) guids, ARRAY_TYPE(lucene_query) &queries, + enum fts_lookup_flags flags, struct fts_multi_result *result) { struct fts_score_map *score; @@ -1421,11 +1429,14 @@ break; } - if (!array_is_created(&br->definite_uids)) { - p_array_init(&br->definite_uids, result->pool, 32); + ARRAY_TYPE(seq_range) *uids_arr = + (flags & FTS_LOOKUP_FLAG_NO_AUTO_FUZZY) == 0 ? + &br->maybe_uids : &br->definite_uids; + if (!array_is_created(uids_arr)) { + p_array_init(uids_arr, result->pool, 32); p_array_init(&br->scores, result->pool, 32); } - if (seq_range_array_add(&br->definite_uids, uid)) { + if (seq_range_array_add(uids_arr, uid)) { /* duplicate result */ } else { score = array_append_space(&br->scores); @@ -1443,7 +1454,8 @@ int lucene_index_lookup_multi(struct lucene_index *index, HASH_TABLE_TYPE(wguid_result) guids, - struct mail_search_arg *args, bool and_args, + struct mail_search_arg *args, + enum fts_lookup_flags flags, struct fts_multi_result *result) { struct mail_search_arg *arg; @@ -1456,15 +1468,15 @@ bool have_definites = false; for (arg = args; arg != NULL; arg = arg->next) { - if (lucene_add_definite_query(index, def_queries, arg, and_args)) { + if (lucene_add_definite_query(index, def_queries, arg, flags)) { arg->match_always = true; have_definites = true; } } if (have_definites) { - if (lucene_index_search_multi(index, guids, - def_queries, result) < 0) + if (lucene_index_search_multi(index, guids, def_queries, flags, + result) < 0) return -1; } return 0; diff -r f206042d6286 -r cdf4edcc6256 src/plugins/fts-lucene/lucene-wrapper.h --- a/src/plugins/fts-lucene/lucene-wrapper.h Fri Aug 08 15:15:03 2014 +0300 +++ b/src/plugins/fts-lucene/lucene-wrapper.h Fri Aug 08 16:20:31 2014 +0300 @@ -42,12 +42,14 @@ int lucene_index_optimize(struct lucene_index *index); int lucene_index_lookup(struct lucene_index *index, - struct mail_search_arg *args, bool and_args, + struct mail_search_arg *args, + enum fts_lookup_flags flags, struct fts_result *result); int lucene_index_lookup_multi(struct lucene_index *index, HASH_TABLE_TYPE(wguid_result) guids, - struct mail_search_arg *args, bool and_args, + struct mail_search_arg *args, + enum fts_lookup_flags flags, struct fts_multi_result *result); struct lucene_index_iter * diff -r f206042d6286 -r cdf4edcc6256 src/plugins/fts-solr/fts-backend-solr-old.c --- a/src/plugins/fts-solr/fts-backend-solr-old.c Fri Aug 08 15:15:03 2014 +0300 +++ b/src/plugins/fts-solr/fts-backend-solr-old.c Fri Aug 08 16:20:31 2014 +0300 @@ -665,11 +665,13 @@ static int fts_backend_solr_lookup(struct fts_backend *_backend, struct mailbox *box, - struct mail_search_arg *args, bool and_args, + struct mail_search_arg *args, + enum fts_lookup_flags flags, struct fts_result *result) { struct solr_fts_backend *backend = (struct solr_fts_backend *)_backend; + bool and_args = (flags & FTS_LOOKUP_FLAG_AND_ARGS) != 0; struct mail_namespace *ns; struct mailbox_status status; string_t *str; @@ -704,7 +706,10 @@ ret = solr_connection_select(backend->solr_conn, str_c(str), pool, &results); if (ret == 0 && results[0] != NULL) { - array_append_array(&result->definite_uids, &results[0]->uids); + if ((flags & FTS_LOOKUP_FLAG_NO_AUTO_FUZZY) == 0) + array_append_array(&result->definite_uids, &results[0]->uids); + else + array_append_array(&result->maybe_uids, &results[0]->uids); array_append_array(&result->scores, &results[0]->scores); } result->scores_sorted = TRUE; @@ -728,6 +733,7 @@ static int solr_search_multi(struct solr_fts_backend *backend, string_t *str, struct mailbox *const boxes[], + enum fts_lookup_flags flags, struct fts_multi_result *result) { struct solr_result **solr_results; @@ -784,7 +790,10 @@ } fts_result = array_append_space(&fts_results); fts_result->box = box; - fts_result->definite_uids = solr_results[i]->uids; + if ((flags & FTS_LOOKUP_FLAG_NO_AUTO_FUZZY) == 0) + fts_result->definite_uids = solr_results[i]->uids; + else + fts_result->maybe_uids = solr_results[i]->uids; fts_result->scores = solr_results[i]->scores; fts_result->scores_sorted = TRUE; } @@ -797,9 +806,11 @@ static int fts_backend_solr_lookup_multi(struct fts_backend *_backend, struct mailbox *const boxes[], - struct mail_search_arg *args, bool and_args, + struct mail_search_arg *args, + enum fts_lookup_flags flags, struct fts_multi_result *result) { + bool and_args = (flags & FTS_LOOKUP_FLAG_AND_ARGS) != 0; struct solr_fts_backend *backend = (struct solr_fts_backend *)_backend; string_t *str; @@ -811,7 +822,7 @@ SOLR_MAX_MULTI_ROWS); if (solr_add_definite_query_args(str, args, and_args)) { - if (solr_search_multi(backend, str, boxes, result) < 0) + if (solr_search_multi(backend, str, boxes, flags, result) < 0) return -1; } /* FIXME: maybe_uids could be handled also with some more work.. */ diff -r f206042d6286 -r cdf4edcc6256 src/plugins/fts-solr/fts-backend-solr.c --- a/src/plugins/fts-solr/fts-backend-solr.c Fri Aug 08 15:15:03 2014 +0300 +++ b/src/plugins/fts-solr/fts-backend-solr.c Fri Aug 08 16:20:31 2014 +0300 @@ -783,9 +783,11 @@ static int fts_backend_solr_lookup(struct fts_backend *_backend, struct mailbox *box, - struct mail_search_arg *args, bool and_args, + struct mail_search_arg *args, + enum fts_lookup_flags flags, struct fts_result *result) { + bool and_args = (flags & FTS_LOOKUP_FLAG_AND_ARGS) != 0; struct mailbox_status status; string_t *str; const char *box_guid; @@ -801,8 +803,11 @@ prefix_len = str_len(str); if (solr_add_definite_query_args(str, args, and_args)) { + ARRAY_TYPE(seq_range) *uids_arr = + (flags & FTS_LOOKUP_FLAG_NO_AUTO_FUZZY) == 0 ? + &result->definite_uids : &result->maybe_uids; if (solr_search(_backend, str, box_guid, - &result->definite_uids, &result->scores) < 0) + uids_arr, &result->scores) < 0) return -1; } str_truncate(str, prefix_len); @@ -817,7 +822,7 @@ static int solr_search_multi(struct fts_backend *_backend, string_t *str, - struct mailbox *const boxes[], + struct mailbox *const boxes[], enum fts_lookup_flags flags, struct fts_multi_result *result) From dovecot at dovecot.org Fri Aug 8 13:29:46 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 08 Aug 2014 13:29:46 +0000 Subject: dovecot-2.2: fts: fts_no_autofuzzy shouldn't disable fuzzying wh... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/1ea3da40ea8f changeset: 17690:1ea3da40ea8f user: Timo Sirainen date: Fri Aug 08 16:27:40 2014 +0300 description: fts: fts_no_autofuzzy shouldn't disable fuzzying when FUZZY search parameter is set. diffstat: src/plugins/fts/fts-storage.c | 24 +++++++++++++++++++++++- 1 files changed, 23 insertions(+), 1 deletions(-) diffs (41 lines): diff -r cdf4edcc6256 -r 1ea3da40ea8f src/plugins/fts/fts-storage.c --- a/src/plugins/fts/fts-storage.c Fri Aug 08 16:20:31 2014 +0300 +++ b/src/plugins/fts/fts-storage.c Fri Aug 08 16:27:40 2014 +0300 @@ -160,6 +160,25 @@ return FALSE; } +static bool fts_args_have_fuzzy(const struct mail_search_arg *args) +{ + for (; args != NULL; args = args->next) { + if (args->fuzzy) + return TRUE; + switch (args->type) { + case SEARCH_OR: + case SEARCH_SUB: + case SEARCH_INTHREAD: + if (fts_args_have_fuzzy(args->value.subargs)) + return TRUE; + break; + default: + break; + } + } + return FALSE; +} + static struct mail_search_context * fts_mailbox_search_init(struct mailbox_transaction_context *t, struct mail_search_args *args, @@ -194,7 +213,10 @@ i_array_init(&fctx->scores->score_map, 64); MODULE_CONTEXT_SET(ctx, fts_storage_module, fctx); - if (mail_user_plugin_getenv(t->box->storage->user, + /* FIXME: we'll assume that all the args are fuzzy. not good, + but would require much more work to fix it. */ + if (!fts_args_have_fuzzy(args->args) && + mail_user_plugin_getenv(t->box->storage->user, "fts_no_autofuzzy") != NULL) fctx->flags |= FTS_LOOKUP_FLAG_NO_AUTO_FUZZY; /* transaction contains the last search's scores. they can be From dovecot at dovecot.org Sat Aug 9 07:12:40 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Sat, 09 Aug 2014 07:12:40 +0000 Subject: dovecot-2.2: doveadm fs put: Added -h parameter to specif... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/73aedf57e311 changeset: 17691:73aedf57e311 user: Timo Sirainen date: Sat Aug 09 10:10:34 2014 +0300 description: doveadm fs put: Added -h parameter to specify the file's hash. The hash (in hex) is automatically detected to be either MD5 or SHA256 based on its size. If the fs backend doesn't support the hash it'll fail. Otherwise it'll make sure that the written file matches the given hash. diffstat: src/doveadm/doveadm-fs.c | 37 ++++++++++++++++++++++++++++++++++++- 1 files changed, 36 insertions(+), 1 deletions(-) diffs (72 lines): diff -r 1ea3da40ea8f -r 73aedf57e311 src/doveadm/doveadm-fs.c --- a/src/doveadm/doveadm-fs.c Fri Aug 08 16:27:40 2014 +0300 +++ b/src/doveadm/doveadm-fs.c Sat Aug 09 10:10:34 2014 +0300 @@ -2,6 +2,10 @@ #include "lib.h" #include "array.h" +#include "md5.h" +#include "sha2.h" +#include "hash-method.h" +#include "hex-binary.h" #include "istream.h" #include "ostream.h" #include "iostream-ssl.h" @@ -77,17 +81,48 @@ static void cmd_fs_put(int argc, char *argv[]) { struct fs *fs; + enum fs_properties props; const char *src_path, *dest_path; struct fs_file *file; struct istream *input; struct ostream *output; + buffer_t *hash = NULL; off_t ret; + int c; + + while ((c = getopt(argc, argv, "h:")) > 0) { + switch (c) { + case 'h': + hash = buffer_create_dynamic(pool_datastack_create(), 32); + if (hex_to_binary(optarg, hash) < 0) + i_fatal("Invalid -h parameter: Hash not in hex"); + break; + default: + fs_cmd_help(cmd_fs_put); + } + } + argc -= optind-1; argv += optind-1; fs = cmd_fs_init(&argc, &argv, 2, cmd_fs_put); src_path = argv[0]; dest_path = argv[1]; file = fs_file_init(fs, dest_path, FS_OPEN_MODE_REPLACE); + props = fs_get_properties(fs); + if (hash == NULL) + ; + else if (hash->used == hash_method_md5.digest_size) { + if ((props & FS_PROPERTY_WRITE_HASH_MD5) == 0) + i_fatal("fs backend doesn't support MD5 hashes"); + fs_write_set_hash(file, + hash_method_lookup(hash_method_md5.name), hash->data); + } else if (hash->used == hash_method_sha256.digest_size) { + if ((props & FS_PROPERTY_WRITE_HASH_SHA256) == 0) + i_fatal("fs backend doesn't support SHA256 hashes"); + fs_write_set_hash(file, + hash_method_lookup(hash_method_sha256.name), hash->data); + } + output = fs_write_stream(file); input = i_stream_create_file(src_path, IO_BLOCK_SIZE); if ((ret = o_stream_send_istream(output, input)) < 0) { @@ -383,7 +418,7 @@ struct doveadm_cmd doveadm_cmd_fs[] = { { cmd_fs_get, "fs get", " " }, - { cmd_fs_put, "fs put", " " }, + { cmd_fs_put, "fs put", "[-h ] " }, { cmd_fs_copy, "fs copy", " " }, { cmd_fs_stat, "fs stat", " " }, { cmd_fs_metadata, "fs metadata", " " }, From dovecot at dovecot.org Mon Aug 11 10:34:13 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 11 Aug 2014 10:34:13 +0000 Subject: dovecot-2.2: lib-mail: Message parser now always returns block->... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/f41d3c771627 changeset: 17692:f41d3c771627 user: Timo Sirainen date: Mon Aug 11 13:30:25 2014 +0300 description: lib-mail: Message parser now always returns block->data=NULL when it's not supposed to be used. diffstat: src/lib-mail/message-parser.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diffs (14 lines): diff -r 73aedf57e311 -r f41d3c771627 src/lib-mail/message-parser.c --- a/src/lib-mail/message-parser.c Sat Aug 09 10:10:34 2014 +0300 +++ b/src/lib-mail/message-parser.c Mon Aug 11 13:30:25 2014 +0300 @@ -1041,6 +1041,10 @@ } } + if (block_r->size == 0) { + /* data isn't supposed to be read, so make sure it's NULL */ + block_r->data = NULL; + } return ret; } From dovecot at dovecot.org Mon Aug 11 10:34:13 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 11 Aug 2014 10:34:13 +0000 Subject: dovecot-2.2: lib-mail: Added comments to message-parser.h Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/051a96b3960f changeset: 17693:051a96b3960f user: Timo Sirainen date: Mon Aug 11 13:32:06 2014 +0300 description: lib-mail: Added comments to message-parser.h diffstat: src/lib-mail/message-parser.h | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diffs (15 lines): diff -r f41d3c771627 -r 051a96b3960f src/lib-mail/message-parser.h --- a/src/lib-mail/message-parser.h Mon Aug 11 13:30:25 2014 +0300 +++ b/src/lib-mail/message-parser.h Mon Aug 11 13:32:06 2014 +0300 @@ -26,7 +26,10 @@ /* non-NULL if a header line was read */ struct message_header_line *hdr; - /* hdr = NULL, size = 0 block returned at the end of headers */ + /* hdr = NULL, size = 0 block returned at the end of headers for the + empty line between header and body (unless the header is truncated). + Later on data and size>0 is returned for blocks of mail body that + is read (see message_parser_flags for what is actually returned) */ const unsigned char *data; size_t size; }; From dovecot at dovecot.org Mon Aug 11 11:21:01 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 11 Aug 2014 11:21:01 +0000 Subject: dovecot-2.2: lib-http server: Call request destroy callback imme... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/0098ed2b4b50 changeset: 17694:0098ed2b4b50 user: Timo Sirainen date: Mon Aug 11 14:18:53 2014 +0300 description: lib-http server: Call request destroy callback immediately after response is finished sending. Regardless of any other references to the request. diffstat: src/lib-http/http-server-private.h | 1 + src/lib-http/http-server-request.c | 15 +++++++++++++-- src/lib-http/http-server.h | 6 +++++- 3 files changed, 19 insertions(+), 3 deletions(-) diffs (62 lines): diff -r 051a96b3960f -r 0098ed2b4b50 src/lib-http/http-server-private.h --- a/src/lib-http/http-server-private.h Mon Aug 11 13:32:06 2014 +0300 +++ b/src/lib-http/http-server-private.h Mon Aug 11 14:18:53 2014 +0300 @@ -157,6 +157,7 @@ struct http_server_request * http_server_request_new(struct http_server_connection *conn); +void http_server_request_destroy(struct http_server_request **_req); void http_server_request_abort(struct http_server_request **_req); void http_server_request_halt_payload(struct http_server_request *req); diff -r 051a96b3960f -r 0098ed2b4b50 src/lib-http/http-server-request.c --- a/src/lib-http/http-server-request.c Mon Aug 11 13:32:06 2014 +0300 +++ b/src/lib-http/http-server-request.c Mon Aug 11 14:18:53 2014 +0300 @@ -55,6 +55,17 @@ return FALSE; } +void http_server_request_destroy(struct http_server_request **_req) +{ + struct http_server_request *req = *_req; + + if (req->destroy_callback != NULL) { + req->destroy_callback(req->destroy_context); + req->destroy_callback = NULL; + } + http_server_request_unref(_req); +} + void http_server_request_set_destroy_callback(struct http_server_request *req, void (*callback)(void *), void *context) @@ -168,11 +179,11 @@ http_server_connection_close(&conn, "Client requested connection close"); } - http_server_request_unref(&req); + http_server_request_destroy(&req); return; } - http_server_request_unref(&req); + http_server_request_destroy(&req); if (tunnel_callback != NULL) { http_server_connection_tunnel(&conn, tunnel_callback, tunnel_context); return; diff -r 051a96b3960f -r 0098ed2b4b50 src/lib-http/http-server.h --- a/src/lib-http/http-server.h Mon Aug 11 13:32:06 2014 +0300 +++ b/src/lib-http/http-server.h Mon Aug 11 14:18:53 2014 +0300 @@ -81,7 +81,11 @@ void http_server_request_fail_close(struct http_server_request *req, unsigned int status, const char *reason); -/* Call the specified callback when HTTP request is destroyed. */ +/* Call the specified callback when HTTP request is destroyed. This always + happens only after the response and its payload is fully sent. (If request + headers aren't fully read, we never call the handle_request() callback. + The request body reading is the responsibility of the caller, which also + needs to handle its errors by sending a failure response.) */ void http_server_request_set_destroy_callback(struct http_server_request *req, void (*callback)(void *), void *context); From dovecot at dovecot.org Mon Aug 11 12:47:33 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 11 Aug 2014 12:47:33 +0000 Subject: dovecot-2.2: lib-http: Don't leak memory if HTTP client disconne... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/9f4529061c5d changeset: 17695:9f4529061c5d user: Timo Sirainen date: Mon Aug 11 15:45:21 2014 +0300 description: lib-http: Don't leak memory if HTTP client disconnects unexpectedly. http_server_connection_disconnect() has several cleanup calls, which weren't done because closed=TRUE was set explicitly and that skipped the cleanup. diffstat: src/lib-http/http-server-connection.c | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diffs (23 lines): diff -r 0098ed2b4b50 -r 9f4529061c5d src/lib-http/http-server-connection.c --- a/src/lib-http/http-server-connection.c Mon Aug 11 14:18:53 2014 +0300 +++ b/src/lib-http/http-server-connection.c Mon Aug 11 15:45:21 2014 +0300 @@ -17,6 +17,10 @@ #include "http-server-private.h" +static void +http_server_connection_disconnect(struct http_server_connection *conn, + const char *reason); + /* * Logging */ @@ -163,7 +167,7 @@ struct http_server_connection *conn = (struct http_server_connection *)_conn; - conn->closed = TRUE; + http_server_connection_disconnect(conn, NULL); http_server_connection_unref(&conn); } From dovecot at dovecot.org Mon Aug 11 12:48:30 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 11 Aug 2014 12:48:30 +0000 Subject: dovecot-2.2: lib-http: Call the destroy callback also when reque... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/33346832b1c2 changeset: 17696:33346832b1c2 user: Timo Sirainen date: Mon Aug 11 15:46:29 2014 +0300 description: lib-http: Call the destroy callback also when request is aborted. diffstat: src/lib-http/http-server-request.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 9f4529061c5d -r 33346832b1c2 src/lib-http/http-server-request.c --- a/src/lib-http/http-server-request.c Mon Aug 11 15:45:21 2014 +0300 +++ b/src/lib-http/http-server-request.c Mon Aug 11 15:46:29 2014 +0300 @@ -90,7 +90,7 @@ req->response = NULL; req->conn = conn; - http_server_request_unref(_req); + http_server_request_destroy(_req); } const struct http_request * From dovecot at dovecot.org Mon Aug 11 12:49:58 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 11 Aug 2014 12:49:58 +0000 Subject: dovecot-2.2: lib-http server: Added http_server_request_is_finis... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/0e04f9c171fc changeset: 17697:0e04f9c171fc user: Timo Sirainen date: Mon Aug 11 15:47:57 2014 +0300 description: lib-http server: Added http_server_request_is_finished() This is intended mainly to be used in asserts and such checks. diffstat: src/lib-http/http-server-request.c | 6 ++++++ src/lib-http/http-server.h | 4 ++++ 2 files changed, 10 insertions(+), 0 deletions(-) diffs (30 lines): diff -r 33346832b1c2 -r 0e04f9c171fc src/lib-http/http-server-request.c --- a/src/lib-http/http-server-request.c Mon Aug 11 15:46:29 2014 +0300 +++ b/src/lib-http/http-server-request.c Mon Aug 11 15:47:57 2014 +0300 @@ -111,6 +111,12 @@ return req->response; } +bool http_server_request_is_finished(struct http_server_request *req) +{ + return req->response != NULL || + req->state == HTTP_SERVER_REQUEST_STATE_ABORTED; +} + void http_server_request_halt_payload(struct http_server_request *req) { i_assert(req->state <= HTTP_SERVER_REQUEST_STATE_QUEUED); diff -r 33346832b1c2 -r 0e04f9c171fc src/lib-http/http-server.h --- a/src/lib-http/http-server.h Mon Aug 11 15:46:29 2014 +0300 +++ b/src/lib-http/http-server.h Mon Aug 11 15:47:57 2014 +0300 @@ -73,6 +73,10 @@ http_server_response_create(), or NULL if none. */ struct http_server_response * http_server_request_get_response(struct http_server_request *req); +/* Returns TRUE if request is finished either because a response was sent + or because the request was aborted. */ +bool http_server_request_is_finished(struct http_server_request *req); + /* Send a failure response to the request with given status/reason. */ void http_server_request_fail(struct http_server_request *req, unsigned int status, const char *reason); From dovecot at dovecot.org Mon Aug 11 12:57:12 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 11 Aug 2014 12:57:12 +0000 Subject: dovecot-2.2: lib: io_stream_copy() no longer attempts to read fu... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/e593dce9468d changeset: 17698:e593dce9468d user: Timo Sirainen date: Mon Aug 11 15:54:43 2014 +0300 description: lib: io_stream_copy() no longer attempts to read full block sizes from input. Although that may be more efficient for writing (to files), it causes unnecessary work for the input stream. The writing part should also be optimized anyway if the caller corks the output stream. diffstat: src/lib/iostream-temp.c | 6 ++---- src/lib/ostream-file.c | 3 +-- src/lib/ostream-private.h | 3 +-- src/lib/ostream.c | 15 +++++---------- 4 files changed, 9 insertions(+), 18 deletions(-) diffs (95 lines): diff -r 0e04f9c171fc -r e593dce9468d src/lib/iostream-temp.c --- a/src/lib/iostream-temp.c Mon Aug 11 15:47:57 2014 +0300 +++ b/src/lib/iostream-temp.c Mon Aug 11 15:54:43 2014 +0300 @@ -129,8 +129,7 @@ input = i_stream_create_limit(tstream->dupstream, size); do { - ret = io_stream_copy(&tstream->ostream.ostream, - input, IO_BLOCK_SIZE); + ret = io_stream_copy(&tstream->ostream.ostream, input); } while (input->v_offset < tstream->dupstream_offset && ret > 0); if (ret < 0 && tstream->ostream.ostream.stream_errno == 0) { i_assert(input->stream_errno != 0); @@ -187,8 +186,7 @@ return -1; outstream->flags &= ~IOSTREAM_TEMP_FLAG_TRY_FD_DUP; } - return io_stream_copy(&outstream->ostream.ostream, - instream, IO_BLOCK_SIZE); + return io_stream_copy(&outstream->ostream.ostream, instream); } static int diff -r 0e04f9c171fc -r e593dce9468d src/lib/ostream-file.c --- a/src/lib/ostream-file.c Mon Aug 11 15:47:57 2014 +0300 +++ b/src/lib/ostream-file.c Mon Aug 11 15:54:43 2014 +0300 @@ -857,8 +857,7 @@ } } - return io_stream_copy(&outstream->ostream, instream, - foutstream->optimal_block_size); + return io_stream_copy(&outstream->ostream, instream); } static off_t o_stream_file_send_istream(struct ostream_private *outstream, diff -r 0e04f9c171fc -r e593dce9468d src/lib/ostream-private.h --- a/src/lib/ostream-private.h Mon Aug 11 15:47:57 2014 +0300 +++ b/src/lib/ostream-private.h Mon Aug 11 15:54:43 2014 +0300 @@ -46,8 +46,7 @@ o_stream_create(struct ostream_private *_stream, struct ostream *parent, int fd) ATTR_NULL(2); -off_t io_stream_copy(struct ostream *outstream, struct istream *instream, - size_t block_size); +off_t io_stream_copy(struct ostream *outstream, struct istream *instream); void o_stream_copy_error_from_parent(struct ostream_private *_stream); /* This should be called before sending data to parent stream. It makes sure diff -r 0e04f9c171fc -r e593dce9468d src/lib/ostream.c --- a/src/lib/ostream.c Mon Aug 11 15:47:57 2014 +0300 +++ b/src/lib/ostream.c Mon Aug 11 15:54:43 2014 +0300 @@ -357,8 +357,7 @@ return ret; } -off_t io_stream_copy(struct ostream *outstream, struct istream *instream, - size_t block_size) +off_t io_stream_copy(struct ostream *outstream, struct istream *instream) { uoff_t start_offset; struct const_iovec iov; @@ -366,9 +365,8 @@ ssize_t ret; start_offset = instream->v_offset; - for (;;) { - (void)i_stream_read_data(instream, &data, &iov.iov_len, - block_size-1); + do { + (void)i_stream_read_data(instream, &data, &iov.iov_len, 0); if (iov.iov_len == 0) { /* all sent */ break; @@ -382,10 +380,7 @@ return -1; } i_stream_skip(instream, ret); - - if ((size_t)ret != iov.iov_len) - break; - } + } while ((size_t)ret == iov.iov_len); return (off_t)(instream->v_offset - start_offset); } @@ -528,7 +523,7 @@ static off_t o_stream_default_send_istream(struct ostream_private *outstream, struct istream *instream) { - return io_stream_copy(&outstream->ostream, instream, IO_BLOCK_SIZE); + return io_stream_copy(&outstream->ostream, instream); } static void o_stream_default_switch_ioloop(struct ostream_private *_stream) From dovecot at dovecot.org Mon Aug 11 12:57:12 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 11 Aug 2014 12:57:12 +0000 Subject: dovecot-2.2: lib-http server: Comment updates Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/531aad735130 changeset: 17699:531aad735130 user: Timo Sirainen date: Mon Aug 11 15:55:03 2014 +0300 description: lib-http server: Comment updates diffstat: src/lib-http/http-server-connection.c | 5 ++- src/lib-http/http-server.h | 36 ++++++++++++++++++++++++++-------- 2 files changed, 30 insertions(+), 11 deletions(-) diffs (80 lines): diff -r e593dce9468d -r 531aad735130 src/lib-http/http-server-connection.c --- a/src/lib-http/http-server-connection.c Mon Aug 11 15:54:43 2014 +0300 +++ b/src/lib-http/http-server-connection.c Mon Aug 11 15:55:03 2014 +0300 @@ -341,6 +341,7 @@ return TRUE; } + /* Request payload is still being uploaded by the client */ return FALSE; } @@ -438,13 +439,13 @@ conn->stats.request_count++; - /* handle request - req may be destroyed after this, so don't refer to it if ret > 0 */ http_server_request_ref(req); T_BEGIN { cont = http_server_connection_handle_request(conn, req); } T_END; if (!cont) { + /* connection closed or request body not read yet. + the request may be destroyed now. */ http_server_request_unref(&req); return; } diff -r e593dce9468d -r 531aad735130 src/lib-http/http-server.h --- a/src/lib-http/http-server.h Mon Aug 11 15:54:43 2014 +0300 +++ b/src/lib-http/http-server.h Mon Aug 11 15:55:03 2014 +0300 @@ -38,10 +38,23 @@ }; struct http_server_callbacks { - /* Reference the server request. Before returning you must either send - a response to the request or reference the request with - http_server_request_ref() and unreference it later after sending - the response. */ + /* Handle the server request. All requests must be sent back a response. + The response is sent either with http_server_request_fail*() or + http_server_response_submit*(). For simple requests you can send the + response back immediately. If you can't do that, you'll need to + reference the request. Then the code flow usually goes like this: + + - http_server_request_set_destroy_callback(destroy_callback) + - http_server_request_ref() + - + - http_server_response_create() + - http_server_response_set_payload() can be used especially with + istream-callback to create a large response without temp files. + - http_server_response_submit() triggers the destroy_callback + after it has finished sending the response and its payload. + - In destroy_callback: http_server_request_unref() and any other + necessary cleanup - the request handling is now fully finished. + */ void (*handle_request)(void *context, struct http_server_request *req); void (*handle_connect_request)(void *context, struct http_server_request *req, struct http_url *target); @@ -85,11 +98,16 @@ void http_server_request_fail_close(struct http_server_request *req, unsigned int status, const char *reason); -/* Call the specified callback when HTTP request is destroyed. This always - happens only after the response and its payload is fully sent. (If request - headers aren't fully read, we never call the handle_request() callback. - The request body reading is the responsibility of the caller, which also - needs to handle its errors by sending a failure response.) */ +/* Call the specified callback when HTTP request is destroyed. This happens + after one of the following: + + a) Response and its payload is fully sent + b) Response was submitted, but it couldn't be sent due to disconnection. + c) http_server_deinit() was called and the request was aborted + + Note client disconnection before response is submitted isn't visible to this. + The request payload reading is the responsibility of the caller, which also + must handle the read errors by submitting a failure response. */ void http_server_request_set_destroy_callback(struct http_server_request *req, void (*callback)(void *), void *context); From dovecot at dovecot.org Mon Aug 11 13:10:45 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 11 Aug 2014 13:10:45 +0000 Subject: dovecot-2.2: Compiler warning fix Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/2ce864f0176a changeset: 17700:2ce864f0176a user: Timo Sirainen date: Mon Aug 11 16:08:44 2014 +0300 description: Compiler warning fix diffstat: src/lib/ostream-file.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diffs (11 lines): diff -r 531aad735130 -r 2ce864f0176a src/lib/ostream-file.c --- a/src/lib/ostream-file.c Mon Aug 11 15:55:03 2014 +0300 +++ b/src/lib/ostream-file.c Mon Aug 11 16:08:44 2014 +0300 @@ -821,7 +821,6 @@ static off_t io_stream_copy_stream(struct ostream_private *outstream, struct istream *instream, bool same_stream) { - struct file_ostream *foutstream = (struct file_ostream *)outstream; uoff_t in_size; off_t in_abs_offset, ret = 0; From dovecot at dovecot.org Mon Aug 11 14:45:32 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 11 Aug 2014 14:45:32 +0000 Subject: dovecot-2.2: lib: Added istream-callback API Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/1b76af8a8ded changeset: 17701:1b76af8a8ded user: Timo Sirainen date: Mon Aug 11 17:43:25 2014 +0300 description: lib: Added istream-callback API diffstat: src/lib/Makefile.am | 2 + src/lib/istream-callback.c | 107 +++++++++++++++++++++++++++++++++++++++++++++ src/lib/istream-callback.h | 35 ++++++++++++++ 3 files changed, 144 insertions(+), 0 deletions(-) diffs (169 lines): diff -r 2ce864f0176a -r 1b76af8a8ded src/lib/Makefile.am --- a/src/lib/Makefile.am Mon Aug 11 16:08:44 2014 +0300 +++ b/src/lib/Makefile.am Mon Aug 11 17:43:25 2014 +0300 @@ -58,6 +58,7 @@ istream.c \ istream-base64-decoder.c \ istream-base64-encoder.c \ + istream-callback.c \ istream-chain.c \ istream-concat.c \ istream-crlf.c \ @@ -191,6 +192,7 @@ iso8601-date.h \ istream.h \ istream-base64.h \ + istream-callback.h \ istream-chain.h \ istream-concat.h \ istream-crlf.h \ diff -r 2ce864f0176a -r 1b76af8a8ded src/lib/istream-callback.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/istream-callback.c Mon Aug 11 17:43:25 2014 +0300 @@ -0,0 +1,107 @@ +/* Copyright (c) 2014 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "buffer.h" +#include "istream-private.h" +#include "istream-callback.h" + +struct callback_istream { + struct istream_private istream; + istream_callback_read_t *callback; + void *context; + + buffer_t *buf; + size_t pending_size; +}; + +static void i_stream_callback_destroy(struct iostream_private *stream) +{ + struct callback_istream *cstream = (struct callback_istream *)stream; + + buffer_free(&cstream->buf); +} + +static ssize_t i_stream_callback_read(struct istream_private *stream) +{ + struct callback_istream *cstream = (struct callback_istream *)stream; + size_t pos; + + if (cstream->callback == NULL) { + /* already returned EOF / error */ + stream->istream.eof = TRUE; + return -1; + } + + if (stream->skip > 0) { + buffer_delete(cstream->buf, 0, stream->skip); + stream->pos -= stream->skip; + stream->skip = 0; + } + pos = cstream->buf->used; + if (cstream->pending_size > 0) { + i_assert(pos >= cstream->pending_size); + pos -= cstream->pending_size; + cstream->pending_size = 0; + } else if (!cstream->callback(cstream->buf, cstream->context)) { + /* EOF / error */ + stream->istream.eof = TRUE; + cstream->callback = NULL; + if (cstream->buf->used == pos || + stream->istream.stream_errno != 0) + return -1; + /* EOF was returned with some data still added to the buffer. + return the buffer first and EOF only on the next call. */ + } else if (cstream->buf->used == pos) { + /* buffer full */ + i_assert(cstream->buf->used > 0); + return -2; + } + i_assert(cstream->buf->used > pos); + stream->buffer = cstream->buf->data; + stream->pos = cstream->buf->used; + return cstream->buf->used - pos; +} + +#undef i_stream_create_callback +struct istream * +i_stream_create_callback(istream_callback_read_t *callback, void *context) +{ + struct callback_istream *cstream; + struct istream *istream; + + i_assert(callback != NULL); + + cstream = i_new(struct callback_istream, 1); + cstream->callback = callback; + cstream->context = context; + cstream->buf = buffer_create_dynamic(default_pool, 1024); + + cstream->istream.iostream.destroy = i_stream_callback_destroy; + cstream->istream.read = i_stream_callback_read; + + istream = i_stream_create(&cstream->istream, NULL, -1); + istream->blocking = TRUE; + return istream; +} + +void i_stream_callback_append(struct istream *input, + const void *data, size_t size) +{ + struct callback_istream *cstream = + (struct callback_istream *)input->real_stream; + + buffer_append(cstream->buf, data, size); + cstream->pending_size += size; +} + +void i_stream_callback_append_str(struct istream *input, const char *str) +{ + i_stream_callback_append(input, str, strlen(str)); +} + +void i_stream_callback_set_error(struct istream *input, int stream_errno, + const char *error) +{ + input->stream_errno = stream_errno; + io_stream_set_error(&input->real_stream->iostream, "%s", error); +} diff -r 2ce864f0176a -r 1b76af8a8ded src/lib/istream-callback.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/istream-callback.h Mon Aug 11 17:43:25 2014 +0300 @@ -0,0 +1,35 @@ +#ifndef ISTREAM_CALLBACK_H +#define ISTREAM_CALLBACK_H + +/* istream-callback can be used to implement an istream that returns data + by calling the specified callback. The callback needs to do: + + a) Add data to buffer unless the buffer size is already too large + (the callback can decide by itself what is too large). Return TRUE + regardless of whether any data was added. + + b) Return FALSE when it's finished adding data or when it reaches an error. + On error i_stream_callback_set_error() must be called before returning. + + i_stream_add_destroy_callback() can be also added to do any cleanups that + the callback may need to do. +*/ +typedef bool istream_callback_read_t(buffer_t *buf, void *context); + +struct istream * +i_stream_create_callback(istream_callback_read_t *callback, void *context); +#define i_stream_create_callback(callback, context) \ + i_stream_create_callback(1 ? (istream_callback_read_t *)callback : \ + CALLBACK_TYPECHECK(callback, bool (*)(buffer_t *buf, typeof(context))), \ + context) + +/* Append data to the istream externally. Typically this is used to add a + header to the stream before the callbacks are called. */ +void i_stream_callback_append(struct istream *input, + const void *data, size_t size); +void i_stream_callback_append_str(struct istream *input, const char *str); + +void i_stream_callback_set_error(struct istream *input, int stream_errno, + const char *error); + +#endif From dovecot at dovecot.org Mon Aug 11 16:21:47 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 11 Aug 2014 16:21:47 +0000 Subject: dovecot-2.2: istream-callback: Added i_stream_callback_get_buffe... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/4cca68644428 changeset: 17702:4cca68644428 user: Timo Sirainen date: Mon Aug 11 19:19:45 2014 +0300 description: istream-callback: Added i_stream_callback_get_buffer(). diffstat: src/lib/istream-callback.c | 23 +++++++++++++++-------- src/lib/istream-callback.h | 4 ++++ 2 files changed, 19 insertions(+), 8 deletions(-) diffs (77 lines): diff -r 1b76af8a8ded -r 4cca68644428 src/lib/istream-callback.c --- a/src/lib/istream-callback.c Mon Aug 11 17:43:25 2014 +0300 +++ b/src/lib/istream-callback.c Mon Aug 11 19:19:45 2014 +0300 @@ -11,7 +11,7 @@ void *context; buffer_t *buf; - size_t pending_size; + size_t prev_pos; }; static void i_stream_callback_destroy(struct iostream_private *stream) @@ -35,13 +35,13 @@ if (stream->skip > 0) { buffer_delete(cstream->buf, 0, stream->skip); stream->pos -= stream->skip; + cstream->prev_pos -= stream->skip; stream->skip = 0; } - pos = cstream->buf->used; - if (cstream->pending_size > 0) { - i_assert(pos >= cstream->pending_size); - pos -= cstream->pending_size; - cstream->pending_size = 0; + i_assert(cstream->buf->used >= cstream->prev_pos); + pos = cstream->prev_pos; + if (cstream->buf->used > pos) { + /* data was added outside the callback */ } else if (!cstream->callback(cstream->buf, cstream->context)) { /* EOF / error */ stream->istream.eof = TRUE; @@ -58,7 +58,7 @@ } i_assert(cstream->buf->used > pos); stream->buffer = cstream->buf->data; - stream->pos = cstream->buf->used; + cstream->prev_pos = stream->pos = cstream->buf->used; return cstream->buf->used - pos; } @@ -91,7 +91,6 @@ (struct callback_istream *)input->real_stream; buffer_append(cstream->buf, data, size); - cstream->pending_size += size; } void i_stream_callback_append_str(struct istream *input, const char *str) @@ -99,6 +98,14 @@ i_stream_callback_append(input, str, strlen(str)); } +buffer_t *i_stream_callback_get_buffer(struct istream *input) +{ + struct callback_istream *cstream = + (struct callback_istream *)input->real_stream; + + return cstream->buf; +} + void i_stream_callback_set_error(struct istream *input, int stream_errno, const char *error) { diff -r 1b76af8a8ded -r 4cca68644428 src/lib/istream-callback.h --- a/src/lib/istream-callback.h Mon Aug 11 17:43:25 2014 +0300 +++ b/src/lib/istream-callback.h Mon Aug 11 19:19:45 2014 +0300 @@ -29,6 +29,10 @@ const void *data, size_t size); void i_stream_callback_append_str(struct istream *input, const char *str); +/* Returns the istream-callback's internal buffer. This buffer can be used to + append data to the stream. */ +buffer_t *i_stream_callback_get_buffer(struct istream *input); + void i_stream_callback_set_error(struct istream *input, int stream_errno, const char *error); From dovecot at dovecot.org Mon Aug 11 16:32:29 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 11 Aug 2014 16:32:29 +0000 Subject: dovecot-2.2: ostream-buffer: Allow modifying the buffer outside ... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/4968b36d9ac8 changeset: 17703:4968b36d9ac8 user: Timo Sirainen date: Mon Aug 11 19:30:15 2014 +0300 description: ostream-buffer: Allow modifying the buffer outside ostream, unless o_stream_seek() is used. Now we'll just append to the end of the buffer instead of forcibly trying to write at the offset where the last ostream write ended. diffstat: src/lib/ostream-buffer.c | 13 +++++++++---- 1 files changed, 9 insertions(+), 4 deletions(-) diffs (41 lines): diff -r 4cca68644428 -r 4968b36d9ac8 src/lib/ostream-buffer.c --- a/src/lib/ostream-buffer.c Mon Aug 11 19:19:45 2014 +0300 +++ b/src/lib/ostream-buffer.c Mon Aug 11 19:30:15 2014 +0300 @@ -7,10 +7,14 @@ struct buffer_ostream { struct ostream_private ostream; buffer_t *buf; + bool seeked; }; static int o_stream_buffer_seek(struct ostream_private *stream, uoff_t offset) { + struct buffer_ostream *bstream = (struct buffer_ostream *)stream; + + bstream->seeked = TRUE; stream->ostream.offset = offset; return 1; } @@ -30,17 +34,18 @@ const struct const_iovec *iov, unsigned int iov_count) { struct buffer_ostream *bstream = (struct buffer_ostream *)stream; - size_t left, n; + size_t left, n, offset; ssize_t ret = 0; unsigned int i; + offset = bstream->seeked ? stream->ostream.offset : bstream->buf->used; + for (i = 0; i < iov_count; i++) { left = bstream->ostream.max_buffer_size - stream->ostream.offset; n = I_MIN(left, iov[i].iov_len); - buffer_write(bstream->buf, stream->ostream.offset, - iov[i].iov_base, n); - stream->ostream.offset += n; + buffer_write(bstream->buf, offset, iov[i].iov_base, n); + stream->ostream.offset += n; offset += n; ret += n; if (n != iov[i].iov_len) break; From dovecot at dovecot.org Tue Aug 12 09:43:01 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 12 Aug 2014 09:43:01 +0000 Subject: dovecot-2.2: fts-lucene: If lucene-indexes dir is unexpectedly l... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/37eff3debe38 changeset: 17704:37eff3debe38 user: Timo Sirainen date: Tue Aug 12 12:39:46 2014 +0300 description: fts-lucene: If lucene-indexes dir is unexpectedly lost, rescan when expunge log update fails. This mainly fixes a repeating error about failing to open the expunge log. It should happen only if dovecot.index thinks that the mailbox is indexed while in reality the entire lucene-indexes directory doesn't exist. diffstat: src/plugins/fts-lucene/fts-backend-lucene.c | 12 +++++++++++- 1 files changed, 11 insertions(+), 1 deletions(-) diffs (23 lines): diff -r 4968b36d9ac8 -r 37eff3debe38 src/plugins/fts-lucene/fts-backend-lucene.c --- a/src/plugins/fts-lucene/fts-backend-lucene.c Mon Aug 11 19:30:15 2014 +0300 +++ b/src/plugins/fts-lucene/fts-backend-lucene.c Tue Aug 12 12:39:46 2014 +0300 @@ -272,8 +272,18 @@ } if (ctx->expunge_ctx != NULL) { - if (fts_expunge_log_append_commit(&ctx->expunge_ctx) < 0) + if (fts_expunge_log_append_commit(&ctx->expunge_ctx) < 0) { + struct stat st; + + if (stat(backend->dir_path, &st) < 0 && errno == ENOENT) { + /* lucene-indexes directory doesn't even exist, + so dovecot.index's last_index_uid is wrong. + rescan to update them. */ + (void)lucene_index_rescan(backend->index); + ret = 0; + } ret = -1; + } } if (fts_backend_lucene_need_optimize(ctx)) { From dovecot at dovecot.org Tue Aug 12 10:14:04 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 12 Aug 2014 10:14:04 +0000 Subject: dovecot-2.2: lib-http server: Delay calling the request's destro... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/40b07d1f7f6a changeset: 17705:40b07d1f7f6a user: Timo Sirainen date: Tue Aug 12 13:12:01 2014 +0300 description: lib-http server: Delay calling the request's destroy callback until handle_request() callback is finished. This simplifies the code in the handle_request() so it doesn't need to keep track of whether the response is already submitted or not. diffstat: src/lib-http/http-server-connection.c | 12 ++++++++++-- src/lib-http/http-server-private.h | 2 ++ src/lib-http/http-server-request.c | 4 +++- 3 files changed, 15 insertions(+), 3 deletions(-) diffs (58 lines): diff -r 37eff3debe38 -r 40b07d1f7f6a src/lib-http/http-server-connection.c --- a/src/lib-http/http-server-connection.c Tue Aug 12 12:39:46 2014 +0300 +++ b/src/lib-http/http-server-connection.c Tue Aug 12 13:12:01 2014 +0300 @@ -440,18 +440,26 @@ conn->stats.request_count++; http_server_request_ref(req); + i_assert(!req->delay_destroy); + req->delay_destroy = TRUE; T_BEGIN { cont = http_server_connection_handle_request(conn, req); } T_END; if (!cont) { /* connection closed or request body not read yet. the request may be destroyed now. */ - http_server_request_unref(&req); + if (req->destroy_pending) + http_server_request_destroy(&req); + else + http_server_request_unref(&req); return; } if (req->req.connection_close) conn->close_indicated = TRUE; - http_server_request_unref(&req); + if (req->destroy_pending) + http_server_request_destroy(&req); + else + http_server_request_unref(&req); /* client indicated it will close after this request; stop trying to read more. */ diff -r 37eff3debe38 -r 40b07d1f7f6a src/lib-http/http-server-private.h --- a/src/lib-http/http-server-private.h Tue Aug 12 12:39:46 2014 +0300 +++ b/src/lib-http/http-server-private.h Tue Aug 12 13:12:01 2014 +0300 @@ -82,6 +82,8 @@ unsigned int payload_halted:1; unsigned int sent_100_continue:1; + unsigned int delay_destroy:1; + unsigned int destroy_pending:1; unsigned int failed:1; }; diff -r 37eff3debe38 -r 40b07d1f7f6a src/lib-http/http-server-request.c --- a/src/lib-http/http-server-request.c Tue Aug 12 12:39:46 2014 +0300 +++ b/src/lib-http/http-server-request.c Tue Aug 12 13:12:01 2014 +0300 @@ -59,7 +59,9 @@ { struct http_server_request *req = *_req; - if (req->destroy_callback != NULL) { + if (req->delay_destroy) { + req->destroy_pending = TRUE; + } else if (req->destroy_callback != NULL) { req->destroy_callback(req->destroy_context); req->destroy_callback = NULL; } From dovecot at dovecot.org Tue Aug 12 11:46:24 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 12 Aug 2014 11:46:24 +0000 Subject: dovecot-2.2: stats: Added num_connected_sessions for domains and... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/f78d4b2bb6c3 changeset: 17706:f78d4b2bb6c3 user: Timo Sirainen date: Tue Aug 12 14:44:11 2014 +0300 description: stats: Added num_connected_sessions for domains and IPs. diffstat: src/stats/client-export.c | 12 +++++++----- src/stats/mail-domain.c | 23 ++++++++++++++++------- src/stats/mail-domain.h | 4 +++- src/stats/mail-ip.c | 8 ++++++++ src/stats/mail-ip.h | 1 + src/stats/mail-session.c | 9 ++++++++- src/stats/mail-stats.h | 2 ++ src/stats/mail-user.c | 9 +++++++-- src/stats/mail-user.h | 1 + 9 files changed, 53 insertions(+), 16 deletions(-) diffs (237 lines): diff -r 40b07d1f7f6a -r f78d4b2bb6c3 src/stats/client-export.c --- a/src/stats/client-export.c Tue Aug 12 13:12:01 2014 +0300 +++ b/src/stats/client-export.c Tue Aug 12 14:44:11 2014 +0300 @@ -401,7 +401,7 @@ if (!cmd->header_sent) { o_stream_nsend_str(client->output, "domain\treset_timestamp\tlast_update" - "\tnum_logins\tnum_cmds"MAIL_STATS_HEADER); + "\tnum_logins\tnum_cmds\tnum_connected_sessions"MAIL_STATS_HEADER); cmd->header_sent = TRUE; } @@ -415,8 +415,9 @@ str_append_tabescaped(cmd->str, domain->name); str_printfa(cmd->str, "\t%ld", (long)domain->reset_timestamp); client_export_timeval(cmd->str, &domain->last_update); - str_printfa(cmd->str, "\t%u\t%u", - domain->num_logins, domain->num_cmds); + str_printfa(cmd->str, "\t%u\t%u\t%u", + domain->num_logins, domain->num_cmds, + domain->num_connected_sessions); client_export_mail_stats(cmd->str, &domain->stats); str_append_c(cmd->str, '\n'); o_stream_nsend(client->output, str_data(cmd->str), @@ -442,7 +443,7 @@ if (!cmd->header_sent) { o_stream_nsend_str(client->output, "ip\treset_timestamp\tlast_update" - "\tnum_logins\tnum_cmds"MAIL_STATS_HEADER); + "\tnum_logins\tnum_cmds\tnum_connected_sessions"MAIL_STATS_HEADER); cmd->header_sent = TRUE; } @@ -458,7 +459,8 @@ } T_END; str_printfa(cmd->str, "\t%ld", (long)ip->reset_timestamp); client_export_timeval(cmd->str, &ip->last_update); - str_printfa(cmd->str, "\t%u\t%u", ip->num_logins, ip->num_cmds); + str_printfa(cmd->str, "\t%u\t%u\t%u", + ip->num_logins, ip->num_cmds, ip->num_connected_sessions); client_export_mail_stats(cmd->str, &ip->stats); str_append_c(cmd->str, '\n'); o_stream_nsend(client->output, str_data(cmd->str), diff -r 40b07d1f7f6a -r f78d4b2bb6c3 src/stats/mail-domain.c --- a/src/stats/mail-domain.c Tue Aug 12 13:12:01 2014 +0300 +++ b/src/stats/mail-domain.c Tue Aug 12 14:44:11 2014 +0300 @@ -19,14 +19,13 @@ return sizeof(*domain) + strlen(domain->name) + 1; } -struct mail_domain *mail_domain_login(const char *name) +struct mail_domain *mail_domain_login_create(const char *name) { struct mail_domain *domain; domain = hash_table_lookup(mail_domains_hash, name); if (domain != NULL) { - domain->num_logins++; - mail_domain_refresh(domain, NULL); + mail_domain_login(domain); return domain; } @@ -37,14 +36,24 @@ hash_table_insert(mail_domains_hash, domain->name, domain); DLLIST_PREPEND_FULL(&stable_mail_domains, domain, stable_prev, stable_next); - DLLIST2_APPEND_FULL(&mail_domains_head, &mail_domains_tail, domain, - sorted_prev, sorted_next); - domain->num_logins++; - domain->last_update = ioloop_timeval; + mail_domain_login(domain); global_memory_alloc(mail_domain_memsize(domain)); return domain; } +void mail_domain_login(struct mail_domain *domain) +{ + domain->num_logins++; + domain->num_connected_sessions++; + mail_domain_refresh(domain, NULL); +} + +void mail_domain_disconnected(struct mail_domain *domain) +{ + i_assert(domain->num_connected_sessions > 0); + domain->num_connected_sessions--; +} + struct mail_domain *mail_domain_lookup(const char *name) { return hash_table_lookup(mail_domains_hash, name); diff -r 40b07d1f7f6a -r f78d4b2bb6c3 src/stats/mail-domain.h --- a/src/stats/mail-domain.h Tue Aug 12 13:12:01 2014 +0300 +++ b/src/stats/mail-domain.h Tue Aug 12 14:44:11 2014 +0300 @@ -5,7 +5,9 @@ extern struct mail_domain *stable_mail_domains; -struct mail_domain *mail_domain_login(const char *name); +struct mail_domain *mail_domain_login_create(const char *name); +void mail_domain_login(struct mail_domain *domain); +void mail_domain_disconnected(struct mail_domain *domain); struct mail_domain *mail_domain_lookup(const char *name); void mail_domain_refresh(struct mail_domain *domain, const struct mail_stats *diff_stats) ATTR_NULL(2); diff -r 40b07d1f7f6a -r f78d4b2bb6c3 src/stats/mail-ip.c --- a/src/stats/mail-ip.c Tue Aug 12 13:12:01 2014 +0300 +++ b/src/stats/mail-ip.c Tue Aug 12 14:44:11 2014 +0300 @@ -26,6 +26,7 @@ ip = hash_table_lookup(mail_ips_hash, ip_addr); if (ip != NULL) { ip->num_logins++; + ip->num_connected_sessions++; mail_ip_refresh(ip, NULL); return ip; } @@ -39,11 +40,18 @@ DLLIST2_APPEND_FULL(&mail_ips_head, &mail_ips_tail, ip, sorted_prev, sorted_next); ip->num_logins++; + ip->num_connected_sessions++; ip->last_update = ioloop_timeval; global_memory_alloc(mail_ip_memsize(ip)); return ip; } +void mail_ip_disconnected(struct mail_ip *ip) +{ + i_assert(ip->num_connected_sessions > 0); + ip->num_connected_sessions--; +} + struct mail_ip *mail_ip_lookup(const struct ip_addr *ip_addr) { return hash_table_lookup(mail_ips_hash, ip_addr); diff -r 40b07d1f7f6a -r f78d4b2bb6c3 src/stats/mail-ip.h --- a/src/stats/mail-ip.h Tue Aug 12 13:12:01 2014 +0300 +++ b/src/stats/mail-ip.h Tue Aug 12 14:44:11 2014 +0300 @@ -4,6 +4,7 @@ extern struct mail_ip *stable_mail_ips; struct mail_ip *mail_ip_login(const struct ip_addr *ip_addr); +void mail_ip_disconnected(struct mail_ip *ip); struct mail_ip *mail_ip_lookup(const struct ip_addr *ip_addr); void mail_ip_refresh(struct mail_ip *ip, const struct mail_stats *diff_stats) ATTR_NULL(2); diff -r 40b07d1f7f6a -r f78d4b2bb6c3 src/stats/mail-session.c --- a/src/stats/mail-session.c Tue Aug 12 13:12:01 2014 +0300 +++ b/src/stats/mail-session.c Tue Aug 12 14:44:11 2014 +0300 @@ -40,6 +40,12 @@ { uint8_t *guid_p = session->guid; + i_assert(!session->disconnected); + + mail_user_disconnected(session->user); + if (session->ip != NULL) + mail_ip_disconnected(session->ip); + hash_table_remove(mail_sessions_hash, guid_p); session->disconnected = TRUE; timeout_remove(&session->to_idle); @@ -238,7 +244,8 @@ if ((ret = mail_session_lookup(args[0], &session, error_r)) <= 0) return ret; - mail_session_disconnect(session); + if (!session->disconnected) + mail_session_disconnect(session); return 0; } diff -r 40b07d1f7f6a -r f78d4b2bb6c3 src/stats/mail-stats.h --- a/src/stats/mail-stats.h Tue Aug 12 13:12:01 2014 +0300 +++ b/src/stats/mail-stats.h Tue Aug 12 14:44:11 2014 +0300 @@ -85,6 +85,7 @@ struct mail_stats stats; unsigned int num_logins; unsigned int num_cmds; + unsigned int num_connected_sessions; int refcount; struct mail_user *users; @@ -100,6 +101,7 @@ struct mail_stats stats; unsigned int num_logins; unsigned int num_cmds; + unsigned int num_connected_sessions; int refcount; struct mail_session *sessions; diff -r 40b07d1f7f6a -r f78d4b2bb6c3 src/stats/mail-user.c --- a/src/stats/mail-user.c Tue Aug 12 13:12:01 2014 +0300 +++ b/src/stats/mail-user.c Tue Aug 12 14:44:11 2014 +0300 @@ -28,8 +28,8 @@ user = hash_table_lookup(mail_users_hash, username); if (user != NULL) { user->num_logins++; - user->domain->num_logins++; mail_user_refresh(user, NULL); + mail_domain_login(user->domain); return user; } @@ -42,7 +42,7 @@ user = i_new(struct mail_user, 1); user->name = i_strdup(username); user->reset_timestamp = ioloop_time; - user->domain = mail_domain_login(domain); + user->domain = mail_domain_login_create(domain); hash_table_insert(mail_users_hash, user->name, user); DLLIST_PREPEND_FULL(&stable_mail_users, user, @@ -59,6 +59,11 @@ return user; } +void mail_user_disconnected(struct mail_user *user) +{ + mail_domain_disconnected(user->domain); +} + struct mail_user *mail_user_lookup(const char *username) { return hash_table_lookup(mail_users_hash, username); diff -r 40b07d1f7f6a -r f78d4b2bb6c3 src/stats/mail-user.h --- a/src/stats/mail-user.h Tue Aug 12 13:12:01 2014 +0300 +++ b/src/stats/mail-user.h Tue Aug 12 14:44:11 2014 +0300 @@ -6,6 +6,7 @@ extern struct mail_user *stable_mail_users; struct mail_user *mail_user_login(const char *username); +void mail_user_disconnected(struct mail_user *user); struct mail_user *mail_user_lookup(const char *username); void mail_user_refresh(struct mail_user *user, From dovecot at dovecot.org Tue Aug 12 15:50:17 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 12 Aug 2014 15:50:17 +0000 Subject: dovecot-2.2: virtual plugin: Optimized syncing a large number of... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/8abf7eea2966 changeset: 17707:8abf7eea2966 user: Timo Sirainen date: Tue Aug 12 18:48:03 2014 +0300 description: virtual plugin: Optimized syncing a large number of physical mailboxes. Especially when the number of mails was large the old code took a lot of CPU time. Based on patch by Teemu Huovila. diffstat: src/plugins/virtual/virtual-sync.c | 128 +++++++++++++++++++++++++++++------- 1 files changed, 102 insertions(+), 26 deletions(-) diffs (179 lines): diff -r f78d4b2bb6c3 -r 8abf7eea2966 src/plugins/virtual/virtual-sync.c --- a/src/plugins/virtual/virtual-sync.c Tue Aug 12 14:44:11 2014 +0300 +++ b/src/plugins/virtual/virtual-sync.c Tue Aug 12 18:48:03 2014 +0300 @@ -36,6 +36,11 @@ ARRAY_TYPE(seq_range) sync_expunges; ARRAY(struct virtual_add_record) all_adds; + + /* all messages in this sync */ + ARRAY(const struct virtual_mail_index_record) all_mails; + uint32_t all_mails_idx, all_mails_prev_mailbox_id; + enum mailbox_sync_flags flags; uint32_t uid_validity; @@ -629,45 +634,79 @@ } } +static void +virtual_sync_backend_add_vmsgs_results(struct virtual_sync_context *ctx, + struct virtual_backend_box *bbox, + uint32_t real_uid, + struct mail_search_result *result, + const uint32_t vseq) +{ + struct virtual_backend_uidmap uidmap; + uint32_t vuid, seq; + + mail_index_lookup_uid(ctx->sync_view, vseq, &vuid); + + memset(&uidmap, 0, sizeof(uidmap)); + uidmap.real_uid = real_uid; + uidmap.virtual_uid = vuid; + array_append(&bbox->uids, &uidmap, 1); + + if (result == NULL) + ; + else if (mail_index_lookup_seq(bbox->box->view, real_uid, &seq)) + seq_range_array_add(&result->uids, real_uid); + else + seq_range_array_add(&result->removed_uids, real_uid); +} + static void virtual_sync_backend_handle_old_vmsgs(struct virtual_sync_context *ctx, struct virtual_backend_box *bbox, struct mail_search_result *result) { - const struct virtual_mail_index_record *vrec; - struct virtual_backend_uidmap uidmap; + const struct virtual_mail_index_record *vrec, *vrecs; const void *data; - uint32_t seq, vseq, vuid, messages; + uint32_t vseq, messages; - /* add the currently existing UIDs to uidmap. remember the messages - that were already expunged */ - memset(&uidmap, 0, sizeof(uidmap)); + /* find the messages that currently exist in virtual index and add them + to the backend mailbox's list of uids. */ array_clear(&bbox->uids); - messages = mail_index_view_get_messages_count(ctx->sync_view); - for (vseq = 1; vseq <= messages; vseq++) { - mail_index_lookup_uid(ctx->sync_view, vseq, &vuid); - mail_index_lookup_ext(ctx->sync_view, vseq, - ctx->mbox->virtual_ext_id, &data, NULL); - vrec = data; - if (vrec->mailbox_id == bbox->mailbox_id) { - uidmap.real_uid = vrec->real_uid; - uidmap.virtual_uid = vuid; - array_append(&bbox->uids, &uidmap, 1); + if (array_is_created(&ctx->all_mails)) { + i_assert(ctx->all_mails_prev_mailbox_id < bbox->mailbox_id); + vrecs = array_get(&ctx->all_mails, &messages); + for (vseq = ctx->all_mails_idx + 1; vseq <= messages; vseq++) { + vrec = &vrecs[vseq - 1]; + if (vrec->mailbox_id != bbox->mailbox_id) { + if (vrec->mailbox_id < bbox->mailbox_id) { + /* stale mailbox_id, ignore */ + continue; + } + /* Should be in mailbox_id order, + so skip to next box */ + break; + } - if (result == NULL) - ; - else if (mail_index_lookup_seq(bbox->box->view, - vrec->real_uid, &seq)) { - seq_range_array_add(&result->uids, - vrec->real_uid); - } else { - seq_range_array_add(&result->removed_uids, - vrec->real_uid); + virtual_sync_backend_add_vmsgs_results(ctx, + bbox, vrec->real_uid, result, vseq); + } + ctx->all_mails_idx = vseq - 1; + ctx->all_mails_prev_mailbox_id = bbox->mailbox_id; + } else { + /* there should be only a single backend mailbox, but in the + existing index there may be stale mailbox_ids that we'll + just skip over. */ + messages = mail_index_view_get_messages_count(ctx->sync_view); + for (vseq = 1; vseq <= messages; vseq++) { + mail_index_lookup_ext(ctx->sync_view, vseq, + ctx->mbox->virtual_ext_id, &data, NULL); + vrec = data; + if (vrec->mailbox_id == bbox->mailbox_id) { + virtual_sync_backend_add_vmsgs_results(ctx, + bbox, vrec->real_uid, result, vseq); } } } - virtual_sync_bbox_uids_sort(bbox); } @@ -1442,6 +1481,33 @@ } } +static int +virtual_sync_mails_mailbox_cmp(const struct virtual_mail_index_record *v1, + const struct virtual_mail_index_record *v2) +{ + if (v1->mailbox_id < v2->mailbox_id) + return -1; + if (v1->mailbox_id > v2->mailbox_id) + return 1; + return 0; +} + +static void virtual_sync_bboxes_get_mails(struct virtual_sync_context *ctx) +{ + uint32_t messages, vseq; + const void *mail_data; + const struct virtual_mail_index_record *vrec; + + messages = mail_index_view_get_messages_count(ctx->sync_view); + for (vseq = 1; vseq <= messages; vseq++) { + mail_index_lookup_ext(ctx->sync_view, vseq, + ctx->mbox->virtual_ext_id, &mail_data, NULL); + vrec = mail_data; + array_append(&ctx->all_mails, vrec, 1); + } + array_sort(&ctx->all_mails, virtual_sync_mails_mailbox_cmp); +} + static int virtual_sync_backend_boxes(struct virtual_sync_context *ctx) { struct virtual_backend_box *const *bboxes; @@ -1453,6 +1519,14 @@ i_array_init(&ctx->all_adds, 128); bboxes = array_get(&ctx->mbox->backend_boxes, &count); + + /* we have different optimizations depending on whether the virtual + mailbox consists of multiple backend boxes or just one */ + if (count > 1) { + i_array_init(&ctx->all_mails, 128); + virtual_sync_bboxes_get_mails(ctx); + } + for (i = 0; i < count; i++) { if (virtual_sync_backend_box(ctx, bboxes[i]) < 0) { /* backend failed, copy the error */ @@ -1471,6 +1545,8 @@ } ret = virtual_sync_backend_add_new(ctx); array_free(&ctx->all_adds); + if (array_is_created(&ctx->all_mails)) + array_free(&ctx->all_mails); return ret; } From dovecot at dovecot.org Tue Aug 12 16:16:55 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 12 Aug 2014 16:16:55 +0000 Subject: dovecot-2.2: lib-storage: Added mail_storage_last_error_push/pop() Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/3e461af4f0ff changeset: 17708:3e461af4f0ff user: Timo Sirainen date: Tue Aug 12 19:05:14 2014 +0300 description: lib-storage: Added mail_storage_last_error_push/pop() diffstat: src/lib-storage/mail-storage-private.h | 6 ++++++ src/lib-storage/mail-storage.c | 27 +++++++++++++++++++++++++++ src/lib-storage/mail-storage.h | 6 ++++++ 3 files changed, 39 insertions(+), 0 deletions(-) diffs (83 lines): diff -r 8abf7eea2966 -r 3e461af4f0ff src/lib-storage/mail-storage-private.h --- a/src/lib-storage/mail-storage-private.h Tue Aug 12 18:48:03 2014 +0300 +++ b/src/lib-storage/mail-storage-private.h Tue Aug 12 19:05:14 2014 +0300 @@ -91,6 +91,11 @@ uoff_t size; }; +struct mail_storage_error { + char *error_string; + enum mail_error error; +}; + struct mail_storage { const char *name; enum mail_storage_class_flags class_flags; @@ -112,6 +117,7 @@ char *error_string; enum mail_error error; + ARRAY(struct mail_storage_error) error_stack; const struct mail_storage *storage_class; struct mail_user *user; diff -r 8abf7eea2966 -r 3e461af4f0ff src/lib-storage/mail-storage.c --- a/src/lib-storage/mail-storage.c Tue Aug 12 18:48:03 2014 +0300 +++ b/src/lib-storage/mail-storage.c Tue Aug 12 19:05:14 2014 +0300 @@ -432,6 +432,10 @@ storage->v.destroy(storage); i_free(storage->error_string); + if (array_is_created(&storage->error_stack)) { + i_assert(array_count(&storage->error_stack) == 0); + array_free(&storage->error_stack); + } *_storage = NULL; pool_unref(&storage->pool); @@ -595,6 +599,29 @@ return error; } +void mail_storage_last_error_push(struct mail_storage *storage) +{ + struct mail_storage_error *err; + + if (!array_is_created(&storage->error_stack)) + i_array_init(&storage->error_stack, 2); + err = array_append_space(&storage->error_stack); + err->error_string = i_strdup(storage->error_string); + err->error = storage->error; +} + +void mail_storage_last_error_pop(struct mail_storage *storage) +{ + unsigned int count = array_count(&storage->error_stack); + struct mail_storage_error *err = + array_idx(&storage->error_stack, count-1); + + i_free(storage->error_string); + storage->error_string = err->error_string; + storage->error = err->error; + array_delete(&storage->error_stack, count-1, 1); +} + bool mail_storage_is_mailbox_file(struct mail_storage *storage) { return (storage->class_flags & diff -r 8abf7eea2966 -r 3e461af4f0ff src/lib-storage/mail-storage.h --- a/src/lib-storage/mail-storage.h Tue Aug 12 18:48:03 2014 +0300 +++ b/src/lib-storage/mail-storage.h Tue Aug 12 19:05:14 2014 +0300 @@ -460,6 +460,12 @@ /* Wrapper for mail_storage_get_last_error(); */ enum mail_error mailbox_get_last_mail_error(struct mailbox *box); +/* Save the last error until it's popped. This is useful for cases where the + storage has already failed, but the cleanup code path changes the error to + something else unwanted. */ +void mail_storage_last_error_push(struct mail_storage *storage); +void mail_storage_last_error_pop(struct mail_storage *storage); + /* Returns TRUE if mailboxes are files. */ bool mail_storage_is_mailbox_file(struct mail_storage *storage) ATTR_PURE; From dovecot at dovecot.org Tue Aug 12 16:16:55 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 12 Aug 2014 16:16:55 +0000 Subject: dovecot-2.2: mailbox_list_index=yes: Make sure storage error doe... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/8948c0d91369 changeset: 17709:8948c0d91369 user: Timo Sirainen date: Tue Aug 12 19:12:04 2014 +0300 description: mailbox_list_index=yes: Make sure storage error doesn't change when updating STATUS info. diffstat: src/lib-storage/list/mailbox-list-index-status.c | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-) diffs (28 lines): diff -r 3e461af4f0ff -r 8948c0d91369 src/lib-storage/list/mailbox-list-index-status.c --- a/src/lib-storage/list/mailbox-list-index-status.c Tue Aug 12 19:05:14 2014 +0300 +++ b/src/lib-storage/list/mailbox-list-index-status.c Tue Aug 12 19:12:04 2014 +0300 @@ -515,7 +515,11 @@ return -1; ctx = NULL; + /* it probably doesn't matter much here if we push/pop the error, + but might as well do it. */ + mail_storage_last_error_push(mailbox_get_storage(box)); (void)index_list_update_mailbox(box); + mail_storage_last_error_pop(mailbox_get_storage(box)); return 0; } @@ -530,7 +534,12 @@ return -1; t = NULL; + /* this transaction commit may have been done in error handling path + and the caller still wants to access the current error. make sure + that whatever we do here won't change the error. */ + mail_storage_last_error_push(mailbox_get_storage(box)); (void)index_list_update_mailbox(box); + mail_storage_last_error_pop(mailbox_get_storage(box)); return 0; } From dovecot at dovecot.org Tue Aug 12 16:26:12 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 12 Aug 2014 16:26:12 +0000 Subject: dovecot-2.2: virtual plugin: Handle physical mailbox deletion wh... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/0ff4dde5490a changeset: 17710:0ff4dde5490a user: Timo Sirainen date: Tue Aug 12 19:24:10 2014 +0300 description: virtual plugin: Handle physical mailbox deletion while virtual mailbox is open. diffstat: src/plugins/virtual/virtual-sync.c | 24 ++++++++++++++++++++++-- 1 files changed, 22 insertions(+), 2 deletions(-) diffs (41 lines): diff -r 8948c0d91369 -r 0ff4dde5490a src/plugins/virtual/virtual-sync.c --- a/src/plugins/virtual/virtual-sync.c Tue Aug 12 19:12:04 2014 +0300 +++ b/src/plugins/virtual/virtual-sync.c Tue Aug 12 19:24:10 2014 +0300 @@ -1061,6 +1061,21 @@ ctx->ext_header_changed = TRUE; } +static void virtual_sync_backend_box_deleted(struct virtual_sync_context *ctx, + struct virtual_backend_box *bbox) +{ + ARRAY_TYPE(seq_range) removed_uids; + const struct virtual_backend_uidmap *uidmap; + + /* delay its full removal until the next time we open the virtual + mailbox. for now just treat it as if it was empty. */ + + t_array_init(&removed_uids, 128); + array_foreach(&bbox->uids, uidmap) + seq_range_array_add(&removed_uids, uidmap->real_uid); + virtual_sync_mailbox_box_remove(ctx, bbox, &removed_uids); +} + static int virtual_sync_backend_box(struct virtual_sync_context *ctx, struct virtual_backend_box *bbox) { @@ -1102,8 +1117,13 @@ &status); if (!bbox_index_opened && bbox->box->opened) virtual_backend_box_opened(ctx->mbox, bbox); - if (ret < 0) - return -1; + if (ret < 0) { + if (mailbox_get_last_mail_error(bbox->box) != MAIL_ERROR_NOTFOUND) + return -1; + /* mailbox was deleted */ + virtual_sync_backend_box_deleted(ctx, bbox); + return 0; + } if (status.uidvalidity == bbox->sync_uid_validity && status.uidnext == bbox->sync_next_uid && status.highest_modseq == bbox->sync_highest_modseq) { From dovecot at dovecot.org Tue Aug 12 16:32:38 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 12 Aug 2014 16:32:38 +0000 Subject: dovecot-2.2: Compiler warning fix Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/0150ca67d7f7 changeset: 17711:0150ca67d7f7 user: Timo Sirainen date: Tue Aug 12 19:30:37 2014 +0300 description: Compiler warning fix diffstat: src/lib-storage/mail-storage.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 0ff4dde5490a -r 0150ca67d7f7 src/lib-storage/mail-storage.c --- a/src/lib-storage/mail-storage.c Tue Aug 12 19:24:10 2014 +0300 +++ b/src/lib-storage/mail-storage.c Tue Aug 12 19:30:37 2014 +0300 @@ -613,7 +613,7 @@ void mail_storage_last_error_pop(struct mail_storage *storage) { unsigned int count = array_count(&storage->error_stack); - struct mail_storage_error *err = + const struct mail_storage_error *err = array_idx(&storage->error_stack, count-1); i_free(storage->error_string); From dovecot at dovecot.org Wed Aug 13 09:53:45 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 13 Aug 2014 09:53:45 +0000 Subject: dovecot-2.2: virtual plugin: Optimized memory allocation. Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/e7c5944ba16b changeset: 17712:e7c5944ba16b user: Timo Sirainen date: Wed Aug 13 12:51:41 2014 +0300 description: virtual plugin: Optimized memory allocation. Patch by Teemu Huovila. diffstat: src/plugins/virtual/virtual-sync.c | 5 ++--- 1 files changed, 2 insertions(+), 3 deletions(-) diffs (23 lines): diff -r 0150ca67d7f7 -r e7c5944ba16b src/plugins/virtual/virtual-sync.c --- a/src/plugins/virtual/virtual-sync.c Tue Aug 12 19:30:37 2014 +0300 +++ b/src/plugins/virtual/virtual-sync.c Wed Aug 13 12:51:41 2014 +0300 @@ -1519,6 +1519,7 @@ const struct virtual_mail_index_record *vrec; messages = mail_index_view_get_messages_count(ctx->sync_view); + i_array_init(&ctx->all_mails, messages); for (vseq = 1; vseq <= messages; vseq++) { mail_index_lookup_ext(ctx->sync_view, vseq, ctx->mbox->virtual_ext_id, &mail_data, NULL); @@ -1542,10 +1543,8 @@ /* we have different optimizations depending on whether the virtual mailbox consists of multiple backend boxes or just one */ - if (count > 1) { - i_array_init(&ctx->all_mails, 128); + if (count > 1) virtual_sync_bboxes_get_mails(ctx); - } for (i = 0; i < count; i++) { if (virtual_sync_backend_box(ctx, bboxes[i]) < 0) { From dovecot at dovecot.org Wed Aug 13 10:36:29 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 13 Aug 2014 10:36:29 +0000 Subject: dovecot-2.2: lib-http: server_request/connection - improve encap... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/c810e288aaed changeset: 17713:c810e288aaed user: Phil Carmody date: Wed Aug 13 13:34:22 2014 +0300 description: lib-http: server_request/connection - improve encapsulation It just feels a bit dirty having the request mess around with the connection's internals, have the connection manage its linked lists itself. No functional changes. Signed-off-by: Phil Carmody diffstat: src/lib-http/http-server-private.h | 14 ++++++++++++++ src/lib-http/http-server-request.c | 17 ++++++----------- 2 files changed, 20 insertions(+), 11 deletions(-) diffs (86 lines): diff -r e7c5944ba16b -r c810e288aaed src/lib-http/http-server-private.h --- a/src/lib-http/http-server-private.h Wed Aug 13 12:51:41 2014 +0300 +++ b/src/lib-http/http-server-private.h Wed Aug 13 13:34:22 2014 +0300 @@ -4,6 +4,7 @@ #include "connection.h" #include "http-server.h" +#include "llist.h" #define HTTP_SERVER_REQUEST_MAX_TARGET_LENGTH 4096 @@ -201,4 +202,17 @@ http_server_tunnel_callback_t callback, void *context); bool http_server_connection_pending_payload(struct http_server_connection *conn); +static inline void http_server_connection_add_request(struct http_server_connection *conn, + struct http_server_request *sreq) +{ + DLLIST2_APPEND(&conn->request_queue_head, &conn->request_queue_tail, sreq); + conn->request_queue_count++; +} +static inline void http_server_connection_remove_request(struct http_server_connection *conn, + struct http_server_request *sreq) +{ + DLLIST2_REMOVE(&conn->request_queue_head, &conn->request_queue_tail, sreq); + conn->request_queue_count--; +} + #endif diff -r e7c5944ba16b -r c810e288aaed src/lib-http/http-server-request.c --- a/src/lib-http/http-server-request.c Wed Aug 13 12:51:41 2014 +0300 +++ b/src/lib-http/http-server-request.c Wed Aug 13 13:34:22 2014 +0300 @@ -1,7 +1,6 @@ /* Copyright (c) 2013-2014 Dovecot authors, see the included COPYING file */ #include "lib.h" -#include "llist.h" #include "http-server-private.h" @@ -18,8 +17,7 @@ req->conn = conn; req->server = conn->server; - DLLIST2_APPEND(&conn->request_queue_head, &conn->request_queue_tail, req); - conn->request_queue_count++; + http_server_connection_add_request(conn, req); return req; } @@ -37,10 +35,9 @@ if (--req->refcount > 0) return TRUE; - if (req->state < HTTP_SERVER_REQUEST_STATE_FINISHED) { + if (req->state < HTTP_SERVER_REQUEST_STATE_FINISHED) { req->state = HTTP_SERVER_REQUEST_STATE_ABORTED; - DLLIST2_REMOVE(&conn->request_queue_head, &conn->request_queue_tail, req); - conn->request_queue_count--; + http_server_connection_remove_request(conn, req); } if (req->destroy_callback != NULL) { @@ -81,10 +78,9 @@ struct http_server_request *req = *_req; struct http_server_connection *conn = req->conn; - if (req->state < HTTP_SERVER_REQUEST_STATE_FINISHED) { + if (req->state < HTTP_SERVER_REQUEST_STATE_FINISHED) { req->state = HTTP_SERVER_REQUEST_STATE_ABORTED; - DLLIST2_REMOVE(&conn->request_queue_head, &conn->request_queue_tail, req); - conn->request_queue_count--; + http_server_connection_remove_request(conn, req); } if (req->response != NULL) @@ -173,8 +169,7 @@ i_assert(req->state < HTTP_SERVER_REQUEST_STATE_FINISHED); req->state = HTTP_SERVER_REQUEST_STATE_FINISHED; - DLLIST2_REMOVE(&conn->request_queue_head, &conn->request_queue_tail, req); - conn->request_queue_count--; + http_server_connection_remove_request(conn, req); conn->stats.response_count++; if (tunnel_callback == NULL && (req->req.connection_close || resp->close)) { From dovecot at dovecot.org Fri Aug 15 11:00:54 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 15 Aug 2014 11:00:54 +0000 Subject: dovecot-2.2: auth: Internal passdb failures were always failing ... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/14082c2d81dd changeset: 17714:14082c2d81dd user: Timo Sirainen date: Fri Aug 15 13:58:47 2014 +0300 description: auth: Internal passdb failures were always failing the request even if another passdb succeeded later. diffstat: src/auth/auth-request.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diffs (21 lines): diff -r c810e288aaed -r 14082c2d81dd src/auth/auth-request.c --- a/src/auth/auth-request.c Wed Aug 13 13:34:22 2014 +0300 +++ b/src/auth/auth-request.c Fri Aug 15 13:58:47 2014 +0300 @@ -651,14 +651,14 @@ request->passdbs_seen_internal_failure = TRUE; } return FALSE; + } else if (request->passdb_success) { + /* either this or a previous passdb lookup succeeded. */ + *result = PASSDB_RESULT_OK; } else if (request->passdbs_seen_internal_failure) { /* last passdb lookup returned internal failure. it may have had the correct password, so return internal failure instead of plain failure. */ *result = PASSDB_RESULT_INTERNAL_FAILURE; - } else if (request->passdb_success) { - /* either this or a previous passdb lookup succeeded. */ - *result = PASSDB_RESULT_OK; } return TRUE; } From dovecot at dovecot.org Fri Aug 15 11:07:34 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 15 Aug 2014 11:07:34 +0000 Subject: dovecot-2.2: ldap: Treat "No such object" errors to search the s... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/5e818f1b376d changeset: 17715:5e818f1b376d user: Timo Sirainen date: Fri Aug 15 14:05:21 2014 +0300 description: ldap: Treat "No such object" errors to search the same as if no results were returned. Trying to look up a nonexistent base returns this error. diffstat: src/auth/db-ldap.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diffs (14 lines): diff -r 14082c2d81dd -r 5e818f1b376d src/auth/db-ldap.c --- a/src/auth/db-ldap.c Fri Aug 15 13:58:47 2014 +0300 +++ b/src/auth/db-ldap.c Fri Aug 15 14:05:21 2014 +0300 @@ -760,7 +760,9 @@ final_result = TRUE; ret = ldap_result2error(conn->ld, res->msg, 0); } - if (ret != LDAP_SUCCESS && request->type == LDAP_REQUEST_TYPE_SEARCH) { + /* LDAP_NO_SUCH_OBJECT is returned for nonexistent base */ + if (ret != LDAP_SUCCESS && ret != LDAP_NO_SUCH_OBJECT && + request->type == LDAP_REQUEST_TYPE_SEARCH) { /* handle search failures here */ struct ldap_request_search *srequest = (struct ldap_request_search *)request; From dovecot at dovecot.org Fri Aug 15 11:43:28 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 15 Aug 2014 11:43:28 +0000 Subject: dovecot-2.2: Handle "out of disk space" and "out of user quota" ... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/286da24ada43 changeset: 17716:286da24ada43 user: Timo Sirainen date: Fri Aug 15 14:41:03 2014 +0300 description: Handle "out of disk space" and "out of user quota" as separate cases. "Out of disk space" is a temporary error that should be logged as error and the failure should be sent to user as "Internal server error". Obsolete the use of MAIL_ERROR_NOSPACE and MAIL_ERRSTR_NO_SPACE. Use the clearer MAIL_ERROR_NOQUOTA and MAIL_ERRSTR_NO_QUOTA instead. diffstat: src/doveadm/doveadm-mail.c | 2 +- src/imap/imap-commands-util.c | 2 +- src/lda/main.c | 2 +- src/lib-storage/index/imapc/imapc-storage.c | 2 +- src/lib-storage/index/maildir/maildir-copy.c | 4 ++-- src/lib-storage/index/maildir/maildir-save.c | 14 +++++++------- src/lib-storage/index/mbox/mbox-storage.c | 4 ++-- src/lib-storage/mail-error.c | 6 +++--- src/lib-storage/mail-error.h | 11 ++++++++--- src/lib/compat.h | 4 ++++ src/lmtp/commands.c | 4 ++-- src/plugins/quota/quota-storage.c | 6 +++--- src/plugins/snarf/snarf-plugin.c | 2 +- src/pop3/pop3-client.c | 2 +- 14 files changed, 37 insertions(+), 28 deletions(-) diffs (260 lines): diff -r 5e818f1b376d -r 286da24ada43 src/doveadm/doveadm-mail.c --- a/src/doveadm/doveadm-mail.c Fri Aug 15 14:05:21 2014 +0300 +++ b/src/doveadm/doveadm-mail.c Fri Aug 15 14:41:03 2014 +0300 @@ -57,7 +57,7 @@ case MAIL_ERROR_PERM: exit_code = EX_NOPERM; break; - case MAIL_ERROR_NOSPACE: + case MAIL_ERROR_NOQUOTA: exit_code = EX_CANTCREAT; break; case MAIL_ERROR_NOTFOUND: diff -r 5e818f1b376d -r 286da24ada43 src/imap/imap-commands-util.c --- a/src/imap/imap-commands-util.c Fri Aug 15 14:05:21 2014 +0300 +++ b/src/imap/imap-commands-util.c Fri Aug 15 14:41:03 2014 +0300 @@ -133,7 +133,7 @@ case MAIL_ERROR_PERM: resp_code = IMAP_RESP_CODE_NOPERM; break; - case MAIL_ERROR_NOSPACE: + case MAIL_ERROR_NOQUOTA: resp_code = IMAP_RESP_CODE_OVERQUOTA; break; case MAIL_ERROR_NOTFOUND: diff -r 5e818f1b376d -r 286da24ada43 src/lda/main.c --- a/src/lda/main.c Fri Aug 15 14:05:21 2014 +0300 +++ b/src/lda/main.c Fri Aug 15 14:41:03 2014 +0300 @@ -452,7 +452,7 @@ fprintf(stderr, "%s\n", errstr); } - if (error != MAIL_ERROR_NOSPACE || + if (error != MAIL_ERROR_NOQUOTA || ctx.set->quota_full_tempfail) { /* Saving to INBOX should always work unless we're over quota. If it didn't, it's probably a diff -r 5e818f1b376d -r 286da24ada43 src/lib-storage/index/imapc/imapc-storage.c --- a/src/lib-storage/index/imapc/imapc-storage.c Fri Aug 15 14:05:21 2014 +0300 +++ b/src/lib-storage/index/imapc/imapc-storage.c Fri Aug 15 14:41:03 2014 +0300 @@ -45,7 +45,7 @@ /* { IMAP_RESP_CODE_CLIENTBUG, 0 }, */ { IMAP_RESP_CODE_CANNOT, MAIL_ERROR_NOTPOSSIBLE }, { IMAP_RESP_CODE_LIMIT, MAIL_ERROR_NOTPOSSIBLE }, - { IMAP_RESP_CODE_OVERQUOTA, MAIL_ERROR_NOSPACE }, + { IMAP_RESP_CODE_OVERQUOTA, MAIL_ERROR_NOQUOTA }, { IMAP_RESP_CODE_ALREADYEXISTS, MAIL_ERROR_EXISTS }, { IMAP_RESP_CODE_NONEXISTENT, MAIL_ERROR_NOTFOUND } }; diff -r 5e818f1b376d -r 286da24ada43 src/lib-storage/index/maildir/maildir-copy.c --- a/src/lib-storage/index/maildir/maildir-copy.c Fri Aug 15 14:05:21 2014 +0300 +++ b/src/lib-storage/index/maildir/maildir-copy.c Fri Aug 15 14:41:03 2014 +0300 @@ -34,9 +34,9 @@ if (errno == ENOENT) return 0; - if (ENOSPACE(errno)) { + if (ENOQUOTA(errno)) { mail_storage_set_error(&mbox->storage->storage, - MAIL_ERROR_NOSPACE, MAIL_ERRSTR_NO_SPACE); + MAIL_ERROR_NOQUOTA, MAIL_ERRSTR_NO_QUOTA); return -1; } diff -r 5e818f1b376d -r 286da24ada43 src/lib-storage/index/maildir/maildir-save.c --- a/src/lib-storage/index/maildir/maildir-save.c Fri Aug 15 14:05:21 2014 +0300 +++ b/src/lib-storage/index/maildir/maildir-save.c Fri Aug 15 14:41:03 2014 +0300 @@ -102,9 +102,9 @@ if (rename(tmp_path, new_path) == 0) { mf->flags |= MAILDIR_FILENAME_FLAG_MOVED; return 0; - } else if (ENOSPACE(errno)) { - mail_storage_set_error(storage, MAIL_ERROR_NOSPACE, - MAIL_ERRSTR_NO_SPACE); + } else if (ENOQUOTA(errno)) { + mail_storage_set_error(storage, MAIL_ERROR_NOQUOTA, + MAIL_ERRSTR_NO_QUOTA); return -1; } else { mail_storage_set_critical(storage, "rename(%s, %s) failed: %m", @@ -376,9 +376,9 @@ *fname_r = tmp_fname; if (fd == -1) { - if (ENOSPACE(errno)) { + if (ENOQUOTA(errno)) { mail_storage_set_error(box->storage, - MAIL_ERROR_NOSPACE, MAIL_ERRSTR_NO_SPACE); + MAIL_ERROR_NOQUOTA, MAIL_ERRSTR_NO_QUOTA); } else { mail_storage_set_critical(box->storage, "open(%s) failed: %m", str_c(path)); @@ -630,9 +630,9 @@ } errno = output_errno; - if (ENOSPACE(errno)) { + if (ENOQUOTA(errno)) { mail_storage_set_error(storage, - MAIL_ERROR_NOSPACE, MAIL_ERRSTR_NO_SPACE); + MAIL_ERROR_NOQUOTA, MAIL_ERRSTR_NO_QUOTA); } else if (errno != 0) { mail_storage_set_critical(storage, "write(%s) failed: %m", path); diff -r 5e818f1b376d -r 286da24ada43 src/lib-storage/index/mbox/mbox-storage.c --- a/src/lib-storage/index/mbox/mbox-storage.c Fri Aug 15 14:05:21 2014 +0300 +++ b/src/lib-storage/index/mbox/mbox-storage.c Fri Aug 15 14:41:03 2014 +0300 @@ -72,9 +72,9 @@ { i_assert(function != NULL); - if (ENOSPACE(errno)) { + if (ENOQUOTA(errno)) { mail_storage_set_error(&mbox->storage->storage, - MAIL_ERROR_NOSPACE, MAIL_ERRSTR_NO_SPACE); + MAIL_ERROR_NOQUOTA, MAIL_ERRSTR_NO_QUOTA); } else { const char *toobig_error = errno != EFBIG ? "" : " (process was started with ulimit -f limit)"; diff -r 5e818f1b376d -r 286da24ada43 src/lib-storage/mail-error.c --- a/src/lib-storage/mail-error.c Fri Aug 15 14:05:21 2014 +0300 +++ b/src/lib-storage/mail-error.c Fri Aug 15 14:41:03 2014 +0300 @@ -10,9 +10,9 @@ if (ENOACCESS(errno)) { *error_r = MAIL_ERROR_PERM; *error_string_r = MAIL_ERRSTR_NO_PERMISSION; - } else if (ENOSPACE(errno)) { - *error_r = MAIL_ERROR_NOSPACE; - *error_string_r = MAIL_ERRSTR_NO_SPACE; + } else if (ENOQUOTA(errno)) { + *error_r = MAIL_ERROR_NOQUOTA; + *error_string_r = MAIL_ERRSTR_NO_QUOTA; } else if (ENOTFOUND(errno)) { *error_r = MAIL_ERROR_NOTFOUND; *error_string_r = errno != ELOOP ? "Not found" : diff -r 5e818f1b376d -r 286da24ada43 src/lib-storage/mail-error.h --- a/src/lib-storage/mail-error.h Fri Aug 15 14:05:21 2014 +0300 +++ b/src/lib-storage/mail-error.h Fri Aug 15 14:41:03 2014 +0300 @@ -7,7 +7,9 @@ #define MAIL_ERRSTR_NO_PERMISSION "Permission denied" /* And just for making error strings consistent: */ -#define MAIL_ERRSTR_NO_SPACE "Not enough disk space" +#define MAIL_ERRSTR_NO_QUOTA "Not enough disk quota" +/* FIXME: Obsolete - remove for v2.3 */ +#define MAIL_ERRSTR_NO_SPACE MAIL_ERRSTR_NO_QUOTA #define MAIL_ERRSTR_LOCK_TIMEOUT "Timeout while waiting for lock" /* Message to show to users when critical error occurs */ @@ -30,8 +32,8 @@ MAIL_ERROR_PARAMS, /* No permission to do the request */ MAIL_ERROR_PERM, - /* Out of disk space or quota */ - MAIL_ERROR_NOSPACE, + /* Out of disk quota for user */ + MAIL_ERROR_NOQUOTA, /* Item (e.g. mailbox) doesn't exist or it's not visible to us */ MAIL_ERROR_NOTFOUND, /* Item (e.g. mailbox) already exists */ @@ -47,6 +49,9 @@ /* Can't do the requested data conversion because the original data isn't valid. */ MAIL_ERROR_INVALIDDATA + + /* FIXME: Obsolete - remove in v2.3 */ + MAIL_ERROR_NOSPACE = MAIL_ERROR_NOQUOTA }; /* Convert errno to mail_error and an error string. Returns TRUE if successful, diff -r 5e818f1b376d -r 286da24ada43 src/lib/compat.h --- a/src/lib/compat.h Fri Aug 15 14:05:21 2014 +0300 +++ b/src/lib/compat.h Fri Aug 15 14:41:03 2014 +0300 @@ -231,8 +231,12 @@ #ifdef EDQUOT # define ENOSPACE(errno) ((errno) == ENOSPC || (errno) == EDQUOT) +# define ENOQUOTA(errno) ((errno) == EDQUOT) #else +/* probably all modern OSes have EDQUOT, but just in case one doesn't assume + that ENOSPC is the same as "over quota". */ # define ENOSPACE(errno) ((errno) == ENOSPC) +# define ENOQUOTA(errno) ((errno) == ENOSPC) #endif /* EPERM is returned sometimes if device doesn't support such modification */ diff -r 5e818f1b376d -r 286da24ada43 src/lmtp/commands.c --- a/src/lmtp/commands.c Fri Aug 15 14:05:21 2014 +0300 +++ b/src/lmtp/commands.c Fri Aug 15 14:41:03 2014 +0300 @@ -488,7 +488,7 @@ ret = mailbox_get_status(box, STATUS_CHECK_OVER_QUOTA, &status); if (ret < 0) { errstr = mailbox_get_last_error(box, &error); - if (error == MAIL_ERROR_NOSPACE) { + if (error == MAIL_ERROR_NOQUOTA) { client_send_line(client, "552 5.2.2 <%s> %s", rcpt->address, errstr); ret = 1; @@ -690,7 +690,7 @@ ret = 0; } else if (storage != NULL) { error = mail_storage_get_last_error(storage, &mail_error); - if (mail_error == MAIL_ERROR_NOSPACE) { + if (mail_error == MAIL_ERROR_NOQUOTA) { client_send_line(client, "%s <%s> %s", dctx.set->quota_full_tempfail ? "452 4.2.2" : "552 5.2.2", diff -r 5e818f1b376d -r 286da24ada43 src/plugins/quota/quota-storage.c --- a/src/plugins/quota/quota-storage.c Fri Aug 15 14:05:21 2014 +0300 +++ b/src/plugins/quota/quota-storage.c Fri Aug 15 14:41:03 2014 +0300 @@ -87,7 +87,7 @@ if ((items & STATUS_CHECK_OVER_QUOTA) != 0) { qt = quota_transaction_begin(box); if ((ret = quota_test_alloc(qt, 0, &too_large)) == 0) { - mail_storage_set_error(box->storage, MAIL_ERROR_NOSPACE, + mail_storage_set_error(box->storage, MAIL_ERROR_NOQUOTA, qt->quota->set->quota_exceeded_msg); ret = -1; } @@ -190,7 +190,7 @@ if (ret > 0) return 0; else if (ret == 0) { - mail_storage_set_error(t->box->storage, MAIL_ERROR_NOSPACE, + mail_storage_set_error(t->box->storage, MAIL_ERROR_NOQUOTA, qt->quota->set->quota_exceeded_msg); return -1; } else { @@ -252,7 +252,7 @@ ret = quota_test_alloc(qt, size, &too_large); if (ret == 0) { mail_storage_set_error(t->box->storage, - MAIL_ERROR_NOSPACE, + MAIL_ERROR_NOQUOTA, qt->quota->set->quota_exceeded_msg); return -1; } else if (ret < 0) { diff -r 5e818f1b376d -r 286da24ada43 src/plugins/snarf/snarf-plugin.c --- a/src/plugins/snarf/snarf-plugin.c Fri Aug 15 14:05:21 2014 +0300 +++ b/src/plugins/snarf/snarf-plugin.c Fri Aug 15 14:41:03 2014 +0300 @@ -67,7 +67,7 @@ error = mailbox_get_last_mail_error(destbox); /* if we failed because of out of disk space, just move those messages we managed to move so far. */ - if (error != MAIL_ERROR_NOSPACE) + if (error != MAIL_ERROR_NOQUOTA) ret = -1; break; } diff -r 5e818f1b376d -r 286da24ada43 src/pop3/pop3-client.c --- a/src/pop3/pop3-client.c Fri Aug 15 14:05:21 2014 +0300 +++ b/src/pop3/pop3-client.c Fri Aug 15 14:41:03 2014 +0300 @@ -714,7 +714,7 @@ errstr = mailbox_get_last_error(client->mailbox, &error); switch (error) { case MAIL_ERROR_TEMP: - case MAIL_ERROR_NOSPACE: + case MAIL_ERROR_NOQUOTA: case MAIL_ERROR_INUSE: client_send_line(client, "-ERR [SYS/TEMP] %s", errstr); break; From dovecot at dovecot.org Fri Aug 15 11:51:56 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 15 Aug 2014 11:51:56 +0000 Subject: dovecot-2.2: Compiling fix for previous change.. Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/5dbd8a63aeb0 changeset: 17717:5dbd8a63aeb0 user: Timo Sirainen date: Fri Aug 15 14:48:08 2014 +0300 description: Compiling fix for previous change.. diffstat: src/lib-storage/mail-error.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 286da24ada43 -r 5dbd8a63aeb0 src/lib-storage/mail-error.h --- a/src/lib-storage/mail-error.h Fri Aug 15 14:41:03 2014 +0300 +++ b/src/lib-storage/mail-error.h Fri Aug 15 14:48:08 2014 +0300 @@ -48,7 +48,7 @@ MAIL_ERROR_CONVERSION, /* Can't do the requested data conversion because the original data isn't valid. */ - MAIL_ERROR_INVALIDDATA + MAIL_ERROR_INVALIDDATA, /* FIXME: Obsolete - remove in v2.3 */ MAIL_ERROR_NOSPACE = MAIL_ERROR_NOQUOTA From dovecot at dovecot.org Fri Aug 15 12:05:22 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 15 Aug 2014 12:05:22 +0000 Subject: dovecot-2.2: pop3: fix msgnum/size parsers Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/88d95b8f8a19 changeset: 17718:88d95b8f8a19 user: Phil Carmody date: Fri Aug 15 15:02:59 2014 +0300 description: pop3: fix msgnum/size parsers The outer if()s are completely unnecessary, and permit `num' to remain uninitialised. Spotted by clang's static analysis. Bug introduced in changeset: 17563:2ed2ab04b63d Note that the lack of a parameter from a broken client is no longer treated as "0". Before the bug was introduced: DELE -ERR There's no message 0. After this patch: DELE -ERR Invalid message number: Signed-off-by: Phil Carmody diffstat: src/pop3/pop3-commands.c | 43 ++++++++++++++++++------------------------- 1 files changed, 18 insertions(+), 25 deletions(-) diffs (61 lines): diff -r 5dbd8a63aeb0 -r 88d95b8f8a19 src/pop3/pop3-commands.c --- a/src/pop3/pop3-commands.c Fri Aug 15 14:48:08 2014 +0300 +++ b/src/pop3/pop3-commands.c Fri Aug 15 15:02:59 2014 +0300 @@ -30,20 +30,16 @@ { unsigned int num; - if (*args != '\0' && *args != ' ') { - if (*args < '0' || *args > '9') { - client_send_line(client, - "-ERR Invalid message number: %s", args); - return NULL; - } - - if (str_parse_uint(args, &num, &args) < 0) { - client_send_line(client, - "-ERR Message number too large: %s", args); - return NULL; - } + if (*args < '0' || *args > '9') { + client_send_line(client, + "-ERR Invalid message number: %s", args); + return NULL; } - + if (str_parse_uint(args, &num, &args) < 0) { + client_send_line(client, + "-ERR Message number too large: %s", args); + return NULL; + } if (num == 0 || num > client->messages_count) { client_send_line(client, "-ERR There's no message %u.", num); @@ -70,18 +66,15 @@ { uoff_t num; - if (*args != '\0' && *args != ' ') { - if (*args < '0' || *args > '9') { - client_send_line(client, "-ERR Invalid size: %s", - args); - return NULL; - } - - if (str_parse_uoff(args, &num, &args) < 0) { - client_send_line(client, "-ERR Size too large: %s", - args); - return NULL; - } + if (*args < '0' || *args > '9') { + client_send_line(client, "-ERR Invalid size: %s", + args); + return NULL; + } + if (str_parse_uoff(args, &num, &args) < 0) { + client_send_line(client, "-ERR Size too large: %s", + args); + return NULL; } while (*args == ' ') args++; From dovecot at dovecot.org Fri Aug 15 12:05:23 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 15 Aug 2014 12:05:23 +0000 Subject: dovecot-2.2: pop3: satisfy some strict parsing rules in RFC 1939 Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/a45147ddd655 changeset: 17719:a45147ddd655 user: Phil Carmody date: Fri Aug 15 15:02:59 2014 +0300 description: pop3: satisfy some strict parsing rules in RFC 1939 "Commands in the POP3 consist of a case-insensitive keyword, possibly followed by one or more arguments. All commands are terminated by a CRLF pair. Keywords and arguments consist of printable ASCII characters. Keywords and arguments are each separated by a single SPACE character." "A server MUST respond to an unrecognized, unimplemented, or syntactically invalid command by responding with a negative status indicator." Therefore the following commands must be rejected: LIST 2600Hz LIST 99 red balloons TOP 1 2 buckle-my-shoe Signed-off-by: Phil Carmody diffstat: src/pop3/pop3-commands.c | 25 +++++++++++++++++-------- 1 files changed, 17 insertions(+), 8 deletions(-) diffs (93 lines): diff -r 88d95b8f8a19 -r a45147ddd655 src/pop3/pop3-commands.c --- a/src/pop3/pop3-commands.c Fri Aug 15 15:02:59 2014 +0300 +++ b/src/pop3/pop3-commands.c Fri Aug 15 15:02:59 2014 +0300 @@ -26,7 +26,7 @@ } static const char *get_msgnum(struct client *client, const char *args, - unsigned int *msgnum) + unsigned int *msgnum, bool thenspace) { unsigned int num; @@ -40,6 +40,11 @@ "-ERR Message number too large: %s", args); return NULL; } + if (*args != (thenspace ? ' ' : '\0')) { + client_send_line(client, + "-ERR Noise after message number: %s", args); + return NULL; + } if (num == 0 || num > client->messages_count) { client_send_line(client, "-ERR There's no message %u.", num); @@ -62,7 +67,7 @@ } static const char *get_size(struct client *client, const char *args, - uoff_t *size) + uoff_t *size, bool thenspace) { uoff_t num; @@ -76,6 +81,10 @@ args); return NULL; } + if (*args != (thenspace ? ' ' : '\0')) { + client_send_line(client, "-ERR Noise after size: %s", args); + return NULL; + } while (*args == ' ') args++; @@ -93,7 +102,7 @@ { unsigned int msgnum; - if (get_msgnum(client, args, &msgnum) == NULL) + if (get_msgnum(client, args, &msgnum, FALSE) == NULL) return -1; if (!client->deleted) { @@ -155,7 +164,7 @@ } else { unsigned int msgnum; - if (get_msgnum(client, args, &msgnum) == NULL) + if (get_msgnum(client, args, &msgnum, FALSE) == NULL) return -1; client_send_line(client, "+OK %u %"PRIuUOFF_T, msgnum+1, @@ -470,7 +479,7 @@ { unsigned int msgnum; - if (get_msgnum(client, args, &msgnum) == NULL) + if (get_msgnum(client, args, &msgnum, FALSE) == NULL) return -1; if (client->lowest_retr_pop3_msn > msgnum+1 || @@ -534,10 +543,10 @@ unsigned int msgnum; uoff_t max_lines; - args = get_msgnum(client, args, &msgnum); + args = get_msgnum(client, args, &msgnum, TRUE); if (args == NULL) return -1; - if (get_size(client, args, &max_lines) == NULL) + if (get_size(client, args, &max_lines, FALSE) == NULL) return -1; client->top_count++; @@ -860,7 +869,7 @@ } else { unsigned int msgnum; - if (get_msgnum(client, args, &msgnum) == NULL) + if (get_msgnum(client, args, &msgnum, FALSE) == NULL) return -1; seq = msgnum_to_seq(client, msgnum); From dovecot at dovecot.org Fri Aug 15 12:25:02 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 15 Aug 2014 12:25:02 +0000 Subject: dovecot-2.2: io_add_istream(): Allow the istream to be added eve... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/7985461cf21c changeset: 17720:7985461cf21c user: Timo Sirainen date: Fri Aug 15 15:19:24 2014 +0300 description: io_add_istream(): Allow the istream to be added even if it doesn't have fd. diffstat: src/lib/ioloop.c | 12 +++++++++--- 1 files changed, 9 insertions(+), 3 deletions(-) diffs (43 lines): diff -r a45147ddd655 -r 7985461cf21c src/lib/ioloop.c --- a/src/lib/ioloop.c Fri Aug 15 15:02:59 2014 +0300 +++ b/src/lib/ioloop.c Fri Aug 15 15:19:24 2014 +0300 @@ -36,7 +36,6 @@ { struct io_file *io; - i_assert(fd >= 0); i_assert(callback != NULL); i_assert((condition & IO_NOTIFY) == 0); @@ -56,7 +55,12 @@ if (io->io.ioloop->handler_context == NULL) io_loop_initialize_handler(io->io.ioloop); - io_loop_handle_add(io); + if (fd != -1) + io_loop_handle_add(io); + else { + /* we're adding an istream whose only way to get notified + is to call i_stream_set_input_pending() */ + } if (io->io.ioloop->io_files != NULL) { io->io.ioloop->io_files->prev = io; @@ -73,6 +77,7 @@ { struct io_file *io; + i_assert(fd >= 0); io = io_add_file(fd, condition, source_linenum, callback, context); return &io->io; } @@ -139,7 +144,8 @@ } io_file_unlink(io_file); - io_loop_handle_remove(io_file, closed); + if (io_file->fd != -1) + io_loop_handle_remove(io_file, closed); } } From dovecot at dovecot.org Fri Aug 15 12:25:02 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 15 Aug 2014 12:25:02 +0000 Subject: dovecot-2.2: istream-chain: Support using io_add_istream() for t... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/664afffb22a3 changeset: 17721:664afffb22a3 user: Timo Sirainen date: Fri Aug 15 15:22:46 2014 +0300 description: istream-chain: Support using io_add_istream() for the chain stream. The callback is notified whenever new streams are added to the chain. It's currently not possible to have nonblocking istreams added to the chain and the callback being called when they have new data, but it would be possible to implement as well if needed at some point. diffstat: src/lib/istream-chain.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diffs (13 lines): diff -r 7985461cf21c -r 664afffb22a3 src/lib/istream-chain.c --- a/src/lib/istream-chain.c Fri Aug 15 15:19:24 2014 +0300 +++ b/src/lib/istream-chain.c Fri Aug 15 15:22:46 2014 +0300 @@ -54,6 +54,9 @@ } } DLLIST2_APPEND(&chain->head, &chain->tail, link); + /* if io_add_istream() has been added to this chain stream, notify + the callback that we have more data available. */ + i_stream_set_input_pending(stream, TRUE); } void i_stream_chain_append(struct istream_chain *chain, struct istream *stream) From dovecot at dovecot.org Fri Aug 15 13:01:36 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 15 Aug 2014 13:01:36 +0000 Subject: dovecot-2.2: lib-http: Added asserts to make sure CR or LF can't... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/8e6d2afb14c5 changeset: 17722:8e6d2afb14c5 user: Timo Sirainen date: Fri Aug 15 15:59:17 2014 +0300 description: lib-http: Added asserts to make sure CR or LF can't be added accidentally to HTTP headers. diffstat: src/lib-http/http-server-response.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diffs (13 lines): diff -r 664afffb22a3 -r 8e6d2afb14c5 src/lib-http/http-server-response.c --- a/src/lib-http/http-server-response.c Fri Aug 15 15:22:46 2014 +0300 +++ b/src/lib-http/http-server-response.c Fri Aug 15 15:59:17 2014 +0300 @@ -68,6 +68,9 @@ const char *key, const char *value) { i_assert(!resp->submitted); + i_assert(strchr(key, '\r') == NULL && strchr(key, '\n') == NULL); + i_assert(strchr(value, '\r') == NULL && strchr(value, '\n') == NULL); + /* mark presence of special headers */ switch (key[0]) { case 'c': case 'C': From dovecot at dovecot.org Fri Aug 15 13:02:18 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 15 Aug 2014 13:02:18 +0000 Subject: dovecot-2.2: lib-http server: Use io_add_istream() to wait for t... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/74e5657964d3 changeset: 17723:74e5657964d3 user: Timo Sirainen date: Fri Aug 15 16:00:07 2014 +0300 description: lib-http server: Use io_add_istream() to wait for the payload istream. This way the stream doesn't necessarily have to have a fd. diffstat: src/lib-http/http-server-response.c | 7 ++----- 1 files changed, 2 insertions(+), 5 deletions(-) diffs (25 lines): diff -r 8e6d2afb14c5 -r 74e5657964d3 src/lib-http/http-server-response.c --- a/src/lib-http/http-server-response.c Fri Aug 15 15:59:17 2014 +0300 +++ b/src/lib-http/http-server-response.c Fri Aug 15 16:00:07 2014 +0300 @@ -204,7 +204,6 @@ struct http_server_connection *conn = resp->request->conn; struct ostream *output = resp->payload_output; off_t ret; - int fd; *error_r = NULL; @@ -251,11 +250,9 @@ //http_server_response_debug(resp, "Partially sent payload"); } else { /* input is blocking */ - fd = i_stream_get_fd(resp->payload_input); conn->output_locked = TRUE; - i_assert(fd >= 0); - conn->io_resp_payload = io_add - (fd, IO_READ, http_server_response_payload_input, resp); + conn->io_resp_payload = io_add_istream(resp->payload_input, + http_server_response_payload_input, resp); } return ret < 0 ? -1 : 0; } From dovecot at dovecot.org Mon Aug 18 08:44:09 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 18 Aug 2014 08:44:09 +0000 Subject: dovecot-2.2: istream-chain: Fixed crash caused by earlier io_add... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/3d30ae287699 changeset: 17724:3d30ae287699 user: Timo Sirainen date: Mon Aug 18 10:43:59 2014 +0200 description: istream-chain: Fixed crash caused by earlier io_add_stream() support change. diffstat: src/lib/istream-chain.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diffs (13 lines): diff -r 74e5657964d3 -r 3d30ae287699 src/lib/istream-chain.c --- a/src/lib/istream-chain.c Fri Aug 15 16:00:07 2014 +0300 +++ b/src/lib/istream-chain.c Mon Aug 18 10:43:59 2014 +0200 @@ -56,7 +56,8 @@ DLLIST2_APPEND(&chain->head, &chain->tail, link); /* if io_add_istream() has been added to this chain stream, notify the callback that we have more data available. */ - i_stream_set_input_pending(stream, TRUE); + if (stream != NULL) + i_stream_set_input_pending(stream, TRUE); } void i_stream_chain_append(struct istream_chain *chain, struct istream *stream) From dovecot at dovecot.org Mon Aug 18 20:41:48 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 18 Aug 2014 20:41:48 +0000 Subject: dovecot-2.2: director: Log a warning when using "director host f... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/bd381e882485 changeset: 17725:bd381e882485 user: Timo Sirainen date: Mon Aug 18 22:39:56 2014 +0200 description: director: Log a warning when using "director host flush" for all hosts. diffstat: src/director/doveadm-connection.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diffs (20 lines): diff -r 3d30ae287699 -r bd381e882485 src/director/doveadm-connection.c --- a/src/director/doveadm-connection.c Mon Aug 18 10:43:59 2014 +0200 +++ b/src/director/doveadm-connection.c Mon Aug 18 22:39:56 2014 +0200 @@ -238,11 +238,16 @@ doveadm_cmd_host_flush_all(struct doveadm_connection *conn) { struct mail_host *const *hostp; + unsigned int total_user_count = 0; array_foreach(mail_hosts_get(conn->dir->mail_hosts), hostp) { + total_user_count += (*hostp)->user_count; director_flush_host(conn->dir, conn->dir->self_host, NULL, *hostp); } + i_warning("Flushed all backend hosts with %u users. This is an unsafe " + "operation and may cause the same users to end up in multiple backends.", + total_user_count); o_stream_nsend(conn->output, "OK\n", 3); } From dovecot at dovecot.org Tue Aug 19 21:53:39 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 19 Aug 2014 21:53:39 +0000 Subject: dovecot-2.2: lib: wildcard_match() should have matched "*" wildc... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/2ca346d91310 changeset: 17726:2ca346d91310 user: Timo Sirainen date: Tue Aug 19 23:51:14 2014 +0200 description: lib: wildcard_match() should have matched "*" wildcard against an empty "" string also. This fixes global ACL "*" matching the root namespace when creating new mailboxes. diffstat: src/lib/wildcard-match.c | 8 +++++--- 1 files changed, 5 insertions(+), 3 deletions(-) diffs (18 lines): diff -r bd381e882485 -r 2ca346d91310 src/lib/wildcard-match.c --- a/src/lib/wildcard-match.c Mon Aug 18 22:39:56 2014 +0200 +++ b/src/lib/wildcard-match.c Tue Aug 19 23:51:14 2014 +0200 @@ -29,9 +29,11 @@ int match = 1; int sofar = 0; - /* null strings should never match */ - if ((ma == NULL) || (na == NULL) || (!*ma) || (!*na)) - return NOMATCH; + if (na[0] == '\0') { + /* empty string can match only "*" wildcard(s) */ + while (ma[0] == '*') ma++; + return ma[0] == '\0' ? MATCH : NOMATCH; + } /* find the end of each string */ while (*(++mask)); mask--; From dovecot at dovecot.org Tue Aug 19 21:54:19 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 19 Aug 2014 21:54:19 +0000 Subject: dovecot-2.2: lib: Added unit tests for wildcard_match() Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/d1d4beff99f7 changeset: 17727:d1d4beff99f7 user: Timo Sirainen date: Tue Aug 19 23:53:18 2014 +0200 description: lib: Added unit tests for wildcard_match() diffstat: src/lib/Makefile.am | 3 +- src/lib/test-lib.c | 1 + src/lib/test-lib.h | 1 + src/lib/test-wildcard-match.c | 44 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 48 insertions(+), 1 deletions(-) diffs (82 lines): diff -r 2ca346d91310 -r d1d4beff99f7 src/lib/Makefile.am --- a/src/lib/Makefile.am Tue Aug 19 23:51:14 2014 +0200 +++ b/src/lib/Makefile.am Tue Aug 19 23:53:18 2014 +0200 @@ -313,7 +313,8 @@ test-time-util.c \ test-unichar.c \ test-utc-mktime.c \ - test-var-expand.c + test-var-expand.c \ + test-wildcard-match.c test_headers = \ test-lib.h diff -r 2ca346d91310 -r d1d4beff99f7 src/lib/test-lib.c --- a/src/lib/test-lib.c Tue Aug 19 23:51:14 2014 +0200 +++ b/src/lib/test-lib.c Tue Aug 19 23:53:18 2014 +0200 @@ -45,6 +45,7 @@ test_unichar, test_utc_mktime, test_var_expand, + test_wildcard_match, NULL }; static enum fatal_test_state (*fatal_functions[])(int) = { diff -r 2ca346d91310 -r d1d4beff99f7 src/lib/test-lib.h --- a/src/lib/test-lib.h Tue Aug 19 23:51:14 2014 +0200 +++ b/src/lib/test-lib.h Tue Aug 19 23:53:18 2014 +0200 @@ -47,5 +47,6 @@ void test_unichar(void); void test_utc_mktime(void); void test_var_expand(void); +void test_wildcard_match(void); #endif diff -r 2ca346d91310 -r d1d4beff99f7 src/lib/test-wildcard-match.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/test-wildcard-match.c Tue Aug 19 23:53:18 2014 +0200 @@ -0,0 +1,44 @@ +/* Copyright (c) 2014 Dovecot authors, see the included COPYING file */ + +#include "test-lib.h" +#include "wildcard-match.h" + +static struct { + const char *data; + const char *mask; + bool result; +} tests[] = { + { "foo", "*", TRUE }, + { "foo", "*foo*", TRUE }, + { "foo", "foo", TRUE }, + { "foo", "f*o*o", TRUE }, + { "foo", "f??", TRUE }, + { "foo", "f?o", TRUE }, + { "foo", "*??", TRUE }, + { "foo", "???", TRUE }, + { "foo", "f??*", TRUE }, + { "foo", "???*", TRUE }, + + { "foo", "", FALSE }, + { "foo", "f", FALSE }, + { "foo", "fo", FALSE }, + { "foo", "fooo", FALSE }, + { "foo", "????", FALSE }, + { "foo", "f*o*o*o", FALSE }, + { "foo", "f???*", FALSE }, + + { "", "*", TRUE }, + { "", "", TRUE }, + { "", "?", FALSE } +}; + +void test_wildcard_match(void) +{ + unsigned int i; + + test_begin("wildcard_match()"); + for (i = 0; i < N_ELEMENTS(tests); i++) { + test_assert_idx(wildcard_match(tests[i].data, tests[i].mask) == tests[i].result, i); + } + test_end(); +} From dovecot at dovecot.org Wed Aug 20 09:10:14 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 20 Aug 2014 09:10:14 +0000 Subject: dovecot-2.2: Several services weren't enforcing their process_li... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/0b86058d4e5e changeset: 17728:0b86058d4e5e user: Timo Sirainen date: Wed Aug 20 11:09:27 2014 +0200 description: Several services weren't enforcing their process_limit=1 requirement. diffstat: src/indexer/indexer-settings.c | 4 +++- src/ipc/ipc-settings.c | 4 +++- src/replication/replicator/replicator-settings.c | 4 +++- src/stats/stats-settings.c | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-) diffs (52 lines): diff -r d1d4beff99f7 -r 0b86058d4e5e src/indexer/indexer-settings.c --- a/src/indexer/indexer-settings.c Tue Aug 19 23:53:18 2014 +0200 +++ b/src/indexer/indexer-settings.c Wed Aug 20 11:09:27 2014 +0200 @@ -44,5 +44,7 @@ .unix_listeners = { { &indexer_unix_listeners_buf, sizeof(indexer_unix_listeners[0]) } }, .fifo_listeners = ARRAY_INIT, - .inet_listeners = ARRAY_INIT + .inet_listeners = ARRAY_INIT, + + .process_limit_1 = TRUE }; diff -r d1d4beff99f7 -r 0b86058d4e5e src/ipc/ipc-settings.c --- a/src/ipc/ipc-settings.c Tue Aug 19 23:53:18 2014 +0200 +++ b/src/ipc/ipc-settings.c Wed Aug 20 11:09:27 2014 +0200 @@ -44,5 +44,7 @@ .unix_listeners = { { &ipc_unix_listeners_buf, sizeof(ipc_unix_listeners[0]) } }, .fifo_listeners = ARRAY_INIT, - .inet_listeners = ARRAY_INIT + .inet_listeners = ARRAY_INIT, + + .process_limit_1 = TRUE }; diff -r d1d4beff99f7 -r 0b86058d4e5e src/replication/replicator/replicator-settings.c --- a/src/replication/replicator/replicator-settings.c Tue Aug 19 23:53:18 2014 +0200 +++ b/src/replication/replicator/replicator-settings.c Wed Aug 20 11:09:27 2014 +0200 @@ -43,7 +43,9 @@ .unix_listeners = { { &replicator_unix_listeners_buf, sizeof(replicator_unix_listeners[0]) } }, .fifo_listeners = ARRAY_INIT, - .inet_listeners = ARRAY_INIT + .inet_listeners = ARRAY_INIT, + + .process_limit_1 = TRUE }; #undef DEF diff -r d1d4beff99f7 -r 0b86058d4e5e src/stats/stats-settings.c --- a/src/stats/stats-settings.c Tue Aug 19 23:53:18 2014 +0200 +++ b/src/stats/stats-settings.c Wed Aug 20 11:09:27 2014 +0200 @@ -52,7 +52,9 @@ sizeof(stats_unix_listeners[0]) } }, .fifo_listeners = { { &stats_fifo_listeners_buf, sizeof(stats_fifo_listeners[0]) } }, - .inet_listeners = ARRAY_INIT + .inet_listeners = ARRAY_INIT, + + .process_limit_1 = TRUE }; /* we're kind of kludging here to avoid "stats_" prefix in the struct fields */ From dovecot at dovecot.org Wed Aug 20 09:19:41 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 20 Aug 2014 09:19:41 +0000 Subject: dovecot-2.2: doveconf: local and remote net/bits addresses were ... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/8d3895feb931 changeset: 17729:8d3895feb931 user: Timo Sirainen date: Wed Aug 20 11:19:15 2014 +0200 description: doveconf: local and remote net/bits addresses were printed with /bits twice. diffstat: src/config/doveconf.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (21 lines): diff -r 0b86058d4e5e -r 8d3895feb931 src/config/doveconf.c --- a/src/config/doveconf.c Wed Aug 20 11:09:27 2014 +0200 +++ b/src/config/doveconf.c Wed Aug 20 11:19:15 2014 +0200 @@ -340,7 +340,7 @@ unsigned int indent = 0; if (filter->local_bits > 0) { - str_printfa(str, "local %s", filter->local_host); + str_printfa(str, "local %s", net_ip2addr(&filter->local_net)); if (IPADDR_IS_V4(&filter->local_net)) { if (filter->local_bits != 32) @@ -361,7 +361,7 @@ if (filter->remote_bits > 0) { str_append_n(str, indent_str, indent*2); - str_printfa(str, "remote %s", filter->remote_host); + str_printfa(str, "remote %s", net_ip2addr(&filter->remote_net)); if (IPADDR_IS_V4(&filter->remote_net)) { if (filter->remote_bits != 32) From dovecot at dovecot.org Wed Aug 20 10:07:40 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 20 Aug 2014 10:07:40 +0000 Subject: dovecot-2.2: lib-storage: Added data stack frame to mail_prefetc... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/9ee7381056d5 changeset: 17730:9ee7381056d5 user: Timo Sirainen date: Wed Aug 20 12:07:19 2014 +0200 description: lib-storage: Added data stack frame to mail_prefetch(). diffstat: src/lib-storage/mail.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diffs (14 lines): diff -r 8d3895feb931 -r 9ee7381056d5 src/lib-storage/mail.c --- a/src/lib-storage/mail.c Wed Aug 20 11:19:15 2014 +0200 +++ b/src/lib-storage/mail.c Wed Aug 20 12:07:19 2014 +0200 @@ -347,7 +347,9 @@ { struct mail_private *p = (struct mail_private *)mail; - p->v.precache(mail); + T_BEGIN { + p->v.precache(mail); + } T_END; } void mail_set_cache_corrupted(struct mail *mail, enum mail_fetch_field field) From dovecot at dovecot.org Wed Aug 20 10:35:40 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 20 Aug 2014 10:35:40 +0000 Subject: dovecot-2.2: last-login: Fixed timeout leak at user deinit. Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/f08d6cf8bdd4 changeset: 17731:f08d6cf8bdd4 user: Timo Sirainen date: Wed Aug 20 12:35:27 2014 +0200 description: last-login: Fixed timeout leak at user deinit. diffstat: src/plugins/last-login/last-login-plugin.c | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diffs (20 lines): diff -r 9ee7381056d5 -r f08d6cf8bdd4 src/plugins/last-login/last-login-plugin.c --- a/src/plugins/last-login/last-login-plugin.c Wed Aug 20 12:07:19 2014 +0200 +++ b/src/plugins/last-login/last-login-plugin.c Wed Aug 20 12:35:27 2014 +0200 @@ -27,12 +27,14 @@ { struct last_login_user *luser = LAST_LOGIN_USER_CONTEXT(user); - if (luser->to != NULL) - timeout_remove(&luser->to); if (luser->dict != NULL) { (void)dict_wait(luser->dict); dict_deinit(&luser->dict); } + /* remove timeout after dict_wait(), which may trigger + last_login_dict_commit() */ + if (luser->to != NULL) + timeout_remove(&luser->to); } static void last_login_user_deinit(struct mail_user *user) From dovecot at dovecot.org Wed Aug 20 10:36:49 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 20 Aug 2014 10:36:49 +0000 Subject: dovecot-2.2: last-login plugin: Added ABI version check. Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/4f6a812817c4 changeset: 17732:4f6a812817c4 user: Timo Sirainen date: Wed Aug 20 12:36:37 2014 +0200 description: last-login plugin: Added ABI version check. diffstat: src/plugins/last-login/last-login-plugin.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diffs (12 lines): diff -r f08d6cf8bdd4 -r 4f6a812817c4 src/plugins/last-login/last-login-plugin.c --- a/src/plugins/last-login/last-login-plugin.c Wed Aug 20 12:35:27 2014 +0200 +++ b/src/plugins/last-login/last-login-plugin.c Wed Aug 20 12:36:37 2014 +0200 @@ -20,6 +20,8 @@ struct timeout *to; }; +const char *last_login_plugin_version = DOVECOT_ABI_VERSION; + static MODULE_CONTEXT_DEFINE_INIT(last_login_user_module, &mail_user_module_register); From dovecot at dovecot.org Wed Aug 20 10:47:32 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 20 Aug 2014 10:47:32 +0000 Subject: dovecot-2.2: lib-dict: Hide internal ioloop from async commit ca... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/a7a5e0737d53 changeset: 17733:a7a5e0737d53 user: Timo Sirainen date: Wed Aug 20 12:47:10 2014 +0200 description: lib-dict: Hide internal ioloop from async commit callbacks. (Redis & memcached fix) diffstat: src/lib-dict/dict-memcached-ascii.c | 35 ++++++++++++++++++++++++--------- src/lib-dict/dict-redis.c | 38 +++++++++++++++++++++++++----------- 2 files changed, 51 insertions(+), 22 deletions(-) diffs (191 lines): diff -r 4f6a812817c4 -r a7a5e0737d53 src/lib-dict/dict-memcached-ascii.c --- a/src/lib-dict/dict-memcached-ascii.c Wed Aug 20 12:36:37 2014 +0200 +++ b/src/lib-dict/dict-memcached-ascii.c Wed Aug 20 12:47:10 2014 +0200 @@ -56,7 +56,7 @@ unsigned int port; unsigned int timeout_msecs; - struct ioloop *ioloop; + struct ioloop *ioloop, *prev_ioloop; struct timeout *to; struct memcached_ascii_connection conn; @@ -66,6 +66,23 @@ static struct connection_list *memcached_ascii_connections; +static void +memcached_ascii_callback(struct memcached_ascii_dict *dict, + const struct memcached_ascii_dict_reply *reply, int ret) +{ + if (reply->callback != NULL) { + if (dict->prev_ioloop != NULL) { + /* Don't let callback see that we've created our + internal ioloop in case it wants to add some ios + or timeouts. */ + current_ioloop = dict->prev_ioloop; + } + reply->callback(ret, reply->context); + if (dict->prev_ioloop != NULL) + current_ioloop = dict->ioloop; + } +} + static void memcached_ascii_conn_destroy(struct connection *_conn) { struct memcached_ascii_connection *conn = @@ -76,10 +93,8 @@ if (conn->dict->ioloop != NULL) io_loop_stop(conn->dict->ioloop); - array_foreach(&conn->dict->replies, reply) { - if (reply->callback != NULL) - reply->callback(-1, reply->context); - } + array_foreach(&conn->dict->replies, reply) + memcached_ascii_callback(conn->dict, reply, -1); array_clear(&conn->dict->replies); array_clear(&conn->dict->input_states); conn->reply_bytes_left = 0; @@ -186,8 +201,7 @@ i_assert(count > 0); i_assert(replies[0].reply_count > 0); if (--replies[0].reply_count == 0) { - if (replies[0].callback != NULL) - replies[0].callback(1, replies[0].context); + memcached_ascii_callback(dict, &replies[0], 1); array_delete(&dict->replies, 0, 1); } return 1; @@ -217,15 +231,16 @@ static int memcached_ascii_input_wait(struct memcached_ascii_dict *dict) { - struct ioloop *old_ioloop = current_ioloop; - + dict->prev_ioloop = current_ioloop; io_loop_set_current(dict->ioloop); if (dict->to != NULL) dict->to = io_loop_move_timeout(&dict->to); connection_switch_ioloop(&dict->conn.conn); io_loop_run(dict->ioloop); - io_loop_set_current(old_ioloop); + io_loop_set_current(dict->prev_ioloop); + dict->prev_ioloop = NULL; + if (dict->to != NULL) dict->to = io_loop_move_timeout(&dict->to); connection_switch_ioloop(&dict->conn.conn); diff -r 4f6a812817c4 -r a7a5e0737d53 src/lib-dict/dict-redis.c --- a/src/lib-dict/dict-redis.c Wed Aug 20 12:36:37 2014 +0200 +++ b/src/lib-dict/dict-redis.c Wed Aug 20 12:47:10 2014 +0200 @@ -48,7 +48,7 @@ unsigned int port; unsigned int timeout_msecs; - struct ioloop *ioloop; + struct ioloop *ioloop, *prev_ioloop; struct redis_connection conn; ARRAY(enum redis_input_state) input_states; @@ -77,6 +77,22 @@ array_delete(&dict->input_states, 0, 1); } +static void redis_callback(struct redis_dict *dict, + const struct redis_dict_reply *reply, int ret) +{ + if (reply->callback != NULL) { + if (dict->prev_ioloop != NULL) { + /* Don't let callback see that we've created our + internal ioloop in case it wants to add some ios + or timeouts. */ + current_ioloop = dict->prev_ioloop; + } + reply->callback(ret, reply->context); + if (dict->prev_ioloop != NULL) + current_ioloop = dict->ioloop; + } +} + static void redis_conn_destroy(struct connection *_conn) { struct redis_connection *conn = (struct redis_connection *)_conn; @@ -85,10 +101,8 @@ conn->dict->connected = FALSE; connection_disconnect(_conn); - array_foreach(&conn->dict->replies, reply) { - if (reply->callback != NULL) - reply->callback(-1, reply->context); - } + array_foreach(&conn->dict->replies, reply) + redis_callback(conn->dict, reply, -1); array_clear(&conn->dict->replies); array_clear(&conn->dict->input_states); @@ -98,10 +112,9 @@ static void redis_wait(struct redis_dict *dict) { - struct ioloop *prev_ioloop = current_ioloop; - i_assert(dict->ioloop == NULL); + dict->prev_ioloop = current_ioloop; dict->ioloop = io_loop_create(); connection_switch_ioloop(&dict->conn.conn); @@ -109,10 +122,11 @@ io_loop_run(dict->ioloop); } while (array_count(&dict->input_states) > 0); - io_loop_set_current(prev_ioloop); + io_loop_set_current(dict->prev_ioloop); connection_switch_ioloop(&dict->conn.conn); io_loop_set_current(dict->ioloop); io_loop_destroy(&dict->ioloop); + dict->prev_ioloop = NULL; } static int redis_input_get(struct redis_connection *conn) @@ -216,8 +230,7 @@ reply = array_idx_modifiable(&dict->replies, 0); i_assert(reply->reply_count > 0); if (--reply->reply_count == 0) { - if (reply->callback != NULL) - reply->callback(1, reply->context); + redis_callback(dict, reply, 1); array_delete(&dict->replies, 0, 1); /* if we're running in a dict-ioloop, we're handling a synchronous commit and need to stop now */ @@ -426,7 +439,6 @@ { struct timeout *to; const char *cmd; - struct ioloop *prev_ioloop = current_ioloop; key = redis_dict_get_full_key(dict, key); @@ -435,6 +447,7 @@ i_assert(dict->ioloop == NULL); + dict->prev_ioloop = current_ioloop; dict->ioloop = io_loop_create(); connection_switch_ioloop(&dict->conn.conn); @@ -464,10 +477,11 @@ timeout_remove(&to); } - io_loop_set_current(prev_ioloop); + io_loop_set_current(dict->prev_ioloop); connection_switch_ioloop(&dict->conn.conn); io_loop_set_current(dict->ioloop); io_loop_destroy(&dict->ioloop); + dict->prev_ioloop = NULL; if (!dict->conn.value_received) { /* we failed in some way. make sure we disconnect since the From dovecot at dovecot.org Wed Aug 20 11:22:49 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 20 Aug 2014 11:22:49 +0000 Subject: dovecot-2.2: fts-lucene: If whitespace_chars was set, we may hav... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/febedba15c7e changeset: 17734:febedba15c7e user: Timo Sirainen date: Wed Aug 20 14:22:28 2014 +0300 description: fts-lucene: If whitespace_chars was set, we may have ended up indexing some garbage words. The final \0 was replaced with space, so everything beyond that was also being indexed. diffstat: src/plugins/fts-lucene/lucene-wrapper.cc | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r a7a5e0737d53 -r febedba15c7e src/plugins/fts-lucene/lucene-wrapper.cc --- a/src/plugins/fts-lucene/lucene-wrapper.cc Wed Aug 20 12:47:10 2014 +0200 +++ b/src/plugins/fts-lucene/lucene-wrapper.cc Wed Aug 20 14:22:28 2014 +0300 @@ -562,7 +562,7 @@ else dest = dest_free = i_new(wchar_t, datasize); lucene_utf8_n_to_tchar(data, size, dest, datasize); - lucene_data_translate(index, dest, datasize); + lucene_data_translate(index, dest, datasize-1); if (hdr_name != NULL) { /* hdr_name should be ASCII, but don't break in case it isn't */ From dovecot at dovecot.org Wed Aug 20 12:36:14 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 20 Aug 2014 12:36:14 +0000 Subject: dovecot-2.2: auth: protocol-specific username settings weren't u... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/c3da5ffaa0f2 changeset: 17735:c3da5ffaa0f2 user: Timo Sirainen date: Wed Aug 20 14:35:27 2014 +0200 description: auth: protocol-specific username settings weren't used for userdb lookups. The username was set before the service-specific settings were looked up, so global settings were always used. This affected auth_default_realm, auth_username_translation and auth_username_format settings. diffstat: src/auth/auth-master-connection.c | 13 +++++++------ src/auth/auth-postfix-connection.c | 6 +++--- 2 files changed, 10 insertions(+), 9 deletions(-) diffs (57 lines): diff -r febedba15c7e -r c3da5ffaa0f2 src/auth/auth-master-connection.c --- a/src/auth/auth-master-connection.c Wed Aug 20 14:22:28 2014 +0300 +++ b/src/auth/auth-master-connection.c Wed Aug 20 14:35:27 2014 +0200 @@ -167,7 +167,7 @@ const char **error_r) { struct auth_request *auth_request; - const char *const *list, *name, *arg; + const char *const *list, *name, *arg, *username; unsigned int id; /* [] */ @@ -182,11 +182,7 @@ auth_request->id = id; auth_request->master = conn; auth_master_connection_ref(conn); - - if (!auth_request_set_username(auth_request, list[1], error_r)) { - *request_r = auth_request; - return 0; - } + username = list[1]; for (list += 2; *list != NULL; list++) { arg = strchr(*list, '='); @@ -209,6 +205,11 @@ } auth_request_init(auth_request); + + if (!auth_request_set_username(auth_request, username, error_r)) { + *request_r = auth_request; + return 0; + } *request_r = auth_request; return 1; } diff -r febedba15c7e -r c3da5ffaa0f2 src/auth/auth-postfix-connection.c --- a/src/auth/auth-postfix-connection.c Wed Aug 20 14:22:28 2014 +0300 +++ b/src/auth/auth-postfix-connection.c Wed Aug 20 14:35:27 2014 +0200 @@ -51,13 +51,13 @@ auth_request->context = conn; auth_postfix_connection_ref(conn); + (void)auth_request_import_info(auth_request, "service", "postfix"); + auth_request_init(auth_request); + if (!auth_request_set_username(auth_request, username, error_r)) { *request_r = auth_request; return FALSE; } - (void)auth_request_import_info(auth_request, "service", "postfix"); - - auth_request_init(auth_request); *request_r = auth_request; return TRUE; } From dovecot at dovecot.org Wed Aug 20 13:32:37 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 20 Aug 2014 13:32:37 +0000 Subject: dovecot-2.2: lmtp: Put back the deduplication code. Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/f0f19e5580f0 changeset: 17736:f0f19e5580f0 user: Timo Sirainen date: Wed Aug 20 15:32:15 2014 +0200 description: lmtp: Put back the deduplication code. Too dangerous after all to change it in the middle of v2.2.x. It's also not causing that much trouble even when it breaks.. diffstat: src/lmtp/client.h | 4 ++ src/lmtp/commands.c | 82 ++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 70 insertions(+), 16 deletions(-) diffs (185 lines): diff -r c3da5ffaa0f2 -r f0f19e5580f0 src/lmtp/client.h --- a/src/lmtp/client.h Wed Aug 20 14:35:27 2014 +0200 +++ b/src/lmtp/client.h Wed Aug 20 15:32:15 2014 +0200 @@ -16,6 +16,7 @@ const char *session_id; const char *mail_from; ARRAY(struct mail_recipient) rcpt_to; + unsigned int rcpt_idx; unsigned int data_end_idx; @@ -28,6 +29,9 @@ struct mail *raw_mail; + struct mail_user *dest_user; + struct mail *first_saved_mail; + unsigned int mail_body_7bit:1; unsigned int mail_body_8bitmime:1; }; diff -r c3da5ffaa0f2 -r f0f19e5580f0 src/lmtp/commands.c --- a/src/lmtp/commands.c Wed Aug 20 14:35:27 2014 +0200 +++ b/src/lmtp/commands.c Wed Aug 20 15:32:15 2014 +0200 @@ -614,7 +614,7 @@ static int client_deliver(struct client *client, const struct mail_recipient *rcpt, - struct mail_deliver_session *session) + struct mail *src_mail, struct mail_deliver_session *session) { struct mail_deliver_context dctx; struct mail_storage *storage; @@ -622,7 +622,6 @@ const struct mail_storage_settings *mail_set; struct lda_settings *lda_set; struct mail_namespace *ns; - struct mail_user *dest_user; struct setting_parser_context *set_parser; void **sets; const char *line, *error, *username; @@ -650,7 +649,7 @@ i_set_failure_prefix("lmtp(%s, %s): ", my_pid, username); if (mail_storage_service_next(storage_service, rcpt->service_user, - &dest_user) < 0) { + &client->state.dest_user) < 0) { client_send_line(client, ERRSTR_TEMP_MAILBOX_FAIL, rcpt->address); return -1; @@ -658,18 +657,18 @@ sets = mail_storage_service_user_get_set(rcpt->service_user); lda_set = sets[1]; settings_var_expand(&lda_setting_parser_info, lda_set, client->pool, - mail_user_var_expand_table(dest_user)); + mail_user_var_expand_table(client->state.dest_user)); memset(&dctx, 0, sizeof(dctx)); dctx.session = session; dctx.pool = session->pool; dctx.set = lda_set; dctx.session_id = client->state.session_id; - dctx.src_mail = client->state.raw_mail; + dctx.src_mail = src_mail; dctx.src_envelope_sender = client->state.mail_from; - dctx.dest_user = dest_user; + dctx.dest_user = client->state.dest_user; if (*dctx.set->lda_original_recipient_header != '\0') { - dctx.dest_addr = mail_deliver_get_address(dctx.src_mail, + dctx.dest_addr = mail_deliver_get_address(src_mail, dctx.set->lda_original_recipient_header); } if (dctx.dest_addr == NULL) @@ -679,12 +678,19 @@ !client->lmtp_set->lmtp_save_to_detail_mailbox) dctx.dest_mailbox_name = "INBOX"; else { - ns = mail_namespace_find_inbox(dest_user->namespaces); + ns = mail_namespace_find_inbox(dctx.dest_user->namespaces); dctx.dest_mailbox_name = t_strconcat(ns->prefix, rcpt->detail, NULL); } + dctx.save_dest_mail = array_count(&client->state.rcpt_to) > 1 && + client->state.first_saved_mail == NULL; + if (mail_deliver(&dctx, &storage) == 0) { + if (dctx.dest_mail != NULL) { + i_assert(client->state.first_saved_mail == NULL); + client->state.first_saved_mail = dctx.dest_mail; + } client_send_line(client, "250 2.0.0 <%s> %s Saved", rcpt->address, client->state.session_id); ret = 0; @@ -711,21 +717,30 @@ rcpt->address); ret = -1; } - mail_user_unref(&dest_user); return ret; } -static void client_deliver_mails(struct client *client, - struct mail_deliver_session *session) +static bool client_deliver_next(struct client *client, struct mail *src_mail, + struct mail_deliver_session *session) { const struct mail_recipient *rcpts; - unsigned int i, count; + unsigned int count; + int ret; rcpts = array_get(&client->state.rcpt_to, &count); - for (i = 0; i < count; i++) { - (void)client_deliver(client, &rcpts[i], session); + while (client->state.rcpt_idx < count) { + ret = client_deliver(client, &rcpts[client->state.rcpt_idx], + src_mail, session); i_set_failure_prefix("lmtp(%s): ", my_pid); + + client->state.rcpt_idx++; + if (ret == 0) + return TRUE; + /* failed. try the next one. */ + if (client->state.dest_user != NULL) + mail_user_unref(&client->state.dest_user); } + return FALSE; } static void client_rcpt_fail_all(struct client *client) @@ -800,16 +815,51 @@ client_input_data_write_local(struct client *client, struct istream *input) { struct mail_deliver_session *session; - uid_t old_uid; + struct mail *src_mail; + uid_t old_uid, first_uid = (uid_t)-1; if (client_open_raw_mail(client, input) < 0) return; session = mail_deliver_session_init(); old_uid = geteuid(); - client_deliver_mails(client, session); + src_mail = client->state.raw_mail; + while (client_deliver_next(client, src_mail, session)) { + if (client->state.first_saved_mail == NULL || + client->state.first_saved_mail == src_mail) + mail_user_unref(&client->state.dest_user); + else { + /* use the first saved message to save it elsewhere too. + this might allow hard linking the files. */ + client->state.dest_user = NULL; + src_mail = client->state.first_saved_mail; + first_uid = geteuid(); + i_assert(first_uid != 0); + } + } mail_deliver_session_deinit(&session); + if (client->state.first_saved_mail != NULL) { + struct mail *mail = client->state.first_saved_mail; + struct mailbox_transaction_context *trans = mail->transaction; + struct mailbox *box = trans->box; + struct mail_user *user = box->storage->user; + + /* just in case these functions are going to write anything, + change uid back to user's own one */ + if (first_uid != old_uid) { + if (seteuid(0) < 0) + i_fatal("seteuid(0) failed: %m"); + if (seteuid(first_uid) < 0) + i_fatal("seteuid() failed: %m"); + } + + mail_free(&mail); + mailbox_transaction_rollback(&trans); + mailbox_free(&box); + mail_user_unref(&user); + } + if (old_uid == 0) { /* switch back to running as root, since that's what we're practically doing anyway. it's also important in case we From dovecot at dovecot.org Wed Aug 20 13:35:54 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 20 Aug 2014 13:35:54 +0000 Subject: dovecot-2.2: pop3: Fixed potential assert-crash on disconnect. Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/d14f30ccd118 changeset: 17737:d14f30ccd118 user: Timo Sirainen date: Wed Aug 20 15:35:43 2014 +0200 description: pop3: Fixed potential assert-crash on disconnect. diffstat: src/pop3/pop3-client.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diffs (13 lines): diff -r f0f19e5580f0 -r d14f30ccd118 src/pop3/pop3-client.c --- a/src/pop3/pop3-client.c Wed Aug 20 15:32:15 2014 +0200 +++ b/src/pop3/pop3-client.c Wed Aug 20 15:35:43 2014 +0200 @@ -811,7 +811,8 @@ if (client->cmd == NULL) { if (o_stream_get_buffer_used_size(client->output) < - POP3_OUTBUF_THROTTLE_SIZE/2 && client->io == NULL) { + POP3_OUTBUF_THROTTLE_SIZE/2 && client->io == NULL && + !client->input->closed) { /* enable input again */ client->io = io_add_istream(client->input, client_input, client); From dovecot at dovecot.org Thu Aug 21 09:41:04 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 21 Aug 2014 09:41:04 +0000 Subject: dovecot-2.2: redis: Added support for path=/unix/socket/path par... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/5832a9ed3ece changeset: 17738:5832a9ed3ece user: Timo Sirainen date: Thu Aug 21 11:40:51 2014 +0200 description: redis: Added support for path=/unix/socket/path parameter instead of host/port. diffstat: src/lib-dict/dict-redis.c | 36 ++++++++++++++++++++---------------- 1 files changed, 20 insertions(+), 16 deletions(-) diffs (100 lines): diff -r d14f30ccd118 -r 5832a9ed3ece src/lib-dict/dict-redis.c --- a/src/lib-dict/dict-redis.c Wed Aug 20 15:35:43 2014 +0200 +++ b/src/lib-dict/dict-redis.c Thu Aug 21 11:40:51 2014 +0200 @@ -43,9 +43,7 @@ struct redis_dict { struct dict dict; - struct ip_addr ip; char *username, *key_prefix; - unsigned int port; unsigned int timeout_msecs; struct ioloop *ioloop, *prev_ioloop; @@ -271,8 +269,7 @@ struct redis_connection *conn = (struct redis_connection *)_conn; if (!success) { - i_error("redis: connect(%s, %u) failed: %m", - net_ip2addr(&conn->dict->ip), conn->dict->port); + i_error("redis: connect(%s) failed: %m", _conn->name); } else { conn->dict->connected = TRUE; } @@ -320,7 +317,9 @@ const char **error_r) { struct redis_dict *dict; - const char *const *args; + struct ip_addr ip; + unsigned int port = REDIS_DEFAULT_PORT; + const char *const *args, *unix_path = NULL; int ret = 0; if (redis_connections == NULL) { @@ -330,22 +329,23 @@ } dict = i_new(struct redis_dict, 1); - if (net_addr2ip("127.0.0.1", &dict->ip) < 0) + if (net_addr2ip("127.0.0.1", &ip) < 0) i_unreached(); - dict->port = REDIS_DEFAULT_PORT; dict->timeout_msecs = REDIS_DEFAULT_LOOKUP_TIMEOUT_MSECS; dict->key_prefix = i_strdup(""); args = t_strsplit(uri, ":"); for (; *args != NULL; args++) { - if (strncmp(*args, "host=", 5) == 0) { - if (net_addr2ip(*args+5, &dict->ip) < 0) { + if (strncmp(*args, "path=", 5) == 0) { + unix_path = *args + 5; + } else if (strncmp(*args, "host=", 5) == 0) { + if (net_addr2ip(*args+5, &ip) < 0) { *error_r = t_strdup_printf("Invalid IP: %s", *args+5); ret = -1; } } else if (strncmp(*args, "port=", 5) == 0) { - if (str_to_uint(*args+5, &dict->port) < 0) { + if (str_to_uint(*args+5, &port) < 0) { *error_r = t_strdup_printf("Invalid port: %s", *args+5); ret = -1; @@ -370,8 +370,13 @@ i_free(dict); return -1; } - connection_init_client_ip(redis_connections, &dict->conn.conn, - &dict->ip, dict->port); + if (unix_path != NULL) { + connection_init_client_unix(redis_connections, &dict->conn.conn, + unix_path); + } else { + connection_init_client_ip(redis_connections, &dict->conn.conn, + &ip, port); + } dict->dict = *driver; dict->conn.last_reply = str_new(default_pool, 256); dict->conn.dict = dict; @@ -453,8 +458,7 @@ if (dict->conn.conn.fd_in == -1 && connection_client_connect(&dict->conn.conn) < 0) { - i_error("redis: Couldn't connect to %s:%u", - net_ip2addr(&dict->ip), dict->port); + i_error("redis: Couldn't connect to %s", dict->conn.conn.name); } else { to = timeout_add(dict->timeout_msecs, redis_dict_lookup_timeout, dict); @@ -526,8 +530,8 @@ if (dict->conn.conn.fd_in == -1 && connection_client_connect(&dict->conn.conn) < 0) { - i_error("redis: Couldn't connect to %s:%u", - net_ip2addr(&dict->ip), dict->port); + i_error("redis: Couldn't connect to %s", + dict->conn.conn.name); } else if (!dict->connected) { /* wait for connection */ redis_wait(dict); From dovecot at dovecot.org Thu Aug 21 12:49:48 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 21 Aug 2014 12:49:48 +0000 Subject: dovecot-2.2: fts-lucene: Make sure Lucene indexes are always clo... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/5f8cff646417 changeset: 17739:5f8cff646417 user: Timo Sirainen date: Thu Aug 21 14:46:47 2014 +0200 description: fts-lucene: Make sure Lucene indexes are always closed at deinit to avoid memory leaks. At least optimize leaked memory. diffstat: src/plugins/fts-lucene/lucene-wrapper.cc | 38 +++++++++++++++++++++---------- 1 files changed, 26 insertions(+), 12 deletions(-) diffs (81 lines): diff -r 5832a9ed3ece -r 5f8cff646417 src/plugins/fts-lucene/lucene-wrapper.cc --- a/src/plugins/fts-lucene/lucene-wrapper.cc Thu Aug 21 11:40:51 2014 +0200 +++ b/src/plugins/fts-lucene/lucene-wrapper.cc Thu Aug 21 14:46:47 2014 +0200 @@ -97,6 +97,8 @@ static bool textcat_broken = FALSE; static int textcat_refcount = 0; +static void lucene_handle_error(struct lucene_index *index, CLuceneError &err, + const char *msg); static void rescan_clear_unseen_mailboxes(struct lucene_index *index, struct rescan_context *rescan_ctx); @@ -141,9 +143,23 @@ void lucene_index_close(struct lucene_index *index) { - _CLDELETE(index->reader); - _CLDELETE(index->writer); _CLDELETE(index->searcher); + if (index->writer != NULL) { + try { + index->writer->close(); + } catch (CLuceneError &err) { + lucene_handle_error(index, err, "IndexWriter::close"); + } + _CLDELETE(index->writer); + } + if (index->reader != NULL) { + try { + index->reader->close(); + } catch (CLuceneError &err) { + lucene_handle_error(index, err, "IndexReader::close"); + } + _CLDELETE(index->reader); + } } void lucene_index_deinit(struct lucene_index *index) @@ -852,12 +868,11 @@ index->reader->deleteDocument(hits->id(i)); } _CLDELETE(hits); - index->reader->close(); - lucene_index_close(index); } catch (CLuceneError &err) { lucene_handle_error(index, err, "rescan search"); failed = true; } + lucene_index_close(index); if (ctx.box != NULL) rescan_finish(&ctx); array_free(&ctx.uids); @@ -965,14 +980,7 @@ } } - try { - if (index->reader != NULL) - index->reader->close(); - lucene_index_close(index); - } catch (CLuceneError &err) { - lucene_handle_error(index, err, "expunge delete"); - ret = -1; - } + lucene_index_close(index); ret2 = fts_expunge_log_read_end(&ctx); if (ret < 0 || ret2 < 0) @@ -997,6 +1005,12 @@ lucene_handle_error(index, err, "IndexWriter::optimize()"); ret = -1; } + try { + writer->close(); + } catch (CLuceneError &err) { + lucene_handle_error(index, err, "IndexWriter::close()"); + ret = -1; + } if (writer != NULL) _CLDELETE(writer); return ret; From dovecot at dovecot.org Thu Aug 21 12:49:53 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 21 Aug 2014 12:49:53 +0000 Subject: dovecot-2.2: fts-lucene: Automatically close index after 2 minut... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/9cdf42df4c4b changeset: 17740:9cdf42df4c4b user: Timo Sirainen date: Thu Aug 21 14:48:41 2014 +0200 description: fts-lucene: Automatically close index after 2 minutes of idling. diffstat: src/plugins/fts-lucene/lucene-wrapper.cc | 16 +++++++++++++--- 1 files changed, 13 insertions(+), 3 deletions(-) diffs (69 lines): diff -r 5f8cff646417 -r 9cdf42df4c4b src/plugins/fts-lucene/lucene-wrapper.cc --- a/src/plugins/fts-lucene/lucene-wrapper.cc Thu Aug 21 14:46:47 2014 +0200 +++ b/src/plugins/fts-lucene/lucene-wrapper.cc Thu Aug 21 14:48:41 2014 +0200 @@ -6,6 +6,7 @@ #include "unichar.h" #include "hash.h" #include "hex-binary.h" +#include "ioloop.h" #include "unlink-directory.h" #include "mail-index.h" #include "mail-search.h" @@ -35,6 +36,7 @@ #define FTS_LUCENE_MAX_SEARCH_TERMS 1000 #define LUCENE_LOCK_OVERRIDE_SECS 60 +#define LUCENE_INDEX_CLOSE_TIMEOUT_MSECS (120*1000) using namespace lucene::document; using namespace lucene::index; @@ -66,6 +68,7 @@ IndexReader *reader; IndexWriter *writer; IndexSearcher *searcher; + struct timeout *to_close; buffer_t *normalizer_buf; Analyzer *default_analyzer, *cur_analyzer; @@ -97,8 +100,6 @@ static bool textcat_broken = FALSE; static int textcat_refcount = 0; -static void lucene_handle_error(struct lucene_index *index, CLuceneError &err, - const char *msg); static void rescan_clear_unseen_mailboxes(struct lucene_index *index, struct rescan_context *rescan_ctx); @@ -143,6 +144,9 @@ void lucene_index_close(struct lucene_index *index) { + if (index->to_close != NULL) + timeout_remove(&index->to_close); + _CLDELETE(index->searcher); if (index->writer != NULL) { try { @@ -274,8 +278,11 @@ static int lucene_index_open(struct lucene_index *index) { - if (index->reader != NULL) + if (index->reader != NULL) { + i_assert(index->to_close != NULL); + timeout_reset(index->to_close); return 1; + } if (!IndexReader::indexExists(index->path)) return 0; @@ -286,6 +293,9 @@ lucene_handle_error(index, err, "IndexReader::open()"); return -1; } + i_assert(index->to_close == NULL); + index->to_close = timeout_add(LUCENE_INDEX_CLOSE_TIMEOUT_MSECS, + lucene_index_close, index); return 1; } From dovecot at dovecot.org Thu Aug 21 12:50:23 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 21 Aug 2014 12:50:23 +0000 Subject: dovecot-2.2: fts-lucene: When deleting corrupted lucene-indexes/... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/58eaff87a81b changeset: 17741:58eaff87a81b user: Timo Sirainen date: Thu Aug 21 14:49:34 2014 +0200 description: fts-lucene: When deleting corrupted lucene-indexes/ directory, don't rmdir it. This at least avoids errors with NFS when some of the files are still open inside it by other processes. diffstat: src/plugins/fts-lucene/lucene-wrapper.cc | 5 ++--- 1 files changed, 2 insertions(+), 3 deletions(-) diffs (22 lines): diff -r 9cdf42df4c4b -r 58eaff87a81b src/plugins/fts-lucene/lucene-wrapper.cc --- a/src/plugins/fts-lucene/lucene-wrapper.cc Thu Aug 21 14:48:41 2014 +0200 +++ b/src/plugins/fts-lucene/lucene-wrapper.cc Thu Aug 21 14:49:34 2014 +0200 @@ -268,8 +268,7 @@ err.number() == CL_ERR_IO)) { /* delete corrupted index. most IO errors are also about missing files and other such corruption.. */ - if (unlink_directory(index->path, - UNLINK_DIRECTORY_FLAG_RMDIR) < 0 && + if (unlink_directory(index->path, 0) < 0 && errno != ENOENT) i_error("unlink_directory(%s) failed: %m", index->path); rescan_clear_unseen_mailboxes(index, NULL); @@ -415,7 +414,7 @@ return ret; /* settings changed, rebuild index */ - if (unlink_directory(index->path, UNLINK_DIRECTORY_FLAG_RMDIR) < 0) { + if (unlink_directory(index->path, 0) < 0) { i_error("unlink_directory(%s) failed: %m", index->path); ret = -1; } else { From dovecot at dovecot.org Thu Aug 21 12:51:31 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 21 Aug 2014 12:51:31 +0000 Subject: dovecot-2.2: fts-lucene: Don't crash when index building fails b... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/b0c301f2d616 changeset: 17742:b0c301f2d616 user: Timo Sirainen date: Thu Aug 21 14:51:11 2014 +0200 description: fts-lucene: Don't crash when index building fails but we were still planning to optimize the index. diffstat: src/plugins/fts-lucene/fts-backend-lucene.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 58eaff87a81b -r b0c301f2d616 src/plugins/fts-lucene/fts-backend-lucene.c --- a/src/plugins/fts-lucene/fts-backend-lucene.c Thu Aug 21 14:49:34 2014 +0200 +++ b/src/plugins/fts-lucene/fts-backend-lucene.c Thu Aug 21 14:51:11 2014 +0200 @@ -289,7 +289,7 @@ if (fts_backend_lucene_need_optimize(ctx)) { if (ctx->lucene_opened) (void)fts_backend_optimize(_ctx->backend); - else { + else if (ctx->first_box_vname != NULL) { struct mail_user *user = backend->backend.ns->user; const char *cmd, *path; int fd; From dovecot at dovecot.org Thu Aug 21 12:52:35 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 21 Aug 2014 12:52:35 +0000 Subject: dovecot-2.2: fts-lucene: Compiling fix for earlier change. Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/9e825d5b0dd0 changeset: 17743:9e825d5b0dd0 user: Timo Sirainen date: Thu Aug 21 15:52:14 2014 +0300 description: fts-lucene: Compiling fix for earlier change. diffstat: src/plugins/fts-lucene/lucene-wrapper.cc | 7 +++++-- 1 files changed, 5 insertions(+), 2 deletions(-) diffs (38 lines): diff -r b0c301f2d616 -r 9e825d5b0dd0 src/plugins/fts-lucene/lucene-wrapper.cc --- a/src/plugins/fts-lucene/lucene-wrapper.cc Thu Aug 21 14:51:11 2014 +0200 +++ b/src/plugins/fts-lucene/lucene-wrapper.cc Thu Aug 21 15:52:14 2014 +0300 @@ -8,6 +8,7 @@ #include "hex-binary.h" #include "ioloop.h" #include "unlink-directory.h" +#include "ioloop.h" #include "mail-index.h" #include "mail-search.h" #include "mail-namespace.h" @@ -100,6 +101,8 @@ static bool textcat_broken = FALSE; static int textcat_refcount = 0; +static void lucene_handle_error(struct lucene_index *index, CLuceneError &err, + const char *msg); static void rescan_clear_unseen_mailboxes(struct lucene_index *index, struct rescan_context *rescan_ctx); @@ -268,7 +271,7 @@ err.number() == CL_ERR_IO)) { /* delete corrupted index. most IO errors are also about missing files and other such corruption.. */ - if (unlink_directory(index->path, 0) < 0 && + if (unlink_directory(index->path, (enum unlink_directory_flags)0) < 0 && errno != ENOENT) i_error("unlink_directory(%s) failed: %m", index->path); rescan_clear_unseen_mailboxes(index, NULL); @@ -414,7 +417,7 @@ return ret; /* settings changed, rebuild index */ - if (unlink_directory(index->path, 0) < 0) { + if (unlink_directory(index->path, (enum unlink_directory_flags)0) < 0) { i_error("unlink_directory(%s) failed: %m", index->path); ret = -1; } else { From dovecot at dovecot.org Thu Aug 21 18:56:55 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 21 Aug 2014 18:56:55 +0000 Subject: dovecot-2.2: doveadm ring status: Help text was shown for wrong ... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/f82f8409334c changeset: 17744:f82f8409334c user: Timo Sirainen date: Thu Aug 21 20:54:46 2014 +0200 description: doveadm ring status: Help text was shown for wrong command. diffstat: src/doveadm/doveadm-director.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 9e825d5b0dd0 -r f82f8409334c src/doveadm/doveadm-director.c --- a/src/doveadm/doveadm-director.c Thu Aug 21 15:52:14 2014 +0300 +++ b/src/doveadm/doveadm-director.c Thu Aug 21 20:54:46 2014 +0200 @@ -711,7 +711,7 @@ const char *line, *const *args; unsigned long l; - ctx = cmd_director_init(argc, argv, "a:", cmd_director_status); + ctx = cmd_director_init(argc, argv, "a:", cmd_director_ring_status); doveadm_print_init(DOVEADM_PRINT_TYPE_TABLE); doveadm_print_header_simple("director ip"); From dovecot at dovecot.org Thu Aug 21 18:57:25 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 21 Aug 2014 18:57:25 +0000 Subject: dovecot-2.2: doveadm exec: Show help if binary name wasn't given. Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/787ebba12684 changeset: 17745:787ebba12684 user: Timo Sirainen date: Thu Aug 21 20:56:40 2014 +0200 description: doveadm exec: Show help if binary name wasn't given. diffstat: src/doveadm/doveadm.c | 12 ++++++++---- 1 files changed, 8 insertions(+), 4 deletions(-) diffs (33 lines): diff -r f82f8409334c -r 787ebba12684 src/doveadm/doveadm.c --- a/src/doveadm/doveadm.c Thu Aug 21 20:54:46 2014 +0200 +++ b/src/doveadm/doveadm.c Thu Aug 21 20:56:40 2014 +0200 @@ -174,10 +174,18 @@ cmd_config, "config", "[doveconf parameters]" }; +static void cmd_exec(int argc ATTR_UNUSED, char *argv[]); +static struct doveadm_cmd doveadm_cmd_exec = { + cmd_exec, "exec", " [binary parameters]" +}; + static void cmd_exec(int argc ATTR_UNUSED, char *argv[]) { const char *path, *binary = argv[1]; + if (binary == NULL) + help(&doveadm_cmd_exec); + path = t_strdup_printf("%s/%s", doveadm_settings->libexec_dir, binary); argv++; argv[0] = t_strdup_noconst(path); @@ -185,10 +193,6 @@ i_fatal("execv(%s) failed: %m", argv[0]); } -static struct doveadm_cmd doveadm_cmd_exec = { - cmd_exec, "exec", " [binary parameters]" -}; - static bool doveadm_try_run_multi_word(const struct doveadm_cmd *cmd, const char *cmdname, int argc, char *argv[]) From pigeonhole at rename-it.nl Sat Aug 23 19:12:06 2014 From: pigeonhole at rename-it.nl (pigeonhole at rename-it.nl) Date: Sat, 23 Aug 2014 21:12:06 +0200 Subject: dovecot-2.2-pigeonhole: lib-sieve: file storage: Warning about a... Message-ID: details: http://hg.rename-it.nl/dovecot-2.2-pigeonhole/rev/3b964432b84b changeset: 1908:3b964432b84b user: Stephan Bosch date: Sat Aug 23 21:11:54 2014 +0200 description: lib-sieve: file storage: Warning about active script not being a symlink was triggered at inappropriate times. Fixed by issueing the warning only when storage is opened as READWRITE (ManageSieve). diffstat: src/lib-sieve/storage/file/sieve-file-storage-active.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diffs (13 lines): diff -r 1e388884d31c -r 3b964432b84b src/lib-sieve/storage/file/sieve-file-storage-active.c --- a/src/lib-sieve/storage/file/sieve-file-storage-active.c Tue Aug 05 18:25:12 2014 +0200 +++ b/src/lib-sieve/storage/file/sieve-file-storage-active.c Sat Aug 23 21:11:54 2014 +0200 @@ -78,7 +78,8 @@ * Activating a script will automatically resolve this, so * there is no need to panic on this one. */ - if ( (storage->flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) == 0 ) { + if ( (storage->flags & SIEVE_STORAGE_FLAG_READWRITE) != 0 && + (storage->flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) == 0 ) { sieve_storage_sys_warning(storage, "Active sieve script symlink %s is no symlink.", fstorage->active_path); From pigeonhole at rename-it.nl Sat Aug 23 19:17:12 2014 From: pigeonhole at rename-it.nl (pigeonhole at rename-it.nl) Date: Sat, 23 Aug 2014 21:17:12 +0200 Subject: dovecot-2.2-pigeonhole: Changed handling of ENOSPACE to a normal... Message-ID: details: http://hg.rename-it.nl/dovecot-2.2-pigeonhole/rev/0b25efe31d79 changeset: 1909:0b25efe31d79 user: Stephan Bosch date: Sat Aug 23 21:16:34 2014 +0200 description: Changed handling of ENOSPACE to a normal temporary failure and added handling of ENOQUOTA as a user error. Patch by Timo Sirainen. diffstat: src/lib-sieve/sieve-actions.c | 6 +--- src/lib-sieve/sieve-types.h | 2 - src/lib-sieve/storage/file/sieve-file-storage-save.c | 24 ++++++++++---------- src/managesieve/managesieve-client.c | 1 - src/plugins/lda-sieve/lda-sieve-plugin.c | 2 +- 5 files changed, 15 insertions(+), 20 deletions(-) diffs (112 lines): diff -r 3b964432b84b -r 0b25efe31d79 src/lib-sieve/sieve-actions.c --- a/src/lib-sieve/sieve-actions.c Sat Aug 23 21:11:54 2014 +0200 +++ b/src/lib-sieve/sieve-actions.c Sat Aug 23 21:16:34 2014 +0200 @@ -634,12 +634,10 @@ error_code = trans->error_code; if ( error_code == MAIL_ERROR_NOTFOUND || - error_code == MAIL_ERROR_PARAMS ) { + error_code == MAIL_ERROR_PARAMS || + error_code == MAIL_ERROR_NOQUOTA ) { sieve_result_error(aenv, "failed to store into mailbox %s: %s", mailbox_name, errstr); - } else if ( error_code == MAIL_ERROR_NOSPACE ) { - sieve_result_global_log_error - (aenv, "failed to store into mailbox %s: %s", mailbox_name, errstr); } else { sieve_result_global_error(aenv, "failed to store into mailbox %s: %s", mailbox_name, errstr); diff -r 3b964432b84b -r 0b25efe31d79 src/lib-sieve/sieve-types.h --- a/src/lib-sieve/sieve-types.h Sat Aug 23 21:11:54 2014 +0200 +++ b/src/lib-sieve/sieve-types.h Sat Aug 23 21:16:34 2014 +0200 @@ -92,8 +92,6 @@ /* No permission to do the request */ SIEVE_ERROR_NO_PERMISSION, /* Out of disk space */ - SIEVE_ERROR_NO_SPACE, - /* Out of disk space */ SIEVE_ERROR_NO_QUOTA, /* Item (e.g. script or binary) cannot be found */ SIEVE_ERROR_NOT_FOUND, diff -r 3b964432b84b -r 0b25efe31d79 src/lib-sieve/storage/file/sieve-file-storage-save.c --- a/src/lib-sieve/storage/file/sieve-file-storage-save.c Sat Aug 23 21:11:54 2014 +0200 +++ b/src/lib-sieve/storage/file/sieve-file-storage-save.c Sat Aug 23 21:16:34 2014 +0200 @@ -111,10 +111,10 @@ *fpath_r = str_c(path); if (fd == -1) { - if (ENOSPACE(errno)) { + if (ENOQUOTA(errno)) { sieve_storage_set_error(storage, - SIEVE_ERROR_NO_SPACE, - "Not enough disk space"); + SIEVE_ERROR_NO_QUOTA, + "Not enough disk quota"); } else { sieve_storage_set_critical(storage, "save: " "open(%s) failed: %m", str_c(path)); @@ -142,10 +142,10 @@ result = 0; else { result = -1; - if ( ENOSPACE(errno) ) { + if ( ENOQUOTA(errno) ) { sieve_storage_set_error(storage, - SIEVE_ERROR_NO_SPACE, - "Not enough disk space"); + SIEVE_ERROR_NO_QUOTA, + "Not enough disk quota"); } else if ( errno == EACCES ) { sieve_storage_set_critical(storage, "save: " "Failed to save Sieve script: " @@ -275,10 +275,10 @@ fsctx->tmp_path = NULL; errno = output_errno; - if ( ENOSPACE(errno) ) { + if ( ENOQUOTA(errno) ) { sieve_storage_set_error(storage, - SIEVE_ERROR_NO_SPACE, - "Not enough disk space"); + SIEVE_ERROR_NO_QUOTA, + "Not enough disk quota"); } else if ( errno != 0 ) { sieve_storage_set_critical(storage, "save: " "write(%s) failed: %m", fsctx->tmp_path); @@ -428,10 +428,10 @@ o_stream_destroy(&output); if (rename(str_c(temp_path), fstorage->active_path) < 0) { - if ( ENOSPACE(errno) ) { + if ( ENOQUOTA(errno) ) { sieve_storage_set_error(storage, - SIEVE_ERROR_NO_SPACE, - "Not enough disk space"); + SIEVE_ERROR_NO_QUOTA, + "Not enough disk quota"); } else if ( errno == EACCES ) { sieve_storage_set_critical(storage, "%s", eacces_error_get("rename", fstorage->active_path)); diff -r 3b964432b84b -r 0b25efe31d79 src/managesieve/managesieve-client.c --- a/src/managesieve/managesieve-client.c Sat Aug 23 21:11:54 2014 +0200 +++ b/src/managesieve/managesieve-client.c Sat Aug 23 21:16:34 2014 +0200 @@ -396,7 +396,6 @@ break; case SIEVE_ERROR_NO_QUOTA: - case SIEVE_ERROR_NO_SPACE: /* Not sure if this is appropriate */ client_send_noresp(client, "QUOTA", error); break; diff -r 3b964432b84b -r 0b25efe31d79 src/plugins/lda-sieve/lda-sieve-plugin.c --- a/src/plugins/lda-sieve/lda-sieve-plugin.c Sat Aug 23 21:11:54 2014 +0200 +++ b/src/plugins/lda-sieve/lda-sieve-plugin.c Sat Aug 23 21:16:34 2014 +0200 @@ -385,7 +385,7 @@ mail_storage_get_last_error(estatus->last_storage, &mail_error); /* Don't bother administrator too much with benign errors */ - if ( mail_error == MAIL_ERROR_NOSPACE ) { + if ( mail_error == MAIL_ERROR_NOQUOTA ) { error_func = sieve_sys_info; user_error_func = sieve_sys_info; } From pigeonhole at rename-it.nl Sat Aug 23 20:52:36 2014 From: pigeonhole at rename-it.nl (pigeonhole at rename-it.nl) Date: Sat, 23 Aug 2014 22:52:36 +0200 Subject: dovecot-2.2-pigeonhole: Added support for Japanese mail addresse... Message-ID: details: http://hg.rename-it.nl/dovecot-2.2-pigeonhole/rev/62abeb85c8a5 changeset: 1910:62abeb85c8a5 user: Stephan Bosch date: Sat Aug 23 22:52:30 2014 +0200 description: Added support for Japanese mail addresses with dots at non-standard places in localpart. Based on patch by Timo Sirainen. diffstat: src/lib-sieve/sieve-address.c | 52 +++++++++++++++++++++++---------- tests/compile/errors/out-address.sieve | 5 +++ tests/extensions/envelope.svtest | 23 +++++++++++++++ 3 files changed, 64 insertions(+), 16 deletions(-) diffs (129 lines): diff -r 0b25efe31d79 -r 62abeb85c8a5 src/lib-sieve/sieve-address.c --- a/src/lib-sieve/sieve-address.c Sat Aug 23 21:16:34 2014 +0200 +++ b/src/lib-sieve/sieve-address.c Sat Aug 23 22:52:30 2014 +0200 @@ -276,10 +276,28 @@ } str_truncate(ctx->local_part, 0); - if (*ctx->parser.data == '"') + if (*ctx->parser.data == '"') { ret = rfc822_parse_quoted_string(&ctx->parser, ctx->local_part); - else - ret = rfc822_parse_dot_atom(&ctx->parser, ctx->local_part); + } else { + ret = -1; + /* NOTE: this deviates from dot-atom syntax to allow some Japanese + mail addresses with dots at non-standard places to be accepted. */ + do { + while (*ctx->parser.data == '.') { + str_append_c(ctx->local_part, '.'); + ctx->parser.data++; + if (ctx->parser.data == ctx->parser.end) { + /* @domain is missing, but local-part + parsing was successful */ + return 0; + } + ret = 1; + } + if (*ctx->parser.data == '@') + break; + ret = rfc822_parse_atom(&ctx->parser, ctx->local_part); + } while (ret > 0 && *ctx->parser.data == '.'); + } if (ret < 0) { sieve_address_error(ctx, "invalid local part"); @@ -780,6 +798,7 @@ str_truncate(parser->str, 0); if ( *parser->data == '"' ) { + /* Quoted-string = DQUOTE *qcontent DQUOTE */ str_append_c(parser->str, *parser->data); parser->data++; @@ -813,13 +832,15 @@ if ( (ret=path_skip_white_space(parser)) < 0 ) return ret; } else { - for (;;) { - if ( !IS_ATEXT(*parser->data) ) - return -1; - str_append_c(parser->str, *parser->data); - parser->data++; + /* Dot-string = Atom *("." Atom) */ - while ( parser->data < parser->end && IS_ATEXT(*parser->data)) { + /* NOTE: this deviates from Dot-String syntax to allow some Japanese + mail addresses with dots at non-standard places to be accepted. */ + + if ( !IS_ATEXT(*parser->data) && *parser->data != '.' ) + return -1; + while ( IS_ATEXT(*parser->data) || *parser->data == '.' ) { + while ( parser->data < parser->end && IS_ATEXT(*parser->data) ) { str_append_c(parser->str, *parser->data); parser->data++; } @@ -827,14 +848,13 @@ if ( (ret=path_skip_white_space(parser)) < 0 ) return ret; - if ( *parser->data != '.' ) - break; + while ( parser->data < parser->end && *parser->data == '.' ) { + str_append_c(parser->str, *parser->data); + parser->data++; + } - str_append_c(parser->str, *parser->data); - parser->data++; - - if ( path_skip_white_space(parser) <= 0 ) - return -1; + if ( (ret=path_skip_white_space(parser)) < 0 ) + return ret; } } diff -r 0b25efe31d79 -r 62abeb85c8a5 tests/compile/errors/out-address.sieve --- a/tests/compile/errors/out-address.sieve Sat Aug 23 21:16:34 2014 +0200 +++ b/tests/compile/errors/out-address.sieve Sat Aug 23 22:52:30 2014 +0200 @@ -24,4 +24,9 @@ redirect "ok at example.com"; redirect " more @ example.com "; +redirect ".japanese at example.com"; +redirect "japanese. at example.com"; +redirect "japanese...localpart at example.com"; +redirect "..japanese...localpart.. at example.com"; + vacation :from "good at voorbeeld.nl.example.com" "Ik ben weg!"; diff -r 0b25efe31d79 -r 62abeb85c8a5 tests/extensions/envelope.svtest --- a/tests/extensions/envelope.svtest Sat Aug 23 21:16:34 2014 +0200 +++ b/tests/extensions/envelope.svtest Sat Aug 23 22:52:30 2014 +0200 @@ -244,3 +244,26 @@ test_fail "failed to parse local_part only path with whitespace"; } } + +test "Envelope - Japanese localpart" { + test_set "envelope.to" ".japanese at example.com"; + if not envelope :localpart :is "to" ".japanese" { + test_fail "failed to parse japanese local_part (1)"; + } + + test_set "envelope.to" "japanese. at example.com"; + if not envelope :localpart :is "to" "japanese." { + test_fail "failed to parse japanese local_part (2)"; + } + + test_set "envelope.to" "japanese...localpart at example.com"; + if not envelope :localpart :is "to" "japanese...localpart" { + test_fail "failed to parse japanese local_part (3)"; + } + + test_set "envelope.to" "..japanese...localpart.. at example.com"; + if not envelope :localpart :is "to" "..japanese...localpart.." { + test_fail "failed to parse japanese local_part (4)"; + } + +} From pigeonhole at rename-it.nl Sat Aug 23 22:27:50 2014 From: pigeonhole at rename-it.nl (pigeonhole at rename-it.nl) Date: Sun, 24 Aug 2014 00:27:50 +0200 Subject: dovecot-2.2-pigeonhole: lib-sieve: Added version to script stora... Message-ID: details: http://hg.rename-it.nl/dovecot-2.2-pigeonhole/rev/3ceab9d20a00 changeset: 1911:3ceab9d20a00 user: Stephan Bosch date: Sun Aug 24 00:27:40 2014 +0200 description: lib-sieve: Added version to script storage class. Updated binary version. diffstat: src/lib-sieve/sieve-binary.h | 2 +- src/lib-sieve/sieve-script.c | 19 +++++++++++++++++++ src/lib-sieve/sieve-storage-private.h | 2 ++ src/lib-sieve/storage/dict/sieve-dict-storage.c | 1 + src/lib-sieve/storage/file/sieve-file-storage.c | 1 + src/lib-sieve/storage/ldap/sieve-ldap-storage.c | 1 + 6 files changed, 25 insertions(+), 1 deletions(-) diffs (100 lines): diff -r 62abeb85c8a5 -r 3ceab9d20a00 src/lib-sieve/sieve-binary.h --- a/src/lib-sieve/sieve-binary.h Sat Aug 23 22:52:30 2014 +0200 +++ b/src/lib-sieve/sieve-binary.h Sun Aug 24 00:27:40 2014 +0200 @@ -13,7 +13,7 @@ */ #define SIEVE_BINARY_VERSION_MAJOR 1 -#define SIEVE_BINARY_VERSION_MINOR 1 +#define SIEVE_BINARY_VERSION_MINOR 2 /* * Binary object diff -r 62abeb85c8a5 -r 3ceab9d20a00 src/lib-sieve/sieve-script.c --- a/src/lib-sieve/sieve-script.c Sat Aug 23 22:52:30 2014 +0200 +++ b/src/lib-sieve/sieve-script.c Sun Aug 24 00:27:40 2014 +0200 @@ -338,6 +338,7 @@ { struct sieve_binary *sbin = sieve_binary_block_get_binary(sblock); string_t *storage_class, *location; + unsigned int version; if ( sieve_binary_block_get_size(sblock) - *offset == 0 ) return 0; @@ -353,6 +354,23 @@ if ( strcmp(str_c(storage_class), script->driver_name) != 0 ) return 0; + /* version */ + if ( !sieve_binary_read_unsigned(sblock, offset, &version) ) { + sieve_script_sys_error(script, + "Binary %s has invalid metadata for script %s: " + "Invalid version", + sieve_binary_path(sbin), sieve_script_location(script)); + return -1; + } + if ( script->storage->version != version ) { + sieve_script_sys_debug(script, + "Binary %s was compiled with different version " + "of the `%s' script storage class (compiled v%d, expected v%d;" + "automatically fixed when re-compiled)", sieve_binary_path(sbin), + script->driver_name, version, script->storage->version); + return 0; + } + /* location */ if ( !sieve_binary_read_string(sblock, offset, &location) ) { sieve_script_sys_error(script, @@ -376,6 +394,7 @@ (struct sieve_script *script, struct sieve_binary_block *sblock) { sieve_binary_emit_cstring(sblock, script->driver_name); + sieve_binary_emit_unsigned(sblock, script->storage->version); sieve_binary_emit_cstring(sblock, ( script->location == NULL ? "" : script->location )); diff -r 62abeb85c8a5 -r 3ceab9d20a00 src/lib-sieve/sieve-storage-private.h --- a/src/lib-sieve/sieve-storage-private.h Sat Aug 23 22:52:30 2014 +0200 +++ b/src/lib-sieve/sieve-storage-private.h Sun Aug 24 00:27:40 2014 +0200 @@ -93,6 +93,8 @@ struct sieve_instance *svinst; const char *driver_name; + unsigned int version; + const struct sieve_storage *storage_class; struct sieve_storage_vfuncs v; diff -r 62abeb85c8a5 -r 3ceab9d20a00 src/lib-sieve/storage/dict/sieve-dict-storage.c --- a/src/lib-sieve/storage/dict/sieve-dict-storage.c Sat Aug 23 22:52:30 2014 +0200 +++ b/src/lib-sieve/storage/dict/sieve-dict-storage.c Sun Aug 24 00:27:40 2014 +0200 @@ -166,6 +166,7 @@ const struct sieve_storage sieve_dict_storage = { .driver_name = SIEVE_DICT_STORAGE_DRIVER_NAME, + .version = 0, .v = { .alloc = sieve_dict_storage_alloc, .destroy = sieve_dict_storage_destroy, diff -r 62abeb85c8a5 -r 3ceab9d20a00 src/lib-sieve/storage/file/sieve-file-storage.c --- a/src/lib-sieve/storage/file/sieve-file-storage.c Sat Aug 23 22:52:30 2014 +0200 +++ b/src/lib-sieve/storage/file/sieve-file-storage.c Sun Aug 24 00:27:40 2014 +0200 @@ -640,6 +640,7 @@ const struct sieve_storage sieve_file_storage = { .driver_name = SIEVE_FILE_STORAGE_DRIVER_NAME, + .version = 0, .allows_synchronization = TRUE, .v = { .alloc = sieve_file_storage_alloc, diff -r 62abeb85c8a5 -r 3ceab9d20a00 src/lib-sieve/storage/ldap/sieve-ldap-storage.c --- a/src/lib-sieve/storage/ldap/sieve-ldap-storage.c Sat Aug 23 22:52:30 2014 +0200 +++ b/src/lib-sieve/storage/ldap/sieve-ldap-storage.c Sun Aug 24 00:27:40 2014 +0200 @@ -158,6 +158,7 @@ const struct sieve_storage sieve_ldap_storage_plugin = { #endif .driver_name = SIEVE_LDAP_STORAGE_DRIVER_NAME, + .version = 0, .v = { .alloc = sieve_ldap_storage_alloc, .init = sieve_ldap_storage_init, From dovecot at dovecot.org Tue Aug 26 05:50:48 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 26 Aug 2014 05:50:48 +0000 Subject: dovecot-2.2: auth: Allow passdb credentials lookup also with aut... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/a2e0e89bc27d changeset: 17746:a2e0e89bc27d user: Timo Sirainen date: Tue Aug 26 14:50:15 2014 +0900 description: auth: Allow passdb credentials lookup also with auth_bind=yes Although we probably can't lookup the password itself, we're also doing passdb lokups for proxying and other purposes. These lookups will still work as long as pass_attrs & pass_filter is specified. diffstat: src/auth/passdb-ldap.c | 5 ----- 1 files changed, 0 insertions(+), 5 deletions(-) diffs (15 lines): diff -r 787ebba12684 -r a2e0e89bc27d src/auth/passdb-ldap.c --- a/src/auth/passdb-ldap.c Thu Aug 21 20:56:40 2014 +0200 +++ b/src/auth/passdb-ldap.c Tue Aug 26 14:50:15 2014 +0900 @@ -438,11 +438,6 @@ (struct ldap_passdb_module *)_module; (void)db_ldap_connect(module->conn); - - if (module->conn->set.auth_bind) { - /* Credential lookups can't be done with authentication binds */ - _module->iface.lookup_credentials = NULL; - } } static void passdb_ldap_deinit(struct passdb_module *_module) From dovecot at dovecot.org Tue Aug 26 07:43:20 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 26 Aug 2014 07:43:20 +0000 Subject: dovecot-2.2: lib-http: Added http_client_request_get_method() Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/4a11d88a280a changeset: 17747:4a11d88a280a user: Timo Sirainen date: Tue Aug 26 16:00:37 2014 +0900 description: lib-http: Added http_client_request_get_method() diffstat: src/lib-http/http-client-request.c | 5 +++++ src/lib-http/http-client.h | 1 + 2 files changed, 6 insertions(+), 0 deletions(-) diffs (26 lines): diff -r a2e0e89bc27d -r 4a11d88a280a src/lib-http/http-client-request.c --- a/src/lib-http/http-client-request.c Tue Aug 26 14:50:15 2014 +0900 +++ b/src/lib-http/http-client-request.c Tue Aug 26 16:00:37 2014 +0900 @@ -336,6 +336,11 @@ return 1; /* valid delay */ } +const char *http_client_request_get_method(struct http_client_request *req) +{ + return req->method; +} + const char *http_client_request_get_target(struct http_client_request *req) { return req->target; diff -r a2e0e89bc27d -r 4a11d88a280a src/lib-http/http-client.h --- a/src/lib-http/http-client.h Tue Aug 26 14:50:15 2014 +0900 +++ b/src/lib-http/http-client.h Tue Aug 26 16:00:37 2014 +0900 @@ -185,6 +185,7 @@ void http_client_request_delay(struct http_client_request *req, time_t seconds); +const char *http_client_request_get_method(struct http_client_request *req); const char *http_client_request_get_target(struct http_client_request *req); enum http_request_state http_client_request_get_state(struct http_client_request *req); From pigeonhole at rename-it.nl Tue Aug 26 22:19:50 2014 From: pigeonhole at rename-it.nl (pigeonhole at rename-it.nl) Date: Wed, 27 Aug 2014 00:19:50 +0200 Subject: dovecot-2.2-pigeonhole: Fixed handling of SMTP errors. Message-ID: details: http://hg.rename-it.nl/dovecot-2.2-pigeonhole/rev/dd2116e13393 changeset: 1912:dd2116e13393 user: Stephan Bosch date: Wed Aug 27 00:19:40 2014 +0200 description: Fixed handling of SMTP errors. Logging was mixed up; it logged permanent SMTP failures as errors rather than mere info. Redirect now handles temporary failure as a separate error condition, causing LDA to return a temporary failure if no other (storage) actions were performed. diffstat: src/lib-sieve/cmd-redirect.c | 14 +++++++------- src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c | 4 ++-- src/lib-sieve/plugins/notify/cmd-notify.c | 4 ++-- src/lib-sieve/plugins/vacation/cmd-vacation.c | 4 ++-- src/lib-sieve/sieve-actions.c | 4 ++-- 5 files changed, 15 insertions(+), 15 deletions(-) diffs (97 lines): diff -r 3ceab9d20a00 -r dd2116e13393 src/lib-sieve/cmd-redirect.c --- a/src/lib-sieve/cmd-redirect.c Sun Aug 24 00:27:40 2014 +0200 +++ b/src/lib-sieve/cmd-redirect.c Wed Aug 27 00:19:40 2014 +0200 @@ -357,17 +357,17 @@ /* Close SMTP transport */ if ( (ret=sieve_smtp_finish(sctx, &error)) <= 0 ) { if ( ret < 0 ) { - sieve_result_global_log_error(aenv, + sieve_result_global_error(aenv, "failed to redirect message to <%s>: %s " "(temporary failure)", str_sanitize(ctx->to_address, 256), str_sanitize(error, 512)); - } else { - sieve_result_global_error(aenv, - "failed to redirect message to <%s>: %s " - "(permanent failure)", - str_sanitize(ctx->to_address, 256), str_sanitize(error, 512)); + return SIEVE_EXEC_TEMP_FAILURE; + } - } + sieve_result_global_log_error(aenv, + "failed to redirect message to <%s>: %s " + "(permanent failure)", + str_sanitize(ctx->to_address, 256), str_sanitize(error, 512)); return SIEVE_EXEC_FAILURE; } diff -r 3ceab9d20a00 -r dd2116e13393 src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c --- a/src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c Sun Aug 24 00:27:40 2014 +0200 +++ b/src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c Wed Aug 27 00:19:40 2014 +0200 @@ -555,11 +555,11 @@ if ( (ret=sieve_smtp_finish(sctx, &error)) <= 0 ) { if (ret < 0) { - sieve_enotify_global_log_error(nenv, + sieve_enotify_global_error(nenv, "failed to send mail notification to %s: %s (temporary failure)", str_c(all), str_sanitize(error, 512)); } else { - sieve_enotify_global_error(nenv, + sieve_enotify_global_log_error(nenv, "failed to send mail notification to %s: %s (permanent failure)", str_c(all), str_sanitize(error, 512)); } diff -r 3ceab9d20a00 -r dd2116e13393 src/lib-sieve/plugins/notify/cmd-notify.c --- a/src/lib-sieve/plugins/notify/cmd-notify.c Sun Aug 24 00:27:40 2014 +0200 +++ b/src/lib-sieve/plugins/notify/cmd-notify.c Wed Aug 27 00:19:40 2014 +0200 @@ -784,11 +784,11 @@ if ( (ret=sieve_smtp_finish(sctx, &error)) <= 0 ) { if (ret < 0) { - sieve_result_global_log_error(aenv, + sieve_result_global_error(aenv, "failed to send mail notification to %s: %s (temporary failure)", str_c(all), str_sanitize(error, 512)); } else { - sieve_result_global_error(aenv, + sieve_result_global_log_error(aenv, "failed to send mail notification to %s: %s (permanent failure)", str_c(all), str_sanitize(error, 512)); } diff -r 3ceab9d20a00 -r dd2116e13393 src/lib-sieve/plugins/vacation/cmd-vacation.c --- a/src/lib-sieve/plugins/vacation/cmd-vacation.c Sun Aug 24 00:27:40 2014 +0200 +++ b/src/lib-sieve/plugins/vacation/cmd-vacation.c Wed Aug 27 00:19:40 2014 +0200 @@ -992,11 +992,11 @@ /* Close smtp session */ if ( (ret=sieve_smtp_finish(sctx, &error)) <= 0 ) { if ( ret < 0 ) { - sieve_result_global_log_error(aenv, + sieve_result_global_error(aenv, "failed to send vacation response to <%s>: %s (temporary error)", str_sanitize(reply_to, 256), str_sanitize(error, 512)); } else { - sieve_result_global_error(aenv, + sieve_result_global_log_error(aenv, "failed to send vacation response to <%s>: %s (permanent error)", str_sanitize(reply_to, 256), str_sanitize(error, 512)); } diff -r 3ceab9d20a00 -r dd2116e13393 src/lib-sieve/sieve-actions.c --- a/src/lib-sieve/sieve-actions.c Sun Aug 24 00:27:40 2014 +0200 +++ b/src/lib-sieve/sieve-actions.c Wed Aug 27 00:19:40 2014 +0200 @@ -873,12 +873,12 @@ if ( (ret=sieve_smtp_finish(sctx, &error)) <= 0 ) { if ( ret < 0 ) { - sieve_result_global_log_error(aenv, + sieve_result_global_error(aenv, "failed to send rejection message to <%s>: %s " "(temporary failure)", str_sanitize(sender, 256), str_sanitize(error, 512)); } else { - sieve_result_global_error(aenv, + sieve_result_global_log_error(aenv, "failed to send rejection message to <%s>: %s " "(permanent failure)", str_sanitize(sender, 256), str_sanitize(error, 512)); From dovecot at dovecot.org Wed Aug 27 04:39:36 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 27 Aug 2014 04:39:36 +0000 Subject: dovecot-2.2: auth ldap: Don't require password field to exist fo... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/4136f64146d0 changeset: 17748:4136f64146d0 user: Timo Sirainen date: Wed Aug 27 13:38:53 2014 +0900 description: auth ldap: Don't require password field to exist for passdb lookups when auth_bind=yes. This should fix lmtp/doveadm proxy lookups with auth_bind=yes diffstat: src/auth/passdb-ldap.c | 15 ++++++++++++--- 1 files changed, 12 insertions(+), 3 deletions(-) diffs (67 lines): diff -r 4a11d88a280a -r 4136f64146d0 src/auth/passdb-ldap.c --- a/src/auth/passdb-ldap.c Tue Aug 26 16:00:37 2014 +0900 +++ b/src/auth/passdb-ldap.c Wed Aug 27 13:38:53 2014 +0900 @@ -36,6 +36,7 @@ } callback; unsigned int entries; + bool require_password; }; static void @@ -83,6 +84,7 @@ "pass_filter matched multiple objects, aborting"); passdb_result = PASSDB_RESULT_INTERNAL_FAILURE; } else if (auth_request->passdb_password == NULL && + ldap_request->require_password && !auth_fields_exists(auth_request->extra_fields, "nopassword")) { auth_request_log_info(auth_request, AUTH_SUBSYS_DB, "No password returned (and no nopassword)"); @@ -273,7 +275,8 @@ } static void ldap_lookup_pass(struct auth_request *auth_request, - struct passdb_ldap_request *request) + struct passdb_ldap_request *request, + bool require_password) { struct passdb_module *_module = auth_request->passdb->passdb; struct ldap_passdb_module *module = @@ -284,6 +287,7 @@ const char **attr_names = (const char **)conn->pass_attr_names; string_t *str; + srequest->require_password = require_password; srequest->request.type = LDAP_REQUEST_TYPE_SEARCH; vars = auth_request_get_var_expand_table(auth_request, ldap_escape); @@ -390,7 +394,7 @@ ldap_request->request.ldap.auth_request = request; if (!conn->set.auth_bind) - ldap_lookup_pass(request, ldap_request); + ldap_lookup_pass(request, ldap_request, TRUE); else if (conn->set.auth_bind_userdn == NULL) ldap_bind_lookup_dn(request, ldap_request); else @@ -401,6 +405,7 @@ lookup_credentials_callback_t *callback) { struct passdb_ldap_request *ldap_request; + bool require_password; ldap_request = p_new(request->pool, struct passdb_ldap_request, 1); ldap_request->callback.lookup_credentials = callback; @@ -408,7 +413,11 @@ auth_request_ref(request); ldap_request->request.ldap.auth_request = request; - ldap_lookup_pass(request, ldap_request); + /* with auth_bind=yes we don't necessarily have a password. + this will fail actual password credentials lookups, but it's fine + for passdb lookups done by lmtp/doveadm */ + require_password = !conn->set.auth_bind; + ldap_lookup_pass(request, ldap_request, require_password); } static struct passdb_module * From dovecot at dovecot.org Wed Aug 27 04:54:04 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 27 Aug 2014 04:54:04 +0000 Subject: dovecot-2.2: auth ldap: Compile fix to previous change.. Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/9b5a197f5da2 changeset: 17749:9b5a197f5da2 user: Timo Sirainen date: Wed Aug 27 07:53:39 2014 +0300 description: auth ldap: Compile fix to previous change.. Looks like on my local build system ldap wasn't enabled.. diffstat: src/auth/passdb-ldap.c | 7 +++++-- 1 files changed, 5 insertions(+), 2 deletions(-) diffs (31 lines): diff -r 4136f64146d0 -r 9b5a197f5da2 src/auth/passdb-ldap.c --- a/src/auth/passdb-ldap.c Wed Aug 27 13:38:53 2014 +0900 +++ b/src/auth/passdb-ldap.c Wed Aug 27 07:53:39 2014 +0300 @@ -287,7 +287,7 @@ const char **attr_names = (const char **)conn->pass_attr_names; string_t *str; - srequest->require_password = require_password; + request->require_password = require_password; srequest->request.type = LDAP_REQUEST_TYPE_SEARCH; vars = auth_request_get_var_expand_table(auth_request, ldap_escape); @@ -404,6 +404,9 @@ static void ldap_lookup_credentials(struct auth_request *request, lookup_credentials_callback_t *callback) { + struct passdb_module *_module = request->passdb->passdb; + struct ldap_passdb_module *module = + (struct ldap_passdb_module *)_module; struct passdb_ldap_request *ldap_request; bool require_password; @@ -416,7 +419,7 @@ /* with auth_bind=yes we don't necessarily have a password. this will fail actual password credentials lookups, but it's fine for passdb lookups done by lmtp/doveadm */ - require_password = !conn->set.auth_bind; + require_password = !module->conn->set.auth_bind; ldap_lookup_pass(request, ldap_request, require_password); } From pigeonhole at rename-it.nl Thu Aug 28 09:34:44 2014 From: pigeonhole at rename-it.nl (pigeonhole at rename-it.nl) Date: Thu, 28 Aug 2014 11:34:44 +0200 Subject: dovecot-2.2-pigeonhole: Doveadm Sieve plugin: Attempting synchro... Message-ID: details: http://hg.rename-it.nl/dovecot-2.2-pigeonhole/rev/591019c327ad changeset: 1913:591019c327ad user: Stephan Bosch date: Thu Aug 28 11:34:37 2014 +0200 description: Doveadm Sieve plugin: Attempting synchronization with LDAP/DICT caused write access error. If the main script storage does not allow synchronization, it is now just logged as a debug message. diffstat: src/lib-sieve/sieve-storage-sync.c | 3 ++- src/lib-sieve/sieve-storage.c | 11 ++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diffs (41 lines): diff -r dd2116e13393 -r 591019c327ad src/lib-sieve/sieve-storage-sync.c --- a/src/lib-sieve/sieve-storage-sync.c Wed Aug 27 00:19:40 2014 +0200 +++ b/src/lib-sieve/sieve-storage-sync.c Thu Aug 28 11:34:37 2014 +0200 @@ -39,7 +39,6 @@ return 0; } - ns = mail_namespace_find_inbox(user->namespaces); storage->sync_inbox = box = mailbox_alloc(ns->list, "INBOX", flags); if (mailbox_open(box) == 0) @@ -67,6 +66,8 @@ { struct mailbox *inbox = storage->sync_inbox; + i_assert( storage->sync_inbox != NULL ); + if (mailbox_transaction_commit(t) < 0) { enum mail_error error; diff -r dd2116e13393 -r 591019c327ad src/lib-sieve/sieve-storage.c --- a/src/lib-sieve/sieve-storage.c Wed Aug 27 00:19:40 2014 +0200 +++ b/src/lib-sieve/sieve-storage.c Thu Aug 28 11:34:37 2014 +0200 @@ -266,7 +266,16 @@ else error_r = &error; - i_assert( storage_class->v.init != NULL ); + i_assert( storage_class->v.init != NULL ); + + if ( (flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) != 0 && + !storage_class->allows_synchronization ) { + sieve_sys_debug(svinst, "%s storage: " + "Storage does not support synchronization", + storage_class->driver_name); + *error_r = SIEVE_ERROR_NOT_POSSIBLE; + return NULL; + } if ((flags & SIEVE_STORAGE_FLAG_READWRITE) && storage_class->v.save_init == NULL) { From dovecot at dovecot.org Thu Aug 28 13:11:09 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 28 Aug 2014 13:11:09 +0000 Subject: dovecot-2.2: dict: Renamed struct dict_settings to dict_server_s... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/d91b43496e72 changeset: 17750:d91b43496e72 user: Timo Sirainen date: Thu Aug 28 22:06:29 2014 +0900 description: dict: Renamed struct dict_settings to dict_server_settings. diffstat: src/dict/dict-settings.c | 10 +++++----- src/dict/dict-settings.h | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diffs (55 lines): diff -r 9b5a197f5da2 -r d91b43496e72 src/dict/dict-settings.c --- a/src/dict/dict-settings.c Wed Aug 27 07:53:39 2014 +0300 +++ b/src/dict/dict-settings.c Thu Aug 28 22:06:29 2014 +0900 @@ -46,17 +46,17 @@ #undef DEF #define DEF(type, name) \ - { type, #name, offsetof(struct dict_settings, name), NULL } + { type, #name, offsetof(struct dict_server_settings, name), NULL } static const struct setting_define dict_setting_defines[] = { DEF(SET_STR, base_dir), DEF(SET_STR, dict_db_config), - { SET_STRLIST, "dict", offsetof(struct dict_settings, dicts), NULL }, + { SET_STRLIST, "dict", offsetof(struct dict_server_settings, dicts), NULL }, SETTING_DEFINE_LIST_END }; -const struct dict_settings dict_default_settings = { +const struct dict_server_settings dict_default_settings = { .base_dir = PKG_RUNDIR, .dict_db_config = "", .dicts = ARRAY_INIT @@ -68,9 +68,9 @@ .defaults = &dict_default_settings, .type_offset = (size_t)-1, - .struct_size = sizeof(struct dict_settings), + .struct_size = sizeof(struct dict_server_settings), .parent_offset = (size_t)-1 }; -const struct dict_settings *dict_settings; +const struct dict_server_settings *dict_settings; diff -r 9b5a197f5da2 -r d91b43496e72 src/dict/dict-settings.h --- a/src/dict/dict-settings.h Wed Aug 27 07:53:39 2014 +0300 +++ b/src/dict/dict-settings.h Thu Aug 28 22:06:29 2014 +0900 @@ -1,13 +1,13 @@ #ifndef DICT_SETTINGS_H #define DICT_SETTINGS_H -struct dict_settings { +struct dict_server_settings { const char *base_dir; const char *dict_db_config; ARRAY(const char *) dicts; }; extern const struct setting_parser_info dict_setting_parser_info; -extern const struct dict_settings *dict_settings; +extern const struct dict_server_settings *dict_settings; #endif From dovecot at dovecot.org Thu Aug 28 13:11:29 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 28 Aug 2014 13:11:29 +0000 Subject: dovecot-2.2: lib-dict: Changed dict.init() API to take struct di... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/77e71a45a475 changeset: 17751:77e71a45a475 user: Timo Sirainen date: Thu Aug 28 21:56:41 2014 +0900 description: lib-dict: Changed dict.init() API to take struct dict_settings and added dict_init_full(). This allows giving more settings to dict in future as needed. Unfortunately it also breaks the internal dict API, but there aren't really any plugins widely using it, so it's not a big problem. diffstat: src/lib-dict/dict-client.c | 11 +++++------ src/lib-dict/dict-file.c | 8 +++----- src/lib-dict/dict-fs.c | 11 +++++------ src/lib-dict/dict-memcached-ascii.c | 10 ++++------ src/lib-dict/dict-memcached.c | 6 ++---- src/lib-dict/dict-private.h | 3 +-- src/lib-dict/dict-redis.c | 12 +++++------- src/lib-dict/dict-sql.c | 5 ++--- src/lib-dict/dict.c | 17 ++++++++++++++--- src/lib-dict/dict.h | 10 +++++++++- 10 files changed, 50 insertions(+), 43 deletions(-) diffs (279 lines): diff -r d91b43496e72 -r 77e71a45a475 src/lib-dict/dict-client.c --- a/src/lib-dict/dict-client.c Thu Aug 28 22:06:29 2014 +0900 +++ b/src/lib-dict/dict-client.c Thu Aug 28 21:56:41 2014 +0900 @@ -477,9 +477,8 @@ static int client_dict_init(struct dict *driver, const char *uri, - enum dict_data_type value_type, const char *username, - const char *base_dir, struct dict **dict_r, - const char **error_r) + const struct dict_settings *set, + struct dict **dict_r, const char **error_r) { struct client_dict *dict; const char *dest_uri; @@ -496,8 +495,8 @@ dict = p_new(pool, struct client_dict, 1); dict->pool = pool; dict->dict = *driver; - dict->value_type = value_type; - dict->username = p_strdup(pool, username); + dict->value_type = set->value_type; + dict->username = p_strdup(pool, set->username); dict->fd = -1; @@ -505,7 +504,7 @@ /* path given */ dict->path = p_strdup_until(pool, uri, dest_uri); } else { - dict->path = p_strconcat(pool, base_dir, + dict->path = p_strconcat(pool, set->base_dir, "/"DEFAULT_DICT_SERVER_SOCKET_FNAME, NULL); } dict->uri = p_strdup(pool, dest_uri + 1); diff -r d91b43496e72 -r 77e71a45a475 src/lib-dict/dict-file.c --- a/src/lib-dict/dict-file.c Thu Aug 28 22:06:29 2014 +0900 +++ b/src/lib-dict/dict-file.c Thu Aug 28 21:56:41 2014 +0900 @@ -3,6 +3,7 @@ #include "lib.h" #include "array.h" #include "hash.h" +#include "home-expand.h" #include "mkdir-parents.h" #include "file-lock.h" #include "file-dotlock.h" @@ -54,10 +55,8 @@ static int file_dict_init(struct dict *driver, const char *uri, - enum dict_data_type value_type ATTR_UNUSED, - const char *username ATTR_UNUSED, - const char *base_dir ATTR_UNUSED, struct dict **dict_r, - const char **error_r) + const struct dict_settings *set ATTR_UNUSED, + struct dict **dict_r, const char **error_r) { struct file_dict *dict; const char *p; @@ -77,7 +76,6 @@ dict->lock_method = FILE_LOCK_METHOD_FLOCK; else { *error_r = t_strdup_printf("Invalid parameter: %s", p+1); - i_free(dict->path); i_free(dict); return -1; } diff -r d91b43496e72 -r 77e71a45a475 src/lib-dict/dict-fs.c --- a/src/lib-dict/dict-fs.c Thu Aug 28 22:06:29 2014 +0900 +++ b/src/lib-dict/dict-fs.c Thu Aug 28 21:56:41 2014 +0900 @@ -16,10 +16,8 @@ static int fs_dict_init(struct dict *driver, const char *uri, - enum dict_data_type value_type ATTR_UNUSED, - const char *username, - const char *base_dir, struct dict **dict_r, - const char **error_r) + const struct dict_settings *set, + struct dict **dict_r, const char **error_r) { struct fs_settings fs_set; struct fs *fs; @@ -36,14 +34,15 @@ } memset(&fs_set, 0, sizeof(fs_set)); - fs_set.base_dir = base_dir; + fs_set.username = set->username; + fs_set.base_dir = set->base_dir; if (fs_init(fs_driver, fs_args, &fs_set, &fs, error_r) < 0) return -1; dict = i_new(struct fs_dict, 1); dict->dict = *driver; dict->fs = fs; - dict->username = i_strdup(username); + dict->username = i_strdup(set->username); *dict_r = &dict->dict; return 0; diff -r d91b43496e72 -r 77e71a45a475 src/lib-dict/dict-memcached-ascii.c --- a/src/lib-dict/dict-memcached-ascii.c Thu Aug 28 22:06:29 2014 +0900 +++ b/src/lib-dict/dict-memcached-ascii.c Thu Aug 28 21:56:41 2014 +0900 @@ -347,9 +347,7 @@ static int memcached_ascii_dict_init(struct dict *driver, const char *uri, - enum dict_data_type value_type ATTR_UNUSED, - const char *username, - const char *base_dir ATTR_UNUSED, + const struct dict_settings *set, struct dict **dict_r, const char **error_r) { struct memcached_ascii_dict *dict; @@ -411,11 +409,11 @@ dict->conn.reply_str = str_new(default_pool, 256); dict->conn.dict = dict; - if (strchr(username, DICT_USERNAME_SEPARATOR) == NULL) - dict->username = i_strdup(username); + if (strchr(set->username, DICT_USERNAME_SEPARATOR) == NULL) + dict->username = i_strdup(set->username); else { /* escape the username */ - dict->username = i_strdup(memcached_ascii_escape_username(username)); + dict->username = i_strdup(memcached_ascii_escape_username(set->username)); } i_array_init(&dict->input_states, 4); i_array_init(&dict->replies, 4); diff -r d91b43496e72 -r 77e71a45a475 src/lib-dict/dict-memcached.c --- a/src/lib-dict/dict-memcached.c Thu Aug 28 22:06:29 2014 +0900 +++ b/src/lib-dict/dict-memcached.c Thu Aug 28 21:56:41 2014 +0900 @@ -169,10 +169,8 @@ static int memcached_dict_init(struct dict *driver, const char *uri, - enum dict_data_type value_type ATTR_UNUSED, - const char *username ATTR_UNUSED, - const char *base_dir ATTR_UNUSED, struct dict **dict_r, - const char **error_r) + const struct dict_settings *set ATTR_UNUSED, + struct dict **dict_r, const char **error_r) { struct memcached_dict *dict; const char *const *args; diff -r d91b43496e72 -r 77e71a45a475 src/lib-dict/dict-private.h --- a/src/lib-dict/dict-private.h Thu Aug 28 22:06:29 2014 +0900 +++ b/src/lib-dict/dict-private.h Thu Aug 28 21:56:41 2014 +0900 @@ -5,8 +5,7 @@ struct dict_vfuncs { int (*init)(struct dict *dict_driver, const char *uri, - enum dict_data_type value_type, - const char *username, const char *base_dir, + const struct dict_settings *set, struct dict **dict_r, const char **error_r); void (*deinit)(struct dict *dict); int (*wait)(struct dict *dict); diff -r d91b43496e72 -r 77e71a45a475 src/lib-dict/dict-redis.c --- a/src/lib-dict/dict-redis.c Thu Aug 28 22:06:29 2014 +0900 +++ b/src/lib-dict/dict-redis.c Thu Aug 28 21:56:41 2014 +0900 @@ -311,10 +311,8 @@ static int redis_dict_init(struct dict *driver, const char *uri, - enum dict_data_type value_type ATTR_UNUSED, - const char *username, - const char *base_dir ATTR_UNUSED, struct dict **dict_r, - const char **error_r) + const struct dict_settings *set, + struct dict **dict_r, const char **error_r) { struct redis_dict *dict; struct ip_addr ip; @@ -383,11 +381,11 @@ i_array_init(&dict->input_states, 4); i_array_init(&dict->replies, 4); - if (strchr(username, DICT_USERNAME_SEPARATOR) == NULL) - dict->username = i_strdup(username); + if (strchr(set->username, DICT_USERNAME_SEPARATOR) == NULL) + dict->username = i_strdup(set->username); else { /* escape the username */ - dict->username = i_strdup(redis_escape_username(username)); + dict->username = i_strdup(redis_escape_username(set->username)); } *dict_r = &dict->dict; diff -r d91b43496e72 -r 77e71a45a475 src/lib-dict/dict-sql.c --- a/src/lib-dict/dict-sql.c Thu Aug 28 22:06:29 2014 +0900 +++ b/src/lib-dict/dict-sql.c Thu Aug 28 21:56:41 2014 +0900 @@ -73,8 +73,7 @@ static int sql_dict_init(struct dict *driver, const char *uri, - enum dict_data_type value_type ATTR_UNUSED, - const char *username, const char *base_dir ATTR_UNUSED, + const struct dict_settings *set, struct dict **dict_r, const char **error_r) { struct sql_dict *dict; @@ -84,7 +83,7 @@ dict = p_new(pool, struct sql_dict, 1); dict->pool = pool; dict->dict = *driver; - dict->username = p_strdup(pool, username); + dict->username = p_strdup(pool, set->username); dict->set = dict_sql_settings_read(pool, uri, error_r); if (dict->set == NULL) { pool_unref(&pool); diff -r d91b43496e72 -r 77e71a45a475 src/lib-dict/dict.c --- a/src/lib-dict/dict.c Thu Aug 28 22:06:29 2014 +0900 +++ b/src/lib-dict/dict.c Thu Aug 28 21:56:41 2014 +0900 @@ -56,10 +56,22 @@ const char *username, const char *base_dir, struct dict **dict_r, const char **error_r) { + struct dict_settings set; + + memset(&set, 0, sizeof(set)); + set.value_type = value_type; + set.username = username; + set.base_dir = base_dir; + return dict_init_full(uri, &set, dict_r, error_r); +} + +int dict_init_full(const char *uri, const struct dict_settings *set, + struct dict **dict_r, const char **error_r) +{ struct dict *dict; const char *p, *name, *error; - i_assert(username != NULL); + i_assert(set->username != NULL); p = strchr(uri, ':'); if (p == NULL) { @@ -74,8 +86,7 @@ *error_r = t_strdup_printf("Unknown dict module: %s", name); return -1; } - if (dict->v.init(dict, p+1, value_type, username, base_dir, - dict_r, &error) < 0) { + if (dict->v.init(dict, p+1, set, dict_r, &error) < 0) { *error_r = t_strdup_printf("dict %s: %s", name, error); return -1; } diff -r d91b43496e72 -r 77e71a45a475 src/lib-dict/dict.h --- a/src/lib-dict/dict.h Thu Aug 28 22:06:29 2014 +0900 +++ b/src/lib-dict/dict.h Thu Aug 28 21:56:41 2014 +0900 @@ -14,10 +14,16 @@ }; enum dict_data_type { - DICT_DATA_TYPE_STRING, + DICT_DATA_TYPE_STRING = 0, DICT_DATA_TYPE_UINT32 }; +struct dict_settings { + enum dict_data_type value_type; + const char *username; + const char *base_dir; +}; + typedef void dict_transaction_commit_callback_t(int ret, void *context); void dict_driver_register(struct dict *driver); @@ -34,6 +40,8 @@ int dict_init(const char *uri, enum dict_data_type value_type, const char *username, const char *base_dir, struct dict **dict_r, const char **error_r); +int dict_init_full(const char *uri, const struct dict_settings *set, + struct dict **dict_r, const char **error_r); /* Close dictionary. */ void dict_deinit(struct dict **dict); /* Wait for all pending asynchronous transaction commits to finish. From dovecot at dovecot.org Thu Aug 28 13:11:50 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 28 Aug 2014 13:11:50 +0000 Subject: dovecot-2.2: lib-dict: file backend now expands ~/ paths if home... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/58c3676c116c changeset: 17752:58c3676c116c user: Timo Sirainen date: Thu Aug 28 21:57:34 2014 +0900 description: lib-dict: file backend now expands ~/ paths if home_dir setting is set. diffstat: src/lib-dict/dict-file.c | 10 ++++++---- src/lib-dict/dict.h | 2 ++ 2 files changed, 8 insertions(+), 4 deletions(-) diffs (50 lines): diff -r 77e71a45a475 -r 58c3676c116c src/lib-dict/dict-file.c --- a/src/lib-dict/dict-file.c Thu Aug 28 21:56:41 2014 +0900 +++ b/src/lib-dict/dict-file.c Thu Aug 28 21:57:34 2014 +0900 @@ -55,11 +55,11 @@ static int file_dict_init(struct dict *driver, const char *uri, - const struct dict_settings *set ATTR_UNUSED, + const struct dict_settings *set, struct dict **dict_r, const char **error_r) { struct file_dict *dict; - const char *p; + const char *p, *path; dict = i_new(struct file_dict, 1); dict->lock_method = FILE_LOCK_METHOD_DOTLOCK; @@ -67,9 +67,9 @@ p = strchr(uri, ':'); if (p == NULL) { /* no parameters */ - dict->path = i_strdup(uri); + path = uri; } else { - dict->path = i_strdup_until(uri, p++); + path = t_strdup_until(uri, p++); if (strcmp(p, "lock=fcntl") == 0) dict->lock_method = FILE_LOCK_METHOD_FCNTL; else if (strcmp(p, "lock=flock") == 0) @@ -80,6 +80,8 @@ return -1; } } + dict->path = set->home_dir == NULL ? i_strdup(path) : + i_strdup(home_expand_tilde(path, set->home_dir)); dict->dict = *driver; dict->hash_pool = pool_alloconly_create("file dict", 1024); hash_table_create(&dict->hash, dict->hash_pool, 0, str_hash, strcmp); diff -r 77e71a45a475 -r 58c3676c116c src/lib-dict/dict.h --- a/src/lib-dict/dict.h Thu Aug 28 21:56:41 2014 +0900 +++ b/src/lib-dict/dict.h Thu Aug 28 21:57:34 2014 +0900 @@ -22,6 +22,8 @@ enum dict_data_type value_type; const char *username; const char *base_dir; + /* home directory for the user, if known */ + const char *home_dir; }; typedef void dict_transaction_commit_callback_t(int ret, void *context); From dovecot at dovecot.org Thu Aug 28 13:12:20 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 28 Aug 2014 13:12:20 +0000 Subject: dovecot-2.2: Replaced dict_init() with dict_init_full() in vario... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/866bb1354e85 changeset: 17753:866bb1354e85 user: Timo Sirainen date: Thu Aug 28 22:10:25 2014 +0900 description: Replaced dict_init() with dict_init_full() in various places. diffstat: src/lib-storage/index/index-attribute.c | 13 ++++++++----- src/plugins/last-login/last-login-plugin.c | 9 +++++++-- src/plugins/quota/quota-dict.c | 10 +++++++--- src/plugins/quota/quota.c | 13 +++++++++---- 4 files changed, 31 insertions(+), 14 deletions(-) diffs (106 lines): diff -r 58c3676c116c -r 866bb1354e85 src/lib-storage/index/index-attribute.c --- a/src/lib-storage/index/index-attribute.c Thu Aug 28 21:57:34 2014 +0900 +++ b/src/lib-storage/index/index-attribute.c Thu Aug 28 22:10:25 2014 +0900 @@ -82,6 +82,7 @@ struct mail_storage *storage = box->storage; struct mail_namespace *ns; struct mailbox_metadata metadata; + struct dict_settings set; const char *error; if (mailbox_get_metadata(box, MAILBOX_METADATA_GUID, &metadata) < 0) @@ -118,11 +119,13 @@ return -1; } - if (dict_init(storage->set->mail_attribute_dict, - DICT_DATA_TYPE_STRING, - storage->user->username, - storage->user->set->base_dir, - &storage->_shared_attr_dict, &error) < 0) { + memset(&set, 0, sizeof(set)); + set.username = storage->user->username; + set.base_dir = storage->user->set->base_dir; + if (mail_user_get_home(storage->user, &set.home_dir) <= 0) + set.home_dir = NULL; + if (dict_init_full(storage->set->mail_attribute_dict, &set, + &storage->_shared_attr_dict, &error) < 0) { mail_storage_set_critical(storage, "mail_attribute_dict: dict_init(%s) failed: %s", storage->set->mail_attribute_dict, error); diff -r 58c3676c116c -r 866bb1354e85 src/plugins/last-login/last-login-plugin.c --- a/src/plugins/last-login/last-login-plugin.c Thu Aug 28 21:57:34 2014 +0900 +++ b/src/plugins/last-login/last-login-plugin.c Thu Aug 28 22:10:25 2014 +0900 @@ -61,6 +61,7 @@ struct mail_user_vfuncs *v = user->vlast; struct last_login_user *luser; struct dict *dict; + struct dict_settings set; struct dict_transaction_context *trans; const char *dict_value, *key_name, *error; @@ -74,8 +75,12 @@ if (dict_value == NULL) return; - if (dict_init(dict_value, DICT_DATA_TYPE_STRING, user->username, - user->set->base_dir, &dict, &error) < 0) { + memset(&set, 0, sizeof(set)); + set.username = user->username; + set.base_dir = user->set->base_dir; + if (mail_user_get_home(user, &set.home_dir) <= 0) + set.home_dir = NULL; + if (dict_init_full(dict_value, &set, &dict, &error) < 0) { i_error("last_login_dict: dict_init(%s) failed: %s", dict_value, error); return; diff -r 58c3676c116c -r 866bb1354e85 src/plugins/quota/quota-dict.c --- a/src/plugins/quota/quota-dict.c Thu Aug 28 21:57:34 2014 +0900 +++ b/src/plugins/quota/quota-dict.c Thu Aug 28 22:10:25 2014 +0900 @@ -32,6 +32,7 @@ const char **error_r) { struct dict_quota_root *root = (struct dict_quota_root *)_root; + struct dict_settings set; const char *username, *p, *error; p = args == NULL ? NULL : strchr(args, ':'); @@ -78,9 +79,12 @@ /* FIXME: we should use 64bit integer as datatype instead but before it can actually be used don't bother */ - if (dict_init(args, DICT_DATA_TYPE_STRING, username, - _root->quota->user->set->base_dir, &root->dict, - &error) < 0) { + memset(&set, 0, sizeof(set)); + set.username = username; + set.base_dir = _root->quota->user->set->base_dir; + if (mail_user_get_home(_root->quota->user, &set.home_dir) <= 0) + set.home_dir = NULL; + if (dict_init_full(args, &set, &root->dict, &error) < 0) { *error_r = t_strdup_printf("dict_init(%s) failed: %s", args, error); return -1; } diff -r 58c3676c116c -r 866bb1354e85 src/plugins/quota/quota.c --- a/src/plugins/quota/quota.c Thu Aug 28 21:57:34 2014 +0900 +++ b/src/plugins/quota/quota.c Thu Aug 28 22:10:25 2014 +0900 @@ -664,10 +664,15 @@ } if (root->limit_set_dict == NULL) { - if (dict_init(root->set->limit_set, DICT_DATA_TYPE_STRING, - root->quota->user->username, - root->quota->user->set->base_dir, - &root->limit_set_dict, error_r) < 0) + struct dict_settings set; + + memset(&set, 0, sizeof(set)); + set.username = root->quota->user->username; + set.base_dir = root->quota->user->set->base_dir; + if (mail_user_get_home(root->quota->user, &set.home_dir) <= 0) + set.home_dir = NULL; + if (dict_init_full(root->set->limit_set, &set, + &root->limit_set_dict, error_r) < 0) return -1; } From pigeonhole at rename-it.nl Thu Aug 28 13:38:52 2014 From: pigeonhole at rename-it.nl (pigeonhole at rename-it.nl) Date: Thu, 28 Aug 2014 15:38:52 +0200 Subject: dovecot-2.2-pigeonhole: doveadm sieve plugin: Fixed segfault occ... Message-ID: details: http://hg.rename-it.nl/dovecot-2.2-pigeonhole/rev/1c90311178ac changeset: 1914:1c90311178ac user: Stephan Bosch date: Thu Aug 28 15:38:39 2014 +0200 description: doveadm sieve plugin: Fixed segfault occuring when main script storage does not support synchronization. Would occur with any other script storage intialization error as well. diffstat: src/plugins/doveadm-sieve/doveadm-sieve-plugin.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diffs (13 lines): diff -r 591019c327ad -r 1c90311178ac src/plugins/doveadm-sieve/doveadm-sieve-plugin.c --- a/src/plugins/doveadm-sieve/doveadm-sieve-plugin.c Thu Aug 28 11:34:37 2014 +0200 +++ b/src/plugins/doveadm-sieve/doveadm-sieve-plugin.c Thu Aug 28 15:38:39 2014 +0200 @@ -62,7 +62,8 @@ { struct sieve_mail_user *suser = SIEVE_USER_CONTEXT(user); - sieve_storage_unref(&suser->sieve_storage); + if (suser->sieve_storage != NULL) + sieve_storage_unref(&suser->sieve_storage); sieve_deinit(&suser->svinst); suser->module_ctx.super.deinit(user); From dovecot at dovecot.org Thu Aug 28 13:45:11 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 28 Aug 2014 13:45:11 +0000 Subject: dovecot-2.2: lib-fs: Fixed metawrap_fs.copy() to work with FS_PR... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/48aa40ae3039 changeset: 17754:48aa40ae3039 user: Timo Sirainen date: Thu Aug 28 22:44:18 2014 +0900 description: lib-fs: Fixed metawrap_fs.copy() to work with FS_PROPERTY_COPY_METADATA backends. This is done by simply copying the entire file with the metadata included instead of rewriting it. diffstat: src/lib-fs/fs-metawrap.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 866bb1354e85 -r 48aa40ae3039 src/lib-fs/fs-metawrap.c --- a/src/lib-fs/fs-metawrap.c Thu Aug 28 22:10:25 2014 +0900 +++ b/src/lib-fs/fs-metawrap.c Thu Aug 28 22:44:18 2014 +0900 @@ -378,7 +378,7 @@ struct metawrap_fs_file *src = (struct metawrap_fs_file *)_src; struct metawrap_fs_file *dest = (struct metawrap_fs_file *)_dest; - if (!dest->fs->wrap_metadata) { + if (!dest->fs->wrap_metadata || !_dest->metadata_changed) { if (_src != NULL) return fs_copy(src->super, dest->super); else From dovecot at dovecot.org Thu Aug 28 14:51:23 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 28 Aug 2014 14:51:23 +0000 Subject: dovecot-2.2: maildir: Handle unlink()=EPERM failure the same as ... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/3bc106fd69d3 changeset: 17755:3bc106fd69d3 user: Timo Sirainen date: Thu Aug 28 23:50:25 2014 +0900 description: maildir: Handle unlink()=EPERM failure the same as EISDIR. EPERM is POSIX, while EISDIR is Linux-specific. diffstat: src/lib-storage/index/maildir/maildir-sync-index.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 48aa40ae3039 -r 3bc106fd69d3 src/lib-storage/index/maildir/maildir-sync-index.c --- a/src/lib-storage/index/maildir/maildir-sync-index.c Thu Aug 28 22:44:18 2014 +0900 +++ b/src/lib-storage/index/maildir/maildir-sync-index.c Thu Aug 28 23:50:25 2014 +0900 @@ -95,7 +95,7 @@ } if (errno == ENOENT) return 0; - if (errno == EISDIR) + if (errno == EISDIR || errno == EPERM) return maildir_lose_unexpected_dir(box->storage, path); mail_storage_set_critical(&mbox->storage->storage, From dovecot at dovecot.org Thu Aug 28 14:53:14 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 28 Aug 2014 14:53:14 +0000 Subject: dovecot-2.2: Added UNLINK_EISDIR() helper macro. Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/0ff8d85a6893 changeset: 17756:0ff8d85a6893 user: Timo Sirainen date: Thu Aug 28 23:52:46 2014 +0900 description: Added UNLINK_EISDIR() helper macro. diffstat: src/lib-storage/index/maildir/maildir-sync-index.c | 2 +- src/lib-storage/list/mailbox-list-delete.c | 5 ++--- src/lib/compat.h | 5 +++++ 3 files changed, 8 insertions(+), 4 deletions(-) diffs (49 lines): diff -r 3bc106fd69d3 -r 0ff8d85a6893 src/lib-storage/index/maildir/maildir-sync-index.c --- a/src/lib-storage/index/maildir/maildir-sync-index.c Thu Aug 28 23:50:25 2014 +0900 +++ b/src/lib-storage/index/maildir/maildir-sync-index.c Thu Aug 28 23:52:46 2014 +0900 @@ -95,7 +95,7 @@ } if (errno == ENOENT) return 0; - if (errno == EISDIR || errno == EPERM) + if (UNLINK_EISDIR(errno)) return maildir_lose_unexpected_dir(box->storage, path); mail_storage_set_critical(&mbox->storage->storage, diff -r 3bc106fd69d3 -r 0ff8d85a6893 src/lib-storage/list/mailbox-list-delete.c --- a/src/lib-storage/list/mailbox-list-delete.c Thu Aug 28 23:50:25 2014 +0900 +++ b/src/lib-storage/list/mailbox-list-delete.c Thu Aug 28 23:52:46 2014 +0900 @@ -200,7 +200,7 @@ so don't bother stat()ing the file first */ if (unlink(str_c(full_path)) == 0) unlinked_something = TRUE; - else if (errno != ENOENT && errno != EISDIR && errno != EPERM) { + else if (errno != ENOENT && !UNLINK_EISDIR(errno)) { mailbox_list_set_critical(list, "unlink_directory(%s) failed: %m", str_c(full_path)); @@ -343,8 +343,7 @@ if (errno == ENOENT) { mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND, T_MAILBOX_LIST_ERR_NOT_FOUND(list, name)); - } else if (errno == EISDIR || - errno == EPERM) { /* Solaris */ + } else if (UNLINK_EISDIR(errno)) { mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE, "Mailbox isn't a symlink"); } else { diff -r 3bc106fd69d3 -r 0ff8d85a6893 src/lib/compat.h --- a/src/lib/compat.h Thu Aug 28 23:50:25 2014 +0900 +++ b/src/lib/compat.h Thu Aug 28 23:52:46 2014 +0900 @@ -254,6 +254,11 @@ #define ECANTLINK(errno) \ ((errno) == EXDEV || (errno) == EMLINK || (errno) == EPERM) +/* Returns TRUE if unlink() failed because it attempted to delete a directory */ +#define UNLINK_EISDIR(errno) \ + ((errno) == EPERM || /* POSIX */ \ + (errno) == EISDIR) /* Linux */ + /* EBUSY is given by some NFS implementations */ #define EDESTDIREXISTS(errno) \ ((errno) == EEXIST || (errno) == ENOTEMPTY || (errno) == EBUSY) From dovecot at dovecot.org Thu Aug 28 15:41:48 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 28 Aug 2014 15:41:48 +0000 Subject: dovecot-2.2: lib-fs: Keep a linked list of all files within fs t... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/2324dea38a03 changeset: 17757:2324dea38a03 user: Timo Sirainen date: Fri Aug 29 00:41:07 2014 +0900 description: lib-fs: Keep a linked list of all files within fs to help debugging. diffstat: src/lib-fs/fs-api-private.h | 4 ++++ src/lib-fs/fs-api.c | 8 ++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diffs (57 lines): diff -r 0ff8d85a6893 -r 2324dea38a03 src/lib-fs/fs-api-private.h --- a/src/lib-fs/fs-api-private.h Thu Aug 28 23:52:46 2014 +0900 +++ b/src/lib-fs/fs-api-private.h Fri Aug 29 00:41:07 2014 +0900 @@ -65,9 +65,13 @@ string_t *last_error; unsigned int files_open_count; + struct fs_file *files; }; struct fs_file { + /* linked list of all files (mainly for debugging leaks) */ + struct fs_file *prev, *next; + struct fs *fs; struct ostream *output; char *path; diff -r 0ff8d85a6893 -r 2324dea38a03 src/lib-fs/fs-api.c --- a/src/lib-fs/fs-api.c Thu Aug 28 23:52:46 2014 +0900 +++ b/src/lib-fs/fs-api.c Fri Aug 29 00:41:07 2014 +0900 @@ -3,6 +3,7 @@ #include "lib.h" #include "array.h" #include "module-dir.h" +#include "llist.h" #include "str.h" #include "hash-method.h" #include "istream.h" @@ -140,9 +141,10 @@ *_fs = NULL; if (fs->files_open_count > 0) { - i_panic("fs-%s: %u files still open", - fs->name, fs->files_open_count); + i_panic("fs-%s: %u files still open (first = %s)", + fs->name, fs->files_open_count, fs_file_path(fs->files)); } + i_assert(fs->files == NULL); i_free(fs->username); i_free(fs->session_id); @@ -174,6 +176,7 @@ } T_END; file->flags = mode_flags & ~FS_OPEN_MODE_MASK; fs->files_open_count++; + DLLIST_PREPEND(&fs->files, file); return file; } @@ -188,6 +191,7 @@ fs_file_close(file); + DLLIST_REMOVE(&file->fs->files, file); file->fs->files_open_count--; T_BEGIN { file->fs->v.file_deinit(file); From dovecot at dovecot.org Thu Aug 28 17:15:19 2014 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 28 Aug 2014 17:15:19 +0000 Subject: dovecot-2.2: lib-index, lib-storage: Fixed race conditions with ... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/6980c53bf7d7 changeset: 17758:6980c53bf7d7 user: Timo Sirainen date: Fri Aug 29 02:14:43 2014 +0900 description: lib-index, lib-storage: Fixed race conditions with deleting mailbox. Now only one process can successfully finish mailbox_mark_index_deleted(). diffstat: src/lib-index/mail-index-sync.c | 31 +++++++++++++++++++------------ src/lib-index/mail-index.h | 6 +++++- src/lib-index/mail-transaction-log-file.c | 1 + src/lib-storage/index/index-sync.c | 7 +++++-- src/lib-storage/mail-storage-private.h | 2 ++ src/lib-storage/mail-storage.c | 5 ++++- 6 files changed, 36 insertions(+), 16 deletions(-) diffs (141 lines): diff -r 2324dea38a03 -r 6980c53bf7d7 src/lib-index/mail-index-sync.c --- a/src/lib-index/mail-index-sync.c Fri Aug 29 00:41:07 2014 +0900 +++ b/src/lib-index/mail-index-sync.c Fri Aug 29 02:14:43 2014 +0900 @@ -360,13 +360,21 @@ } } - if (!mail_index_need_sync(index, flags, - log_file_seq, log_file_offset)) { + if (!mail_index_need_sync(index, flags, log_file_seq, log_file_offset) && + !index->index_deleted) { if (locked) mail_transaction_log_sync_unlock(index->log); return 0; } + if (!locked) { + /* it looks like we have something to sync. lock the file and + check again. */ + flags &= ~MAIL_INDEX_SYNC_FLAG_REQUIRE_CHANGES; + return mail_index_sync_begin_init(index, flags, log_file_seq, + log_file_offset); + } + if (index->index_deleted && (flags & MAIL_INDEX_SYNC_FLAG_DELETING_INDEX) == 0) { /* index is already deleted. we can't sync. */ @@ -375,14 +383,6 @@ return -1; } - if (!locked) { - /* it looks like we have something to sync. lock the file and - check again. */ - flags &= ~MAIL_INDEX_SYNC_FLAG_REQUIRE_CHANGES; - return mail_index_sync_begin_init(index, flags, log_file_seq, - log_file_offset); - } - hdr = &index->map->hdr; if (hdr->log_file_tail_offset > hdr->log_file_head_offset || hdr->log_file_seq > seq || @@ -482,7 +482,8 @@ ctx->ext_trans = mail_index_transaction_begin(ctx->view, trans_flags); ctx->ext_trans->sync_transaction = TRUE; ctx->ext_trans->commit_deleted_index = - (flags & MAIL_INDEX_SYNC_FLAG_DELETING_INDEX) != 0; + (flags & (MAIL_INDEX_SYNC_FLAG_DELETING_INDEX | + MAIL_INDEX_SYNC_FLAG_TRY_DELETING_INDEX)) != 0; *ctx_r = ctx; *view_r = ctx->view; @@ -789,10 +790,16 @@ index_undeleted = ctx->ext_trans->index_undeleted; delete_index = index->index_delete_requested && !index_undeleted && - (ctx->flags & MAIL_INDEX_SYNC_FLAG_DELETING_INDEX) != 0; + (ctx->flags & (MAIL_INDEX_SYNC_FLAG_DELETING_INDEX | + MAIL_INDEX_SYNC_FLAG_TRY_DELETING_INDEX)) != 0; if (delete_index) { /* finish this sync by marking the index deleted */ mail_index_set_deleted(ctx->ext_trans); + } else if (index->index_deleted && !index_undeleted && + (ctx->flags & MAIL_INDEX_SYNC_FLAG_TRY_DELETING_INDEX) == 0) { + /* another process just marked the index deleted. + finish the sync, but return error. */ + ret = -1; } mail_index_sync_update_mailbox_offset(ctx); diff -r 2324dea38a03 -r 6980c53bf7d7 src/lib-index/mail-index.h --- a/src/lib-index/mail-index.h Fri Aug 29 00:41:07 2014 +0900 +++ b/src/lib-index/mail-index.h Fri Aug 29 02:14:43 2014 +0900 @@ -159,7 +159,11 @@ MAIL_INDEX_SYNC_FLAG_FSYNC = 0x10, /* If we see "delete index" request transaction, finish it. This flag also allows committing more changes to a deleted index. */ - MAIL_INDEX_SYNC_FLAG_DELETING_INDEX = 0x20 + MAIL_INDEX_SYNC_FLAG_DELETING_INDEX = 0x20, + /* Same as MAIL_INDEX_SYNC_FLAG_DELETING_INDEX, but finish index + deletion only once and fail the rest (= avoid race conditions when + multiple processes try to mark the index deleted) */ + MAIL_INDEX_SYNC_FLAG_TRY_DELETING_INDEX = 0x40 }; enum mail_index_view_sync_flags { diff -r 2324dea38a03 -r 6980c53bf7d7 src/lib-index/mail-transaction-log-file.c --- a/src/lib-index/mail-transaction-log-file.c Fri Aug 29 00:41:07 2014 +0900 +++ b/src/lib-index/mail-transaction-log-file.c Fri Aug 29 02:14:43 2014 +0900 @@ -1284,6 +1284,7 @@ if (file->sync_offset < file->index_undeleted_offset) break; file->log->index->index_deleted = TRUE; + file->log->index->index_delete_requested = FALSE; file->index_deleted_offset = file->sync_offset + trans_size; break; case MAIL_TRANSACTION_INDEX_UNDELETED: diff -r 2324dea38a03 -r 6980c53bf7d7 src/lib-storage/index/index-sync.c --- a/src/lib-storage/index/index-sync.c Fri Aug 29 00:41:07 2014 +0900 +++ b/src/lib-storage/index/index-sync.c Fri Aug 29 02:14:43 2014 +0900 @@ -17,8 +17,11 @@ if ((box->flags & MAILBOX_FLAG_DROP_RECENT) != 0) sync_flags |= MAIL_INDEX_SYNC_FLAG_DROP_RECENT; - if (box->deleting) - sync_flags |= MAIL_INDEX_SYNC_FLAG_DELETING_INDEX; + if (box->deleting) { + sync_flags |= box->delete_sync_check ? + MAIL_INDEX_SYNC_FLAG_TRY_DELETING_INDEX : + MAIL_INDEX_SYNC_FLAG_DELETING_INDEX; + } return sync_flags; } diff -r 2324dea38a03 -r 6980c53bf7d7 src/lib-storage/mail-storage-private.h --- a/src/lib-storage/mail-storage-private.h Fri Aug 29 00:41:07 2014 +0900 +++ b/src/lib-storage/mail-storage-private.h Fri Aug 29 02:14:43 2014 +0900 @@ -332,6 +332,8 @@ unsigned int creating:1; /* Mailbox is being deleted */ unsigned int deleting:1; + /* Don't use MAIL_INDEX_SYNC_FLAG_DELETING_INDEX for sync flag */ + unsigned int delete_sync_check:1; /* Delete mailbox only if it's empty */ unsigned int deleting_must_be_empty:1; /* The backend wants to skip checking if there are 0 messages before diff -r 2324dea38a03 -r 6980c53bf7d7 src/lib-storage/mail-storage.c --- a/src/lib-storage/mail-storage.c Fri Aug 29 00:41:07 2014 +0900 +++ b/src/lib-storage/mail-storage.c Fri Aug 29 02:14:43 2014 +0900 @@ -1319,7 +1319,10 @@ /* sync the mailbox. this finishes the index deletion and it can succeed only for a single session. we do it here, so the rest of the deletion code doesn't have to worry about race conditions. */ - if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ) < 0) + box->delete_sync_check = TRUE; + ret = mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ); + box->delete_sync_check = FALSE; + if (ret < 0) return -1; box->marked_deleted = del;