SOURCES: dovecot-branch.diff (NEW) - from mercurial upstream repo

arekm arekm at pld-linux.org
Thu Jun 28 09:44:25 CEST 2007


Author: arekm                        Date: Thu Jun 28 07:44:25 2007 GMT
Module: SOURCES                       Tag: HEAD
---- Log message:
- from mercurial upstream repo

---- Files affected:
SOURCES:
   dovecot-branch.diff (NONE -> 1.1)  (NEW)

---- Diffs:

================================================================
Index: SOURCES/dovecot-branch.diff
diff -u /dev/null SOURCES/dovecot-branch.diff:1.1
--- /dev/null	Thu Jun 28 09:44:25 2007
+++ SOURCES/dovecot-branch.diff	Thu Jun 28 09:44:20 2007
@@ -0,0 +1,445 @@
+diff --git a/src/auth/passdb-pam.c b/src/auth/passdb-pam.c
+--- a/src/auth/passdb-pam.c
++++ b/src/auth/passdb-pam.c
+@@ -229,8 +229,7 @@ static int pam_auth(struct auth_request 
+ 	        }
+ 	}
+ 
+-	/* FIXME: this doesn't actually work since we're in the child
+-	   process.. */
++	/* FIXME: this works only with blocking=yes */
+ 	status = pam_get_item(pamh, PAM_USER, (linux_const void **)&item);
+ 	if (status != PAM_SUCCESS) {
+ 		*error = t_strdup_printf("pam_get_item() failed: %s",
+diff --git a/src/imap/client.c b/src/imap/client.c
+--- a/src/imap/client.c
++++ b/src/imap/client.c
+@@ -485,13 +485,18 @@ int _client_output(void *context)
+ 
+ static void idle_timeout(void *context __attr_unused__)
+ {
+-	time_t idle_time;
++	time_t idle_time, last_change;
+ 
+ 	if (my_client == NULL)
+ 		return;
+ 
+-	idle_time = ioloop_time -
++	/* We mostly want to check last_input here, but if there is a very long
++	   running command (like copying thousands of messages), we don't want
++	   to disconnect the client just after the command was finished.
++	   But any output that IDLE has sent should be ignored. */
++	last_change = my_client->idling ? my_client->last_input :
+ 		I_MAX(my_client->last_input, my_client->last_output);
++	idle_time = ioloop_time - last_change;
+ 
+ 	if (my_client->command_pending &&
+ 	    o_stream_get_buffer_used_size(my_client->output) > 0 &&
+diff --git a/src/imap/client.h b/src/imap/client.h
+--- a/src/imap/client.h
++++ b/src/imap/client.h
+@@ -52,6 +52,7 @@ struct client {
+ 	unsigned int input_pending:1;
+ 	unsigned int output_pending:1;
+ 	unsigned int handling_input:1;
++	unsigned int idling:1;
+ 	unsigned int input_skip_line:1; /* skip all the data until we've
+ 					   found a new line */
+ };
+diff --git a/src/imap/cmd-append.c b/src/imap/cmd-append.c
+--- a/src/imap/cmd-append.c
++++ b/src/imap/cmd-append.c
+@@ -285,8 +285,7 @@ static bool cmd_append_continue_parsing(
+ 	if (ctx->msg_size == 0) {
+ 		/* no message data, abort */
+ 		client_send_tagline(cmd, "NO Append aborted.");
+-		cmd_append_finish(ctx);
+-		return TRUE;
++		return cmd_append_cancel(ctx, nonsync);
+ 	}
+ 
+ 	/* save the mail */
+diff --git a/src/imap/cmd-idle.c b/src/imap/cmd-idle.c
+--- a/src/imap/cmd-idle.c
++++ b/src/imap/cmd-idle.c
+@@ -56,6 +56,7 @@ static void idle_finish(struct cmd_idle_
+ 	if (client->mailbox != NULL)
+ 		mailbox_notify_changes(client->mailbox, 0, NULL, NULL);
+ 
++	client->idling = FALSE;
+ 	if (done_ok)
+ 		client_send_tagline(ctx->cmd, "OK Idle completed.");
+ 	else
+@@ -263,6 +264,7 @@ bool cmd_idle(struct client_command_cont
+ 	client->io = io_add(i_stream_get_fd(client->input),
+ 			    IO_READ, idle_client_input, ctx);
+ 
++	client->idling = TRUE;
+ 	client->command_pending = TRUE;
+ 	cmd->func = cmd_idle_continue;
+ 	cmd->context = ctx;
+diff --git a/src/imap/cmd-list.c b/src/imap/cmd-list.c
+--- a/src/imap/cmd-list.c
++++ b/src/imap/cmd-list.c
+@@ -135,6 +135,15 @@ list_namespace_mailboxes(struct client *
+ 					continue;
+ 				str_append(name_str, ctx->ns->prefix);
+ 			}
++			if ((list->flags & MAILBOX_NOCHILDREN) != 0 &&
++			    strncmp(ctx->ns->prefix, "INBOX", 5) == 0 &&
++			    ctx->ns->prefix[5] == ctx->ns->sep) {
++				/* FIXME: It's unlikely there's only a single
++				   INBOX mailbox, but it's possible. We should
++				   check that instead of assuming it. */
++				list->flags |= MAILBOX_CHILDREN;
++				list->flags &= ~MAILBOX_NOCHILDREN;
++			}
+ 		} else {
+ 			str_append(name_str, ctx->ns->prefix);
+ 		}
+diff --git a/src/imap/imap-fetch.c b/src/imap/imap-fetch.c
+--- a/src/imap/imap-fetch.c
++++ b/src/imap/imap-fetch.c
+@@ -322,6 +322,7 @@ int imap_fetch(struct imap_fetch_context
+ 		ctx->line_finished = TRUE;
+ 		if (o_stream_send(ctx->client->output, ")\r\n", 3) < 0)
+ 			return -1;
++		ctx->client->last_output = ioloop_time;
+ 
+ 		ctx->cur_mail = NULL;
+ 		ctx->cur_handler = 0;
+@@ -362,12 +363,11 @@ int imap_fetch_deinit(struct imap_fetch_
+ 		mailbox_header_lookup_deinit(&ctx->all_headers_ctx);
+ 
+ 	if (ctx->trans != NULL) {
+-		if (ctx->failed)
+-			mailbox_transaction_rollback(&ctx->trans);
+-		else {
+-			if (mailbox_transaction_commit(&ctx->trans, 0) < 0)
+-				ctx->failed = TRUE;
+-		}
++		/* even if something failed, we want to commit changes to
++		   cache, as well as possible \Seen flag changes for FETCH
++		   replies we returned so far. */
++		if (mailbox_transaction_commit(&ctx->trans, 0) < 0)
++			ctx->failed = TRUE;
+ 	}
+ 	return ctx->failed ? -1 : 0;
+ }
+diff --git a/src/lib-index/mail-transaction-log-view.c b/src/lib-index/mail-transaction-log-view.c
+--- a/src/lib-index/mail-transaction-log-view.c
++++ b/src/lib-index/mail-transaction-log-view.c
+@@ -97,9 +97,10 @@ mail_transaction_log_view_set(struct mai
+ 			      uint32_t max_file_seq, uoff_t max_file_offset,
+ 			      enum mail_transaction_type type_mask)
+ {
+-	struct mail_transaction_log_file *file, *first;
++	struct mail_transaction_log_file *file, *const *files;
++	unsigned int i;
+ 	uint32_t seq;
+-	uoff_t end_offset;
++	uoff_t start_offset, end_offset;
+ 	int ret;
+ 
+ 	i_assert(view->log != NULL);
+@@ -159,12 +160,8 @@ mail_transaction_log_view_set(struct mai
+ 		return -1;
+ 	}
+ 
+-	end_offset = min_file_seq == max_file_seq ?
+-		max_file_offset : (uoff_t)-1;
+-	ret = mail_transaction_log_file_map(file, min_file_offset, end_offset);
+-	if (ret <= 0)
+-		return ret;
+-	first = file;
++	view->tail = file;
++	view->head = file;
+ 
+ 	for (seq = min_file_seq+1; seq <= max_file_seq; seq++) {
+ 		file = file->next;
+@@ -192,40 +189,57 @@ mail_transaction_log_view_set(struct mai
+ 			/* missing files in the middle */
+ 			return 0;
+ 		}
+-
++		view->head = file;
++	}
++
++	/* we have all of them. update refcounts. */
++	mail_transaction_log_view_unref_all(view);
++
++	/* reference all used files */
++	for (file = view->tail;; file = file->next) {
++		array_append(&view->file_refs, &file, 1);
++		file->refcount++;
++
++		if (file == view->head)
++			break;
++	}
++
++	/* Map the files only after we've found them all. Otherwise if we map
++	   one file and then another file just happens to get rotated, we could
++	   include both files in the view but skip the last transactions from
++	   the first file.
++
++	   We're mapping the files in reverse order so that _log_file_map()
++	   can verify that prev_file_offset matches how far it actually managed
++	   to sync the file. */
++	files = array_idx(&view->file_refs, 0);
++	for (i = array_count(&view->file_refs); i > 0; i--) {
++		file = files[i-1];
++		start_offset = file->hdr.file_seq == min_file_seq ?
++			min_file_offset : file->hdr.hdr_size;
+ 		end_offset = file->hdr.file_seq == max_file_seq ?
+ 			max_file_offset : (uoff_t)-1;
+-		ret = mail_transaction_log_file_map(file, file->hdr.hdr_size,
++		ret = mail_transaction_log_file_map(file, start_offset,
+ 						    end_offset);
+ 		if (ret <= 0)
+ 			return ret;
+ 	}
+ 
++	i_assert(max_file_seq == (uint32_t)-1 ||
++		 max_file_seq == view->head->hdr.file_seq);
+ 	i_assert(max_file_offset == (uoff_t)-1 ||
+-		 max_file_offset <= file->sync_offset);
+-
+-	/* we have all of them. update refcounts. */
+-	mail_transaction_log_view_unref_all(view);
+-
+-	view->tail = first;
+-	view->head = view->log->head;
+-
+-	/* reference all used files */
+-	for (file = view->tail; file != NULL; file = file->next) {
+-		array_append(&view->file_refs, &file, 1);
+-		file->refcount++;
+-	}
++		 max_file_offset <= view->head->sync_offset);
+ 
+ 	view->prev_file_seq = 0;
+ 	view->prev_file_offset = 0;
+ 
+-	view->cur = first;
++	view->cur = view->tail;
+ 	view->cur_offset = min_file_offset;
+ 
+ 	view->min_file_seq = min_file_seq;
+ 	view->min_file_offset = min_file_offset;
+ 	view->max_file_seq = max_file_seq;
+-	view->max_file_offset = max_file_offset;
++	view->max_file_offset = I_MIN(max_file_offset, view->head->sync_offset);
+ 	view->type_mask = type_mask;
+ 	view->broken = FALSE;
+ 
+diff --git a/src/lib-index/mail-transaction-log.c b/src/lib-index/mail-transaction-log.c
+--- a/src/lib-index/mail-transaction-log.c
++++ b/src/lib-index/mail-transaction-log.c
+@@ -1145,15 +1145,20 @@ mail_transaction_log_file_sync(struct ma
+ 		if (file->sync_offset - file->buffer_offset + hdr_size > size)
+ 			break;
+ 		file->sync_offset += hdr_size;
++		hdr_size = 0;
+ 	}
+ 
+ 	avail = file->sync_offset - file->buffer_offset;
+-	if (avail != size && avail >= sizeof(*hdr)) {
+-		/* record goes outside the file we've seen. or if
+-		   we're accessing the log file via unlocked mmaped
+-		   memory, it may be just that the memory was updated
+-		   after we checked the file size. */
+-		if (file->locked || file->mmap_base == NULL) {
++	if (avail != size) {
++		/* There's more data than we could sync at the moment. If the
++		   last record's size wasn't valid, we can't know if it will
++		   be updated unless we've locked the log.
++
++		   Without locking we can be sure only if we're not using
++		   mmaping, because with mmaping the data and the file size
++		   can get updated at any time. */
++		if (file->locked ||
++		    (hdr_size != 0 && file->mmap_base == NULL)) {
+ 			if (hdr_size != 0) {
+ 				mail_transaction_log_file_set_corrupted(file,
+ 					"hdr.size too large (%u)", hdr_size);
+diff --git a/src/lib-storage/mail-copy.c b/src/lib-storage/mail-copy.c
+--- a/src/lib-storage/mail-copy.c
++++ b/src/lib-storage/mail-copy.c
+@@ -2,7 +2,7 @@
+ 
+ #include "lib.h"
+ #include "istream.h"
+-#include "mail-storage.h"
++#include "mail-storage-private.h"
+ #include "mail-copy.h"
+ 
+ int mail_storage_copy(struct mailbox_transaction_context *t, struct mail *mail,
+@@ -31,6 +31,8 @@ int mail_storage_copy(struct mailbox_tra
+ 	}
+ 
+ 	if (input->stream_errno != 0) {
++		mail_storage_set_critical(t->box->storage,
++					  "copy: i_stream_read() failed: %m");
+ 		mailbox_save_cancel(&ctx);
+ 		return -1;
+ 	}
+diff --git a/src/lib/ioloop-notify-inotify.c b/src/lib/ioloop-notify-inotify.c
+--- a/src/lib/ioloop-notify-inotify.c
++++ b/src/lib/ioloop-notify-inotify.c
+@@ -155,7 +155,12 @@ void io_loop_notify_handler_init(struct 
+ 
+ 	ctx->inotify_fd = inotify_init();
+ 	if (ctx->inotify_fd == -1) {
+-		i_error("inotify_init() failed: %m");
++		if (errno != EMFILE)
++			i_error("inotify_init() failed: %m");
++		else {
++			i_warning("Inotify instance limit for user exceeded, "
++				  "disabling.");
++		}
+ 		ctx->disabled = TRUE;
+ 		return;
+ 	}
+diff --git a/src/lib/lib-signals.c b/src/lib/lib-signals.c
+--- a/src/lib/lib-signals.c
++++ b/src/lib/lib-signals.c
+@@ -21,10 +21,11 @@ struct signal_handler {
+ /* Remember that these are accessed inside signal handler which may be called
+    even while we're initializing/deinitializing. Try hard to keep everything
+    in consistent state. */
+-static struct signal_handler *signal_handlers[MAX_SIGNAL_VALUE+1];
+-static int sig_pipe_fd[2];
+-
+-static struct io *io_sig;
++static struct signal_handler *signal_handlers[MAX_SIGNAL_VALUE+1] = { NULL, };
++static int sig_pipe_fd[2] = { -1, -1 };
++
++static bool signals_initialized = FALSE;
++static struct io *io_sig = NULL;
+ 
+ static void sig_handler(int signo)
+ {
+@@ -99,6 +100,18 @@ static void signal_read(void *context __
+ 	}
+ }
+ 
++static void lib_signals_set(int signo, bool ignore)
++{
++	struct sigaction act;
++
++	if (sigemptyset(&act.sa_mask) < 0)
++		i_fatal("sigemptyset(): %m");
++	act.sa_flags = 0;
++	act.sa_handler = ignore ? sig_ignore : sig_handler;
++	if (sigaction(signo, &act, NULL) < 0)
++		i_fatal("sigaction(%d): %m", signo);
++}
++
+ void lib_signals_set_handler(int signo, bool delayed,
+ 			     signal_handler_t *handler, void *context)
+ {
+@@ -109,17 +122,10 @@ void lib_signals_set_handler(int signo, 
+ 			signo, MAX_SIGNAL_VALUE);
+ 	}
+ 
+-	if (signal_handlers[signo] == NULL) {
++	if (signal_handlers[signo] == NULL &&
++	    (handler == NULL || signals_initialized)) {
+ 		/* first handler for this signal */
+-		struct sigaction act;
+-
+-		if (sigemptyset(&act.sa_mask) < 0)
+-			i_fatal("sigemptyset(): %m");
+-		act.sa_flags = 0;
+-		act.sa_handler = handler != NULL ? sig_handler : sig_ignore;
+-		if (sigaction(signo, &act, NULL) < 0)
+-			i_fatal("sigaction(%d): %m", signo);
+-
++		lib_signals_set(signo, handler == NULL);
+ 		if (handler == NULL) {
+ 			/* we're ignoring the handler, just return */
+ 			return;
+@@ -133,7 +139,10 @@ void lib_signals_set_handler(int signo, 
+ 			i_fatal("pipe() failed: %m");
+ 		fd_close_on_exec(sig_pipe_fd[0], TRUE);
+ 		fd_close_on_exec(sig_pipe_fd[1], TRUE);
+-		io_sig = io_add(sig_pipe_fd[0], IO_READ, signal_read, NULL);
++		if (signals_initialized) {
++			io_sig = io_add(sig_pipe_fd[0], IO_READ,
++					signal_read, NULL);
++		}
+ 	}
+ 
+ 	h = i_new(struct signal_handler, 1);
+@@ -186,10 +195,18 @@ void lib_signals_unset_handler(int signo
+ 
+ void lib_signals_init(void)
+ {
+-        sig_pipe_fd[0] = sig_pipe_fd[1] = -1;
+-	io_sig = NULL;
+-
+-	memset(signal_handlers, 0, sizeof(signal_handlers));
++	int i;
++
++	signals_initialized = TRUE;
++
++	/* add signals that were already registered */
++	for (i = 0; i < MAX_SIGNAL_VALUE; i++) {
++		if (signal_handlers[i] != NULL)
++			lib_signals_set(i, FALSE);
++	}
++
++	if (sig_pipe_fd[0] != -1)
++		io_sig = io_add(sig_pipe_fd[0], IO_READ, signal_read, NULL);
+ }
+ 
+ void lib_signals_deinit(void)
+diff --git a/src/plugins/quota/quota-maildir.c b/src/plugins/quota/quota-maildir.c
+--- a/src/plugins/quota/quota-maildir.c
++++ b/src/plugins/quota/quota-maildir.c
+@@ -234,7 +234,7 @@ static int maildirsize_write(struct mail
+ 	if (fd == -1) {
+ 		if (errno == EAGAIN) {
+ 			/* someone's just in the middle of updating it */
+-			return -1;
++			return 1;
+ 		}
+ 
+ 		mail_storage_set_critical(storage,
+diff --git a/src/plugins/quota/quota.c b/src/plugins/quota/quota.c
+--- a/src/plugins/quota/quota.c
++++ b/src/plugins/quota/quota.c
+@@ -373,7 +373,8 @@ void quota_free(struct quota_transaction
+ 
+ const char *quota_last_error(struct quota *quota)
+ {
+-	return quota->last_error != NULL ? quota->last_error : "Unknown error";
++	return quota->last_error != NULL ? quota->last_error :
++		"Unknown quota error";
+ }
+ 
+ void quota_set_error(struct quota *quota, const char *errormsg)
+diff --git a/src/pop3/client.c b/src/pop3/client.c
+--- a/src/pop3/client.c
++++ b/src/pop3/client.c
+@@ -102,7 +102,7 @@ static int init_mailbox(struct client *c
+ 		mail_free(&mail);
+ 		if (mailbox_search_deinit(&ctx) < 0) {
+ 			client_send_storage_error(client);
+-			mailbox_transaction_rollback(&t);
++			(void)mailbox_transaction_commit(&t, 0);
+ 			break;
+ 		}
+ 
+@@ -113,8 +113,9 @@ static int init_mailbox(struct client *c
+ 			return TRUE;
+ 		}
+ 
+-		/* well, sync and try again */
+-		mailbox_transaction_rollback(&t);
++		/* well, sync and try again. we might have cached virtual
++		   sizes, make sure they get committed. */
++		(void)mailbox_transaction_commit(&t, 0);
+ 	}
+ 
+ 	if (i == 2)
================================================================


More information about the pld-cvs-commit mailing list