dovecot-1.3: lmtp: If mail is >128 kB, write it to a temporary f...

dovecot at dovecot.org dovecot at dovecot.org
Fri Apr 17 19:54:54 EEST 2009


details:   http://hg.dovecot.org/dovecot-1.3/rev/a80db92d296b
changeset: 9133:a80db92d296b
user:      Timo Sirainen <tss at iki.fi>
date:      Fri Apr 17 12:54:49 2009 -0400
description:
lmtp: If mail is >128 kB, write it to a temporary file.

diffstat:

1 file changed, 68 insertions(+), 6 deletions(-)
src/lmtp/commands.c |   74 ++++++++++++++++++++++++++++++++++++++++++++++-----

diffs (115 lines):

diff -r dad05c75bd48 -r a80db92d296b src/lmtp/commands.c
--- a/src/lmtp/commands.c	Fri Apr 17 12:54:10 2009 -0400
+++ b/src/lmtp/commands.c	Fri Apr 17 12:54:49 2009 -0400
@@ -3,7 +3,10 @@
 #include "lib.h"
 #include "ioloop.h"
 #include "array.h"
+#include "str.h"
 #include "istream.h"
+#include "ostream.h"
+#include "safe-mkstemp.h"
 #include "mail-storage-service.h"
 #include "index/raw/raw-storage.h"
 #include "lda-settings.h"
@@ -256,8 +259,14 @@ static int client_open_raw_mail(struct c
 	struct istream *input;
 	enum mail_error error;
 
-	input = i_stream_create_from_data(client->state.mail_data->data,
-					  client->state.mail_data->used);
+	if (client->state.mail_data_output != NULL) {
+		o_stream_unref(&client->state.mail_data_output);
+		input = i_stream_create_fd(client->state.mail_data_fd,
+					   MAIL_READ_BLOCK_SIZE, FALSE);
+	} else {
+		input = i_stream_create_from_data(client->state.mail_data->data,
+						  client->state.mail_data->used);
+	}
 	client->state.raw_box = box =
 		mailbox_open(&raw_storage, "Dovecot Delivery Mail", input,
 			     MAILBOX_OPEN_NO_INDEX_FILES);
@@ -325,10 +334,55 @@ static void client_input_data_finish(str
 	}
 }
 
-static void
+static int client_input_add_file(struct client *client,
+				 const unsigned char *data, size_t size)
+{
+	string_t *path;
+	int fd;
+
+	if (client->state.mail_data_output != NULL) {
+		/* continue writing to file */
+		if (o_stream_send(client->state.mail_data_output,
+				  data, size) != (ssize_t)size)
+			return -1;
+		return 0;
+	}
+
+	/* move everything to a temporary file. FIXME: it really shouldn't
+	   be in /tmp.. */
+	path = t_str_new(256);
+	str_append(path, "/tmp/dovecot.lmtp.");
+	fd = safe_mkstemp_hostpid(path, 0600, (uid_t)-1, (gid_t)-1);
+	if (fd == -1)
+		return -1;
+
+	/* we just want the fd, unlink it */
+	if (unlink(str_c(path)) < 0) {
+		/* shouldn't happen.. */
+		i_error("unlink(%s) failed: %m", str_c(path));
+		(void)close(fd);
+		return -1;
+	}
+
+	client->state.mail_data_fd = fd;
+	client->state.mail_data_output = o_stream_create_fd_file(fd, 0, FALSE);
+	o_stream_cork(client->state.mail_data_output);
+	if (o_stream_send(client->state.mail_data_output,
+			  data, size) != (ssize_t)size)
+		return -1;
+	return 0;
+}
+
+static int
 client_input_add(struct client *client, const unsigned char *data, size_t size)
 {
-	buffer_append(client->state.mail_data, data, size);
+	if (client->state.mail_data->used + size <=
+	    CLIENT_MAIL_DATA_MAX_INMEMORY_SIZE) {
+		buffer_append(client->state.mail_data, data, size);
+		return 0;
+	} else {
+		return client_input_add_file(client, data, size);
+	}
 }
 
 static void client_input_data_handle(struct client *client)
@@ -353,7 +407,11 @@ static void client_input_data_handle(str
 			}
 		} else if (client->state.data_end_idx == DATA_DOT_NEXT_POS) {
 			/* saw a dot at the beginning of line. drop it. */
-			client_input_add(client, data, i-1);
+			if (client_input_add(client, data, i-1) < 0) {
+				client_destroy(client, "451 4.3.0",
+					       "Temporary internal failure");
+				return;
+			}
 			start = i;
 			client->state.data_end_idx = 0;
 		} else {
@@ -366,7 +424,11 @@ static void client_input_data_handle(str
 		rewind = client->state.data_end_idx - DATA_DOT_NEXT_POS + 1;
 		i -= rewind; size -= rewind;
 	}
-	client_input_add(client, data + start, i-start);
+	if (client_input_add(client, data + start, i-start) < 0) {
+		client_destroy(client, "451 4.3.0",
+			       "Temporary internal failure");
+		return;
+	}
 	i_stream_skip(client->input, skip == 0 ? i : skip);
 
 	if (i < size) {


More information about the dovecot-cvs mailing list